Strange behavior with rotation matrices

余生颓废 提交于 2019-12-08 01:38:34

问题


I am trying to render a spaceship directly in front of a camera, with the model rotating with the camera's view. This works, as long as the player only yaws or rolls. If he does both, it goes into a tumble. A video of the problem is here: http://youtu.be/voKTsdy5TFY

The relevant code follows, edited for clarity:

D3DXMatrixRotationAxis(&playeryaw, &up, yawangle);
D3DXMatrixRotationAxis(&playerpitch, &right, pitchangle);

playerrot =  playeryaw * playerpitch;
D3DXMatrixTranslation(&playertrans, pos.x, pos.y, pos.z);
D3DXMatrixScaling(&playerscale, 0.05 / ((float)i + 1),  0.05 / ((float)i + 1),  0.05 / ((float)i + 1));
playercom = playerscale * playerrot *  playertrans;
device->SetTransform(D3DTS_WORLD, &playercom);
playermesh.render();

EDIT: Expanded code at the behest of Optillect Team.


回答1:


It seems you apply the same transform to the spaceship. You should:

  1. Apply rotation matricies to the spaceship, then translation matrix (position of the spaceship).
  2. Apply those matricies for up and right vectors.
  3. Build view (camera) matrix based on up and right vectors (first translate back of the spaceship, then rotate, then translate to the position of the spaceship)

Something like this:

    D3DXMatrixRotationAxis(&shipyaw, &up, yawangle);
    D3DXMatrixRotationAxis(&shippitch, &right, pitchangle);
    D3DXMatrixTranslate(&shippos, x, y, z);
    shipmatrix = shippitch * shipyaw * shippos;

    D3DXMatrixTranslate(&viewoffset, 0, 0, -10);
    D3DXMatrixRotationAxis(&viewyaw, &up, -yawangle);
    D3DXMatrixRotationAxis(&viewpitch, &right, -pitchangle);
    D3DXMatrixTranslate(&viewpos, -x, -y, -z);
    viewmatrix = viewoffset * viewpitch * viewyaw * viewpos;



回答2:


Na7coldwater may be right on the gimbal lock. The 2 angles you use, yawangle and pitchangle are euler angles and hence susceptible to gimble lock.

You could avoid gimbal lock by either using quaternions or by storing the current rotation and then build a delta rotation matrix and multiply to the previous rotation matrix.

ie where you build your rotation matrix you will be storing the delta from the previous rotation rather than the absoloute rotation from the model's origin state.

e.g

D3DXMatrixRotationAxis(&playeryaw, &up, yawanglethisframe);
D3DXMatrixRotationAxis(&playerpitch, &right, pitchanglethisframe);

playerrot =  playerrot * (playeryaw * playerpitch); // This line has changed!!
D3DXMatrixTranslation(&playertrans, pos.x, pos.y, pos.z);
D3DXMatrixScaling(&playerscale, 0.05 / ((float)i + 1),  0.05 / ((float)i + 1),  0.05 / ((float)i + 1));
playercom = playerscale * playerrot *  playertrans;
device->SetTransform(D3DTS_WORLD, &playercom);
playermesh.render();

where playerrot is stored from frame to frame.




回答3:


That looks like Gimbol lock, which is a known limitation of using Euler angles for representing three-dimensional rotations. You might want to use matrices or quaternions instead to represent your spaceship's rotation.



来源:https://stackoverflow.com/questions/6699172/strange-behavior-with-rotation-matrices

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!