我有一些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的引用也将受到赞赏)
答案 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 Rotations或Quaternion 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
}