如何在3D环境中以C ++面向的方向移动对象

时间:2012-11-20 21:07:31

标签: c++ opengl graphics 3d

我试图用C ++中的opengl移动一个金字塔,我试图让它朝着它面向的方向前进。但是,我似乎无法弄清楚如何做到这一点。这是我绘制金字塔的代码:

void drawTriangle()
{
    //back
    glBegin(GL_POLYGON);
        glColor3f(1,0,0);
        glVertex3f(-1,-1,-1);
        glVertex3f(1,-1,-1);
        glVertex3f(0,1,0);
    glEnd();

    //front
    glBegin(GL_POLYGON);
        glColor3f(0,1,0);
        glVertex3f(-1,-1,1);
        glVertex3f(1,-1,1);
        glVertex3f(0,1,0);
    glEnd();

    //right
    glBegin(GL_POLYGON);
        glColor3f(0,0,1);
        glVertex3f(1,-1,-1);
        glVertex3f(1,-1,1);
        glVertex3f(0,1,0);
    glEnd();

    //left
    glBegin(GL_POLYGON);
        glColor3f(1,1,0);
        glVertex3f(-1,-1,-1);
        glVertex3f(-1,-1,1);
        glVertex3f(0,1,0);
    glEnd();

    //bottom
    glBegin(GL_POLYGON);
        glColor3f(1,0,1);
        glVertex3f(-1,-1,-1);
        glVertex3f(1,-1,-1);
        glVertex3f(1,-1,1);
        glVertex3f(-1,-1,1);
    glEnd();
}

这是金字塔被绘制到屏幕的方式:

glPushMatrix();
    glTranslatef(Xtri,0,Ztri);
    glRotatef(heading,0,1,0);
    drawTriangle();
    glPopMatrix();

    glFlush();

以下是变量的更新方式,以便金字塔可以移动:

void processKeys()
{
    if(keys[VK_LEFT])
    {
        heading-=1.0f;
    }
    if(keys[VK_RIGHT])
    {
        heading+=1.0f;
    }
    if(keys[VK_UP])
    {
        Vtri-=0.001f;
    }
    if(keys[VK_DOWN])
    {
        Vtri+=0.001f;
    }
}
void update()
{
    Xtri += Vtri*cos((90+heading)*(PI/180.0f));
    Ztri += Vtri*sin((90+heading)*(PI/180.0f));
}

我试图让金字塔向前移动,以便红色或背面是我想要成为金字塔移动方向的面部但是当我使用这个代码时它根本不会那样工作它以一种非常有趣的方式移动。

3 个答案:

答案 0 :(得分:2)

这是你可以做到的一种方式。它基于Direct3D,但我认为它应该与OpenGL非常相似。

为您的金字塔设置两个向量:一个包含其位置,另一个包含其旋转。最初都初始化为0,0,0。还有一个方向向量最初面向你的对象所做的方向(例如1,0,0)和速度,再次设置为0.

按a或d时,将旋转矢量的y元素调整到所需的角度。同样按w或s调整对象的速度。您可能希望将帧渲染时间考虑在内以使移动fps独立。

然后像Y一样在Y轴周围创建一个旋转矩阵。使用该矩阵通过将其与初始位置矢量相乘来创建新的标准化矢量。然后将此向量乘以速度添加到您的位置坐标,并将这些坐标用于平移矩阵。

希望它有意义。这是一些伪代码:

// in constructor:
x = y = z = 0.0f;   // position
ry = 0.0f;          // rotation
speed = 0.0f;
initVec(1,0,0);     // initial direction vector

// in event handler:
// upon key press adjust speed and/or ry

// in move():
// create rotation matrix around Y axis by ry = rotationMatrix

// use it to find new direction vector
newDirectionVector = initVec * rotationMatrix;

// adjust your position
x += newDirectionVector * speed;
y += newDirectionVector * speed;
z += newDirectionVector * speed;

glTranslatef(x, y, z);

// render

答案 1 :(得分:2)

我在搜索类似问题的想法时遇到了这个问题,并决定分享我的解决方案:

对于具有1个单位基数和2个单位高度的三角形,在y = 0.3 = pos [2]

void triangle::draw() {
    glPushMatrix();
    //pos[0] is the x value initialized to 0
    //pos[2] is the z value initialized to 0
    glTranslatef(pos[0], 0, pos[2]);
    glRotatef(direction, 0, 1, 0);
    glBegin(GL_TRIANGLES);
    glVertex3f(.5, pos[1], 0);
    glVertex3f(-.5, pos[1], 0);
    glVertex3f(0, pos[1], 2);
    glEnd();
    glPopMatrix();
}

//called when key w is pressed
void triangle::forward() {
    // convert degrees to rads and multiply (I used 0.5)
    pos[0] += sin(M_PI * direction / 180) * .5;
    pos[2] += cos(M_PI * direction / 180) * .5;
    std::cout << pos[0] << "," << pos[2] << std::endl;
}

//called when key s is pressed
void triangle::back() {
    pos[0] -= sin(M_PI * direction / 180) * .5;
    pos[2] -= cos(M_PI * direction / 180) * .5;
    std::cout << pos[0] << "," << pos[2] << std::endl;
}

//called when key d is pressed
void triangle::right() {
    direction -= 5;
    //direction is the angle (int)
    //this is probably not needed but, if you keep turning in the same direction
    //an overflow is not going to happen
    if (direction <= 360)direction %= 360;
    std::cout << direction << std::endl;
}

//called when key a is pressed
void triangle::left() {
    direction += 5;
    if (direction >= -360)direction %= 360;
    std::cout << direction << std::endl;
}

希望我有所帮助,因为遇到类似问题的人会遇到这种情况。

答案 2 :(得分:0)

您需要在翻译之前进行旋转,假设您的对象位于原点(如果我正确地回忆起我的数学运算)。我相信所应用的旋转矩阵围绕轴(0,1,0)旋转,如果您已经转换到新位置,旋转将影响您的位置以及您所面对的方向。