鼠标移动加速代码执行



我正在自学如何使用OpenGL创建图形,我有一个基本的螺旋脚本+旋转。Y轴旋转是基于计时器功能自动进行的,但我注意到,当我在窗口内移动鼠标时,它的旋转速度似乎比预期的要快。有人能看看我的脚本,告诉我是什么导致了计时器功能的加速吗?

#include <Windows.h>
#include <glut.h>
#include <stdio.h>
#include <math.h>
// Change viewing volume and viewport. Called when window is resized
void ChangeSize(GLsizei w, GLsizei h)
{
    GLfloat nRange = 100.0f;
    //Prevent a divide by zero
    if(h == 0)
        h = 1;
    // Set Viewport to window dimensions
    glViewport(0, 0, w, h);
    // Reset projection matrix stack
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    // Establish clipping volume (left, right, buttom, top, near, far)
    if (w<= h)
        glOrtho (-nRange, nRange, -nRange*h/w, nRange*h/w, -nRange, nRange);
    else
        glOrtho (-nRange*w/h, nRange*w/h, -nRange, nRange, -nRange, nRange);
//Reset Model view matrix stack
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}
//Define a constant for pi
#define GL_PI 3.1415f
// This function does all the initialization
void SetupRC()
{
    // Black background
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
    // Set drawing color to green
    glColor3f(0.0f, 1.0f, 0.0f);
}

// Test declaration of rotation angle
GLfloat xRot = 0;
GLfloat yRot = 0;
// Modifiable variables for the eccentricity
    GLfloat xMod = 50.0f;
    GLfloat yMod = 50.0f;
// Called to draw scene
void RenderScene(void)
{
    GLfloat x,y,z,angle; // Storage for coordinates and angles
    GLfloat sizes[2]; // Store supported point size range
    GLfloat step; // Store point size increments
    GLfloat curSize; //Store current point size
    // Get supported point size range and step size
    glGetFloatv(GL_POINT_SIZE_RANGE, sizes);
    glGetFloatv(GL_POINT_SIZE_GRANULARITY, &step);
//Set the initial point size
curSize = sizes[0];
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT);
// Save matrix state and do the rotation
glPushMatrix();
glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);
// specify point size before primitive is specified
glPointSize(curSize);
//Call only once for remaining points
glBegin(GL_LINE_STRIP);
//Set beginning z coordinate
z = -50.0f;
//Loop around in a circle three times
for (angle = 0.0f; angle <= (2.0f*GL_PI)*3.0f; angle += 0.1f)
{
    // Calculate x and y values on the circle (the major and minor axis)
    x = xMod*sin(angle);
    y = yMod*cos(angle);
    // Specify the point and move the z value up a little
    glVertex3f(x, y, z);
    z += 0.5f;
}
// Done drawing points
glEnd();


// Restore transformations
glPopMatrix();
//Flush drawing commands
glFlush();
}
// Modifier Code
void CircleController (int key, int x, int y)
    {
 switch (key) 
{    
   case 27 :      break;
   case 100 : 
               (yRot -= 5.0f);  ;  break;
   case 102 :  
               (yRot += 5.0f);  ;  break;
   case 101 :  
               (xRot -= 5.0f);  ;  break;
   case 103 :    
               (xRot += 5.0f);  ;  break;
glutDisplayFunc(RenderScene);
}
}
void MouseHandler (int button, int state, int x, int y)
{
    // Holder variable assigned to overcome printf limitation and prevent double-    printing due to MouseUp function call
    GLfloat Holder = xMod;
    // Increases size, and decreases timer speed by increasing the amount of time     needed.
    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
        {
                xMod+= 5.0f;
    }
        // Decreases size, and increases timer speed by decreasing the amount of     time needed.
    if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
        {
            xMod-= 5.0f ;
    }
    if (Holder != xMod)
        printf("%d n", Holder);
}
void TimerFunction(int value)
{
    //Call the arrow key function
    glutSpecialFunc(CircleController);
    //Call the Mouseclick Modifier function
    glutMouseFunc(MouseHandler);
     if (xRot < 360)
    (xRot += 1.0f);
    else
    (xRot = 0.0f);

    // Redraw the scene with new coordinates
    glutPostRedisplay();
    glutTimerFunc(1.6666f, TimerFunction, 1);
}

void main(void)
{
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutCreateWindow("Drawing Lines");
    glutDisplayFunc(RenderScene);
    glutReshapeFunc(ChangeSize);
    glutTimerFunc(1.6666f, TimerFunction, 1);
    SetupRC();
    glutMainLoop();
}

Eric Palace让我开始

我个人的理论一直是,这与窗口焦点以及哪个程序有更多的CPU时间有关,但这只是猜测。

这对我来说很有道理。但等等,你不只是在计时器上画画吗?这难道不会阻止额外的CPU时间来修改移动速度吗?是的,有点。

glutTimerFunc(1.6666f, TimerFunction, 1);

glutTimerFunc的文档表示,第一个参数是unsigned int,以毫秒为单位表示计时器。所以你告诉glut"每1毫秒调用一次这个函数。"(大约1000FPS)由于执行时间超过一毫秒,你实际上告诉它"尽可能快地反复运行这个函数"。确实如此。因此,额外的CPU时间正在产生影响。

为了避免这种情况(除了校正1.6666f参数外),通常建议

  • 在不同的功能中更新"世界"与绘制屏幕。事实上,我认为拥有两个或多个世界更新函数是很常见的。一个是需要用油漆更新的东西:箭头和奔跑的角色,一个是每秒只改变一次的东西:魔法回复和npc决定,还有一个是非常慢的东西:重生
  • 在"更新"过程中,检查自上次更新以来经过了多少时间(最长半秒左右),并使世界更新那么多。然后,如果出于任何原因,更新的频率是原来的两倍或一半,游戏似乎不会加速或减速,只会增加/减少帧数

以下是这样的更新可能看起来像

radians xrot = 0; //use a units class
radians rot_per_second = .01;
void updateFrame(double time_passed) {
     assert(time_passed>=0 && time_passed <= 1.0);
     radians rotate_thistime = rot_per_second * time_passed;
     xrot += rotate_thistime;
}
void do_updates() {
     static clock_t lastupdatetime = clock()-1; //use openGL functions instead of C
     clock_t thisupdatetime = clock();
     double seconds = double(thisupdatetime-lastupdatetime)/CLOCKS_PER_SEC;
     if (seconds > 0.5) //if something happened and haven't update in a long time
         seconds = 0.5; //pretend only half a second passed.
     //this can happen if
     //   computer is overloaded
     //   computer hibernates
     //   the process is debugged
     //   the clock changes
     if (seconds <= 0.0) //computer is REALLY fast or clock changed
         return; //skip this update, we'll do it when we have sane numbers
     updateFrame(seconds);
     lastupdatetime = thisupdatetime;
}

最新更新