C ++和GLUT运动平稳

时间:2014-11-12 15:42:21

标签: c++ opengl glut

我是使用C ++图形的新手,我有以下代码 tutorial

这是代码

#include <windows.h>
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif

#include <stdlib.h>
#include <math.h>

float angle = 0.0f;
float lx = 0.0f, lz = -1.0f;
float x = 0.0f, z = 5.0f;

float deltaAngle = 0.0f;
float deltaMove = 0;

void drawSnowMan(){

    glColor3f(1.0f, 1.0f, 1.0f);

    glTranslatef(0.0f, 0.75f, 0.0f);
    glutSolidSphere(0.75f, 20, 20);

    glTranslatef(0.0f, 1.0f, 0.0f);
    glutSolidSphere(0.25f, 20, 20);

    glPushMatrix();
    glColor3f(0.0f, 0.0f, 0.0f);
    glTranslatef(0.5f, 0.10f, 0.18f);
    glutSolidSphere(0.05f, 10, 10);
    glTranslatef(-0.1f, 0.0f, 0.0f);
    glutSolidSphere(0.05f, 10, 10);
    glPopMatrix();

    glColor3f(1.0f, 0.5f, 0.5f);
    glutSolidCone(0.8f, 0.5f, 10, 2);

}

void changeSize(int w, int h){

    if(h == 0)
        h = 1;
    float ratio = 1.0*w/h;

    glMatrixMode(GL_PROJECTION);

    glLoadIdentity();

    glViewport(0,0,w,h);

    gluPerspective(45.0f, ratio, 0.1f, 100.0f);

    glMatrixMode(GL_MODELVIEW);

}

void computePos(float deltaMove){
    x += deltaMove * lx * 0.1f;
    z += deltaMove * lz * 0.1f;
}

void computeDir(float deltaAngle){
    angle += deltaAngle;
    lx = sin(angle/75.0);
    lz = -cos(angle/75.0);
}

void pressKey(int key, int xx, int yy){
    switch(key){
    case GLUT_KEY_LEFT: deltaAngle = -0.5f; break;
    case GLUT_KEY_RIGHT: deltaAngle = 0.5; break;
    case GLUT_KEY_UP: deltaMove = 0.5f; break;
    case GLUT_KEY_DOWN: deltaMove = -0.5f; break;
    }
}

void relaseKey(int key, int x, int y){
    switch(key){
    case GLUT_KEY_LEFT:
    case GLUT_KEY_RIGHT: deltaAngle = 0.0f; break;
    case GLUT_KEY_UP:
    case GLUT_KEY_DOWN: deltaMove = 0; break;
    }
}

void renderScene(void){

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glLoadIdentity();

    if(deltaMove)
        computePos(deltaMove);
    if(deltaAngle)
        computeDir(deltaAngle);

    gluLookAt(  x, 1.0f, z,
                x+lx, 1.0f, z+lz,
                0.0f, 1.0f, 0.0f
              );

    glColor3f(0.9f, 0.9f, 0.9f);

    glBegin(GL_QUADS);
        glVertex3f(-100.0f, 0.0f, -100.0f);
        glVertex3f(-100.0f, 0.0f, 100.0f);
        glVertex3f(100.0f, 0.0f, 100.0f);
        glVertex3f(100.0f, 0.0f, -100.0f);
    glEnd();

    angle += 0.1f;

    for(int i = -3; i < 3; i++){
        for(int j = -3; j < 3; j++){
            glPushMatrix();
            glTranslatef(i*10.0,0, j*10.0);
            drawSnowMan();
            glPopMatrix();
        }
    }
    glutSwapBuffers();
}

int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitWindowSize(320,320);
    glutInitWindowPosition(100,100);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);

    glutCreateWindow("Lighthouse 3D");

    glutDisplayFunc(renderScene);
    glutReshapeFunc(changeSize);

    glutIdleFunc(renderScene);

    glutSpecialFunc(pressKey);
    glutIgnoreKeyRepeat(1);
    glutSpecialUpFunc(relaseKey);

    glEnable(GL_DEPTH_TEST);

    glutMainLoop();

    return 1;
}

我的问题如下,当我尝试向左转,我按下左键时,一切正常。当我尝试击中左侧时,一旦动作不顺畅。在某些情况下,如果按钮行程太快,它甚至会转向相反的方向!

2 个答案:

答案 0 :(得分:2)

我认为你的意思是键盘而不是鼠标,在这种情况下,要有一个更好的&#34;更顺畅的&#34;和#34;慢&#34;您需要调整deltaAngle值,这可能会过高。

