我终于解决了这个问题,改用一直为每艘船携带一个矩阵。俯仰、偏航和横滚仅在需要时计算,这种情况很少见。最后,glRotatef 完成了这项工作——你只需要将它应用到已经旋转的矩阵上——并保存结果,这样就不会丢弃更改。
以下代码是我在载有 x、y、z、Matrix[16]、dx、dy、dz 的船结构上的实现。(请注意,所有船舶数组都必须使用 IdentityMatrix 进行初始化):
//*************************** Turn Ship **********************************
void TurnShip(long nr,float yaw, float pitch=0,float roll=0) {
//Turns ship by pitch, yaw and roll degrees.
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(&ship[nr].Matrix[0]);
glRotatef(yaw,0,1,0);
glGetFloatv(GL_MODELVIEW_MATRIX,&ship[nr].Matrix[0]);
glLoadMatrixf(&ship[nr].Matrix[0]);
glRotatef(pitch,1,0,0);
glGetFloatv(GL_MODELVIEW_MATRIX,&ship[nr].Matrix[0]);
glLoadMatrixf(&ship[nr].Matrix[0]);
glRotatef(roll,0,0,1);
glGetFloatv(GL_MODELVIEW_MATRIX,&ship[nr].Matrix[0]);
}
该函数所做的是加载存储在一个简单浮点数组中的船舶矩阵,对其进行操作,然后将其保存回数组。在游戏的图形部分,该数组将使用 glLoadMatrixf 加载,因此将应用到飞船上,无需任何麻烦或数学运算。
//*************************** Accelerate Ship relative to own orientation **
void AccelerateShip(long nr,float speedx,float speedy, float speedz)
{ //use speedz to move object "forward".
ship[nr].dx+= speedx*ship[nr].Matrix[0]; //accelerate sidewards (x-vector)
ship[nr].dy+= speedx*ship[nr].Matrix[1]; //accelerate sidewards (x-vector)
ship[nr].dz+= speedx*ship[nr].Matrix[2]; //accelerate sidewards (x-vector)
ship[nr].dx+= speedy*ship[nr].Matrix[4]; //accelerate upwards (y-vector)
ship[nr].dy+= speedy*ship[nr].Matrix[5]; //accelerate upwards (y-vector)
ship[nr].dz+= speedy*ship[nr].Matrix[6]; //accelerate upwards (y-vector)
ship[nr].dx+= speedz*ship[nr].Matrix[8]; //accelerate forward (z-vector)
ship[nr].dy+= speedz*ship[nr].Matrix[9]; //accelerate forward (z-vector)
ship[nr].dz+= speedz*ship[nr].Matrix[10]; //accelerate forward (z-vector)
}
这是我今天学到的最好的部分——教程通常不会告诉你的部分,因为它们都是关于数学的——我可以从矩阵中提取指向上方、左侧和前方的向量对它们施加加速度,这样我的船就可以向左、向右、向上、加速和制动——glRotatef 关心它们,所以它们总是更新,我们这边完全不涉及数学:-)