一、实验目的
1.了解和掌握2D图形变换:学会使用OpenGL平移、旋转和比例缩放函数,掌握基本图形变换和复合图形变换实现的方法。
2.综合运用2D图形变换函数、人机交互函数,设计2D交互图形程序。
二、实验内容
要求使用OpenGL几何变换函数改写代码。
1)使用glTranslatef()函数,实现2D图形平移,可以改写实验二的矩形交互移动程序,如图6-1。
a)平移前 b)平移后
图6-1 平移变换
2)使用glRotatef()函数,实现2D图形绕平面固定点旋转,可以改写实验三的六边形旋转程序,如图6-2。
a)旋转前 b)旋转后
图6-2 旋转变化
3)使用glScalef()函数,实现绕固定点缩放2D图形,在前面程序的基础上设计修改,如图6-3。
a)缩放前 b)缩放后
图6-3 比例变换
4)修改代码,使得一面带杆小三角红旗沿着杆底不断旋转,如图6-4
图6-4 旋转的小红旗
5)正六边形边旋转边放大,放大到接近整个显示屏后再不停缩小,如此往复。
三、参考函数
1.glTranslatef(x,y,z);//x、y、z分别代表x、y、z方向的平移量,对于2D图形,z=0
2.glRotatef(Q,x,y,z);//Q为逆时针方向旋转的角度度数(0~360),(x,y,z)为旋转轴的方向矢量,(x,y,z)=(0,0,1)时代表沿z轴方向旋转;(x,y,z)=(1,0,0)时代表沿x轴方向旋转;(x,y,z)=(0,1,0)时代表沿y轴方向旋转。
3.glScalef(x,y,z);//x、y、z分别表示x、y、z方向的比例因子。对于2D图形,z=0。比例因子取-1时,产生对称变换。
四、代码示例
1.某图形沿水平方向和垂直方向分别平移Tx、Ty段距离。
清屏
glMatrixMode(GL_MODELVIEW);//设置矩阵模式为模型变换模式,表示在世界坐标系下
glLoadIdentity();//将当前矩阵设置为单位矩阵
glTranslatef(Tx,Ty,0)
DrawSomeShape();
刷新
2.某图形绕任意点(cx,cy)旋转ALPHA角度。
清屏
glMatrixMode(GL_MODELVIEW);//设置矩阵模式为模型变换模式,表示在世界坐标系下
glLoadIdentity();//将当前矩阵设置为单位矩阵
glTranslatef(cx,cy,0)//平移回去
glRotatef(ALPHA,0,0,1);//绕原点旋转ALPHA角度
glTranslatef(-cx,-cy,0)//平移回原点
DrawSomeShape();
刷新
3.某图形绕任意点(cx,cy)缩放Sx、Sy比例因子。
清屏
glMatrixMode(GL_MODELVIEW);//设置矩阵模式为模型变换模式,表示在世界坐标系下
glLoadIdentity();//将当前矩阵设置为单位矩阵
glTranslatef(cx,cy,0)//平移回去
glScalef(Sx,Sy,1);//绕原点水平缩放系数Sx,垂直缩放系数Sy
glTranslatef(-cx,-cy,0)//平移回原点
DrawSomeShape();
刷新
五、思考题
1.绕某个固定点旋转时,代码的顺序改写为:
glTranslatef(-cx,-cy,0)//平移回原点
glRotatef(ALPHA,0,0,1);//绕原点旋转ALPHA角度
glTranslatef(cx,cy,0)//平移回去
图形将变成怎样?
答:图形形状不变,但是位置会改变。因为因为glTranslatef的变换是以当前位置来变换的,也就是说用的是相对坐标而不是绝对坐标。
2.绕某个固定点进行比例缩放时,代码的顺序改写为:
glTranslatef(-cx,-cy,0)//平移回原点
glScalef(Sx,Sy,1);//绕原点水平缩放系数Sx,垂直缩放系数Sy
glTranslatef(cx,cy,0)//平移回去
图形将变成怎样?为什么?
答:会缩放,但是位置会改变。因为缩放是相对于原点进行的,而不是自身的中心。当平移后再缩放,再平移回去,会改变坐标。
六、完整代码
#include
#include
#include
#include"math.h"
#define PI 3.1415926
int n = 6,flag=0;
float R = 0.5,theta=0,sx=1,sy=1;
void myidle()
{
theta += 1.0;
Sleep(5);
if (theta >= 360) theta -= 360;
/*if (sx >= 2.83) flag = 1;
if (sx <= 0.1) flag = 0;
if (flag == 0)
{
sx *= 1.01, sy *= 1.01;
}
if(flag==1)
{
sx *= 0.99, sy *=0.99;
}*/
glutPostRedisplay();
}
void display(void)
{
glClearColor(1, 1, 1, 1);//设置清屏颜色
glClear(GL_COLOR_BUFFER_BIT);//刷新颜色缓存区
glColor3f(0, 0, 0); //设置黑色绘图颜色
glMatrixMode(GL_MODELVIEW);//设置矩阵模式为模型变换模式,表示在世界坐标系下
glLoadIdentity();//将当前矩阵设置为单位矩阵
glTranslatef(-0.5, -0.5, 0);//平移回原点
glScalef(0.5, 0.5, 1);//绕原点水平缩放系数Sx,垂直缩放系数Sy
//glTranslatef(0.5, 0.5, 0);//平移回去
//glTranslatef(0.5, 0.5, 0);//平移
//glRotatef(45, 0, 0, 1);//绕z轴旋转45°
//glScalef(0.5, 0.5, 0);//缩小
//glRotatef(theta, 0, 0, 1);//绕z轴不停旋转
//glScalef(sx, sy, 0);//放大
glRectf(-0.5, -0.5,0.5,0.5);//矩形
/*glBegin(GL_POLYGON); //六边形
for (int i = 0; i < n; i++)
glVertex2f(R*cos(i * 2 * PI / n), R*sin(i * 2 * PI / n));
glEnd();
*/
/*
glColor3f(1, 0, 0); //画小红旗
glBegin(GL_LINES);
glVertex2f(0, 0);
glVertex2f(0, 0.7);
glEnd();
glBegin(GL_TRIANGLES);
glVertex2f(0, 0.8);
glVertex2f(0.4, 0.8);
glVertex2f(0, 0.5);
glEnd();
*/
glFlush();//刷新命令队列和缓存区,使所有尚未执行的OpenGL命令得到执行
}
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
char *argv[] = { "hello "," " };
int argc = 2;
glutInit(&argc, argv); //初始化GLUT库;
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); //设置显示模式;(缓冲,颜色类型)
glutInitWindowSize(300, 300);//绘制窗口大小
glutInitWindowPosition(1024 / 2 - 250, 768 / 2 - 250);//窗口左上角在屏幕的位置
glutCreateWindow("hello"); //创建窗口,标题为“hello”;
glutDisplayFunc(display); //显示回调函数用于绘制当前窗口;
glutIdleFunc(myidle);
glutMainLoop(); //表示开始运行程序,用于程序的结尾;
return 0;
}