我在教自己如何使用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();
}
答案 0 :(得分:0)
Eric Palace给了我一个开始
我的个人理论总是与窗口焦点有关,哪个程序有更多的CPU时间,但这只是纯粹的推测。
这对我有意义。但是等等,你不只是在计时器上画画吗?这不会阻止额外的CPU时间来修改移动速度吗?是的你是。 Sortof。
glutTimerFunc(1.6666f, TimerFunction, 1);
glutTimerFunc的文档说第一个参数是unsigned int
,以毫秒为单位表示计时器。所以你要说的是“每1毫秒调用一次这个功能”。 (大约1000FPS)并且由于执行时间超过一毫秒,因此您可以有效地告诉它“尽可能快地反复运行此功能”。它做的。因此,额外的CPU时间 会产生影响。
为了避免这样的情况(除了纠正1.6666f参数),通常会建议
以下是这样的更新可能是什么样的
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;
}