openGL学习笔记4(动画)


下面是通过看  《OpenGL入门教程》得来的~~~版权还是作者的啊,只是找不到来源了,我吐舌头



OpenGL动画和传统意义上的动画相似,都是把画面一幅一幅的呈现在观众面前。一旦画面变换的速度快了,观众就会认为画面是连续的。
双缓冲技术是一种在计算机图形中普遍采用的技术,绝大多数OpenGL实现都支持双缓冲技术。
通常都是利用CPU空闲的时候绘制动画,但也可以有其它的选择。




  双缓冲技术
在计算机上的动画与实际的动画有些不同:实际的动画都是先画好了,播放的时候直接拿出来显示就行。

计算机动画则是画一张,就拿出来一张,再画下一张,再拿出来。

如果所需要绘制的图形很简单,那么这样也没什么问题。但一旦图形比较复杂,绘制需要的时间较长,问题就会变得突出。


让我们把计算机想象成一个画图比较快的人,假如他直接在屏幕上画图,而图形比较复杂,则有可能在他只画了某幅图的一半的时候就被观众看到。而后面虽然他把画补全了,但观众的眼睛却又没有反应过来,还停留在原来那个残缺的画面上。也就是说,有时候观众看到完整的图象,有时却又只看到残缺的图象,这样就造成了屏幕的闪烁


如何解决这一问题呢?我们设想有两块画板,画图的人在旁边画,画好以后把他手里的画板与挂在屏幕上的画板相交换。这样以来,观众就不会看到残缺的画了。

这一技术被应用到计算机图形中,称为双缓冲技术。即:在存储器(很有可能是显存)中开辟两块区域,一块作为发送到显示器的数据,一块作为绘画的区域,在适当的时候交换它们。由于交换两块内存区域实际上只需要交换两个指针,这一方法效率非常高,所以被广泛的采用。


注意:虽然绝大多数平台都支持双缓冲技术,但这一技术并不是OpenGL标准中的内容。OpenGL为了保证更好的可移植性,允许在实现时不使用双缓冲技术。当然,我们常用的PC都是支持双缓冲技术的。


要启动双缓冲功能,最简单的办法就是使用GLUT工具包。我们以前在main函数里面写:


glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);


其中GLUT_SINGLE表示单缓冲,如果改成GLUT_DOUBLE就是双缓冲了。


当然还有需要更改的地方——每次绘制完成时,我们需要交换两个缓冲区,把绘制好的信息用于屏幕显示(否则无论怎么绘制,还是什么都看不到)。如果使用GLUT工具包,也可以很轻松的完成这一工作,只要在绘制完成时简单的调用glutSwapBuffers函数就可以了。




glMatrixMode

这个函数其实就是对接下来要做什么进行一下声明,也就是在要做下一步之前告诉计算机我要对什么进行操作了,这个什么glMatrixMode“()”里的选项(参数)有,GL_PROJECTIONGL_MODELVIEWGL_TEXTURE


如果参数是GL_PROJECTION,这个是投影的意思,就是要对投影相关进行操作,也就是把物体投影到一个平面上,就像我们照相一样,把3维物体投到2维的平面上。这样,接下来的语句可以是跟透视相关的函数,比如 glFrustum() 或 gluPerspective()


如果参数是GL_MODELVIEW,这个是对模型视景的操作,接下来的语句描绘一个以模型为基础的适应,这样来设置参数,接下来用到的就是像 gluLookAt() 这样的函数;


若是GL_TEXTURE,就是对纹理相关进行操作;


OpenGL里面的操作,很多是基于对矩阵的操作的,比如位移,旋转,缩放。

所以,这里其实说的规范一点就是glMatrixMode是用来指定哪一个矩阵是当前矩阵,而它的参数代表要操作的目标,GL_PROJECTION是对投影矩阵操作,GL_MODELVIEW是对模型视景矩阵操作,GL_TEXTURE是对纹理矩阵进行随后的操作。


==========================================================

下面这个函数的解释来自:http://www.cppblog.com/COOOOOOOOL/archive/2009/12/28/104255.html   解释的真很好哇~~哈哈

gluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear,GLdouble zFar)
设置透视投影矩阵
首先得设置gluPerspective,来看看它的参数都表示什么意思
fovy,这个最难理解,我的理解是,眼睛睁开的角度,即,视角的大小,如果设置为0,相当你闭上眼睛了,所以什么也看不到,如果为180,那么可以认为你的视界很广阔,
aspect,这个好理解,就是实际窗口的纵横比,即x/y
zNear,这个呢,表示你近处,的裁面,
zFar表示远处的裁面,

