I have a direction vector that applied to a position gives me the point at which the camera should look. How can I get from that yaw, pitch and roll in order to use glRotatef properly?
Thanks in advance
None of these equations are 'wrong' but all are a little clumsy.
Ryder052, you example does not account certain cases as you've commented. Why not use atan2?
Given unit (normalized) direction vector d
pitch = asin(-d.Y);
yaw = atan2(d.X, d.Z)
You cannot get yaw, pitch and roll from a direction vector as the direction vector will only tell which direction to look in (yaw and pitch)
To get the yaw and pitch you use trigonometry - I assume you have some working knowledge. Check out this wiki page for some useful diagrams to visualize the angles.
Letting Y = yaw, P = pitch.
First to get yaw you want:
tan(Y) = x/(-y)
Now to get pitch:
tan(P) = sqrt(x^2 + y^2)/z
To get the actual values for Y and P you'll need to use inverse tan, I've written it above using tan to make the derivation clearer.
Note that the minus signs depend on how you define you angles and axes, but you should get the idea.
You can then set roll to be 0 or whatever you like.
You probably don't actually want the yaw, pitch and roll. You just need the correct transformation. Try using gluLookAt to build it. Documentation.
pheelicks's equations are wrong. Dear future googlers, here you got what's working:
Assuming pitch: rotation by X axis, yaw: rotation by Y axis, roll: rotation by Z axis. Direction vector V(x,y,z)
pitch = asin(V.y / length(V));
yaw = asin( V.x / (cos(pitch)*length(V)) ); //Beware cos(pitch)==0, catch this exception!
roll = 0;
Well, I am not sure what any of these answers are about because I could not get any of them to work.
I created my own solution...
// get world target offset
// convert world target offset to world direction normal
// get my world transposed (inverted)
// rotate world direction normal to my space normal
Vector3D lWorldTargetOffset = gWorldTargetLocation - gWorldMyLocation;
Vector3D lWorldTargetDirection = lWorldTargetOffset.Normalize();
MatrixD lMyWorldTransposed = MatrixD.Transpose(MyWorldMatrix);
Vector3D lMySpaceTargetDirection = Vector3D.Rotate(lWorldTargetDirection, lMyWorldTransposed);
you now have the world target direction normal in my space
lMySpaceTargetDirection.X = pitch
lMySpaceTargetDirection.Y = yaw.
lMySpaceTargetDirection.Z = <0 infront >0 behind.
As per direction normals all values are -1 to 1 so if you want degrees simply * 90.
Not saying this is the best solution but it is the only one I could get to work after spending hours searching online and wading through copious amounts of obtuse and nebulous crud.
I hope you, someone, or anyone, will enjoy simply rotating the target direction normal making it relative to myspace, and find it easy and helpful :)
Related
I have been using a 6dof LSM6DS0 IMU unit (with accelerometer and gyroscope). And I am trying to calculate the angle of rotation around all the three axes. I have tried may methods but not getting the results as expected.
Methods tried:
(i) Complementatry filter approach - I am able to get the angles using the formula provided in the link Angle comutation method.
But the problem is that angles are not at all consistent and drifts a lot. Moreover when the IMU is rotated around one axis, angles calculated over other axis are wobbling too much.
(ii) Quaternion based angle calculation : There were plenty of resources claiming the angles are calcluated very well using quaternion approach but none had a clear explanation. I have used this method in order to update the quaternion for every values taken from the IMU unit. But the link dint explain how to calculate the angles from quaternion.
I have used glm math library inorder to convert the quaternion to euler angles and also have tried the formula specified in wiki link. With this method since in pitch calculation asin returns only -90 to +90 degrees I am not able to rotate the object in 3D as the one they have been doing in the mentioned link.
Does anyone have tried the quaternion to angle conversion before?? I need to calculate the angles around all the three axis in the range 0 to 360 degrees or -180 to +180 degrees.
Any help could be really appreciated. Thanks in advance.
http://davidegironi.blogspot.com.ar/2013/02/avr-atmega-mpu6050-gyroscope-and.html#.VzjDKfnhCUk
Sq = [q0, q1, q2, q3]
//sensor quaternion can be translated to aerospace sequence of yaw/pitch/roll angles
yaw = atan2(2*q1*q2 - 2*q0*q3, 2*(q0^2) + 2*(q1^2) - 1)
pitch = -asin(2*q1*q3 + 2*q0*q2)
roll = atan2(2*q2*q3 - 2*q0*q1, 2*(q0^2) + 2*(q3^2) - 1)
Ray r = new Ray(this.transform.position, this.transform.eulerAngles);
RaycastHit hit;
if(Physics.Raycast(r, out hit, 3000, 256 /*layer 8*/ )){
That little bit of code won't give me a forward raycast, and I've searched for a number of solutions over multiple hours, to no avail.
So, the above won't give me a straight raycast out the front of the object and I don't know why. I figure it's probably an oversight.
The constructor for Ray takes an origin and a direction. transform.eulerAngles returns a vector of three angles around the x, y, and z axes. "Direction" might sound similar to angles, but it's not: the angles are rotation, not direction. The important distinction is that a direction vector "points" a certain way, but rotation describes how something is oriented. You could create a direction vector using the rotation information, but fortunately Unity can do this for you.
The easiest way to fix this is to use Unity's built-in way to get an object's forward direction vector (as seen in the Ray doc):
// Create a ray from the transform position along the transform's z-axis
Ray ray = new Ray(transform.position, transform.forward);
transform.forward gives you the forward direction vector of transform, meaning that the ray will be shot in the direction the object's facing.
So I have a bit of a math problem. Here are the pieces.
Input:
Rot = Rotation (degrees). This is the rotation of the "player". This is also the yaw.
Vel.X = This is the left/rightward movement that would be happening if it weren't rotated
Vel.Z = Same as last except its up/down movement
Output:
Result.X = This is the actual movement that should be happening along the x axis considering rotation
Result.Z = Same as last
Basically the scenario is that a player is standing on a platform with "Rot" rotation. When directional keys are pressed velocity is added accordingly to the "Vel" value. However if rotation isn't 0 this wont produce the right result because when the player rotates moving left becomes relative.
Could you please tell me a formula that would find the proper x and y movement that would result in the player moving around relative to its rotation?
This problem is probably the most basic rotation question in game programming.
Using your Vel.X and Vel.Z values, you have what you might think of as the vector you wish to rotate in the x/z plane (instead of x/y - but same idea). Whether velocity or position, the approach is the same. With a simple google search we find that for 2D vector rotation, the formula is:
Result.X = Vel.X * cos(Rot) - Vel.Z * sin(Rot);
Result.Z = Vel.X * sin(Rot) + Vel.Z * cos(Rot);
I've gone through a lot of questions online for the last few hours trying to figure out how to calculate the rotation between two vectors, using the least distance. Also, what is the difference between using Atan2 and using the dot product? I see them the most often.
The purpose is to rotate in the y axis only based on differences in X/Z position (Think top down rotation in a 3D world).
Option 1: use Atan2. Seems to work really well, except when it switchs the radians from positive to negative.
float radians = (float)Math.Atan2(source.Position.X - target.Position.X, source.Position.Z - target.Position.Z);
npc.ModelPosition.Rotation = new Vector3(0,
npc.ModelPosition.Rotation.Y + (radians),
0);
This works fine, except at one point it starts jittering then swings back the other way.
Use the dot product. Can't seem to make it work well, it ALWAYS turns in the same direction - is it possible to get it to swing in the least direction? I understand it ranges from 0 to pi - can I use that?
float dot = Vector3.Dot(Vector3.Normalize(source.Position), Vector3.Normalize(target.Position));
float angle = (float)Math.Acos(dot);
npc.ModelPosition.Rotation = new Vector3(0,
npc.ModelPosition.Rotation.Y + (angle),
0);
Thanks,
James
You calculate two different angles:
Angle alpha is the angle calculated with atan2 (which equals opposite side / adjacent side). Angle beta is the one calculated with the dot product.
You can achieve similar results (as with atan) with the dot product with
angle = acos(dot(normalize(target - source), -z))
(-z is the unit vector in negative z direction)
However, you will lose the sign.
Hey I can't figure out what the equation to find the new angle of travel of an object is after reflecting off of a wall.... The angle of travel is also based off the unit circle so 0degrees would be traveling right, 180 traveling left, 270 down, etc.
Just making the angle negative doesn't work either, any tips?
I think this is what you're looking for. I added in the angle of the wall, even if you didn't need it.
reflectionAngle = wallAngle + ((wallAngle + 180) - (incidenceAngle + 180))
If the wall is just vertical, its angle would be 90 degrees.
I hope this helps, and good luck!
EDIT: As a more simplified method, posted by Casey below:
reflectionAngle = 2*wallAngle - incidenceAngle
You have to change the angle relative to the wall coordinate system (t, n) and then transform back to (x, y) coordinates. The wall coordinate n is perpendicular to the wall; the direction t is created by taking the cross-product of the t-vector into the z-direction.
The algorithm would say that the incoming (v_t, v_n) velocity are changed as follows:
perpendicular component v_n changes sign.
tangential component v_t is unchanged, assuming no friction.
Once you have those, transform back to (x, y) coordinates.
It's easy if you think in terms of 2D vectors.
It would be
outAngle = 360 - inAngle