如何使一个立方体平滑地落在y轴在开放Gl, c++

How to make a cube fall smoothly down the Y-Axis in Open Gl, C++

本文关键字:Gl c++ 立方体 平滑 何使一      更新时间:2023-10-16

我试图为一个学校项目创建一个非常简单的物理模拟器,我想要做的就是有一个立方体,它落在重力下,当它撞到地板时,它会反弹等等,直到立方体没有能量,它只会停止移动,例如在地板上休息。我还没有添加碰撞检测,但大多数其他的东西工作得很好,我唯一的问题是,立方体不顺利下降,它非常跳跃,例如它下降和加速,然后减速,然后再次加速,我不知道为什么。

我包含了下面的代码:

timestep++;
velo += 0.005;
cout << velo << "n";
glTranslatef(0.0, -velo, 0.0);//timestep * gravity, 0.0);

我还包含了整个程序代码,以防在其他地方出现问题,上面的摘录只是在显示函数

的顶部
#include <GLTools.h>
#include <GLShaderManager.h>
#include <GLFrustum.h>
#include <GLBatch.h> 
#include <GLFrame.h>
#include <GLMatrixStack.h>
#include <GLGeometryTransform.h>
#include <StopWatch.h>
#include <math.h>
#include <stdio.h>
#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif
#include <iostream>;
using namespace std;
void display();
void specialKeys(int, int, int);
void animate();
double rotate_y = 0;
double rotate_x = 0;
// Gravity Varibles
int timestep = 0;
float gravity = 0.0098;
float velo = 0.0f;

int main( int argc, char* argv[] )
{
    glutInit(&argc, argv);
    glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL );
    glutCreateWindow("DANIELS CUBE");
    glEnable(GL_DEPTH_TEST);
    glShadeModel(GL_SMOOTH);
    glutDisplayFunc(display);
    glutSpecialFunc(specialKeys);
    glutIdleFunc(animate);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-2.0, 2.0, -2.0, 2.0, -2.0, 2.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(5.0, 5.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
    glutMainLoop();
    return 0;
}
void animate()
{
    glutPostRedisplay();
}
void display()
{
    //Clears the window
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    // Changes the way the polygons are drawn so it looks like a wire frame
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    ///////////
    // CUBE ///
    ///////////
    // Resets the transformation matrix
    glLoadIdentity();
    glScalef(0.2, 0.2, 0.2);
    // Rotates the cuube around the x by 'rotate_x'
    glRotatef( rotate_x, 1.0, 0.0, 0.0 );
    // Rotates the cuube around the y by 'rotate_y'
    glRotatef( rotate_y, 0.0, 1.0, 0.0 ); 
    // move dew to gravity
    timestep++;
    velo += 0.005;
    cout << velo << "n";
    glTranslatef(0.0, -velo, 0.0);//timestep * gravity, 0.0);
    // Defines the folowing verticys as this polygon
    glBegin(GL_POLYGON);
    //Changes color
    glColor3f( 1.0, 0.0, 0.5 );
    // Adds verted to polygon
    glVertex3f( -0.5, -0.5, -0.5 ); // F1
    glColor3f( 0.0, 1.0, 0.0 );
    glVertex3f( -0.5, 0.5, -0.5  ); // F2
    glColor3f( 0.0, 0.0, 1.0 );
    glVertex3f( 0.5, 0.5, -0.5 );   // F3
    glColor3f( 1.0, 0.0, 1.0 );
    glVertex3f( 0.5, -0.5, -0.5 );  // F4
    // Closes the polygon
    glEnd();
    glBegin(GL_POLYGON);
    glColor3f( 1.0, 1.0, 1.0 );
    glVertex3f( 0.5, -0.5, -0.5 );  // Back1
    glVertex3f( 0.5, 0.5, -0.5  );  // Back2
    glVertex3f( 0.5, 0.5, 0.5 );    // Back3
    glVertex3f( 0.5, -0.5, 0.5 );   // Back4
    glEnd();
    glBegin(GL_POLYGON);
    glColor3f( 1.0, 0.0, 1.0 );
    glVertex3f( 0.5, -0.5, -0.5 );  // F1
    glVertex3f( 0.5, 0.5, -0.5  );  // F2
    glVertex3f( 0.5, 0.5, 0.5 );    // F3
    glVertex3f( 0.5, -0.5, 0.5 );   // F4
    glEnd();
    glBegin(GL_POLYGON);
    glColor3f( 0.0, 1.0, 0.0 );
    glVertex3f( -0.5, -0.5, 0.5 );  // F1
    glVertex3f( -0.5, 0.5, 0.5  );  // F2
    glVertex3f( -0.5, 0.5, -0.5 );  // F3
    glVertex3f( -0.5, -0.5, -0.5 ); // F4
    glEnd();
    glBegin(GL_POLYGON);
    glColor3f( 0.0, 0.0, 1.0 );
    glVertex3f( 0.5, 0.5, 0.5 );    // F1
    glVertex3f( 0.5, 0.5, -0.5  );  // F2
    glVertex3f( -0.5, 0.5, -0.5 );  // F3
    glVertex3f( -0.5, 0.5, 0.5 );   // F4
    glEnd();
    glBegin(GL_POLYGON);
    glColor3f( 1.0, 0.0, 0.0 );
    glVertex3f( 0.5, -0.5, -0.5 );  // F1
    glVertex3f( 0.5, -0.5, 0.5  );  // F2
    glVertex3f( -0.5, -0.5, 0.5 );  // F3
    glVertex3f( -0.5, 0.5, -0.5 );  // F4
    glEnd();
    ////////////
    // Floor //
    //////////
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    glLoadIdentity();
    // Rotates the cuube around the x by 'rotate_x'
    glRotatef( rotate_x, 1.0, 0.0, 0.0 );
    // Rotates the cuube around the y by 'rotate_y'
    glRotatef( rotate_y, 0.0, 1.0, 0.0 );
    glColor3f(1.0, 1.0, 1.0);
    glBegin(GL_LINES);
    for( GLfloat i =  -2.5; i < 2.5; i += 0.25 )
    {
        glVertex3f(i, -1.0, 2.5);
        glVertex3f(i, -1.0, -2.5);
        glVertex3f(2.5, -1.0, i);
        glVertex3f(-2.5, -1.0, i);
    }
    glEnd();
    // Flushes the buffers
    glFlush();
    // Draws what has just been done on the screen
    glutSwapBuffers();
    }
