我应先翻译还是先转动?

时间:2012-04-03 13:31:03

标签: c macos opengl translation rotation

我正在尝试创建一个简单的场景,我可以四处走动,其标准是能够平移并四处走动。但是,在我的绘制场景功能中,当我翻译场景而不是旋转时,周围的平移无法正常工作,因为整个场景只是在我周围旋转,导致物体通过我。当我旋转而不是翻译我的场景时,我可以正确地平移,但是,我只能朝某个方向移动,所以如果我向右移动90度,我将向左移动而不是向前移动。无论如何,我可以将这两种效果放在一起吗?

这是我用来绘制视图的代码:


glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glPushMatrix();

glTranslated(xposition, 0, zposition); //This is where I translate my views
glRotated(yrot, 0, 1, 0); //

glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER_ARB, quadVBO);

glNormalPointer(GL_FLOAT, 0, (void*)sizeof(sideArray));
glColorPointer(3, GL_FLOAT, 0, (void*)sizeof(sideArray)+sizeof(normals));
glVertexPointer(3, GL_FLOAT, 0, 0);

glDrawArrays(GL_QUADS, 0, sizeof(sideArray)/sizeof(GLfloat)/3);

glPopMatrix();
glFlush();
glDisableClientState(GL_VERTEX_ARRAY);  
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);

以下是一些现在说明我的问题的图片:

旋转然后翻译:

PIC1

http://dl.dropbox.com/u/2747708/Screen%20Shot%202012-04-03%20at%2010.17.39%20PM.PNG

PIC2

我可以模仿相机的转动

http://dl.dropbox.com/u/2747708/Screen%20Shot%202012-04-03%20at%2010.17.48%20PM.PNG

PIC3

然而,当我向前走时,它只朝一个方向走,而不是我正在看的方向。

http://dl.dropbox.com/u/2747708/Screen%20Shot%202012-04-03%20at%2010.18.30%20PM.PNG

http://dl.dropbox.com/u/2747708/Screen%20Shot%202012-04-03%20at%2010.18.39%20PM.PNG

翻译然后旋转:

PIC1

http://dl.dropbox.com/u/2747708/Screen%20Shot%202012-04-03%20at%2010.19.44%20PM.PNG

PIC2

我可以自由走动,直接走向我正在看的任何方向。

http://dl.dropbox.com/u/2747708/Screen%20Shot%202012-04-03%20at%2010.19.52%20PM.PNG

PIC3

但是,当我旋转场景时,整个事物会旋转,这会导致物体在我身上剪辑,并且不会像在旋转时那样“平移”视图,然后翻译我的视图。

http://dl.dropbox.com/u/2747708/Screen%20Shot%202012-04-03%20at%2010.20.01%20PM.PNG

2 个答案:

答案 0 :(得分:3)

您的问题不在于转换的顺序。你应该轮流进行翻译。

问题是您在移动时没有考虑轮换。运动公式:

movementX = sin(direction);
movementY = cos(direction);

其中direction是从北方顺时针转动的弧度数,正X是东方,正Y是北方。

答案 1 :(得分:1)

我不确定如何评论或添加肯德尔的答案,所以我只是将其添加为新答案。

我认为你可能正在使用Y,所以如果方向是弧度,你可以使用它:

movementX = sin(direction);
movementZ = cos(direction);

如果方向以度为单位,则必须将其转换为弧度:

radians = degrees*(PI/180);

根据您是向前还是向后移动,将运动乘以1或-1:

movementX = sin(direction)*forwardsBackwards;
movementZ = cos(direction)*forwardsBackwards;

如果你还需要扫射,你可以这样做:

movementX = sin(direction)*forwardsBackwards+sin(direction+1.5707)*sideToSide;
movementZ = cos(direction)*forwardsBackwards+cos(direction+1.5707)*sideToSide;

如果您向左或向右扫射,则sideToSide为1或-1。 1.5707是弧度90度(PI / 2),这意味着无论你面向什么方向,它都需要90度角。如果需要,您还可以在转换前为度数旋转添加90度。

按所需的移动速度乘以整个物体:

movementX = (sin...eToSide)*speed;
movementZ = (cos...eToSide)*speed;

然而,如果你一次向两个方向移动,你将会产生更快的移动效果。如果你想这样做就不会发生这种情况,在计算运动之前加上它:

if (!forwardsBackwards && !sideToSide )
{
    forwardsBackwards *= 0.7071; 
    sideToSide *= 0.7071;
}

如果您需要非常准确,也可以用cos(45)替换.7071。

或者你可以:

float diagonalMod = 1;
if (!forwardsBackwards && !sideToSide)
     diagonalMod = 0.7071; // or cos(45)

movementX = (sin...eToSide)*speed*diagonalMod;
movementZ = (cos...eToSide)*speed*diagonalMod;

您需要先旋转然后翻译。另一方面,如果我正确地考虑它,基本上就像移动相机旋转的点,即枢轴点。这就是你在旋转时剪切对象的原因。

此外,你应该执行"相机"紧跟glLoadIdentity()之后的旋转和平移;因为你希望场景中的其他东西都能移动和旋转,因为这就是OpenGL"相机"功能。这就是它的设置方式:

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

glRotated(yrot, 0, 1, 0);
glTranslated(xposition, 0, zposition);

glPushMatrix();

如果您展开它,以供将来参考:

glRotatef(Pitch, 1, 0, 0); // Up and down look
glRotatef(Yaw, 0, 1, 0); // Left and right look
glRotatef(Roll, 0, 0, 1); // Like a barrel roll in a jet
glTranslatef(X,Y,Z);