How to find The Rotation of a 3d Triangle - c#

I need a function so that, when given the Vector3 for a, b and c, will give me a new Vector3, the rotation of the Triangle. Pretty much, for point d, if I want to move it out, adjacent to the triangle, I just have to multiply the distance I want to move it by the Vector3 rotation, and add the old position to get the new Location.

The vector you want is called the unit normal vector. "Unit" means the length is 1 (so that you can just multiply by distance), and "normal" is the name of the vector that's perpendicular to a surface.
To get it, take the cross-product of any two edges of your triangle, and normalize the result. Look at this question for details on how to do this mathematically.
Note: "Normalizing" a vector means to keep the direction the same, but change the length to 1. It doesn't directly relate to a "normal vector".

Related

Unity Quaternion - get Euler angles of a component B relative to component A

I cannot get my head around Quaternions, and have tried many combination of operators on this (after reading / viewing tutorials). No success - just shows my lack of understanding. Even tried it with angles and atan2() - but all that really showed me was what gimbal lock was. The problem I am trying to solve is:
I have a component (say A, a cube) with some rotation in the world frame of reference (doesn't actually matter what that rotation is, could be orientated any direction).
Then I have another component (say B, another cube) elsewhere in the world space. Doesn't matter what that component's rotation is, either.
What I want to get to in the end are the (Euler) angles of B relative to A, BUT relative to A's frame of reference, not world space. The reason is I want to add forces to A based on B's direction from A, which I can then do with A.rigidbody.addRelativeForce(x, y, z); .
Stuck.
With thanks for the comments, I think I have it.
For reference, considering a vector and rotation within the same (world frame) coordinates, a new vector representing the original, but viewed from the perspective of local frame coordinates, being those of the original world rotation, can be calculated as:
static Vector3 createVectorForLocalRotationFrame(Vector3 worldVector, Quaternion worldRotation, bool normalise)
{
Vector3 localVector = Quaternion.Inverse(worldRotation) * worldVector;
if (normalise)
localVector.Normalize();
return localVector;
}
The normalise option is just something I needed. Don't ask me how it works, but it appears to be right.

given 2 point and 2 direction how do I know if they intersect?

I am doing some collision test in c#, and I have the following problem.
I have object1 and object2, they move in a direction.
I want to activate an effect only if object1 and object2 are colliding in a certain angle
the data I have
Vector2 object1Position
Vector2 object1Direction
float object1ColliderRadius
Vector2 object2Position
Vector2 object2Direction
float object2ColliderRadius
I already made a test to know if object1 is colliding with object2.
What I miss, is the angle of collision in order to activate or not something else in my code. follow this image .
The angle is easily calculated from, e.g., the dot product. The more interesting question is, if the two collide at all. This depends on the speed, of course. It is easily dealt with by adding an additional dimension. Here you'd put z = t. Using 3D affine geometry, you check if the 3D lines intersect. If yes, the objects with 2D trajectories collide. This is for point objects of course, so in detail you have to check for the closest distance of the lines.

Knowing when and how to rotate object

The CSV below gives me the x,z coordinates of a car with id = 1 at a given time t in seconds.
I am able to update the car gameobject's transform position at each second just fine. The issue is that when the car's direction changes, I need to be able to rotate (or realistically turn) the car to make it point in the direction it's going. I'm trying to do this with a simple Lerp rotation for now (and then use the standard asset CarController script to make a turn more realistic afterwards).
The current issue I'm having is knowing when the car is turning and how to conclude which direction it's going in, and therefore which way to rotate it. How could I go about this?
t,id,x,z
908,1,0.00,755.17
909,1,-1.50,732.50
910,1,-1.50,715.84
911,1,-1.50,699.17
912,1,-1.50,682.50
913,1,-1.50,679.19
914,1,-1.50,679.19
915,1,-1.50,679.19
916,1,-1.50,653.52
917,1,-1.50,636.85
918,1,-1.50,620.19
919,1,-1.50,603.52
920,1,-1.50,586.85
921,1,-1.50,570.19
922,1,-1.50,553.52
923,1,-1.50,536.85
924,1,-1.50,521.94
925,1,-1.50,521.94
926,1,-1.50,521.94
927,1,-1.50,521.94
928,1,-1.50,521.94
929,1,-1.50,521.94
930,1,-1.50,521.94
931,1,-1.50,496.28
932,1,-1.50,479.61
933,1,-1.50,462.94
934,1,-1.50,446.28
935,1,-1.50,429.61
936,1,-1.50,412.94
937,1,-1.50,396.28
938,1,-1.50,379.61
939,1,-1.50,378.74
940,1,-1.50,378.74
941,1,-1.50,378.74
942,1,-1.50,378.74
943,1,-1.50,378.74
944,1,-1.50,378.74
945,1,-1.50,378.74
946,1,-1.50,350.07
947,1,-1.50,333.40
948,1,-1.50,316.74
949,1,-1.50,300.07
950,1,-1.50,283.40
951,1,-1.50,266.74
952,1,-1.50,250.07
953,1,-1.50,233.40
954,1,-1.50,232.39
955,1,-1.50,232.39
956,1,-1.50,232.39
957,1,-1.50,232.39
958,1,-1.50,232.39
959,1,-4.50,209.72
960,1,-4.50,193.05
961,1,-4.50,176.39
962,1,-4.50,159.72
963,1,-4.50,143.05
964,1,-4.50,126.39
965,1,-4.50,109.72
966,1,-4.50,93.05
967,1,-4.50,76.39
968,1,-4.50,59.72
969,1,-4.50,43.05
970,1,-4.50,26.39
971,1,-4.50,9.72
972,1,-4.50,6.00
973,1,-4.50,6.00
974,1,-4.50,6.00
975,1,-4.50,6.00
976,1,-4.50,6.00
977,1,-4.50,6.00
978,1,-4.50,6.00
979,1,-4.50,6.00
980,1,-4.50,6.00
981,1,-4.50,6.00
982,1,-4.50,6.00
983,1,-4.50,6.00
984,1,28.22,-4.50
985,1,49.25,-4.50
986,1,69.00,-4.50
987,1,87.67,-4.50
988,1,105.12,-4.50
989,1,121.45,-4.50
990,1,136.32,-4.50
991,1,149.74,-4.50
992,1,161.36,-4.50
993,1,171.13,-4.50
994,1,179.02,-4.50
995,1,185.12,-4.50
996,1,189.57,-4.50
997,1,192.60,-4.50
998,1,194.49,-4.50
999,1,195.56,-4.50
1000,1,196.11,-4.50
1001,1,196.37,-4.50
1002,1,196.48,-4.50
1003,1,196.54,-4.50
1004,1,196.54,-4.50
1005,1,196.60,-4.50
1006,1,196.60,-4.50
1007,1,197.25,-4.50
1008,1,198.58,-4.50
1009,1,200.53,-4.50
1010,1,200.53,-4.50
1011,1,201.35,-4.50
1012,1,201.45,-4.50
1013,1,202.27,-4.50
1014,1,202.27,-4.50
1015,1,202.60,-4.50
1016,1,202.60,-4.50
1017,1,202.60,-4.50
1018,1,202.60,-4.50
1019,1,202.60,-4.50
1020,1,202.60,-4.50
1021,1,202.60,-4.50
1022,1,202.60,-4.50
1023,1,202.60,-4.50
1024,1,202.60,-4.50
1025,1,202.60,-4.50
1026,1,202.60,-4.50
1027,1,202.60,-4.50
1028,1,202.60,-4.50
1029,1,202.60,-4.50
1030,1,202.60,-4.50
1031,1,202.60,-4.50
1032,1,202.60,-4.50
1033,1,202.60,-4.50
1034,1,202.60,-4.50
1035,1,203.32,-4.50
1036,1,204.85,-4.50
1037,1,206.85,-4.50
1038,1,206.98,-4.50
1039,1,207.90,-4.50
1040,1,207.90,-4.50
1041,1,208.48,-4.50
1042,1,208.48,-4.50
1043,1,208.48,-4.50
1044,1,208.48,-4.50
1045,1,208.48,-4.50
1046,1,208.48,-4.50
1047,1,208.48,-4.50
1048,1,208.48,-4.50
1049,1,208.48,-4.50
1050,1,208.48,-4.50
1051,1,208.48,-4.50
1052,1,208.48,-4.50
1053,1,208.48,-4.50
1054,1,208.48,-4.50
1055,1,209.48,-4.50
1056,1,211.48,-4.50
1057,1,214.45,-4.50
1058,1,214.45,-4.50
1059,1,214.45,-4.50
1060,1,214.45,-4.50
1061,1,214.45,-4.50
1062,1,214.45,-4.50
1063,1,214.45,-4.50
1064,1,214.45,-4.50
1065,1,214.45,-4.50
1066,1,242.67,-1.50
1067,1,264.63,-1.50
1068,1,286.36,-1.50
1069,1,307.90,-1.50
1070,1,329.29,-1.50
1071,1,350.45,-1.50
1072,1,371.40,-1.50
1073,1,392.12,-1.50
1074,1,412.58,-1.50
1075,1,432.75,-1.50
1076,1,452.60,-1.50
1077,1,472.06,-1.50
1078,1,491.06,-1.50
1079,1,509.51,-1.50
1080,1,527.29,-1.50
1081,1,544.25,-1.50
1082,1,560.23,-1.50
1083,1,575.01,-1.50
1084,1,588.37,-1.50
1085,1,600.11,-1.50
1086,1,610.06,-1.50
1087,1,618.16,-1.50
1088,1,624.44,-1.50
1089,1,629.05,-1.50
1090,1,632.22,-1.50
1091,1,634.21,-1.50
1092,1,635.36,-1.50
1093,1,635.95,-1.50
1094,1,636.23,-1.50
1095,1,636.35,-1.50
1096,1,636.42,-1.50
1097,1,636.42,-1.50
1098,1,636.48,-1.50
1099,1,636.48,-1.50
1100,1,636.48,-1.50
1101,1,637.48,-1.50
1102,1,639.48,-1.50
1103,1,642.45,-1.50
Note that there is a follow-up question here: Unity: turning a car realistically given target point and direction
The problem is, as I understand:
We are given a series of object positions at particular times
The desired output is the set of vectors which describe the direction the object is facing, given the constraint that the object is facing in the direction of its current motion.
That's straightforward to compute, but a caution first. It does not always look realistic for a vehicle to be pointing in the direction that it is currently moving, particularly if it is turning. Cars skid and drift when turning sharply. Airplanes and rockets maneuver precisely by pointing themselves in the direction that they are not moving and producing thrust. Sailboats are incapable of pointing in the direction they are moving unless they are moving dead downwind. And so on. You might find that you need a more nuanced approach, but walk before you run.
But determining the velocity vector is straightforward. Velocity is the first time derivative of position, and you have position and time.
The simplest thing to do is to take the "current" position and the "next" position, subtract them, and divide by the time difference:
t, id, x, z
908, 1, 0.00, 755.17
909, 1, -1.50, 732.50
Subtract the first from the second to get the deltas:
t, id, Δt, Δx, Δz
908, 1, 1, -1.50, -22.67
Velocity is distance divided by time, so the velocity vector vaverage is (Δx/Δt, Δz/Δt), so that's the direction you should point your car.
Exercise: Can you compute the acceleration vectors at each point? Acceleration is the second derivative of position with respect to time. The third is "jerk", because we perceive a sudden change in acceleration as a "jerky" movement; can you compute it?
Exercise: Suppose you are given an initial position and a time series of velocities; can you go the other way, and produce the positions from the velocities?
Exercise: Suppose your object has a particular mass, and you are given an initial position, an initial velocity, and a time series of force vectors. Can you compute the velocities and positions? (Hint: what does Newton tell us about the relationship between force, mass and acceleration?)
Exercise: Rockets in space point in the direction they are accelerating, not the direction they are moving. But rockets in space are frictionless, and cars only work because there is friction against the road, so cars tend to point in the direction they are moving. A car that loses traction need not be pointing in the direction it is moving. Can you come up with a model for determining when a car loses traction?

How to move an object back based on its rotation and bounds in Unity?

Alright, so I have an object and it also has a bounds. I also have an anchorPoint, if you will, which is where the object is positioned and I have a boundary Vector3 position that I don't want the object to pass.
EDIT:
I will clarify my example in the following scenario:
Alright, lets take a rectangular prism since it is a perfect example. Obviously, when you are looking at it long ways it won't be as close to you if you rotate it 90 degrees on the y to where you are looking at the end of the object. Even though the object didn't change positions and is essentially in the same position, just rotated. I want to check if during rotation did the object pass a certain point called boundary. If it is past the point then I want to move the object forward in its z-direction so that the end of the object intersects the boundary position.
Assume that the object's initial position stays the same in the image below.
END EDIT
The problem comes into play when I want to rotate the object. How do I detect if part of the object has moved in front of this boundary position; that is not to say that the center of the object has passed this position but that part of the object has. I figured the best way to do this would be using bounds but, I'm not quite sure how to incorporate the rotation in with the bounds.
I haven't really had any luck with anything I have written so far. Any help on the matter would be greatly appreciated.
Assuming the simplest case, where you have a rectangular, axis aligned bounding box, then you have 8 points that make up your bounding box (the 8 corners).
The first check you want to make is to see if your anchor point is on the "wrong" side of your boundary plane. This is a simple vector dot product check.
Vector3 anchorDir = anchorPoint - boundaryPoint;
bool wrongSide = Vector3.Dot(anchorDir, boundaryDir) <= 0;
As long as your anchor point is on the right side of the boundary, you can move on to check each of the 8 bounding box points in the exact same way. However, you will need to make sure that your bounding points and your boundaryPoint are in the same coordinate system (world vs local) (this actually applies to your anchorPoint too). You could translate all the points to World space using Transform.TransformPoint (https://docs.unity3d.com/ScriptReference/Transform.TransformPoint.html) but it would be more efficient to translate the boundaryPoint to your bounding box's local coordinate system using InverseTransformPoint (https://docs.unity3d.com/ScriptReference/Transform.InverseTransformPoint.html).
Transform boundingBox = ...
Vector3 localBoundaryPoint = boundingBox.InverseTransformPoint(worldBoundaryPoint);
Vector3 localBoundaryDir = boundingBox.InverseTransformDirection(boundaryDirection);
foreach(Vector3 pt in boundingBoxPoints)
{
Vector3 pointDir = pt- localBoundaryPoint;
bool ptWrongSide = Vector3.Dot(pointDir , localBoundaryDir ) <= 0;
//How you handle that is up to you (return false, set a local flag and break, whatever)
}
EDIT:
If you want to know how far you are past the boundary so that you can shift your box back, you will need to handle that a little differently. You will have to check all the points and not just return when you find the first violator because you can't be sure which one is furthest.
float maxDistance = 0;
foreach(Vector3 pt in boundingBoxPoints)
{
Vector3 pointDir = pt- localBoundaryPoint;
//note the negative sign
float distance = -Vector3.Dot(pointDir, localBoundaryDir );
if (distance > maxDistance) maxDistance = distance;
}
if (maxDistance> 0)
{
//Shift your object by maxDistance amount along the localBoundaryDir;
}
Note that for your Dot Product to return the correct distance, localBoundaryDir needs to be a unit vector.
EDIT 2
Easier to describe the Boundary Point issue here than in the comments.
Your question doesn't explain how you define a Boundary Point, but let's assume that it's just a GameObject. You can implement a script on it but technically you don't even need that.
GameObject boundaryObject = ...
Vector3 boundaryPoint = boundaryObject.transform.position;
Vector3 boundaryDir = boundaryObject.transform.forward;
transform.forward always points along the z-axis, the blue arrow. So if, in the Unity editor you are constructing your scene, the blue arrow points along your plane's normal. Your "boundary line" extends to the right and left (x axis, red arrow) and up and down (y axis, green arrow).

Diagnosing backface culling issues

The setup: I'm using a cubemap projection to create a planet out of blocks. A cubemap projection is quite simple: take the vector from the center of a cube to any point on that cube, normalize it, then multiply that by the radius of a sphere and you have your coordinate's new position. Here's a quick illustration in 2D:
[link]
Now, as I said, I've created this so that it's made of blocks. So in practice, I divide my cube into equal square subdivisions (like a rubik's cube). I use a custom coordinate: (Face, X, Y, Shell). Face refers to which face on the cube the point is on. X and Y refer to its position on the face. Shell refers to its 'height'. In practice this translates into the radius of the sphere I project the point onto. If I haven't explained it well, hopefully an image will help:
[link]
--That's a planet generated with an entirely random heightmap, with backface culling turned off. Anyways, now that you have the idea of what I'm working with--
My problem is that I cannot get backface culling to work predictably. My current system works as follows:
Calculate the center of the block
Get the normal of the vertices on each triangle of the block by taking the cross product of two sides of the triangle
Get the vector from the center of the triangle (the average of the triangle's vertices) to the center of the block, normalize it.
Take the dot product of the normal of the triangle and the normal to the center of the block
If the dot product is >= 0, flip the first and last indices of the triangle
Here's that in code:
public bool CheckIndices(Quad q, Vector3 centerOfBlock)
{
Vector3[] vertices = new Vector3[3];
for (int v = 0; v < 3; v++)
vertices[v] = q.Corners[indices[v]].Position;
Vector3 center = (vertices[0] + vertices[1] + vertices[2]) / 3f;
Vector3 normal = Vector3.Cross(vertices[1] - vertices[0], vertices[2] - vertices[0]);
Vector3 position = center - centerOfBlock;
position.Normalize();
normal.Normalize();
float dotProduct = Vector3.Dot(position, normal);
if (dotProduct >= 0)
{
int swap = indices[0];
indices[0] = indices[2];
indices[2] = swap;
return false;
}
return true;
}
I use a Quad class to hold triangles and some other data. Triangles store an int[3] for indices which correspond to the vertices stored in Quad.
However, when I use this method, at least half of the faces are drawn in the wrong direction. I have noticed two patterns in the problem:
Faces which point outward from the center of the planet are always correct
Faces which point inward toward the center of the planet are always incorrect
This led me to believe that my calculated center of the block was incorrect and in fact somewhere between the block and the center of the planet. However, changing my calculations for the center of the block was ineffective.
I have used two different methods to calculate the center of the block. The first was to find the projected position of a coordinate which had +.5 X, +.5 Y, and +.5 Shell (Z) from the block's position. Because I define block position using the bottom-left-back corner, this new coordinate would naturally be in the center of the block. The other method I use is to calculate the real position of each corner of the block and then average these vectors. This method seemed pretty foolproof to me, yet it did not succeed.
For this reason I am beginning to doubt the code I pasted above which determines if a triangle must be flipped. I do not remember all of the reasoning behind some of the logic, specifically behind the >= 0 statement. I just need another pair of eyes: is something wrong here?
The problem was that I was being too general in my cubemap projection when I got the position of an arbitrary point on a cube. Compare the GetCorrectedCubePosition method here to the same method here to see the improvements made. The methods for clockwise index order checking I noted in my post should are still unknown in effectiveness, as I won't be using them anymore. Using a correct projection means I can hard-define my vertices as clockwise in the generation methods themselves instead of having to guess.

Categories

Resources