这只是一个临时修复,因为这些值可能以不同的方式影响其他机器 - 有些可能更快,有些可能更慢。您需要在渲染循环中计算主机的FPS并将delta值乘以它,以便在每台计算机上具有相同的性能。这称为基于时间的移动,是每个现代图形应用程序的基本功能。

这正是以下教程中发生的事情,当点在屏幕上移动太快时。

http://lazyfoo.net/SDL_tutorials/lesson32/index.php

答案 1 :(得分:0)

  • glutIdleFunc()将占用您的所有电池/ CPU / GPU,而是使用glutTimerFunc()重绘可预测的,理智的计划。
  • 在帧之间累积您的输入状态并将其应用于glutTimerFunc(),而不是尝试在您的keyup / keydown回调中正确执行。
  • 不需要glutResizeFunc(),在抽奖之前完成所有操作。
  • 您正在使用C ++,因此您应该使用C标头的C ++版本,例如<cmath>而不是<math.h>

所有在一起:

#include <GL/glut.h>
#include <cmath>
#include <map>

std::map< int, bool > keys;
void pressKey(int key, int xx, int yy)
{
    keys[ key ] = true;
}
void relaseKey(int key, int x, int y)
{
    keys[ key ] = false;
}

float angle = 0.0f;
float lx = 0.0f, lz = -1.0f;
float x = 0.0f, z = 5.0f;
void update()
{
    const float angleStep = 0.5f;
    if( keys[ GLUT_KEY_LEFT  ] )    angle -= angleStep;
    if( keys[ GLUT_KEY_RIGHT ] )    angle += angleStep;

    const float moveStep = 0.5f;
    float move = 0.0f;
    if( keys[ GLUT_KEY_DOWN  ] )    move -= moveStep;
    if( keys[ GLUT_KEY_UP    ] )    move += moveStep;

    x += move * lx * 0.1f;
    z += move * lz * 0.1f;

    lx = sin(angle/75.0);
    lz = -cos(angle/75.0);
}

void drawSnowMan()
{
    glColor3f(1.0f, 1.0f, 1.0f);

    glTranslatef(0.0f, 0.75f, 0.0f);
    glutSolidSphere(0.75f, 20, 20);

    glTranslatef(0.0f, 1.0f, 0.0f);
    glutSolidSphere(0.25f, 20, 20);

    glPushMatrix();
    glColor3f(0.0f, 0.0f, 0.0f);
    glTranslatef(0.5f, 0.10f, 0.18f);
    glutSolidSphere(0.05f, 10, 10);
    glTranslatef(-0.1f, 0.0f, 0.0f);
    glutSolidSphere(0.05f, 10, 10);
    glPopMatrix();

    glColor3f(1.0f, 0.5f, 0.5f);
    glutSolidCone(0.8f, 0.5f, 10, 2);
}

void renderScene(void)
{
    glEnable(GL_DEPTH_TEST);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    const double w = glutGet( GLUT_WINDOW_WIDTH );
    const double h = glutGet( GLUT_WINDOW_HEIGHT );
    gluPerspective(45.0f, w / h, 0.1f, 100.0f);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    gluLookAt
        (
        x, 1.0f, z,
        x+lx, 1.0f, z+lz,
        0.0f, 1.0f, 0.0f
        );

    glColor3f(0.9f, 0.9f, 0.9f);

    glBegin(GL_QUADS);
    glVertex3f(-100.0f, 0.0f, -100.0f);
    glVertex3f(-100.0f, 0.0f, 100.0f);
    glVertex3f(100.0f, 0.0f, 100.0f);
    glVertex3f(100.0f, 0.0f, -100.0f);
    glEnd();

    for(int i = -3; i < 3; i++)
    {
        for(int j = -3; j < 3; j++)
        {
            glPushMatrix();
            glTranslatef(i*10.0,0, j*10.0);
            drawSnowMan();
            glPopMatrix();
        }
    }

    glutSwapBuffers();
}

void timer( int value )
{
    update();
    glutTimerFunc( 16, timer, 0 );
    glutPostRedisplay();
}

int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitWindowSize(320,320);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);

    glutCreateWindow("Lighthouse 3D");

    glutDisplayFunc(renderScene);
    glutSpecialFunc(pressKey);
    glutSpecialUpFunc(relaseKey);
    glutTimerFunc( 0, timer, 0 );

    glutMainLoop();

    return 1;
}