在本文将实现一个正方形在屏幕不停移动,到达边界后再返回的效果。GLUT库提供了登记回调函数的功能,使得动画序列的设置更为简单。glutTimerFunc采用某个要调用的函数的名称以及调用该函数才需的等待时间为参数,格式如下:
void glutTimerFunc( unsigned int msecs, void (*func)(int value), int value);
这行代码将glut设置为调用函数func前等待msecs毫秒。与windows定时器Timer不一样,该函数只激发一次,为了实现连续的动画效果,必须在定时器函数中再次重新设置定时器。
该功能实现的源码如下:
// opengldemo.cpp : 定义控制台应用程序的入口点。//
#include "stdafx.h"
#include <gl/glut.h>
// squre position and size
GLfloat x1 = 100.0f;
GLfloat y1 = 150.0f;
GLsizei rsize = 50;
// move steps
GLfloat xstep = 1.0f;
GLfloat ystep = 1.0f;
// window width and height
GLfloat widonwWidth;
GLfloat windowHeight;
// called draw scene
void RenderScene(void)
{
// clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT);
// set current drawing color to red
glColor3f(1.0f, 0.0f, 0.0f);
// draw rectangle with current color
glRectf(x1, y1, x1+rsize, y1+rsize);
// Flush drawing commands & swap
//glFlush();
glutSwapBuffers();
}
// resized or moved
void TimerFunction(int value)
{
if ( x1<0 )
xstep = 1;
if ( y1<0 )
ystep = 1;
// clipping volume
if ( x1> widonwWidth-rsize)
{
x1 = widonwWidth - rsize - 1;
xstep = -1;
}
if ( y1> windowHeight-rsize)
{
y1 = windowHeight - rsize - 1;
ystep = -1;
}
x1 += xstep;
y1 += ystep;
// redraw the scene with new coordinates
glutPostRedisplay();
glutTimerFunc(33, TimerFunction, 1);
}
// Setup the renderiing state
void SetupRC(void)
{
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
}
// called by GLUT library when the window has changed size
void ChangeSize(GLsizei w, GLsizei h)
{
if ( h ==0)
h = 1;
// Set Viewport to window dimensions
glViewport(0, 0, w, h);
// Reset coordinate system
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// widht and height for later use
if ( w<=h )
{
widonwWidth = 250.0f;
windowHeight = 250.0f*h/w;
}
else
{
widonwWidth = 250.0f*w/h;
windowHeight = 250.0f;
}
glOrtho(0.0f, widonwWidth, 0.0f, windowHeight, 1.0, -1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int _tmain(int argc, char* argv[])
{
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);
glutCreateWindow("Bounce");
glutDisplayFunc(RenderScene);
glutReshapeFunc(ChangeSize);
glutTimerFunc(13, TimerFunction, 1);
SetupRC();
glutMainLoop();
return 0;
}
上面代码中:
1、RenderScene中有个重要的函数glutSwapBuffers();需要简单说明下。
对于任何图形软件包来说最重要的功能之一就是对双缓冲技术的支持。这项功能使你执行绘图代码时能够在一个屏幕之外的缓冲区进行渲染(渲染就是计算机根据模型绘制图像的过程),然后用交换命令把图像瞬间放到屏幕上。双缓冲技术有两个用途:
(1)有些复杂的图形可能要花很长的时间绘制,而你不希望图像合成的所有步骤都被人看到。使用双缓冲技术,就可以合成一副图像并完成后才显示出来,用户永远看不到不完整的图像(不会出现闪屏的现象)。
(2)制作动画。每一帧都在画面外的缓冲区绘制,完成后再很快的交换到屏幕上。
要使用双缓冲技术,首先需要将glutInitDisplayMode设置为:glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);然后在绘制或渲染函数的末尾进行缓冲区的交换:glutSwapBuffers();。
2、ChangeSize()函数实现窗口的缩放比例
几乎所有的窗口程序,用户都可以更改窗口的大小,在该事件发生时,窗口通常会做出响应,重新绘制内容,并考虑窗口的新尺寸。GLUT库提供了glutReshapeFunc函数登记一个回调函数,只要窗口尺寸发生变化,就会调用该函数。在ChangeSize()函数中,首先根据窗口的大小定义了视见区:
glViewport(0, 0, w, h);
可用用视见区来渲染窗口不同区域中的多幅图形,视见区定义了实际屏幕坐标中OpenGL可用用来绘图的窗口区域。
定义修剪区:
glOrtho(0.0f, widonwWidth, 0.0f, windowHeight, 1.0, -1.0);
在本文中,通过对修剪区的重新定义,使纵横比保持为正方形(纵横比是垂直方向上的一个单位长度的像素数与水平方向上相同长度单位的像素数之比,纵横比为1.0时就为正方形)。如下代码确保纵横比为1.0:
// widht and height for later use
if ( w<=h )
{
widonwWidth = 250.0f;
windowHeight = 250.0f*h/w;
}
else
{
widonwWidth = 250.0f*w/h;
windowHeight = 250.0f;
}
3、TimerFunction函数的调用
该函数是作为glutTimerFunc的回调函数使用的,在该函数中主要实现绘制图形的移动,确定图形的坐标位置后,进行图形的重新绘制,并激发计时器,代码如下:
// redraw the scene with new coordinates
glutPostRedisplay();
glutTimerFunc(33, TimerFunction, 1);
作者: kezunhai 出处: http://blog.csdn.net/kezunhai 欢迎转载或分享,但请务必声明文章出处。