计算机图形学实验三 图形的变换2

在模型变换实验的基础上,通过实现下述实验内容,掌握OpenGL中三维观察、透视投影、正交投影的参数设置。

要求:1)添加键盘对场景的控制(上、下、左、右移动,键盘:w、s、a、d),并能使用键盘移动观察相机(按键z、c),在透视投影和正交投影间切换(按键p),如图2、3所示。
2)添加键盘对茶壶的控制,主要是茶壶沿着桌面的平移操作(上、下、左、右,按键为:i、k 、j、l,如图4-4中绿色和蓝色标示)和茶壶绕自身轴(按键为: e,如图4中红色标示)的旋转操作。
在这里插入图片描述

#include <GL/glut.h>

float fTranslate;
float fRotate; //场景自转角度
float fScale = 1.0f;

bool bPersp = false; //透视模式
bool bAnim = false; //场景自转
bool bWire = false;//边缘填充

int wHeight = 0;
int wWidth = 0;
//通过改变下面参数来控制茶壶
bool isTeapotRotate = false;
float teapotRotate = 0.0;//茶壶旋转
float teapotPos[] = { 0,0 }; //茶壶的位置

//窗口形状改变时调用
void reshape(int width, int height);
void updateView(int width, int height);
//绘图
void redraw();
void Draw_leg();
void Draw_Scene();
//按键调整参数
void key(unsigned char k, int x, int y);
//动画
void idle();


int main(int argc, char* argv[]) {
	//初始化工具包
	glutInit(&argc, argv);
	//设置显示模式
	glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB);
	//窗口设置
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(400, 400);
	glutCreateWindow("模型变换");
	//全局回调函数,不断监听
	glutReshapeFunc(reshape);
	glutDisplayFunc(redraw);
	glutKeyboardFunc(key);
	glutIdleFunc(idle);//动画渲染的关键

	glutMainLoop();//进入循环
	return 0;
}

void reshape(int width, int height) {//参数是窗口的宽和高
	if (height == 0) {
		height = 1;
	}// 窗口太小时的处理
	wHeight = height;
	wWidth = width;
	updateView(wHeight, wWidth);
}
void updateView(int width,int height) {
	glViewport(0, 0, width, height);//重置当前视口
	//投影
	glMatrixMode(GL_PROJECTION);//选择投影矩阵
	glLoadIdentity();//重置投影矩阵
	//计算宽高比
	float whRatio = (GLfloat)width / (GLfloat)height;
	//是否开启透视模式
	if (bPersp) {
		gluPerspective(45.0f, whRatio, 0.1f, 100.0f);
	}
	else
		glOrtho(-3, 3, -3, 3, -100, 100);//建立修剪空间的范围

	glMatrixMode(GL_MODELVIEW);//选择模型视图矩阵
}

void idle() {
	glutPostRedisplay();//渲染动画
}

float eye[] = { 0,0,8 };
float center[] = { 0,0,0 };

void key(unsigned char k, int x, int y) {
	switch (k)
	{
	case 'q':exit(0); break;//退出
	case 'p':bPersp = !bPersp; updateView(wHeight, wWidth);break;//开启或关闭透视模式
	case ' ':bAnim = !bAnim;break;//开启或关闭场景自转
	case'o':bWire = !bWire;break;//开启或关闭边缘填充
	case 'a':eye[0] += 0.2; center[0] += 0.2; break;//更改eye和center在x轴上的坐标	
	case 'd':eye[0] -= 0.2; center[0] -= 0.2; break;//更改eye和center在x轴上的坐标	
	case 'w':eye[1] -= 0.2; center[1] -= 0.2; break;//更改eye和center在y轴上的坐标	
	case 's':eye[1] += 0.2; center[1] += 0.2; break;//更改eye和center在y轴上的坐标	
	case 'z':eye[2] -= 0.2; break;//更改eye在z轴上的坐标	
	case 'c':eye[2] += 0.2;  break;//更改eye在z轴上的坐标
		//茶壶相关操作
	case'l':if (teapotPos[0] < 2.0)teapotPos[0] += 0.1;break;
	case'j':if (teapotPos[0] > -2.0)teapotPos[0] -= 0.1; break;
	case'i':if (teapotPos[1] < 1.5)teapotPos[1] += 0.1; break;
	case'k':if (teapotPos[1] > -1.5)teapotPos[1] -= 0.1; break;
	case'e':isTeapotRotate = !isTeapotRotate; break;//开启或关闭茶壶自转
	default:
		break;
	}
}

void Draw_leg() {
	//画一个比例为1:1:3的桌子腿
	glScalef(1, 1, 3);
	glutSolidCube(1.0);
}
void Draw_Scene() {
	//画茶壶
	glPushMatrix();//当前坐标状态(未作变换的)入栈
	glTranslatef(teapotPos[0], 0, 4 + 1+teapotPos[1]);
	glRotatef(teapotRotate, 0, 0, 1);
	glRotatef(90, 1, 0, 0);
	glutSolidTeapot(1);
	glPopMatrix();//坐标状态(未作变换的)出栈

	//画桌子板
	glPushMatrix();//当前坐标状态(未作变换的)入栈
	glTranslatef(0, 0, 3.5);
	glScalef(5, 4, 1);
	glRotatef(90, 1, 0, 0);
	glutSolidCube(1.0);
	glPopMatrix();

	//画桌子腿
	glPushMatrix();
	glTranslatef(1.5, 1, 1.5);
	Draw_leg();
	glPopMatrix();

	glPushMatrix();
	glTranslatef(-1.5, 1, 1.5);
	Draw_leg();
	glPopMatrix();

	glPushMatrix();
	glTranslatef(1.5, -1, 1.5);
	Draw_leg();
	glPopMatrix();

	glPushMatrix();
	glTranslatef(-1.5, -1, 1.5);
	Draw_leg();
	glPopMatrix(); 
}
void redraw() {
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();//重置当前modelview
	//定义视景转换,视点中心由eye[]控制,场景中心由center[]控制,y轴向上
	gluLookAt(eye[0], eye[1], eye[2], center[0], center[1], center[2], 0, 1, 0);
	//是否开启边缘绘制模式
	if (bWire) {
		glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);//设置两面均为边缘绘制方式
	}
	else {
		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);//设置两面均为填充绘制方式
	}

	// 用来开启更新深度缓冲区的功能,也就是,如果通过比较后深度值发生变化了,
	//会进行更新深度缓冲区的操作。启动它,OpenGL就可以跟踪再Z轴上的像素,
	//这样,它只会再那个像素前方没有东西时,才会绘画这个像素。	
	//在做绘画3D时,这个功能最好启动,视觉效果比较真实。
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_LIGHTING);//启动光照
	//设置光源LIGHT0的参数
	GLfloat white[] = { 1.0,1.0,1.0,1.0 };
	GLfloat light_pos[] = { 5,5,5,1 };
	glLightfv(GL_LIGHT0, GL_POSITION, light_pos); //设置光源位置
	glLightfv(GL_LIGHT0, GL_AMBIENT, white);//设置环境光颜色
	glEnable(GL_LIGHT0);//启动光源LIGHT0

	glRotatef(fRotate, 0, 1.0f, 0);//场景自转
	glRotatef(-90, 1, 0, 0);
	glScalef(0.2, 0.2, 0.2);
	Draw_Scene();

	if (bAnim) fRotate += 0.5f;
	if (isTeapotRotate) teapotRotate += 0.5f;//茶壶转角增加

	glutSwapBuffers();
}
  • 8
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值