Jump to content
  • Advertisement
Sign in to follow this  
DeadMG

Matrix Begins To Rotate Incorrectly

This topic is 2894 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites

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.)

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

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).

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

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.)

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

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).

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!