0

我正在自学如何使用 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();
}
4

1 回答 1

0

埃里克宫给了我开始

我个人的理论一直是它与窗口焦点有关,以及哪个程序获得了更多的 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;
}
于 2013-07-12T19:06:34.103 回答