1. 程式人生 > >實驗六 2D圖形變換

實驗六 2D圖形變換

一、實驗目的

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 旋轉的小紅旗

  1. 正六邊形邊旋轉邊放大,放大到接近整個顯示屏後再不停縮小,如此往復。

        

三、參考函式

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<glut.h>
#include<stdio.h>
#include<windows.h>
#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;
}