鼠标移动加速代码执行?

时间:2013-07-12 18:52:20

标签: c++ opengl

我在教自己如何使用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();
}

1 个答案:

答案 0 :(得分:0)

Eric Palace给了我一个开始

  

我的个人理论总是与窗口焦点有关,哪个程序有更多的CPU时间,但这只是纯粹的推测。

这对我有意义。但是等等,你不只是在计时器上画画吗?这不会阻止额外的CPU时间来修改移动速度吗?是的你是。 Sortof。

glutTimerFunc(1.6666f, TimerFunction, 1);

glutTimerFunc的文档说第一个参数是unsigned int,以毫秒为单位表示计时器。所以你要说的是“每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;
}