2

我有一些 3D 模型,我在 3D 空间中在 OpenGL 中渲染,并且在这个世界中通过旋转和平移移动“角色”(即相机)时遇到了一些令人头疼的问题。

我从一些外部事件(图像用户输入或来自 GPS + 罗盘设备的一些数据)接收输入(即移动的坐标/要转动的坐标),事件类型是旋转平移

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

- (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 的引用也将不胜感激)

4

2 回答 2

1

听起来您在这里发生了几件事:

首先是你需要知道旋转是围绕原点发生的。因此,当您平移然后旋转时,您不是围绕您认为的原点旋转,而是围绕 T -1 0 的新原点(原点由您的平移的倒数变换)。

其次,你让事情变得比你真正需要的要困难得多。您可能要考虑的是使用gluLookAt。你基本上在你的场景中给它一个位置,在你的场景中给它一个要查看的点和一个“向上”向量,它会正确设置场景。要正确使用它,请跟踪您的相机所在的位置,调用该向量p和一个向量n(对于正常 ... 表示您正在寻找的方向)和u(您的向上向量)。如果nu是正交向量(即它们彼此正交并且具有单位长度),它将使更高级的特征变得更容易。如果你这样做,你可以计算r = nx u,(您的“右”向量),它将是与其他两个正交的法线向量。然后,您“查看” p + n并提供u作为向上向量。

理想情况下,您的nur具有一些规范形式,例如:

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

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

于 2010-11-15T20:48:58.730 回答
1

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

伪代码:

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

redraw()
{
  glClear()
  glRotatef(currentDeg, 0, 0, 1);
  glTranslatef(currentLat, -currentLong, 0);
  ... // draw stuff
}
于 2010-11-15T20:52:04.263 回答