1

我试图在 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));
}

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

4

3 回答 3

2

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

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

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

然后像你一样创建一个围绕 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
于 2012-11-21T04:06:41.500 回答
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;
}

希望我对遇到类似问题的人有所帮助。

于 2013-05-18T12:43:07.043 回答
0

你需要在翻译之前进行旋转,假设你的对象是在原点开始的(如果我没记错的话)。我相信应用的旋转矩阵围绕轴 (0, 1, 0) 旋转,如果您已经平移到新位置,该旋转将影响您的位置以及您所面对的方向。

于 2012-11-20T21:14:34.800 回答