void specialKeys( int key, int x, int y )
{
    if( key == GLUT_KEY_RIGHT )
    {
        rotate_y += 5;
    }
    else if( key == GLUT_KEY_LEFT )
    {
        rotate_y -= 5;
    }
    else if( key == GLUT_KEY_UP )
    {
        rotate_x += 5;
    }
    else if( key == GLUT_KEY_DOWN )
    {
        rotate_x -= 5;
    }
    glutPostRedisplay();
}

我看到你的代码有几个问题:

假设时间步长固定您的显示函数不能保证以均匀间隔被调用。本质上,你给立方体的速度是"米/帧(m/f)"而不是"米/秒(m/s)"。(这里我使用米作为一般距离单位)

所以,一些基本的数学告诉我m/f = m/s * s/f。换句话说,你想要根据上一帧的实际时间步长来调整每帧立方体的移动量。

<<p> 速度问题/strong>你的代码是这样写的,你的velo变量实际上代表了位置,你用0.005这个数字更新每一帧,我认为这就是你想要的加速度。如果你想让某物因重力而加速,你需要存储两个值,它的位置和速度。然后每一帧,你需要通过添加加速度来更新速度,通过添加速度来更新位置。

下面的代码可以同时做这两件事

int lastTime=0;
void display() {
    int time = glutGet(GLUT_ELAPSED_TIME); // Time since the start of the program
    if (lastTime>0) { // Don't move anything the first frame
        int deltaTime = time-lastTime; // millis elapsed since the last frame
        velo += -0.005*deltaTime; // Gravity accelerates downwards
        pos += velo*deltaTime; // Position updated by velocity
        glTranslateF(0.0, pos, 0.0); // Actually position the square in the correct location
    }
    lastTime = deltaTime;
}

请注意,当我用加速度更新速度时,我将其缩放为deltaTime,当我用速度更新位置时,我也是这样做的。同样,前面的单位分析是记住这一点的简单方法:deltaTime告诉您自上一帧以来经过的毫秒数,所以它的单位是"s/f"。velo应该有单位"m/s",以使运动随着时间的推移而平滑。这一帧的位置更新量为m/s * s/f = m/f。这些单位是有意义的,它们测量每帧的距离