如何使用glRotatef()和glTranslatef()在3D世界中逐步移动

时间:2010-11-15 20:01:58

标签: iphone objective-c opengl-es translate glrotate

我有一些3D模型,我在OpenGL中在3D空间中渲染,我在移动'字符'时遇到了一些麻烦(即相机在这个世界里有旋转和翻译。

我从一些外部事件(图像用户输入或来自GPS +指南针设备的某些数据)接收输入(即移动/转移dregrees的坐标),并且事件类型为 rotation < / em>或翻译

我写过这个方法来管理这些事件:

- (void)moveThePlayerPositionTranslatingLat:(double)translatedLat Long:(double)translatedLong andRotating:(double)degrees{

    [super startDrawingFrame];
    if (degrees != 0)
    {
        glRotatef(degrees, 0, 0, 1);
    }

    if (translatedLat != 0)
    {
        glTranslatef(translatedLat, -translatedLong, 0);
    }

   [self redrawView];
}

然后在redrawView我正在绘制场景和我的模型。它类似于:

glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

NSInteger nModels = [models count];

for (NSInteger i = 0; i < nModels; i++) 
{
    MD2Object * mdobj = [models objectAtIndex:i];
    glPushMatrix();
    double * deltas = calloc(sizeof(double),2);

    deltas[0] = currentCoords[0] - mdobj.modelPosition[0];
    deltas[1] = currentCoords[1] - mdobj.modelPosition[1];

    glTranslatef(deltas[0], -deltas[1], 0);

    free(deltas);
    [mdobj setupForRenderGL];
    [mdobj renderGL];   
    [mdobj cleanupAfterRenderGL];
    glPopMatrix();

}
[super drawView];

问题在于,当平移时,一个接一个地调用旋转事件:例如,当我逐渐旋转一些迭代(仍然在原点附近)然后我翻译并最终再次旋转但看起来最后一次旋转不会出现在当前(已翻译)位置周围,而是围绕旧位置(旧原点)。我很清楚,当转换的顺序颠倒时会发生这种情况,但我相信在绘制之后,世界的新中心是由翻译系统给出的。

我错过了什么?我怎样才能解决这个问题? (任何对OpenGL的引用也将受到赞赏)

2 个答案:

答案 0 :(得分:1)

听起来你在这里发生了一些事情:

首先,你需要知道关于原点的旋转。因此,当您翻译然后旋转时,您不会旋转您认为的原点,而是新的原点是T -1 0(原点由您的翻译的倒数转换)。

其次,你制造的东西比你真正需要的要难得多。您可能需要考虑的是使用gluLookAt。你基本上给它在场景中的位置和场景中的一个点来查看和一个'向上'矢量,它将正确设置场景。要正确使用它,请跟踪相机所在的位置,调用该矢量 p 和矢量 n (正常...表示您正在查找的方向)和 u (你的向上矢量)。如果 n u 是正交向量(即它们彼此正交且具有单位长度),它将使更高级的特征更容易。如果你这样做,你可以计算 r = n x u ,(你的'右'矢量),这将是一个正常的矢量正交矢量到另外两个。然后你'看' p + n 并提供 u 作为向上矢量。

理想情况下, n u r 有一些规范形式,例如:

n = <0, 0, 1>
u = <0, 1, 0>
r = <1, 0, 0>

然后逐渐累积旋转并将它们应用于oritentation矢量的规范。您可以使用Euler RotationsQuaternion Rotations来累积轮换(我非常欣赏各种reasons的四元数方法。)

答案 1 :(得分:1)

我建议不要在事件处理程序中进行累积转换,而是在内部存储转换的当前值,然后只转换一次,但我不知道这是否是您想要的行为。

伪代码:

someEvent(lat, long, deg)
{
  currentLat += lat;
  currentLong += long;
  currentDeg += deg;
}

redraw()
{
  glClear()
  glRotatef(currentDeg, 0, 0, 1);
  glTranslatef(currentLat, -currentLong, 0);
  ... // draw stuff
}