1.实验目的:
进一步掌握二维、三维变换的数学知识、变换原理、变换种类、变换方法;进一步理解采用齐次坐标进行二维、三维变换的必要性;利用OpenGL实现二维、三维图形变换。
2.实验内容:
(1) 掌握二维、三维变换的原理及数学公式;
(2) 利用OpenGL实现二维、三维图形变换,在屏幕上显示变换过程或变换结果。
3.实验原理:
OpenGL的三个基本几何变换函数介绍如下:
(1) 平移变换
平移变换函数如下:
void glTranslate{fd}(TYPE x,TYPE y,TYPE z);
三个函数参数就是目标分别沿三个轴向平移的偏移量。这个函数表示用这三个偏移量生成的矩阵乘以当前矩阵。当参数是(0.0,0.0,0.0)时,表示对函数glTranslate*()的操作是单位矩阵,也就是对物体没有影响。
(2) 旋转变换
旋转变换函数如下:
void glRotate{fd}(TYPE angle,TYPE x,TYPE y,TYPE z);
函数中第一个参数是表示目标沿从点(x,y,z)到原点的方向逆时针旋转的角度,后三个参数是旋转的方向点坐标。这个函数表示用这四个参数生成的矩阵乘以当前矩阵。当角度参数是0.0时,表示对物体没有影响。
(3) 比例变换
比例变换函数如下:
void glScale{fd}(TYPE x,TYPE y,TYPE z);
三个函数参数值就是目标分别沿三个轴向缩放的比例因子。这个函数表示用这三个比例因子生成的矩阵乘以当前矩阵。这个函数能完成沿相应的轴对目标进行拉伸、压缩和反射三项功能。当参数是(1.0,1.0,1.0)时,表示对函数glScale*()操作是单位矩阵,也就是对物体没有影响。当其中某个参数为负值时,表示将对目标进行相应轴的反射变换,且这个参数不为1.0,则还要进行相应轴的缩放变换。最好不要令三个参数值都为零,这将导致目标沿三轴都缩为零。
有关OpenGL变换详细内容还可参看:http://blog.chinaunix.net/u/26313/showart_218525.html
4.实验代码:
#include <GL/glut.h>
#include <stdlib.h>
GLfloat rtri;//金字塔旋转角度
void init(void)
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glShadeModel(GL_SMOOTH);//设为smooth处理方式,注意看区别
glEnable(GL_DEPTH_TEST);//激活深度测试
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除颜色缓存和深度缓存
glLoadIdentity();
glTranslatef(-1.5f,0.0f,-6.0f);//请尝试修改此函数,掌握其用法与参数含义
glRotatef(rtri,0.0f,1.0f,0.0f);//请尝试修改此函数,掌握其用法与参数含义
glBegin(GL_TRIANGLES);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f( 1.0f,-1.0f, -1.0f);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f( 1.0f,-1.0f, -1.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(-1.0f,-1.0f, -1.0f);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glEnd();
rtri+=0.1f;//加一个角度
glutSwapBuffers();//交换双缓存
}
void reshape (int width, int height)
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, (GLfloat)width/(GLfloat)height, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void keyboard(unsigned char key, int x, int y)
{//请参考"变换示例参考"一文,考虑添加键盘命令,交互式来控制金字塔的旋转
switch (key)
{
case ‘x’:
exit(0);
break;
default:
break;
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);//使用双缓存模式和深度缓存
glutInitWindowSize(640, 480);
glutInitWindowPosition(100, 100);
glutCreateWindow("Transform2");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutIdleFunc(display);//设置空闲时调用的函数
glutMainLoop();
return 0;
}
代码注释:
这个程序需要注意的地方有几点。
使用了双缓存模式,程序在空闲时一直不停的调用display函数,这个函数绘制完图像后,改变旋转的角度,然后交换双缓存,这样,每画完一帧就交换,形成了动画。
另外,使用了深度缓存,激活了深度测试,这样,被遮挡的面就不会显示,大家可以把激活深度缓存的一行去掉看看效果。大家还可以改变变换的方式,达到不同的效果。
5.思考题
参考"CG实验指导四参考实例"一文考虑为本程序加上键盘交互控制功能,使得通过键盘可以控制对象的运动方式,如不同的旋转,或绕X轴或绕Z轴等.