【问题标题】:Turn a mesh based on its local coordinates根据局部坐标转动网格
【发布时间】:2013-01-18 01:45:33
【问题描述】:

我在 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.

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

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

【问题讨论】:

  • 解决问题的不是四元数,而是小旋转的累积解决了问题,使用四元数的原因是因为矩阵会产生可能会累积的舍入误差,而四元数可以很容易地归一化......这可能会更好地解释:arcsynthesis.org/gltut/Positioning/Tutorial%2008.html,阅读本章,四元数的用法可能会变得更加清晰,希望这有助于=D
  • 感谢卢克,教程帮助了一点 :-) (可能与你同在...)

标签: c++ opengl 3d quaternions


【解决方案1】:

我终于解决了这个问题,改用一直为每艘船携带一个矩阵。俯仰、偏航和横滚仅在需要时计算,这种情况很少见。最后,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 关心它们,所以它们总是更新,我们这边完全不涉及数学:-)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-03
    • 1970-01-01
    • 1970-01-01
    • 2021-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多