glPushMatrix()和glPopmatirx()

OpenGL有三个矩阵堆栈,分别是GL_MODELVIEW(模型视图矩阵堆栈)、GL_PROJECTION(投影矩阵堆栈)、GL_TEXTURE(纹理矩阵堆栈),用法和普通堆栈一样;

这里我们只讲模型视图矩阵堆栈,OpenGL提供了相应的接口:glPushMatirx()和glPopMatrix()。

这个模型视图矩阵堆栈是干嘛用的呢?我们在三维空间中绘制模型,大部分时候需要对模型进行移动、旋转、缩放操作,其实OpenGL移动的不是模型,而是坐标系(效果是一样的啦,就比如你坐在车上,跟你并排的还有一辆车,都是静止不动的,这时候你倒车的效果和旁边那辆车前进的效果是不是一样的)。但是,但空间中有多个模型的时候,这个时候,问题来了,我们怎么确定每个模型都绘制在预期的位置呢?

比如,我们想要绘制太阳系,中间是太阳,静止不动,地球围绕太阳旋转,月亮围绕地球旋转,如下图所示的情景:


我们首先将坐标系移动到太阳的位置,绘制太阳,再将坐标系移动到地球的位置,绘制地球,然后将坐标系移动到月亮的位置,绘制月亮;如果还有金星、木星、火星呢,他们也都是以太阳为中心旋转,这样子,我们可以绘制完月亮之后再将坐标系回退到绘制地球的时候的坐标系,移动相应的位置,绘制金星,然后再回退或者移动新位置绘制木星。。。。。。这样的操作不但麻烦,而且容易出错(麻烦的东西都比较容易出错,所以要简洁),那怎么办最好呢,其实就是绘制地球、金星、木星、火星等的时候以太阳为坐标原点,在绘制地球之前先把当前的模型视图矩阵压入堆栈中保存下来(glPushMatirx),这样你在进行变换就不会影响到堆栈中的矩阵,这个时候将坐标系移动到地球的位置绘制地球,绘制完成之后将模型视图矩阵堆栈中的栈顶矩阵(就是我们刚才保存的矩阵)弹出(glPopMatrix),恢复原来的坐标系,再压入堆栈,绘制金星,再弹出。。。。。。

可以使用嵌套,即:

绘制太阳

压栈

(栈顶矩阵为太阳对应的模型视图矩阵)

移动坐标系到地球位置

绘制地球

压栈(这里就嵌套了)

(栈顶矩阵为地球地球对应的模型视图矩阵)

移动坐标系到月亮的位置

绘制月亮

压栈(嵌套又见嵌套)

(栈顶局长为月亮对应的模型视图矩阵)

移动坐标系到月亮的月亮(虚构)的位置

绘制月亮的月亮

出栈

(栈顶矩阵恢复为地球地球对应的模型视图矩阵,这时可以绘制第二个月亮了)

出栈

(栈顶矩阵恢复为太阳对应的模型视图矩阵,这时可以绘制金星、木星、火星等等了)

出栈

(栈顶为最初的模型视图矩阵,这时可以绘制太阳2,太阳3.。。。。。。太阳9,后羿射日前)

具体代码为(代码只实现了绘制两个月亮,也是嵌套,没有那么多,原理是一样的)

// Called to draw scene
void RenderScene(void)
	{
	// Earth and Moon angle of revolution
	static float fMoonRot = 0.0f;
	static float fEarthRot = 0.0f;

	// Clear the window with current clearing color
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	// Save the matrix state and do the rotations
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();

	// Translate the whole scene out and into view	
	glTranslatef(0.0f, 0.0f, -300.0f);	
	
	// Set material color, Red
	// Sun
        glDisable(GL_LIGHTING);
	glColor3ub(255, 255, 0);
	glutSolidSphere(15.0f, 30, 17);
        glEnable(GL_LIGHTING);

	// Move the light after we draw the sun!
	glLightfv(GL_LIGHT0,GL_POSITION,lightPos);

	// Rotate coordinate system
	glRotatef(fEarthRot, 0.0f, 1.0f, 0.0f);

	// Draw the Earth
	glColor3ub(0,0,255);
	glTranslatef(105.0f,0.0f,0.0f);
	glutSolidSphere(15.0f, 30, 17);

	glPushMatrix();
	// Rotate from Earth based coordinates and draw Moon
	glColor3ub(200,200,200);
	glRotatef(fMoonRot,0.0f, 1.0f, 0.0f);
	glTranslatef(30.0f, 0.0f, 0.0f);
	fMoonRot+= 15.0f;
	if(fMoonRot > 360.0f)
		fMoonRot = 0.0f;
	glutSolidSphere(6.0f, 30, 17);
	glPopMatrix();

	glColor3ub(100, 250, 0);
	glRotatef(fMoonRot, 1.0f, 0.0f, 0.0f);
	glTranslatef(0.0f, 20.0f, 0.0f);
	glutSolidSphere(6.0f, 30, 17);

	// Restore the matrix state
	glPopMatrix();	// Modelview matrix

	// Step earth orbit 5 degrees
	fEarthRot += 5.0f;
	if(fEarthRot > 360.0f)
		fEarthRot = 0.0f;

	// Show the image
	glutSwapBuffers();
}
实现效果图:

不过需要注意的是,模型视图矩阵堆栈最大为32个,Windows平台,有数量限制,超出的话将会报错。



  • 24
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值