Oddities with rotation matrices

Started by
2 comments, last by Lode 14 years, 2 months ago
I'm trying to get an 3D arrow object to rotate depending on the angle between two positions, like in many open-world racing games. The way I'm seeing it, I get the Z angle (Z, in this engine, being up/down) and apply it to the objects Y angle. However, obviously, since this object needs to look like an 2-dimensional element, the Z angle of the object needs to be adjusted towards the camera. Now, to fix up the Y angle (since the angle with world-orientation is not oriented to the new Z angle) I tried doing some matrix maths, since it's the only method I could find to 'multiply' two positions. My code:

            RotationMatrix basem = RotationMatrix.Rotate(180, 0, 90);

            var basep = cpPoses1[a];
            var nextp = cpPoses2[a];

            var cpos = MarkerHack.GetCameraPosition(false);
            var ctrg = MarkerHack.GetCameraPosition(true);

            var corAng = MarkerHack.Angle(cpos.X, cpos.Y, ctrg.X, ctrg.Y);

            var angle = MarkerHack.Angle(basep.X, basep.Y, nextp.X, nextp.Y); // degree-based Z angle for distance
            angle -= corAng;

            var ang = MarkerHack.Angle(basep.X, basep.Y, cpos.X, cpos.Y); // degree-based Z angle for camera vs. object

            RotationMatrix matrixZ = RotationMatrix.Rotate(0f, 0f, (float)ang);
            RotationMatrix matrixCP = RotationMatrix.Rotate(0f, -((float)angle), 0f);

            RotationMatrix matrix = basem * matrixZ * matrixCP;
Some variable explanations go first: basem is a rotation matrix to apply to the arrow object to make it point up, with the 'visible' side (what, it's a 2D arrow!) to the north/south angle a is just an index to which of the two objects to modify. cpPoses1 contains the 'base' position, where the object is placed. cpPoses2 contains the next checkpoint, the other comparison point of the direction. cpos is the camera position vector, ctrg is the camera 'look at' vector. MarkerHack.Angle is a function which calculates the angle between two 2D points, in degrees. All other functions take degrees as well, so that's not an issue. Now, this code works almost perfectly if the first checkpoint and the camera are apart in a 'straight' angle (near 0, 90, 180, 270 degrees), but if on a curve, the object's rotation goes completely out of sync, seemingly the Z rotation is no longer applied and as such it doesn't look like an 2D object anymore. Also, the object points in the wrong direction once this happens. I think I might have missed a major point in the usage of matrices (I originally tried to multiply by 'just' doing 'left.M11 * right.M11', which obviously was wrong... I'm not that much of a math genius. :) It'd be a huge help if somebody can help by pointing out alternatives, a major oversight, or something else. -- Bas
Advertisement
I don't understand your code, but I think you can solve your problem without ever using angles. If you think of the problem in terms of vectors, you often get code that is easier to get write, cleaner and faster to execute.

If you describe exactly what inputs you have, and what outputs you need, I can try to find a solution without angles.
Well, the output API requires Euler angles to be used, so 'not using angles' is a bit of a bad idea. I finally got it to work, had to flip around the angle value returned for the Z angle a bit, and change one of the input vectors... I hate these maths. :)
Quote:Original post by NTAuthority
Well, the output API requires Euler angles to be used, so 'not using angles' is a bit of a bad idea. I finally got it to work, had to flip around the angle value returned for the Z angle a bit, and change one of the input vectors... I hate these maths. :)


If the API requires euler angles, it could be worth it to calculate everything with vector math and only convert from/to euler angles at the beginning/end of the calculation...

This topic is closed to new replies.

Advertisement