Knowing when and how to rotate object - c#

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?

Related

Spawning objects parallel to the terrain

Story
so I'm working on making a procedural terrain generator script to spawn rocks on the ground all the big rocks don't care what rotation they are but I have some small rocks that have to be parallel to the terrain or they look weird, part of them floating off the ground other part stuck in the ground the quaternions I don't seem to understand
Problem
i am getting the terrainData.GetInterpolatedNormal and putting it into a vector3 called normals then when i am spawning my rock i rotate it towards ground
Instantiate(SmallRock, new Vector3(point.x, Heights, point.y) transform.rotation = new Quaternion(normals.x,normals.y, normals.z, 90));
my problem lies in the Quaternion(normals.x,normals.y, normals.z, 90)
I don't know what to put where like should I only put the normals.x/z there or should I put the normals.y in there too and I don't even know what 90 at the end does, and yes I know that the interpolatednormals returns a 0 to 1 so I tried multiplying it to make it rotate more than 1 but it seems to just not rotate the right way if you can't tell by now I really have no clue how quaternions work but everywhere i search I can't find anything that helps and I didn't really feel like learning about how quaternions work so thanks for saving me time
Quaternions use compound(Imaginary) numbers to represent a sequence of rotations in 3d space.
When you instantiate a new Quaternion using it's constructor you are providing it with what you think the Quaternion's real and imaginary numbers should be.
Despite the seemingly familiar x, y, and z names you should not manually modify or provided them, they are not euler angles, cartesian coordinates, or traditional vector components.
What you're currently passing it is portions of a direction instead of the real and imaginary parts of a Quaternion.
A normal is an "outwards direction" from a given position. So to get a rotation we need some other direction to compare it to in order to get a rotation.
Compare your direction with the up direction and you'll get a rotation that you can use.
Quaternion rotation = Quaternion.FromToRotation(Vector3.up, normalDirection);

Bouncing my player further the closer I am

I'm recreating the movement system from the DS game Dragon Quest Heroes Rocket Slime in Unity. Currently I've got pretty desirable results but it's not 100%.
One of the things that are different is that my player bounces back from walls further on long distance slings than he does in the original game. (left is my recreation, right is original game). Obviously, I can't find out how the game was made and the exact maths/values they use for slinging but one of the things I got from the game is that:
The player moves at constant velocity while slinging in a direction (no slow down, they just stop at a certain point)
Which led me to believe the game doesn't use traditional velocity mechanics so I made it so:
While stretching, the players 'pVelocity' (potentialVelocity) goes up. When they let go a point create at curPlayerPosition + pVelocity is created. I then move the player at a constant velocity to that point. My idea to fix my issue of bouncing too far is by getting the distance from the position where I slung from to the end point and making the player bounce less the larger the distance and further the smaller the distance.
Problem is, I'm not really sure how to do that last part.
Here's my code:
Vector2 reflectedVelocity = Vector2.Reflect(pVelNormalized, foundHit.normal);
playerAnimator.SetFloat("VelocityX", reflectedVelocity.x);
playerAnimator.SetFloat("VelocityY", reflectedVelocity.y);
float DistanceFromOrigin = Vector3.Distance(slingOrigin, transform.position);
print(DistanceFromOrigin);
//ToDo: reflectedVelocity is lower the higher DistanceFromOrigin is.
The other solution I thought of is that maybe my idea of how the 'velocity' works in the original game is completely wrong and if so, please tell me how it actually is/looks to be actually done
reflectedVelocity is lower the higher DistanceFromOrigin is.
So reflectedVelocity should have an inverse relationship with DistanceFromOrigin
Vector2 reflectedVelocity = Vector2.Reflect(pVelNormalized, foundHit.normal);
float DistanceFromOrigin = Vector3.Distance(slingOrigin, transform.position);
if(DistanceFromOrigin == 0) DistanceFromOrigin = 0.00001f;//to avoid division by zero
reflectedVelocity *= (SomeConstant / DistanceFromOrigin);
playerAnimator.SetFloat("VelocityX", reflectedVelocity.x);
playerAnimator.SetFloat("VelocityY", reflectedVelocity.y);
You may use a linear relationship instead of non-linear:
reflectedVelocity *= (SomeConstant - DistanceFromOrigin);

