根据局部坐标转动网格

时间:2013-02-03 01:10:27

标签: c++ opengl 3d quaternions

我在3D世界中有一架飞机,它的方向以任何方式保存(例如俯仰,偏航和滚转)。现在,当我希望飞机向左转时,但是glRotatef没有完成这项工作,因为它坚持全球坐标,并不关心飞机的旋转,只是改变偏航也无济于事,因为这也不是相对于飞机的实际旋转而言,当飞机直接飞向地平线时,仅意味着“左”。我需要的是这样的:

    float pitch = 10 , yaw = 20, roll = 30;        //some initial values
    Turn(&pitch, &yaw, &roll ,  5, 0 , 0 )   //calculate new pitch, yaw and roll as if 
    //the plane had turned 5 degrees to the right (relative to its current orientation and roll!)
    //pitch, yaw and roll are updated to reflect the new orientation.

许多人建议使用Quaternions,但我不知道如何将它们实现为Turn函数(一个工作示例是Blitz3D,它具有用于全局旋转的“RotateEntity”函数,如glRotatef和“TurnEntity”用于旋转基于方向)我认为函数内部的工作原理如下:

  • 将俯仰,偏航,滚动变为像EulerToQuat中的四元数 OpenGL + SDL rotation around local axis
  • 使用Quaternion数学(未找到来源)
  • 执行局部旋转
  • 将四元数变回偏航,滚动,俯仰(未找到来源)

1 个答案:

答案 0 :(得分:0)

我终于通过切换到每艘船周围都有一个矩阵解决了这个问题。仅在需要时计算俯仰,偏航和侧倾,这种情况很少发生。最后, 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关心它们以便它们始终更新,并且我们的所有方面都没有数学: - )