OpenGL(三)图形变换之矩阵堆栈

时间:2022-04-28 10:22:23

通过原子核动画 示例学习知识点:

<span style="font-size:18px;">#include<windows.h>
#include<gl/gl.h>
#include<gl/glut.h>


//还是以俯视理解


void SetupRC(void)
{

	glEnable(GL_DEPTH_TEST);//启动深度测试
	glFrontFace(GL_CCW);   //指定逆时针绕法表示多边形正面
	//设置窗口背景颜色为白色
	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
}



void ChangeSize(int w, int h)
{
	if (h == 0)
		h = 1;
	//设置视区尺寸
	glViewport(0, 0, w, h);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	//设置修剪空间
	GLfloat fAspect = (float)w / (float)h;

	gluPerspective(45.0,fAspect,1.0,500.0);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

void RenderScene(void)
{

	//绕原子核旋转的角度
	static float fElect1 = 0.0f;

	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

	//设置当前操作矩阵为模型视图矩阵,并复位为单位矩阵

	//重置模型视图矩阵
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	//将图形沿z轴负方向移动
	//越往z轴负方向,视图越小
	glTranslatef(0.0f, 0.0f, -250.0f);

	//绘制红色的原子核
	glColor3f(1.0f,0.0f,0.0f);
	//该函数用于渲染一个球体。球体球心位于原点。
	//在OpenGL中默认的原点就是窗口客户区的中心
	glutSolidSphere(10.0f,15,15);

    //当前绘制颜色为黑色
	glColor3f(0.0f,0.0f,0.0f);

	//保存当前的模型
	glPushMatrix();
	//绘制第一个电子
	//绕y轴旋转一定的角度
	glRotatef(fElect1,0.0f,1.0f,0.0f);
	//平移一段距离
	glTranslated(90.0f,0.0,0.0f);//向x轴正方向平移
	glColor3f(1.0f, 1.0f, 0.0f);//黄
	glutSolidSphere(6.0f,15,15);//画出电子
	//恢复矩阵
	glPopMatrix();


	//绘制第二个电子
	glPushMatrix();
	glRotatef(45.0f,0.0f,0.0f,1.0);
	glRotatef(fElect1, 0.0f, 1.0f, 0.0);
	glTranslatef(-70.0f,0.0f,0.0f);//向y轴负方向平移
	glColor3f(0.0f, 1.0f, 0.0f); //绿
	glutSolidSphere(6.0f,15,15);
	glPopMatrix();

	//绘制第三个电子
	glPushMatrix();
	glRotatef(-45.0f,0.0f,0.0f,1.0f);
	glRotatef(fElect1,0.0f,1.0f,0.0f);
	glTranslatef(0.0f,0.0f,60.0f); //向z轴正方向平移
	glColor3f(0.0f, 0.0f, 1.0f);//蓝色
	glutSolidSphere(6.0f,15,15);
	glPopMatrix();

	//增加旋转步长
	fElect1 += 10.0f;

	if (fElect1 > 360.0f)
		fElect1 = 10.0f;
	//交换两个缓冲区的指针
	//功能:防止复杂绘制时屏幕闪烁
	glutSwapBuffers();

}

void TimerFunc(int value)
{
	glutPostRedisplay();
	glutTimerFunc(100,TimerFunc,1);
}
int main(int argc, char *argv[])
{
	//glutInit is used to initialize the GLUT library
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB|GLUT_DEPTH);
	glutCreateWindow("原子示例");
	glutDisplayFunc(RenderScene);
	glutReshapeFunc(ChangeSize);

	glutTimerFunc(500,TimerFunc,1);

	SetupRC();
	glutMainLoop();
	return 0;
}
</span>


本程序使用了透视投影,可以清楚地看到电子在旋转到远处时,体积逐渐变小,而旋转到近处时,体积有渐渐变大。
运行结果:

OpenGL(三)图形变换之矩阵堆栈


学习知识点:

1.矩阵堆栈(其实前面已经接触过了)

OpenGL 为模型视图矩阵和投影矩阵各维护这一个“”矩阵堆栈“”,工作方式跟我们普通堆栈一样。

我们可以吧当前矩阵压到堆栈中保存它,然后对当前矩阵进行修改,把矩阵弹出堆栈即可恢复。

使用函数如下:

void glPushMatrix(void );

void glPopMatrix(void );

函数glPushMatrix(void )用户将当前矩阵压人矩阵堆栈,常用于保存当前矩阵。

glPopMatrix常用于将最后一个矩阵弹出当前矩阵堆栈,常用于恢复当前变换矩阵原先的状态。

2:、OpenGL 维护两个栈:投影变换栈,几何变换栈。

投影: glOrtho,gluPerspective--------------------glMatrixMode(GL_PROJECTION); 

几何变 换:glTranslatef,glRotatef,glScalef--------glMatrixMode(GL_MODELVIEW); 

在调用glMatrixMode(GL_MODELVIEW)时,系统会自动将几何变换桟清空并压入单位矩阵,因此不必再调用glLoadIdentity()函数。

glMatrixMode(GL_MODELVIEWING或GL_PROJECTION);本命令执行后参数所指矩阵栈就成为当前矩阵栈,以后的矩阵栈操纵命令将作用于它。