I am starting out on Molehill and am having a lot of problems grasping Matrix3D. My first problem is how to manage a Matrix3D that describes a single model's orientation.
I use Matrix3D.appendRotation() to do this. But depending on the order I append in I get a different result (obviously, since I am rotating one at a time in the global space). I know this is a common problem, I have run into it with 3d software modeling. But this time, I have to fix it programtically. This is where I need help.
First, in case there is any confusion, here is the problem in pictures:
Step 1: I render a model.
Step 2a: I rotate it on the X-axis. Looks correct!
Step 2b: I rotate it on the Z-axis. Looks correct!
So... if I rotate on the model's X AND Z axis I want this:
But, sadface, I get this:
I can see the problem. I am appending the rotations one at a time in the global space. I need to rotate in the object's local space. I have NO idea how to do this or what I should even be searching for (terminology, etc.). The code is simple (and wrong):
modelLocalMatrix.identity();
modelLocalMatrix.appendRotation(modelZRot, Vector3D.Z_AXIS);
modelLocalMatrix.appendRotation(modelXRot, Vector3D.X_AXIS);
//eventually y-axis rotation as well...
renderMatrix.append(modelLocalMatrix);
I am guessing that instead of using the Vector3D axis constants, I want to use some normalized vector and some... uh, thing... in place of modelZRot, modelXRot, and eventually modelYRot. Can anyone tell me what the best-practice solution is for applying the desired type of rotation above?
UPDATE: Having spent the day hitting the "books" (aka KhanAcademy on YouTube) and starting on this presentation here: The Mathematics of the 3d Rotation Matrix I have stumbled upon a sort of "look at" method which is very close to my desired solution. Unfortunately, I only 50% understand it. I still hope someone can shed some light on this topic!
var angleOfRotation:Number = Math.PI / 2; //90 degrees...
var axisOfRotation:Vector3D = new Vector3D(0, 1, 0); //some point to look at...
//normalize the vector!
axisOfRotation.normalize();
var x:Number = axisOfRotation.x;
var y:Number = axisOfRotation.y;
var z:Number = axisOfRotation.z;
var c:Number = Math.cos(angleOfRotation);
var s:Number = Math.sin(angleOfRotation);
var t:Number = 1 - c;
//Graphics Gems (Glassner, Academic Press, 1990).
modelLocalMatrix = new Matrix3D(new <Number>[
t * (x * x) + c, t * x * y - s * z, t * x * z + s * y, 0,
t * x * y + s * z, t * (y * y) + c, t * y * z - s * x, 0,
t * x * z - s * y, t * y * z + s * x, t * (z * z) + c, 0,
0, 0, 0, 1
]);
Thing is, this seems rather clunky. Especially since the angle of rotation for a Vector3D should be the fourth (w) value. More importantly, Matrix3D already appears to have a lookAt() method. I don't get it yet... please someone save me from hours of trial and error!