实验6—2D图形变换

一、实验目的

1.了解和掌握2D图形变换:学会使用OpenGL平移、旋转和比例缩放函数,掌握基本图形变换和复合图形变换实现的方法。
2.综合应用2D图形变换函数、人机交互函数,设计2D交互图形程序。

二、实验内容

要求使用OpenGL几何变换函数改写代码。
1)使用glTranslatef()函数,实现2D图形平移,可以改写实验二的矩形交互移动程序,如下图所示。
a)平移前
在这里插入图片描述

a)平移后
在这里插入图片描述
核心代码:

void Display(void)
{
    
    
    glClear(GL_COLOR_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glTranslatef(tx,ty,0);
	glColor3f(1.0f, 1.0f, 1.0f);
    glBegin(GL_POLYGON);
	glVertex2f( -0.5, -0.5 );
	glVertex2f( -0.5, 0.5 );
	glVertex2f( 0.5, 0.5 );
	glVertex2f( 0.5, -0.5 );
	glEnd();
	glutSwapBuffers();
}

2)使用glRotatef()函数,实现2D图形绕平面固定点旋转,可以改写实验三的六边形旋转程序。如下图所示:

在这里插入图片描述
在这里插入图片描述

三、参考函数

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) = (l, 0, 0 )代表沿x轴方向旋转;(x,y,z) = (O, 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); glLoadldentity();	//设置矩阵模式为模型变换模式,表示在世界坐标系下.
glLoadIdentity();					 //将当前矩阵设置为单位矩阵
glTranslatef(cx,cy,0);		//平移回去
glRotatef(ALPHA,0,0,1);     //绕原点旋转ALPHA角度
glTranslatef(-cx,-cy,0);      //平移回原点
 DrawSomeShape ();	
//刷新

3.某图形绕任意点(ex, cy)缩放Sx、Sy比例因子。

//清屏
glMatrixMode(GL_MODELVIEW); //设置矩阵模式为模型变换模式,表示在世界坐标系下
glLoadldentity();	 //将当前矩阵设置为单位矩阵
glTranslatef(cx,cy,0);//平移回去
 glScalef(Sx,Sy,1);	//绕原点水平缩放系数Sx,垂直缩放系数Sy
glTranslatef(-cx,-cy,0);	//平移回原点
DrawSomeShape(); 
//刷新

核心代码:

void Display(void)
{
    
    
    glClear(GL_COLOR_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glTranslatef(tx,ty,0);
	glColor3f(1.0f, 1.0f, 1.0f);
    glBegin(GL_POLYGON);
	glVertex2f( -0.5, -0.5 );
	glVertex2f( -0.5, 0.5 );
	glVertex2f( 0.5, 0.5 );
	glVertex2f( 0.5, -0.5 );
	glEnd();
	glutSwapBuffers();
}

2)使用glRotatef()函数,实现2D图形绕平面固定点旋转,可以改写实验三的六边形旋
转程序。如下图所示:
a)旋转前:
在这里插入图片描述
b)旋转后
在这里插入图片描述
核心代码:

void Display(void)
{
    
    
    glClear(GL_COLOR_BUFFER_BIT);                    //清屏
    glMatrixMode(GL_MODELVIEW);                      //设置矩阵模式为模型变换模式,表示在世界坐标下
    glLoadIdentity();                                //将当前矩阵设置为单位矩阵
    glTranslatef(cx, cy, 0);                         //平移回去
    glRotatef(theta, 0, 0, 1);                       //绕原点旋转theta角度
    glTranslatef(-cx, -cy, 0);                       //平移回原点
    glColor3f(1.0f, 0.0f, 0.0f);                     //设置红色绘图颜色
    glBegin(GL_POLYGON);                             //开始绘制六边形 
    for (int i = 0; i < n; i++)
        glVertex2f(R * cos(theta + i * 2 * PI / n), R * sin(theta + i * 2 * PI / n));  //顶点坐标 
    glEnd();
    glutSwapBuffers();              //双缓存的刷新模式
}
void myidle()
{
    
    
theta += 1.0 ;                     //旋转角增加1° 
    if (theta >= 360) theta -= 360;    //旋转角复位
    glutPostRedisplay();   
}

3)使用glScalef()函数,实现绕固定点缩放2D图形,在前面程序基础上设计修改。如下图所示:
a)缩放前
在这里插入图片描述

b)锁放后
在这里插入图片描述
核心代码:

