代码之家  ›  专栏  ›  技术社区  ›  rano

如何使用glRotatef()和gltranslateef()在三维世界中增量移动

  •  2
  • rano  · 技术社区  · 14 年前

    我有一些在OpenGL中在3D空间中渲染的3D模型,在移动 '字符' (即 照相机 )在这个世界里有旋转和平移。

    我从某个外部事件(如用户输入的图像或来自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)

    2 回复  |  直到 14 年前
        1
  •  1
  •   Sebastian Negraszus    14 年前

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

    伪码:

    someEvent(lat, long, deg)
    {
      currentLat += lat;
      currentLong += long;
      currentDeg += deg;
    }
    
    redraw()
    {
      glClear()
      glRotatef(currentDeg, 0, 0, 1);
      glTranslatef(currentLat, -currentLong, 0);
      ... // draw stuff
    }
    
        2
  •  1
  •   andand    14 年前

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

    首先,你需要知道旋转是围绕原点发生的。所以当你平移然后旋转的时候,你不是围绕你认为的原点旋转,而是围绕新的原点旋转 -1个 0(由平移的反方向变换的原点)。

    第二,你让事情变得比你真正需要的更困难。你应该考虑的是 gluLookAt . 你本质上是给它一个在你的场景中的位置,一个在你的场景中可以看到的点和一个“向上”的向量,它将正确地设置场景。要正确使用它,请跟踪相机的位置,调用该向量 第页 ,和向量 n个 (正常情况下。。。指示您正在寻找的方向)和 u型 (你的上方向向量)。如果 n个 u型 是正交向量(即它们彼此正交且具有单位长度)。如果你这样做,你可以计算 = n个 u型 ,(你的“右”向量),它将是与另外两个向量正交的法向量。然后你“看” 第页 + n个 并提供 u型 作为上方向向量。

    理想情况下,你的 n个 , u型 有一些规范形式,例如:

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

    然后逐渐累积旋转,并将其应用于oritenation向量的规范for。你可以用任何一个 Euler Rotations Quaternion Rotations 为了积累你的旋转(我已经开始真正欣赏四元数方法的各种 reasons ).

    推荐文章