如何在 OpenGL 中更新"forward"运动

How to update the "forward" movement in OpenGL

本文关键字:forward 运动 更新 OpenGL      更新时间:2023-10-16

我的OpenGL应用程序有问题,您可以在这张gif图中清楚地看到。基本上,我想沿着光标指向的方向移动,但这并没有发生,相反,"向前"的方向保持不变。

例如,如果我转过180°并按"w"向前走,我会向后走。我之所以说走路,是因为我试图复制第一人称相机,就像在FPS游戏中一样。

在这里你可以看到我迄今为止写的代码:

#include <GLglew.h>
#include <GLfreeglut.h>
#include <iostream>
#include <cstdlib>
#include "imageLoader.h"
using namespace std;
float _angleY = 0.0f;
float _angleX = 0.0f;
bool about_y = true;
float oldMouseX;
float oldMouseY;
int valid = 0;
float posX = 0.0;
float posZ = 0.0;
// actual vector representing the camera's direction
float lx = 0.0f, lz = -1.0f;
// XZ position of the camera
float x = 0.0f, z = 5.0f;
// the key states. These variables will be zero
// when no key is being presses
float deltaAngle = 0.0f;
float deltaMove = 0;
int xOrigin = -1;
// angle of rotation for the camera direction
float angle = 0.0f;
void mouseMove(int x, int y) {
    // this will only be true when the left button is down
    if (xOrigin >= 0) {
        // update deltaAngle
        deltaAngle = (x - xOrigin) * 0.001f;
        // update camera's direction
        lx = sin(angle + deltaAngle)*2;
        lz = -cos(angle + deltaAngle)*2;
    }
}
void mouseButton(int button, int state, int x, int y) {
    // only start motion if the left button is pressed
    if (button == GLUT_LEFT_BUTTON) {
        // when the button is released
        if (state == GLUT_UP) {
            angle += deltaAngle;
            xOrigin = -1;
        }
        else  {// state = GLUT_DOWN
            xOrigin = x;
        }
    }
}
void handleKeys(unsigned char key, int x, int y){
    switch (key)
    {
        case 'w':
            posZ+=4;
            cout << "FORWARDn";
            break;
        case 's':
            posZ-=4;
            cout << "BACKn";
            break;
        case 'd':
            posX-=4;
            cout << "RIGHTn";
            break;
        case 'a':
            posX+=4;
            cout << "LEFTn";
            break;
        case 27:
            exit(0);
            break;
    }
}
//initializes 3d rendering 
void initRendering(){
    glEnable(GL_DEPTH_TEST); //permits one object to show up behind another one
    glEnable(GL_COLOR_MATERIAL); 
    glEnable(GL_LIGHTING); //enables the lighting function
    glEnable(GL_LIGHT0);   //enables light num. 1
    glEnable(GL_LIGHT1);   //enables light num. 2
    glEnable(GL_NORMALIZE); 
    Image* image = loadBMP("bricks.bmp");
    _textureId = loadTexture(image);
    delete image;
}
//handles the resize of the window
void handleResize(int w, int h){
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0, double(w) / double(h), 1.0, 800.0);
}
void computePos(float deltaMove) {
    x += deltaMove * lx * 0.1f;
    z += deltaMove * lz * 0.1f;
}
//draws the 3D sccene
void drawScene(){
    cout << "ANGLE: "<<angle<<"n";
    if (deltaMove){
        computePos(deltaMove);
    }
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    // Set the camera
    gluLookAt(x, 1.0f, z,
        x + lx, 1.0f, z + lz,
        0.0f, 1.0f, 0.0f);
    glTranslatef(posX, 0.0f, posZ);
    //HERE WE ADD THE AMBIENT LIGHT
    GLfloat ambientColor[] = { 0.3f, 0.3f, 0.3f, 1.0f }; //the first 3 floats represent the                                                      //RGB intensity of the light 
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientColor);
    //HERE WE ADD THE POSITIONED LIGHT (WHITE INTENSE)
    GLfloat lightColor0[] = { 0.5f, 0.5f, 0.5f, 1.0f }; //LIGHT0 color
    GLfloat lightPos0[] = { 4.0f, 0.0f, 8.0f, 1.0f };   //LIGHT0 position is (4,0,8)
    glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor0); //sets color/intensity of the light
    glLightfv(GL_LIGHT0, GL_DIFFUSE, lightPos0);   //sets position of the light
    //HERE WE ADD THE DIRECTIONAL LIGHT (RED)
    GLfloat lightColor1[] = { 0.5f, 0.2f, 0.2f, 1.0f }; //LIGHT1 color
    GLfloat lightPos1[] = { -1.0f, 0.5f, 0.5f, 0.0f };  //LIGHT1 is coming from (-1,0.5,0.5)
                                                        //NOTE: we just have to put the 4th 
                                                        //parameter to 0.0f to make it directional
    glLightfv(GL_LIGHT1, GL_DIFFUSE, lightColor1); //sets color/intensity of the light
    glLightfv(GL_LIGHT1, GL_DIFFUSE, lightPos1);   //sets position of the light
    glColor3f(1.0f, 1.0f, 0.0f); //we set the cube color
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, _textureId);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    //HERE WE DEFINE COORDINATES FOR THE CUBE
    glBegin(GL_QUADS);
    //Front
    glNormal3f(0.0f, 0.0f, 1.0f);
    glTexCoord2f(0.0f, 0.0f);
    glVertex3f(-40.5f, -40.0f, 40.5f);
    glTexCoord2f(1.0f, 0.0f);
    glVertex3f(40.5f, -40.0f, 40.5f);
    glTexCoord2f(1.0f, 1.0f);
    glVertex3f(40.5f, 40.0f, 40.5f);
    glTexCoord2f(0.0f, 1.0f);
    glVertex3f(-40.5f, 40.0f, 40.5f);
    //Right
    glNormal3f(1.0f, 0.0f, 0.0f);
    glTexCoord2f(0.0f, 0.0f);
    glVertex3f(40.5f, -40.0f, -80.5f);
    glTexCoord2f(0.0f, 1.0f);
    glVertex3f(40.5f, 40.0f, -80.5f);
    glTexCoord2f(1.0f, 1.0f);
    glVertex3f(40.5f, 40.0f, 40.5f);
    glTexCoord2f(1.0f, 0.0f);
    glVertex3f(40.5f, -40.0f, 40.5f);
    //Back
    glNormal3f(0.0f, 0.0f, -1.0f);
    glTexCoord2f(0.0f, 1.0f);
    glVertex3f(-40.5f, -40.0f, -80.5f);
    glTexCoord2f(0.0f, 0.0f);
    glVertex3f(-40.5f, 40.0f, -80.5f);
    glTexCoord2f(1.0f, 0.0f);
    glVertex3f(40.5f, 40.0f, -80.5f);
    glTexCoord2f(1.0f, 1.0f);
    glVertex3f(40.5f, -40.0f, -80.5f);
    //Left
    glNormal3f(-1.0f, 0.0f, 0.0f);
    glTexCoord2f(0.0f, 0.0f);
    glVertex3f(-40.5f, -40.0f, -80.5f);
    glTexCoord2f(1.0f, 0.0f);
    glVertex3f(-40.5f, -40.0f, 40.5f);
    glTexCoord2f(1.0f, 1.0f);
    glVertex3f(-40.5f, 40.0f, 40.5f);
    glTexCoord2f(0.0f, 1.0f);
    glVertex3f(-40.5f, 40.0f, -80.5f);
    glEnd();
    glutSwapBuffers();
}
//main loop of the program
void update(int value){
    glutPostRedisplay();
    glutTimerFunc(25, update, 0);
}

您应该创建direction的向量。每次移动鼠标时,都应该根据角度对其进行重新评估。方向矢量应该是单位圆上的矢量。

假设你有方向向量direction = (0.4X, 0.6Z)(例如,数字可以是不真实的,但让它是真实的),那么为了向前移动,你应该把它乘以velocity = 4的标量,所以向量velocity = (1.6X, 2.4Z)。意思是posX += 1.6, posZ += 2.4;

如果需要向右旋转,将其旋转90度并乘以速度标量。

若要旋转方向矢量,可以使用函数的sincos,因为它是单位圆上的位置。

要向后和向左移动,可以使用负速度。