0
\$\begingroup\$

I have a camera class that contains a 4x4 view matrix as a member variable. Most of my camera controls work fine when doing them directly on the view matrix. In an attempt to unify all of my scene objects I want to do all of these transformations on the local matrix.

I plan on ultimately switching to a model with scale, position and rotation stored separately but that isn't the question at the moment.

Here my question again in a (hopefully more clear way):

I want to perform a turn table animation on a camera (rotation around an arbitrary point) I have working code for doing it directly on the view matrix. Also very important, the rotation must be around a set up axis (in my case +Y).

How can I achieve the same affect by transforming the local matrix directly?

Working turn table control directly on view matrix

// dX and dY are mouse deltas for the current frame
Vector3 position = viewMatrix.getPosition();
Vector3 forward = viewMatrix.getForward();
Vector3 right = viewMatrix.getRight();

// rotate around the focal point in front of us
Vector3 rotationPoint = position + forward * focalPoint;

Matrix4 rot;
rot.translate(rotationPoint);
rot.rotate(-dY, right);
rot.rotate(-dX, Vector3::Y_AXIS);
rot.translate(-rotationPoint);

viewMatrix = viewMatrix * rot;

Attempt to make it work on the local matrix:

// dX and dY are mouse deltas for the current frame
Vector3 position = localMatrix.getPosition();
Vector3 forward = localMatrix.getForward();
Vector3 right = localMatrix.getRight();

// rotate around the focal point in front of us
Vector3 rotationPoint = position + forward * focalPoint;

Matrix4 rot;
rot.translate(-rotationPoint);
rot.rotate(dX, Vector3::Y_AXIS);
rot.rotate(dY, right);
rot.translate(rotationPoint);

localMatrix = localMatrix * rot;

What happens: The animation is wonky, the pivot point seem to move while I rotate and the camera slowly drifts away.

Additional information:

Why do I need that? I want to be able to transform any scene object the same way. I might want to rotate a mesh around a point like I do the camera.

Is it easier to achieve what I want with a scale/position/rotation model? Even if it is I'm still interested on where I'm making a mistake here.

I will edit this post in the morning if there are any uncertain parts.

------------------------------------------------------

Edit:

I tried to rephrase my problem a bit I will leave the initial post for now, I hope I am more clear in this second attempt.

My Problem: I have working code for controlling a cameras view matrix and orbiting around a point in space.

Here is said code:

// get position and look at, look up and look right directions for the view matrix
Vector3 pos, la, lu, lr;
viewMatrix.lookAt(&pos, &la, &lu, &lr);

// rotate around point 5 units in front of us
Vector3 rotationPoint = pos+ la * 5; 

Matrix4 rot;
rot.translate(rotationPoint);
rot.rotate(-dY, lr);
rot.rotate(-dX, Vector3(0,1,0));
rot.translate(-rotationPoint);
viewMatrix *= rot;

here is the code for the lookAt function used above: It will retrieve you the position and forward, right, up directions from a VIEW matrix.

void Matrix4::lookAt(Vector3* eye, Vector3* at, Vector3* up, Vector3* ri)
{  
    Matrix3 invRot(_m);               // get the current view matrix
    invRot.translation(0,0,0);          // remove the translation
    invRot.transpose();                 // transpose it to get inverse rot.
    eye->set(invRot.multVec(-translation())); // setMatrix eye
    ri->set( _m[0], _m[4], _m[8]);            // normalized look right vector
    up->set( _m[1], _m[5], _m[9]);            // normalized look up vector
    at->set(-_m[2],-_m[6],-_m[10]);           // normalized look at vector
}

Note: the matrices are column major.

The code above works, the camera orbits an object around the world Y axis perfeclty. What I want to do: I want this same behaviour, but on a cube or other mesh! So I obviously don't need to do it on the view matrix then, since the transformation of that cube uses a world matrix. Now I could of course use the above and just invert it, but that is kind of cheating.

Here is my attempt to make the above work on a world space matrix:

// get the position and the three axis directions for the world matrix
Vector3 pos, la, lu, lr;
pos = worldMatrix.translation();
la.set(-worldMatrix.m(8), -worldMatrix.m(9), -worldMatrix.m(10));
lr.set(worldMatrix.m(0), worldMatrix.m(1), worldMatrix.m(2));
lu.set(worldMatrix.m(4), worldMatrix.m(5), worldMatrix.m(6));


Vector3 rotationPoint = pos + la * 5;

Matrix4 rot;
rot.translate(-rotationPoint);
rot.rotate(dX, Vector3(0,1,0));
rot.rotate(dY, lr);
rot.translate(rotationPoint);

worldMatrix *= rot;

The matrix is still column major. The retrieved position, look at, look right and look up vectors are correct. But when I print out the rotationPoint it moves. So the question is as simple as: Why does the above world matrix code not rotate my cube around the Y and look right axis around 'rotationPoint'?

\$\endgroup\$
1
\$\begingroup\$

Assuming you are dealing with additive operations (i.e. rotation translation order is important). Generally you would want to update your Camera matrix in this order:

  1. Take identity matrix.
  2. Translate to FocalPoint
  3. Rotate to look in to the right direction
  4. Translate away from the FocalPoint by the DistanceFromFocal

Same works with any Object that you want to place instead of Camera.

If above approach works for the Camera, but not for the Object, then there's a bug in your code somewhere

\$\endgroup\$
  • \$\begingroup\$ Yes I get that part. It is working in my first code example (which uses a view matrix). The is that I can't do the same thing on a world space matrix! The second code example is me trying to do it but the rotations are wrong and the rotation point changes. \$\endgroup\$ – derkie Aug 15 '14 at 12:59
  • \$\begingroup\$ So .. you have a working code for a proper turntable (Camera orbiting Objects). Now you want to redo it into static Camera looking at rotating World? This kind of defeats the point of having a Camera, don't you think? ;) \$\endgroup\$ – Kromster Aug 15 '14 at 14:07
  • \$\begingroup\$ I don't know if you missed it in my post or if I was unclear about it. But the reason I want to do the same in world space is because I want to apply this orbiting animation to a cube or other mesh. If I was to reuse my 'working' code I would have to do the rotation on a view matrix and then invert it to use that matrix as the model matrix for said cube. This seems unnecessary since I could just transform the model matrix (world matrix) directly. \$\endgroup\$ – derkie Aug 15 '14 at 21:23
  • \$\begingroup\$ I tried to redo my post in an edit but left the original post up for now. Maybe you understand what I mean if you read the second try. \$\endgroup\$ – derkie Aug 15 '14 at 21:25
  • \$\begingroup\$ @derkie: Answer updated \$\endgroup\$ – Kromster Aug 16 '14 at 6:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.