void Display(void)
{
    
    
    glClear(GL_COLOR_BUFFER_BIT);                    //清屏
    glMatrixMode(GL_MODELVIEW);                      //设置矩阵模式为模型变换模式,表示在世界坐标下
    glLoadIdentity();                                //将当前矩阵设置为单位矩阵
    glTranslatef(cx, cy, 0);                         //平移回去
    glRotatef(theta, 0, 0, 1);                       //绕原点旋转theta角度
    glScalef(sx, sy, 1);                             //比例缩放变换
    glTranslatef(-cx, -cy, 0);                       //平移回原点
    glColor3f(1.0f, 0.0f, 0.0f);                     //设置红色绘图颜色
    glBegin(GL_POLYGON);                             //开始绘制六边形 
    for (int i = 0; i < n; i++)
        //glVertex2f(R * cos(theta + i * 2 * PI / n), R * sin(theta + i * 2 * PI / n));  //顶点坐标 
        glVertex2f(R * cos(i * 2 * PI / n), R * sin(i * 2 * PI / n));  //顶点坐标 
    glEnd();
    glutSwapBuffers();              //双缓存的刷新模式
}
void myidle()
{
    
    
theta += 0.2;                     //旋转角度增量 
    if (theta >= 360) theta -= 360;    //旋转角复位(旋转角大于360°时减去360°)
    //比例因子放大一个增量
    sx = sx * 0.999;
    sy = sy * 0.999;
    if (sx > 3)      sx = 1;
    if (sy > 3)      sy = 1;
    glutPostRedisplay(); 
}

4)修改代码,使得一面带杆小三角红旗沿着杆底不断旋转。如下图所示:
a)旋转的小红旗
在这里插入图片描述
核心代码:

void Display(void)
{
    
    
    glClear(GL_COLOR_BUFFER_BIT);                    //清屏
    glMatrixMode(GL_MODELVIEW);                      //设置矩阵模式为模型变换模式,表示在世界坐标下
    glLoadIdentity();                                //将当前矩阵设置为单位矩阵
    glTranslatef(cx, cy, 0);                         //平移回去
    glRotatef(theta, 0, 0, 1);                       //绕原点旋转theta角度
    glTranslatef(-cx, -cy, 0);                       //平移回原点
    
    //旗杆
    glColor3f(1.0f, 1.0f, 1.0f);                     //设置白色色绘图颜色
    glBegin(GL_LINES);                             
    glVertex2f(0.0f,0.0f);                          
    glVertex2f(0.0f, R);
    glEnd();

    //旗帜
    glColor3f(1.0f, 0.0f, 0.0f);                     //设置红色绘图颜色
    glBegin(GL_POLYGON);  
    glVertex2f(0.0f, R);
    glVertex2f(0.0f, R-n);
    glVertex2f(n , R);
    glEnd();
    glutSwapBuffers();              //双缓存的刷新模式
}
void myidle()
{
    
    
theta += 0.2;                     //旋转角度增量 
    if (theta >= 360) theta -= 360;    //旋转角复位(旋转角大于360°时减去360°)
    glutPostRedisplay();
}

5)正六边形边旋转边放大,放大到接近整个显示屏后再不停缩小,如此反复。如下图:
a)初始态
在这里插入图片描述

b)放大到
在这里插入图片描述

c)缩小到
在这里插入图片描述
核心代码:

void Display(void)
{
    
    
    glClear(GL_COLOR_BUFFER_BIT);                    //清屏
    glMatrixMode(GL_MODELVIEW);                      //设置矩阵模式为模型变换模式,表示在世界坐标下
    glLoadIdentity();                                //将当前矩阵设置为单位矩阵
    glTranslatef(cx, cy, 0);                         //平移回去
    glRotatef(theta, 0, 0, 1);                       //绕原点旋转theta角度
    glScalef(sx, sy, 1);                             
    glTranslatef(-cx, -cy, 0);                       //平移回原点
    glColor3f(1.0f, 0.0f, 0.0f);                     //设置红色绘图颜色
    glBegin(GL_POLYGON);                             //开始绘制六边形 
    for (int i = 0; i < n; i++)
        //glVertex2f(R * cos(theta + i * 2 * PI / n), R * sin(theta + i * 2 * PI / n));  //顶点坐标 
        glVertex2f(R * cos(i * 2 * PI / n), R * sin(i * 2 * PI / n));  //顶点坐标 
    glEnd();
    glutSwapBuffers();              

}
bool k=true;
void myidle()
{
    
    
theta += 0.2;                     //旋转角度增量 
    if (theta >= 360) theta -= 360;    //旋转角复位(旋转角大于360°时减去360°)
    //比例因子放大一个增量
    if (!k) {
    
    
        sx = sx * 0.99;
        sy = sy * 0.99;
    }
    else {
    
    
        sx = sx * 1.01;
        sy = sy * 1.01;
    }
    if (sx > 1.5 & sy > 1.5)    k = false;
    if(sx < 0.3 & sy < 0.3)     k = true;
    glutPostRedisplay(); 
}

五、思考题

1.绕某个固定点旋转时,代码的顺序改写为:

glTranslatef(-cx,-cy,0); //平移回原点
glRotatef(ALPHA,0,0,1); //绕原点旋转ALPHA角度
glTranslatef(cx,cy,0); //平移回去

图形将变成怎样?
答:图形将绕(-cx,-cy)进行旋转。
2.绕某个固定点进行比例缩放时,代码的顺序改写为:

glTranslatef(-cx,-cy,0); //平移回原点
glScalef(Sx,Sy,0); //绕原点水平缩放系数Sx,垂直缩放系数Sy
glTranslatef(cx,cy,0); //平移回去

图形将变成怎样?
答:图形将以(-cx,-cy)为中心进行比例放缩。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_52030647/article/details/130728432