0

我正在尝试为一个学校项目创建一个非常简单的物理模拟器,我想要它做的就是有一个立方体,它会因重力而落下露水,当它撞到地板上时它会反弹等等,直到立方体没有能量并且它将停止移动,例如在地板上休息。我还没有添加碰撞检测,但大多数其他事情都很好,我唯一的问题是立方体不能平稳下降它非常跳跃,例如它下降并加速然后减速然后再次加速,我有不知道为什么。

我已包含以下代码:

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();
}
4

1 回答 1

4

我在您的代码中看到了几个问题:

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

所以,一些基本的数学告诉我m/f = m/s * s/f。换句话说,您希望通过自上一帧以来的实际时间步长来缩放每帧移动立方体的量。

速度问题 你的代码编写方式,你的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 * s/f = m/f。这些单位很有意义,它们测量每帧的距离。

于 2013-03-07T23:17:09.673 回答