Matrix Begins To Rotate Incorrectly

Started by
8 comments, last by Zakwayda 13 years, 3 months ago
I've got a simple matrix (4x4) intended to store rotations for my camera (in 3D). In response to mouse input, I pitch or yaw the camera, and always pass in constant zero for roll. However, after some uses, the camera begins to roll if the mouse is moved in a circular fashion. I've posted both my camera translation and rotation functions below.


D3DXMATRIX CameraRotationMatrix;
D3DXVECTOR3 CameraPosition;
//D3DXVECTOR3 CameraRotation;

inline D3DXMATRIX GetRotationMatrix() {
return CameraRotationMatrix;
}
inline void TranslateCamera(float x, float y, float z) {
D3DXVECTOR3 rvec, vec(x, y, z);
#pragma warning(disable : 4238)
D3DXVec3TransformNormal(&rvec, &vec, &GetRotationMatrix());
#pragma warning(default : 4238)
CameraPosition += rvec;
RecomputeVPMatrix();
}
inline void RotateCamera(float x, float y, float z) {
D3DXVECTOR3 RotationRequested(x, y, z);
D3DXVECTOR3 XAxis, YAxis, ZAxis;
D3DXMATRIX rotationx, rotationy, rotationz;
XAxis = D3DXVECTOR3(1, 0, 0);
YAxis = D3DXVECTOR3(0, 1, 0);
ZAxis = D3DXVECTOR3(0, 0, 1);

#pragma warning(disable : 4238)
D3DXVec3TransformNormal(&XAxis, &XAxis, &GetRotationMatrix());
D3DXVec3TransformNormal(&YAxis, &YAxis, &GetRotationMatrix());
D3DXVec3TransformNormal(&ZAxis, &ZAxis, &GetRotationMatrix());
#pragma warning(default : 4238)
D3DXMatrixRotationAxis(&rotationx, &XAxis, RotationRequested.x);
D3DXMatrixRotationAxis(&rotationy, &YAxis, RotationRequested.y);
D3DXMatrixRotationAxis(&rotationz, &ZAxis, RotationRequested.z);
CameraRotationMatrix *= (rotationx * rotationy * rotationz);
RecomputeVPMatrix();
}


I appreciate that this is the generic forum and this code is written with D3DX Maths, but I'm fairly sure that this is generic enough to qualify. If anyone would like some explaining comments, just ask.

I tried writing a RotateYZ function that never went near X rotations, and the problem still manifests. I also tried spamming calls to this function with 0,0,0 (1500/sec) and the problem remained the same. So I'm fairly confident that it doesn't originate from the use of an accumulated matrix or the use of constant zero. But as for what the problem actually is, I don't know. The roll is always camera relative roll, not a world axis.
Advertisement
What you are seeing is the correct behaviour, there's nothing wrong with your code. A camera will start to roll even if you're only inputting a sequence of pitch and yaw operations, because these are applied on the local coordinate system instead of the global coordinate system.

If you imagine holding a camera, hold it pointed straight ahead, then rotate it upward 90 degrees so it points up, then "pitch" it 90 degrees to the right. You'll find that it has in a sense "rolled" by 90 degrees, in that the bottom of the camera is no longer pointing to the ground. That's the similar effect that you're seeing.

If you want to force no roll whatsoever, than store an internal count of pitch degrees and yaw degrees, and build your view matrix each frame from a pitch then yaw. This will give you more typical behaviour like you might expect in a first person camera.
[size=2]My Projects:
[size=2]Portfolio Map for Android - Free Visual Portfolio Tracker
[size=2]Electron Flux for Android - Free Puzzle/Logic Game
How can I store internal pitch/yaw counts? If I want the camera to rotate relative to itself, then the axis around which those pitch and yaw degrees make sense change. They can't just go around the world axis.

Perhaps I should store separate Quaternions for each rotation?

How can I store internal pitch/yaw counts? If I want the camera to rotate relative to itself, then the axis around which those pitch and yaw degrees make sense change. They can't just go around the world axis.

If your objective is to implement simple 'fixed-up' motion where pitch is always about the local side axis and yaw is always about the world up axis, then you simply store the yaw and pitch angles as single scalar values. Then, when it comes times to build the orientation, you combine these two rotations in the order pitch->yaw. (How you combine the rotations is secondary; you can use matrices or quaternions, and you can do it 'by hand' or use an Euler-angle conversion function - in each case, the end result will essentially be the same.)
They're all about the local axis- the camera is completely free-floating in 3D space and the world axis mean nothing to the intended rotations.

Storing separate Quaternions didn't really work out.

They're all about the local axis- the camera is completely free-floating in 3D space and the world axis mean nothing to the intended rotations.

In that case, the behavior you're seeing is the expected behavior (like karwosts said).
Is it preventable? It's not that I find it particularly objectionable personally, and I provide for roll controls so it's not exactly a death sentence, I just feel that potential players won't understand and find it confusing. On the other hand, I guess that the exact maneuvers required to produce a noticable result won't exactly be standard fare in the game vision I have, so I doubt that it'll be a big deal. I'll just leave it how it is.

Is it preventable? It's not that I find it particularly objectionable personally, and I provide for roll controls so it's not exactly a death sentence, I just feel that potential players won't understand and find it confusing. On the other hand, I guess that the exact maneuvers required to produce a noticable result won't exactly be standard fare in the game vision I have, so I doubt that it'll be a big deal. I'll just leave it how it is.


It's not preventable per se, in that it's a natural consequence of full 6DOF motion. As such, any sort of 'solution' will necessarily be context-dependent; that is, it'll have to be suited to the particular game or simulation. (Just as an example, the game Descent had an optional 'auto-leveling' feature that would gradually align the ship with any surface that happened to be under it. Again though, this was optional and could be turned off if the player preferred.)
Ah, interesting. I guess it's so rare that you come across a game with such freedom of motion, I've never come across it in any game I played and therefore assumed that it was an error. I guess that it can just live how it is.

Ah, interesting. I guess it's so rare that you come across a game with such freedom of motion, I've never come across it in any game I played and therefore assumed that it was an error. I guess that it can just live how it is.

It's not that common in games, probably for the very reason that it can be disorienting for the player. Descent and a few other space-based games are the only games I know of that use this control scheme (although I'm sure there are a few others).

This topic is closed to new replies.

Advertisement