OpenGL + SDL rotation around local axis

I've been working on a semi flight simulator. What I am trying to do is use a pitch roll and yaw to rotate an object. I have already looked online a lot, and although they explain what the problem is I have no idea how to implement the solution. So for example I do:

glRotatef(yaw,0,1,0);
glRotatef(pitch,1,0,0);

The yaw doesn't act properly, the pitch will work fine. And from what I have been reading it seems that the objects local axis has been changed so I need to find the object's new local axis and rotate around that. So I tried that with something like:

newpitch=pitch/57.29
VectorA(0,cos(newpitch)-sin(newpitch),sin(newpitch)+cos(newpitch));
glRotatef(yaw,vec.getXAxis(),vec.getYAxis(),vec.getZAxis());
glRotatef(pitch,1,0,0);

This seems to not work either.

I've also tried making a general rotation matrix and giving it both pitch and yaw and still the same problem. And I've tried using quaternions and the same problem still exists!

Here is my code for quaternions:

void Quat::eulerToQuat(float roll,float pitch,float yaw){
    float radiansY = yaw/57.2;
    float radiansZ = roll/57.2;
    float radiansX = pitch/57.2;

    float sY = sinf(radiansY * 0.5);
    float cY = cosf(radiansY * 0.5);
    float sZ = sinf(radiansZ * 0.5);
    float cZ = cosf(radiansZ * 0.5);
    float sX = sinf(radiansX * 0.5);
    float cX = cosf(radiansX * 0.5);

    w = cY * cZ * cX - sY * sZ * sX;
    x = sY * sZ * cX + cY * cZ * sX;
    y = sY * cZ * cX + cY * sZ * sX;
    z = cY * sZ * cX - sY * cZ * sX;
}

Then I converted this into a matrix and use glMultMatrix(matrix) with the modelview matrix, and this has the same problem. So I'm confident it wouldn't be gimble lock =).

So in my code I do:

float matrix[4][4];
Quat this;
this.eularToQuat(roll,pitch,yaw);
this.toMatrix(matrix);
glMultMatrix(matrix);

I think you're referring to gimbal lock? You're right that each rotation modifies the axes around which subsequent local rotations will occur. In your case that affects the yaw because the OpenGL matrix stack works so that each thing you add to it occurs conceptually before whatever is already on the stack (ie, it's post multiplication in matrix terms).

Your solution, however, won't solve the problem even if implemented correctly. What you're trying to do is get the global y axis in local coordinate space so that you can rotate around the global y even after you've rotated around the global z, shifting the local axes. But that just buys you much the same problems as if you'd stuck with global axes throughout and applied the rotations in the other order. The second rotation will now interfere with the first rather than vice versa.

Another way to convince yourself that what you're doing is wrong is to look at how much information you have. You're trying to describe the orientation of an object with two numbers. Two numbers isn't enough to describe any rotation whatsoever, so there's obviously some other rule in there to convert two numbers into a complete orientation. Whatever you do to modify that rule, you're going to end up limiting the orientations you can reach. But with an aeroplane you really want to be able to reach any orientation, so that's a fundamental contradiction.

The confusion comes because, if you have a suitable way of storing orientation, it's completely valid to work forward from that by saying 'what is the orientation if I modify that by rotating around local y by 5, then around local z by 10?', etc. The problem is trying to aggregate all those transformations into a single pair of rotations. It isn't possible.

The easiest solution if you're already generally up on OpenGL tends to be to store the orientation as a complete matrix. You accumulate pitch and yaw rotations by applying them as they occur to that matrix. You pass that matrix to OpenGL via glMultMatrix to perform your drawing.

It's not an optimal solution but a quick fix test solution would be to use glLoadMatrix and glGet to apply transformations by loading your matrix to and then retrieving it from the OpenGL matrix stack, separately from your drawing. It's not really what the stack is for so you'll probably get some performance problems and over time rounding errors will cause odd behaviour but you can fix those once you're persuaded by the approach. The OpenGL man pages give the formulas for all transformation matrices and you should look up matrix normalisation (you'll probably be using an orthonormal matrix whether you realise it or not, which should help with Google) to deal with cumulative rounding.

EDIT: with respect to the code you've posted while I was rambling, quaternions are another valid way of representing orientation and another thing that you can apply incremental updates to safely. They're also compact very easy to protect from rounding errors. However I think your problem may be that you aren't using quaternions as the storage for orientation, merely as an intermediate container. So adding them to the chain doesn't fix any of your problems.

EDIT2: a further bit of hand-waving explanation to push the idea that directly storing pitch and yaw isn't good enough: imagine that, from the point of view of the pilot, you apply a yaw of 90 degrees, then a pitch of 30 degrees, then a yaw of -90 degrees. Then you end up exactly as if you'd applied a roll of 30 degrees. But if you're just storing pitch and yaw then you've no way of storing roll. Furthermore, if you just add up the total yaw and total pitch you end up thinking you've applied a pitch of 30 degrees rather than a roll. So it doesn't matter what order you apply pitch and yaw, or whether you use global or local axes, you get the wrong result.


You should yaw, pitch and roll using one transformation. Cause when you don't, you'll pushing yourself towards gimbal lock. Excerpt:

Gimbal lock is the loss of one degree of freedom in a three-dimensional space that occurs when the axes of two of the three gimbals are driven into a parallel configuration, "locking" the system into rotation in a degenerate two-dimensional space.

Consider this example of Gimbal locked airplane:

万向座锁着的飞机

When the pitch (green) and yaw (magenta) gimbals become aligned, changes to roll (blue) and yaw apply the same rotation to the airplane

链接地址: http://www.djcxy.com/p/95468.html

上一篇: 防止碰撞在子弹物理学中应用冲量

下一篇: 围绕本地轴的OpenGL + SDL旋转