How to find The Rotation of a 3d Triangle

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".

world velocity to local (ship might be flying backward so need worlds negative velocity etc.)

title pretty much says it all.. say I have a ship, its worldVelocity is a Vector3 with these values:
X: 0
Y: 0
Z: 1
(assuming +Z is Forward, +Y is Up, and +X is Right)
this Vector3 is added to the ships worldTranslations Matrix which stores translation and rotation.
worldTranslations.Translation += worldVelocity
and my ship goes forward, and it stops accelerating at speed 1 (correctly) as this is its target velocity, but what if the ship has been rotated Right 180 degrees, so its now flying backwards. Automatically the ships target velocity should detect this and begin trying to fly forward again.
The problem is I don't know how to get the local velocity out of my ships velocity and localTransforms, and I cant find an answer anywhere..
so at the moment my ship uses the world velocity for checking if its reached its target speed, so long as the ship doesnt rotate, it flies properly. My target speed will be one, so my ship compares its current velocity (0,0,0) to target velocity (0,0,1) and properly accelerates till it reaches its target (0,0,1) and stops accelerating to maintain a constant speed, but if i turn (say just 90 degrees right), current velocity is now (-1,0,0) because the ship is drifting left now, so it should use that relative velocity to determine that it needs to accelerate (1,0,1) to get back to (0,0,1) but I have no idea how to get relative velocity so it currently uses world velocity which is still (0,0,1) even though its flying left and so it thinks its all good but its still drifting left..
Thanks.. again everyone :)
The answer was to transform the velocity vector by the inverse rotation matrix.
This post was made as my friend realised the desired result was achieved in Unity3D using one of its built in functions, but ultimately is the same question:
XNA equivalency of unity function Transform.InverseTransformDirection
More detailed explanation can be found on that page.
However if this does not work for you, as it didn't immediately fix my problem, try examining one component of the vector at a time. I had to multiply only the Z component of the vector by -1 to make it work. Most likely interference by other maths so I recommend you examine the result vectors components results individually.
-Aaron
The ship's world matrix has a 'Forward' property which is a unit length vector that always points in the ship's forward direction. This vector is updated anytime the ship's rotation is changed and the world matrix updated to store the change.
So you can key the velocity off that vector and it will always go forward relative to the rotation of the ship.
Velocity = shipMatrix.Forward * speed;
ShipMatrix.Translation += velocity;

C# XNA Simulate Gravity

I have a question regarding using primitive shapes and simulating a circle to be free falling. How would I go about this? Do I use the formula for gravity?
It depends how detailed you want to be. Newtonian gravity laws dictate an force which has inverse square relationship between two bodies and their distance.
F is the magnitude of the gravitational force between the two point masses,
G is the gravitational constant,
m1 is the mass of the first point mass,
m2 is the mass of the second point mass, and
r is the distance between the two point masses.
So if you are simulating large bodies (say a planetary system) you need to apply gravity between each pair of objects.
Obviously, once you know the force you can apply Newton's second law (force=mass*acceleration) to calculate the acceleration you should apply to each body.
On the other end of the simplicity scale, if you have a fixed reference frame with respect to a single very large body (the ground) and multiple small objects, all you really need to do is apply a constant acceleration towards the ground. In this case, (in a vacuum) gravity on earth applies a constant acceleration of 9.81m/s2 to all objects. CodeInChaos gives a good code example of this.
(Of course we now know that Newtonian gravity isn't quite right and it breaks down at very large and very small scales. But that's a bit beyond this answer)
Gravity is just constant acceleration downwards.
Pseudocode:
const Vector3D Gravity=(0, 0, -9.8 m/s^2);
Vector3D Acceleration=Gravity;//insert other forces here
Vector3D Position+=Speed*DeltaT+0.5*Acceleration*DeltaT*DeltaT.
Vector3D Speed+=Acceleration*DeltaT;
You can use a physics engine, like Farseer:
http://roy-t.nl/index.php/2010/09/10/xna-farseer-platformer-physics-tutorial/
Simple version: if your circle has direction and speed then gravity is just a additional direction and speed pointing at the direction you want your gravity to pull.
Even simpler: just move the location of the circle downwards.
After this just fine tune it to fit your purpose with acceleration and setting the speed.

Categories

Resources