如果还没有理解就继续看,
我们知道,远处的东西看起来要小一些,近处的东西看起来会大一些,这就是透视原理
如下图所示


openGL学习笔记4(动画)_第1张图片


================================================================================================

下面这个函数 来自 百度百科:http://baike.baidu.com/view/2341537.htm

 视点转换

  函数原型:
  void gluLookAt(GLdouble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble centerz,GLdouble upx,GLdouble upy,GLdouble upz);

参数:

 gluLookAt()共有九个参数,分别是眼睛的位置,眼睛朝向的位置,以及相片朝上的方向。

  该 函数定义了视点 矩阵,并用该矩阵乘以当前矩阵。eyex、eyey、eyez定义了视点的位置;centerx、centery和centerz变量指定了参考点的位置,该点通常为相机所瞄准的场景中心轴线上的点;upx、upy、upz变量指定了向上向量的方向。

说明:

 通常,视点转换操作在模型转换操作之后发出,以便模型转换先对物体发生作用。场景中物体的顶点经过模型转换之后移动到所希望的位置,然后再对场景进行视点定位等操作。模型转换和视点转换共同构成模型视景矩阵

  这个函数是对模型矩阵进行变换(GL_MODELVIEW),而gluPerspective函数是对投影矩阵进行变换(GL_PROJECTION),这一点一定要搞清楚。
  你可以用gluPerspective函数设置近平面、远平面


介绍了垂直同步的相关知识。



介绍了一种简单的计算帧速(FPS)的方法。
最后,我们列出了一份完整的天体动画程序清单。

code:

#include <GL/glut.h>
#include <stdio.h>
#include <time.h>

// 太阳、地球和月亮
// 假设每个月都是12天
// 一年12个月,共是360天
static int day = 100; // day的变化:从0到359

double CalFrequency()
{
	static int count;
	static double save;
	static clock_t last, current;
	double timegap;

	++count;
	if( count <= 50 )
		return save;
	count = 0;
	last = current;
	current = clock();
	timegap = (current-last)/(double)CLK_TCK;
	save = 50.0/timegap;
	return save;
}

void myDisplay(void)
{
	double FPS = CalFrequency();
	printf("FPS = %f\n", FPS);

	glEnable(GL_DEPTH_TEST);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glMatrixMode(GL_PROJECTION); //对投影矩阵操作
	glLoadIdentity(); //把坐标移动到中心位置
	gluPerspective(75, 1, 1, 400000000); //设置透视投影矩阵
	glMatrixMode(GL_MODELVIEW); //对模型视景矩阵操作
	glLoadIdentity(); //将当前的用户坐标系的原点移到了屏幕中心:类似于一个复位操作
	gluLookAt(0, -200000000, 200000000, 0, 0, 0, 0, 0, 1); // 视点转换

	// 绘制红色的“太阳”
	glColor3f(1.0f, 0.0f, 0.0f);
	glutSolidSphere(69600000, 20, 20);
	// 绘制蓝色的“地球”
	glColor3f(0.0f, 0.0f, 1.0f);
	glRotatef(day/360.0*360.0, 0.0f, 0.0f, -1.0f);
	glTranslatef(150000000, 0.0f, 0.0f);
	glutSolidSphere(15945000, 20, 20);
	// 绘制黄色的“月亮”
	glColor3f(1.0f, 1.0f, 0.0f);
	glRotatef(day/30.0*360.0 - day/360.0*360.0, 0.0f, 0.0f, -1.0f);
	glTranslatef(38000000, 0.0f, 0.0f);
	glutSolidSphere(4345000, 20, 20);

	glFlush();
	glutSwapBuffers(); //交换两个缓冲区
} 

/* 新的函数,在空闲时调用,作用是把日期往后移动一天并重新绘制,达到动画效果 */
void myIdle(void)
{
	++day;
	if( day >= 360 )
		day = 0;
	myDisplay();
}

int main(int argc, char *argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(400, 400);
	glutCreateWindow("太阳,地球和月亮");
	glutDisplayFunc(&myDisplay);
	glutIdleFunc(&myIdle);
	glutMainLoop();
	return 0;
}

result:

openGL学习笔记4(动画)_第2张图片di


地球围绕太阳转。月球围绕地球和太阳转。


你可能感兴趣的:(百度,存储,buffer,360,工具,图形)