天天看點

圖形學實驗(2)--OpenGL 入門圖形幾何變換及裁剪真實感圖形繪制互動技術與計算機動畫

文章目錄

  • 圖形幾何變換及裁剪
    • 圖形的幾何變換
    • 掌握OpenGL中三維觀察、透視投影、正交投影的參數設定。
    • 線段裁剪的Cohen-Sutherland算法
    • 定義裁剪平面對網狀球體裁剪
  • 真實感圖形繪制
    • 1.了解程式架構
    • 2.産生一個三維物體,進行消隐處理
    • 3.移動光源
    • 4.一維紋理映射,畫彩虹
  • 互動技術與計算機動畫
    • 繪制折線
    • 繪制矩形
    • 模型函數繪制示例(菜單)
    • 動畫:日地月模型

圖形幾何變換及裁剪

圖形的幾何變換

  • 把模型矩陣複位,

    即通過給模型視圖矩陣加載上機關矩陣來複位原點。下面的代碼把機關矩陣加載到模型視圖矩陣中:

    glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();

    第一個函數用于指定目前操作的矩陣,其函數原型如下:

    glMatrixMode(GLenum mode);

    其中參數mode 用于确定将哪個矩陣堆棧用于矩陣操作,它的取值有:GL_MODELVIEW

    (模型視圖矩陣堆棧),GL_PROJECTION(投影矩陣堆棧)和GL_TEXTURE(紋理矩陣堆

    棧)。一旦設定了目前操作矩陣,它就将保持為活動的矩陣,直到你修改它為止。

    第二個函數作用就是給目前操作矩陣加載上機關矩陣,。

#include<GL/glut.h>

//初始化視窗
void Initial();

void ChangeSize(int w, int h);

void Display();

//繪制三角形
void DrawTriangle();

int main(int argc, char* argv[])
{
	//初始化工具包
	glutInit(&argc, argv);
	//設定顯示模式
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
	//視窗設定
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(400, 400);
	glutCreateWindow("1812030065-李詩雨");
	//調用繪圖函數,回調函數,不斷監聽
	glutReshapeFunc(ChangeSize);
	glutDisplayFunc(Display);

	Initial();//必要的其他初始化函數
	glutMainLoop();//進入循環
	return 0;
}
void Initial(void)
{
	//設定視窗背景色
	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
}

void DrawTriangle(void)
{
	glBegin(GL_TRIANGLES);
	glVertex2f(0.0f, 0.0f);
	glVertex2f(40.0f, 0.0f);
	glVertex2f(20.0f, 40.0f);
	glEnd();
}

void ChangeSize(int w, int h)
{
	if (h == 0) h = 1;
	glViewport(0, 0, w, h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	if (w <= h)
		glOrtho(-120.0f, 120.0f, -120.0f * h / w, 120.0f * h / w, -120.0f, 120.0f);
	else
		glOrtho(-120.0f * w / h, 120.0f * w / h, -120.0f, 120.0f, -120.0f, 120.0f);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

void Display(void)
{
	glClear(GL_COLOR_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	
	//繪制黑色坐标軸
	glColor3f(0.0f, 0.0f, 0.0f);
	//不裁剪視窗的話,螢幕的坐标位于視窗中心
	glBegin(GL_LINES);
	glVertex2f(-120.0f, 0.0f);
	glVertex2f(120.0f, 0.0f);
	glVertex2f(0.0f, -120.0f);
	glVertex2f(0.0f, 120.0f);
	glEnd();

	//繪制紅色的三角形
	glColor3f(1.0f, 0.0, 0.0f);
	DrawTriangle();

	//畫一個逆時針旋轉200度的綠色三角形
	  //第一個參數表示逆時針旋轉的度數,後三個參數指定旋轉的矢量坐标
	glRotatef(200.0f, 0.0f, 0.0f, 1.0f);//以z軸為旋轉軸(垂直螢幕方向),旋轉的是坐标系
	glColor3f(0.0f, 1.0f, 0.0f);
	DrawTriangle();

	//畫沿着x軸負向平移80的黃色三角形
	  //因為旋轉的是坐标系,是以經過一次旋轉之後要重置一下
	glLoadIdentity();
	glTranslatef(-80.0f, 0.0f, 0.0f);
	glColor3f(1.0, 1.0f, 0.0f);
	DrawTriangle();

	//畫出沿x軸對稱,沿x軸正向平移10,沿y軸負向平移10,縮放因子為 1.5,2.0,1.0的藍色三角形
	glLoadIdentity();
	glTranslatef(10.0f, -10.0f, 0.0f);
	glRotatef(180.0f, 1.0f, 0.0f, 0.0f);
	glScalef(1.5f, 2.0f, 1.0f);
	glColor3f(0.0f, 0.0f, 1.0f);
	DrawTriangle();

	glFlush();
}
           
圖形學實驗(2)--OpenGL 入門圖形幾何變換及裁剪真實感圖形繪制互動技術與計算機動畫

掌握OpenGL中三維觀察、透視投影、正交投影的參數設定。

  • 關于幾何變換抵消坐标積累變換的方法

    glPushMatrix 變換 glPopMatrix 這個可以了解為把目前坐标狀态(未作變換的)入棧,經過變換後坐标狀态(未作變換的)出棧

    具體參考glPushMatrix ,glPopMatrix 的了解

  • 定義視景轉換

    視點中心由eye[]控制,場景中心由center[]控制,y軸向上

    gluLookAt(eye[0], eye[1], eye[2], center[0], center[1], center[2], 0, 1, 0);

    函數原型

    void gluLookAt(GLdouble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble centerz,GLdouble upx,GLdouble upy,GLdouble upz);

    該函數定義一個視圖矩陣,并與目前矩陣相乘。

    第一組eyex, eyey,eyez 相機在世界坐标的位置

    第二組centerx,centery,centerz 相機鏡頭對準的物體在世界坐标的位置

    第三組upx,upy,upz 相機向上的方向在世界坐标中的方向

    你把相機想象成為你自己的腦袋:

    第一組資料就是腦袋的位置

    第二組資料就是眼睛看的物體的位置

    第三組就是頭頂朝向的方向(因為你可以歪着頭看同一個物體)

    如果我們向前或向後移動,則相應的圖像會變大或變小,這裡其實就是運用了透視原理,近處的物體大,遠處的物體小,實際物體的大小是不變的,

    同理改變center坐标(眼睛看去的那個點,可簡單了解為視線的終點)也會影響球的大小,同樣可以認為是改變了物體與觀察點的距離所緻。

    gluLookAt函數詳解

  • gluPerspective 透視投影 gluperspective詳解
  • glortho 建立一個正交平行的視景體(正投影),詳解

關于裡面的旋轉不懂。。。

#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("1812030065-李詩雨");
	//全局回調函數,不斷監聽
	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();
}
           

線段裁剪的Cohen-Sutherland算法

#include<stdio.h>
#include<stdlib.h>
#include<GL/glut.h>

#define LEFT_EDGE 1
#define RIGHT_EDGE 2
#define BOTTOM_EDGE 4
#define TOP_EDGE 8

void LineGL(int x0, int y0, int x1, int y1)
{
	glBegin(GL_LINES);
	glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(x0, y0);
	glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(x1, y1);
	glEnd();
}
//螢幕rect
struct Rectangle_
{
	float xmin, xmax, ymax, ymin;
};
Rectangle_ rect;

void Init();
void Reshape(int w, int h);
void keyboard(unsigned char key, int x, int y);
//繪制螢幕和未裁剪的直線段
void myDisplay();

int x0, y0, x1, y1;//直線段兩端頂點坐标
//給點編碼,D3D2D1D0,如果x小于rect.xmin,則D0=1否則為0,編碼從右往左,比較順序:左右下上
int CompCode(int x, int y, Rectangle_ rect);
//Cohen Sutherland 裁剪算法,畫出裁剪後的線段
int cohensutherlandlineclip(Rectangle_ rect, int& x0, int& y0, int& x1, int& y1);



int main(int argc, char* argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(640, 480);
	glutCreateWindow("1812030065李詩雨");
	Init();
	glutDisplayFunc(myDisplay);
	glutReshapeFunc(Reshape);
	glutKeyboardFunc(keyboard);
	glutMainLoop();
	return 0;
}

void Init()
{
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glShadeModel(GL_FLAT);
	rect.xmin = 100;
	rect.xmax = 300;
	rect.ymin = 100;
	rect.ymax = 300;
	x0 = 450, y0 = 0, x1 = 0, y1 = 450;
	printf("Press key 'c' to Clip!\nPress key 'r' to Restore!\n");
}
void myDisplay()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(1.0f, 0.0f, 0.0f);
	glRectf(rect.xmin, rect.ymin, rect.xmax, rect.ymax);
	//繪制未裁剪的直線段
	LineGL(x0, y0, x1, y1);
	glFlush();
}
void Reshape(int w, int h)
{
	glViewport(0, 0, (GLsizei)w, (GLsizei)h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0.0, (GLdouble)w, 0.0, (GLdouble)h);
}
void keyboard(unsigned char key, int x, int y)
{
	switch (key)
	{
	case 'c'://Cohen Sutherland 裁剪
		cohensutherlandlineclip(rect, x0, y0, x1, y1);
		glutPostRedisplay();
		break;
	case 'r'://恢複
		Init();
		glutPostRedisplay();
		break;
	case 'x':
		exit(0);
		break;
	default:
		break;
	}
}

int CompCode(int x, int y, Rectangle_ rect)
{
	//二進制或運算 把符合條件的的位編碼置1
	int code = 0;
	if (y < rect.ymin)
		code = code | 4;
	if (y > rect.ymax)
		code = code | 8;
	if (x > rect.xmax)
		code = code | 2;
	if (x < rect.xmin)
		code = code | 1;
	return code;
}
int cohensutherlandlineclip(Rectangle_ rect, int& x0, int& y0, int& x1, int& y1)
{
	int accept, done;
	float x, y;
	accept = 0;//=1表示取得裁剪範圍内的線段
	done = 0;//=1表示裁剪完畢
	//給直線的兩個頂點編碼
	int code0, code1, codeout;
	code0 = CompCode(x0, y0, rect);
	code1 = CompCode(x1, y1, rect);
	//隻要沒裁剪完就繼續求交裁剪
	do
	{
		if (!(code0 | code1))
		{//簡取
			accept = 1;
			done = 1;
		}
		else if (code0 & code1)
		{//簡棄
			done = 1;
		}
		else
		{
			//選擇一個不在裁剪範圍内的頂點,把編碼賦給codeout
			if (code0 != 0)
				codeout = code0;
			else
				codeout = code1;
			//根據codeout和邊界按位&的結果來确定直線跟那條邊界相交并求交點
			if (codeout & LEFT_EDGE)
			{
				y = y0 + (y1 - y0) * (rect.xmin - x0) / (x1 - x0);
				x = (float)rect.xmin;
			}
			else if (codeout & RIGHT_EDGE)
			{
				y = y0 + (y1 - y0) * (rect.xmax - x0) / (x1 - x0);
				x = (float)rect.xmax;
			}
			else if (codeout & BOTTOM_EDGE)
			{
				x = x0 + (x1 - x0) * (rect.ymin - y0) / (y1 - y0);
				y = (float)rect.ymin;
			}
			else if (codeout & TOP_EDGE)
			{
				x = x0 + (x1 - x0) * (rect.ymax - y0) / (y1 - y0);
				y = (float)rect.ymax;
			}

			//把跟邊界的交點編碼
			if (codeout == code0)
			{
				x0 = x; y0 = y;
				code0 = CompCode(x0, y0, rect);
			}
			else {
				x1 = x; y1 = y;
				code1 = CompCode(x1, y1, rect);
			}
		}
	} while (!done);
	//如果裁剪範圍内有線段,就畫出來
	if (accept)
		LineGL(x0, y0, x1, y1);
	return accept;
}
           

定義裁剪平面對網狀球體裁剪

#include <GL\glut.h>

// 旋轉參數 
static GLfloat xRot = 0.0f;
static GLfloat yRot = 0.0f;

void Initial(void);
void ChangeSize(GLsizei w, GLsizei h);

// 在視窗中繪制圖形 
void Display(void);
void SpecialKeys(int key, int x, int y);

int main(int argc, char* argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(400, 400);
	glutCreateWindow("1812030065李詩雨");
	glutDisplayFunc(Display);  
	glutSpecialFunc(SpecialKeys);
	glutReshapeFunc(ChangeSize);
	Initial();
	glutMainLoop();
	return 0;
}

void Initial(void)
{
	glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
	glShadeModel(GL_FLAT);
}

void ChangeSize(GLsizei w, GLsizei h)
{
	if (h == 0)  h = 1;
	// 設定視區尺寸     
	glViewport(0, 0, w, h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	// 建立修剪空間的範圍    
	gluPerspective(60.0f, (GLfloat)w / (GLfloat)h, 1.0f, 20.0f);

	glMatrixMode(GL_MODELVIEW);
}

void Display(void)
{
	//定義裁減平面方程系數
	GLdouble eqn[4] = { 1.0, 1.0, 0.0, 1.0 };
	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(1.0f, 0.0f, 0.0f);
	glPushMatrix();

	//沿 z 軸負向平移一段距離,保證良好的觀察效果    
	glTranslatef(0.0, 0.0, -5.0);
	//設定裁減平面    
	glClipPlane(GL_CLIP_PLANE0, eqn);
	glEnable(GL_CLIP_PLANE0);
	//使球體旋轉  
	glRotatef(xRot, 1.0f, 0.0f, 0.0f);
	glRotatef(yRot, 0.0f, 1.0f, 0.0f);
	glutWireSphere(2.0f, 20, 20);
	glPopMatrix();
	glFlush();
}

void SpecialKeys(int key, int x, int y)
{
	if (key == GLUT_KEY_UP)  xRot -= 5.0f;
	if (key == GLUT_KEY_DOWN) xRot += 5.0f;
	if (key == GLUT_KEY_LEFT) yRot -= 5.0f;
	if (key == GLUT_KEY_RIGHT) yRot += 5.0f;

	if (xRot > 356.0f) xRot = 0.0f;
	if (xRot < -1.0f) xRot = 355.0f;
	if (yRot > 356.0f) yRot = 0.0f;
	if (yRot < -1.0f) yRot = 355.0f;

	glutPostRedisplay();
}
           
圖形學實驗(2)--OpenGL 入門圖形幾何變換及裁剪真實感圖形繪制互動技術與計算機動畫

真實感圖形繪制

1.了解程式架構

體會遮擋關系

#include<GL/glut.h>

enum{FILL,WIRE};
enum{SPHERE=1,CONE,WALLS};
int rendermode = FILL;
GLUquadricObj* sphere, * cone, * base;

static GLfloat lightpos[] = { 50.f,50.f,-320.f,1.f };
static GLfloat wall_mat[] = { 0.8f,0.8f,0.8f,1.f };
static GLfloat sphere_mat[] = { 1.0f,0.2f,0.2f,1.f };
static GLfloat cone_mat[] = { 0.2f,1.0f,0.2f,1.f };

void Initial();
void Display();
void menu(int );
void drawscene();

int main(int argc, char** argv) {
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);

	glutInitWindowPosition(100, 100);
	glutInitWindowSize(500, 500);
	glutCreateWindow("Wireframe and ZBuffer 1812030065-李詩雨");
	glutDisplayFunc(Display);

	glutCreateMenu(menu);
	glutAddMenuEntry("Solid Fill", FILL);//把FILL這個位置的參數傳入到menu函數中
	glutAddMenuEntry("Wireframe", WIRE);
	glutAttachMenu(GLUT_RIGHT_BUTTON);//按右鍵顯示菜單


	Initial();//必要的其他初始化函數
	glutMainLoop();//進入循環
	return 0;
}
void Initial() {
	glMatrixMode(GL_PROJECTION);
	glFrustum(-100.0, 100.0, -100.0, 100.0, 320.0, 640.0);//透視顯示:左右下上近遠
	glMatrixMode(GL_MODELVIEW);

	glEnable(GL_DEPTH_TEST);//打開深度緩沖設定
	glDepthFunc(GL_LEQUAL);//判斷遮擋關系時,離視點近的遮擋離視點遠的物體。GL-NEVER不判斷,GL_ALWAYS,GL_LESS,GL_LEQUAL
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

	glLightfv(GL_LIGHT0, GL_POSITION, lightpos);

	glNewList(SPHERE, GL_COMPILE);
	sphere = gluNewQuadric();//建立一個對象
	glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, sphere_mat);
	gluSphere(sphere, 50.f, 40, 40);//讓該對象畫球,參數:球體,半徑,經度分割線,緯度分割線
	gluDeleteQuadric(sphere);//釋放對象
	glEndList();

	glNewList(CONE, GL_COMPILE);
	cone = gluNewQuadric();
	base = gluNewQuadric();
	glPushMatrix();
	glRotatef(-90.f, 1.f, 0.f, 0.f);
	glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cone_mat);
	gluQuadricOrientation(base, GLU_INSIDE);
	gluDisk(base, 0., 40., 20, 1);//碟盤(圓錐的底,如果畫圓柱需要兩個底)參數:對象,内環半徑,外環半徑,分割線,同心圓線
	gluCylinder(cone, 40., 0., 120., 20, 20);//圓錐,參數:對象,下半徑,上半徑,高,經度分割線,緯度分割線
	glPopMatrix();
	gluDeleteQuadric(cone);
	gluDeleteQuadric(base);
	glEndList();

	//WALLS
	glNewList(WALLS,GL_COMPILE);
	glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, wall_mat);

	glBegin(GL_QUADS);
	glNormal3f(0.f, 1.f, 0.f);
	glVertex3f(-100.f, -100.f, -320.f);
	glVertex3f(100.f, -100.f, -320.f);
	glVertex3f(100.f, -100.f, -520.f);
	glVertex3f(-100.f, -100.f, -520.f);

	//left wall
	glNormal3f(1.f, 0.f, 0.f);
	glVertex3f(-100.f, -100.f, -320.f);
	glVertex3f(-100.f, -100.f, -520.f);
	glVertex3f(-100.f, 100.f, -520.f);
	glVertex3f(-100.f, 100.f, -320.f);
	//right wall
	glNormal3f(-1.f, 0.f, 0.f);
	glVertex3f(100.f, -100.f, -320.f);
	glVertex3f(100.f, 100.f, -320.f);
	glVertex3f(100.f, 100.f, -520.f);
	glVertex3f(100.f, -100.f, -520.f);
	//ceiling
	glNormal3f(0.f, -1.f, 0.f);
	glVertex3f(-100.f, 100.f, -320.f);
	glVertex3f(-100.f, 100.f, -520.f);
	glVertex3f(100.f, 100.f, -520.f);
	glVertex3f(100.f, 100.f, -320.f);
	//back wall
	glNormal3f(0.f, 0.f, 1.f);
	glVertex3f(-100.f, -100.f, -520.f);
	glVertex3f(100.f, -100.f, -520.f);
	glVertex3f(100.f, 100.f, -520.f);
	glVertex3f(-100.f, 100.f, -520.f);
	glEnd();
	glEndList();
}

void menu(int selection) {
	rendermode = selection;
	glutPostRedisplay();
}

void drawscene() {
	glCallList(WALLS);
	glPushMatrix();
	glTranslatef(-20.f, -40.f, -400.f);
	glCallList(SPHERE);
	glPopMatrix();

	glPushMatrix();
	glTranslatef(40.f, -100.f, -420.f);
	glCallList(CONE);
	glPopMatrix();

	glPushMatrix();
	glTranslatef(-40.f, -40.f, -400.f);
	glCallList(CONE);
	glPopMatrix();
}

void Display() {
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	switch (rendermode)
	{
	case FILL:
		drawscene(); break;
	case WIRE:
		glDisable(GL_LIGHTING);
		glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);//GL_POINTS,GL_FILL
		glColor4f(0.0, 0.0, 0.0, 1.0);
		drawscene();
		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
		glEnable(GL_LIGHTING);
		break;

	default:
		break;
	}
	glFlush();
}

           
圖形學實驗(2)--OpenGL 入門圖形幾何變換及裁剪真實感圖形繪制互動技術與計算機動畫

2.産生一個三維物體,進行消隐處理

#include<GL/glut.h>
static GLfloat xRot = 0.0f;
static GLfloat yRot = 0.0f;
void RenderScene() {
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
	glEnable(GL_DEPTH_TEST);//深度測試
	glDepthFunc(GL_LEQUAL);
	glPushMatrix();
	glRotatef(xRot, 1.0f, 0.0f, 0.0f);
	glRotatef(yRot, 0.0f, 1.0f, 0.0f);

	glBegin(GL_QUADS);
	glColor3f(1.0, 0.0, 0.0);//red
	glVertex3f(10.0f, 10.0f, 10.0f);//上面
	glVertex3f(-10.0f, 10.0f, 10.0f);
	glVertex3f(-10.0f, -10.0f, 10.0f);
	glVertex3f(10.0f, -10.0f, 10.0f);

	glColor3f(0.0, 1.0, 0.0);//green
	glVertex3f(10.0f, 10.0f, -10.0f);//右面
	glVertex3f(10.0f, 10.0f, 10.0f);
	glVertex3f(10.0f, -10.0f, 10.0f);
	glVertex3f(10.0f, -10.0f, -10.0f);


	glColor3f(0.0, 0.0, 1.0);//blue
	glVertex3f(10.0f, -10.0f, -10.0f);//下面
	glVertex3f(-10.0f, -10.0f, -10.0f);
	glVertex3f(-10.0f, 10.0f, -10.0f);
	glVertex3f(10.0f, 10.0f, -10.0f);


	glColor3f(1.0, 1.0, 0.0);//yellow
	glVertex3f(-10.0f, 10.0f, 10.0f);//left
	glVertex3f(-10.0f, 10.0f, -10.0f);
	glVertex3f(-10.0f, -10.0f, -10.0f);
	glVertex3f(-10.0f, -10.0f, 10.0f);

	glColor3f(0.0, 1.0, 1.0);
	glVertex3f(10.0f, 10.0f, -10.0f);//back
	glVertex3f(-10.0f, 10.0f, -10.0f);
	glVertex3f(-10.0f, 10.0f, 10.0f);
	glVertex3f(10.0f, 10.0f, 10.0f);

	glColor3f(1.0, 0.0, 1.0);
	glVertex3f(10.0f, -10.0f, 10.0f);//front
	glVertex3f(-10.0f, -10.0f, 10.0f);
	glVertex3f(-10.0f, -10.0f, -10.0f);
	glVertex3f(10.0f, -10.0f, -10.0f);
	glEnd();
	glPopMatrix();
	glutSwapBuffers();
}

void Init() {
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
	glColor3f(0.0f, 1.0f, 0.0f);
	glShadeModel(GL_FLAT);
	glFrontFace(GL_CW);

}

void SpecialKeys(int key, int x, int y) {
	if (key == GLUT_KEY_UP)
		xRot -= 5.0f;
	if (key == GLUT_KEY_DOWN)
		xRot += 5.0f;
	if (key == GLUT_KEY_RIGHT)
		yRot -= 5.0f;
	if (key == GLUT_KEY_LEFT)
		yRot += 5.0f;
	if (key > 356.0f)
		xRot = 0.0f;
	if (key < -1.0f)
		xRot = 355.0f;
	if (key > 356.0f)
		yRot = 0.0f;
	if (key < -1.0f)
		yRot = 355.0f;
	glutPostRedisplay();
}

void ChangeSize(int w, int h)
{
	GLfloat nRange = 30.0f;
	if (h == 0) h = 1;
	glViewport(0, 0, w, h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	if (w <= h)
		glOrtho(-nRange, nRange, -nRange * h / w, nRange * h / w, -nRange, nRange);
	else
		glOrtho(-nRange * w / h, nRange * w / h, -nRange, nRange, -nRange, nRange);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

int main(int argc, char* argv[])
{
	//初始化工具包
	glutInit(&argc, argv);
	//設定顯示模式
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB|GLUT_DEPTH);
	//視窗設定
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(400, 400);
	glutCreateWindow("cube 1812030065-李詩雨");
	//調用繪圖函數,回調函數,不斷監聽
	glutReshapeFunc(ChangeSize);
	glutSpecialFunc(SpecialKeys);
	glutDisplayFunc(RenderScene);

	Init();//必要的其他初始化函數
	glutMainLoop();//進入循環
	return 0;
}


           
圖形學實驗(2)--OpenGL 入門圖形幾何變換及裁剪真實感圖形繪制互動技術與計算機動畫
圖形學實驗(2)--OpenGL 入門圖形幾何變換及裁剪真實感圖形繪制互動技術與計算機動畫

3.移動光源

#include<GL/glut.h>
static GLfloat xRot = 0.0f;
static GLfloat yRot = 0.0f;
static GLfloat xRot1 = 0.0f;
static GLfloat yRot1 = 0.0f;

void Initial() {
	GLfloat light_diffuse[] = { 1.0,1.0,1.0,1.0 };
	GLfloat light_ambient[] = { 0.0,0.5,0.5,1.0 };
	glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); 
	glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);//設定環境光顔色

	GLfloat light1_diffuse[] = { 1.0,1.0,1.0,1.0 };
	GLfloat light1_ambient[] = { 0.0,0.5,0.5,1.0 };
	glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse); 
	glLightfv(GL_LIGHT1, GL_AMBIENT, light1_ambient);//設定環境光顔色

	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);//啟動光源LIGHT0
	glEnable(GL_LIGHT1);//啟動光源LIGHT1
	glEnable(GL_DEPTH_TEST);//深度測試
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}

void ChangeSize(int w, int h)
{
	if (h == 0) h = 1;
	glViewport(0, 0, w, h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(40.0f, (GLfloat)w / (GLfloat)h, 1.0f, 20.0f);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

void Display() {
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	GLfloat light0_position[] = { 0.0f,0.0f,1.5f,1.0f };//最後一個參數1.0指前面設定的點位置,0.0為無限遠處
	GLfloat light1_position[] = { 0.0f,0.0f,1.5f,1.0f };

	glLoadIdentity();
	glTranslatef(0.0f, 0.0f, -5.0f);
	glRotated(yRot, 0.0f, 1.0f, 0.0f);
	glRotated(xRot, 1.0f, 0.0f, 0.0f);
	//設定光源的位置
	glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
	glTranslatef(0.0f, 0.0f, 1.5f);
	//繪制一個黃色的光球
	glDisable(GL_LIGHTING);
	glColor3f(1.0f, 1.0f, 0.0f);
	glutSolidSphere(0.1f, 50.0f, 50.0f);
	glEnable(GL_LIGHTING);

	glLoadIdentity();
	glTranslatef(0.0f, 0.0f, -5.0f);
	glRotated(yRot1, 0.0f, 1.0f, 0.0f);
	glRotated(xRot1, 1.0f, 0.0f, 0.0f);
	//設定光源的位置
	glLightfv(GL_LIGHT1, GL_POSITION, light1_position);
	glTranslatef(0.0f, 0.0f, 1.5f);
	//繪制一個紅色的光球
	glDisable(GL_LIGHTING);
	glColor3f(1.0f, 0.0f, 0.0f);
	glutSolidSphere(0.1f, 50.0f, 50.0f);
	glEnable(GL_LIGHTING);

	glLoadIdentity();
	//設定材質屬性
	GLfloat mat_diffuse[] = { 0.0f,0.5f,1.0f,1.0f };
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
	glTranslatef(0.0f, 0.0f, -5.0f);

	glutSolidTorus(0.275, 0.85, 50, 50);
	glLoadIdentity();

	glutSwapBuffers();
}

void Keys(unsigned char key, int x, int y) {
	switch (key)
	{
	case 'i':xRot -= 5.0f; break;
	case 'k':xRot += 5.0f; break;
	case 'j':yRot -= 5.0f; break;
	case 'l':yRot += 5.0f; break;

	case 'w':xRot1 -= 5.0f; break;
	case 's':xRot1 += 5.0f; break;
	case 'a':yRot1 -= 5.0f; break;
	case 'd':yRot1 += 5.0f; break;
	default:
		break;
	}

	if (key > 356.0f)
		xRot = 0.0f;
	if (key < -1.0f)
		xRot = 355.0f;
	if (key > 356.0f)
		yRot = 0.0f;
	if (key < -1.0f)
		yRot = 355.0f;

	if (key > 356.0f)
		xRot1 = 0.0f;
	if (key < -1.0f)
		xRot1 = 355.0f;
	if (key > 356.0f)
		yRot1 = 0.0f;
	if (key < -1.0f)
		yRot1 = 355.0f;

	glutPostRedisplay();
}

int main(int argc, char* argv[])
{
	//初始化工具包
	glutInit(&argc, argv);
	//設定顯示模式
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
	//視窗設定
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(400, 400);
	glutCreateWindow("移動光源 1812030065-李詩雨");
	//調用繪圖函數,回調函數,不斷監聽
	glutReshapeFunc(ChangeSize);
	glutDisplayFunc(Display);
	glutKeyboardFunc(Keys);

	Initial();//必要的其他初始化函數
	glutMainLoop();//進入循環
	return 0;
}


           
圖形學實驗(2)--OpenGL 入門圖形幾何變換及裁剪真實感圖形繪制互動技術與計算機動畫

4.一維紋理映射,畫彩虹

#include<GL/glut.h>
#include <math.h>
#ifndef M_pI
#define M_PI 3.141592649
#endif

static GLubyte roygbiv_image[8][3] = {
	{0x3f,0x00,0x3f},//深藍紫色
	{0x7f,0x00,0x7f},//藍紫色
	{0xbf,0x00,0xbf},//靛藍
	{0x00,0x00,0xff},//藍色
	{0x00,0xff,0x00},//綠色
	{0xff,0xff,0x00},//黃色
	{0xff,0x7f,0x00},//橙色
	{0xff,0x00,0x00},//紅色
};

void ChangeSize(int width, int height) {
	glViewport(0, 0, width, height);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(30.0, (float)width / (float)height, 0.1, 1000.0);
	glMatrixMode(GL_MODELVIEW);
}

void Initial() {
	glClearColor(0.3, 0.8, 1.0, 1.0);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	//最基本的執行紋理映射的步驟
	//1.定義紋理,2.控制紋理,3.說明紋理映射的方式,4.繪制場景
	//1.定義紋理
	glTexImage1D(GL_TEXTURE_1D, 0, 3, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, roygbiv_image);
	//2.控制紋理,設定紋理如何對應螢幕像素,實作紋理縮放紋理重複
	glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	//3.說明紋理映射方式
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

	//表示使用最靠近使用紋理像素的四個紋素的權重平均值
	//定義一維紋理,顔色分量為RGB
	//寬度為8,邊界為0,使用無符号整數
	//定義紋理環境參數,使用紋理圖像
}

void Display() {
	GLfloat x, y, z, th;
	//draw ground
	glDisable(GL_TEXTURE_1D);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);

	glPushMatrix();
	glRotatef(10.0f, 0.0f, 1.0f, 0.0f);
	glTranslatef(0.0, -40.0, -100.0);

	glColor3f(0.0, 0.8, 0.0);
	glBegin(GL_POLYGON);
	for (th = 0.0; th < (2.0 * M_PI); th += (0.03125 * M_PI)) {
		x = cos(th) * 200.0;
		z = sin(th) * 200.0;
		glVertex3f(x, 0.0, z);
	}
	glEnd();

	//draw rainbow
	glEnable(GL_TEXTURE_1D);
	glBegin(GL_QUAD_STRIP);//共享四邊形
	for (th = 0.0; th < (2.0 * M_PI); th += (0.03125 * M_PI)) {
		x = cos(th) * 50.0;
		y = sin(th) * 50.0;
		z = -50.0;
		glTexCoord1f(0.0);
		glVertex3f(x, y, z);

		x = cos(th) * 55.0;
		y = sin(th) * 55.0;
		z = -50.0;
		glTexCoord1f(1.0);
		glVertex3f(x, y, z);
	}
	glEnd();
	glPopMatrix();
	glFlush();
}

int main(int argc, char *argv[]) {
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(792, 753);
	glutCreateWindow("rainbow 1812030065-李詩雨");
	//調用繪圖函數,回調函數,不斷監聽
	glutReshapeFunc(ChangeSize);
	glutDisplayFunc(Display);

	Initial();//必要的其他初始化函數
	glutMainLoop();//進入循環
	return 0;
}
           
圖形學實驗(2)--OpenGL 入門圖形幾何變換及裁剪真實感圖形繪制互動技術與計算機動畫

互動技術與計算機動畫

繪制折線

#include<gl/glut.h>
#include <iostream>
using namespace std;
int iPointNum = 0;
int a[100], b[100], w1, h1, w2, h2;
int winwidth = 400, winHeight = 300;
//變量的定義
void Initial() {
	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
}
void ChangeSize(int w, int h) {
	winwidth = w;
	winHeight = h;
	glViewport(0, 0, w, h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0.0, winwidth, 0.0, winHeight);
}

void Display() {
	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(1.0f, 0.0f, 0.0f);
	//繪制折線
	if (iPointNum > 1) {
		glBegin(GL_LINE_STRIP);
		for (int i = 0; i < iPointNum; i++)
			glVertex2i(a[i], b[i]);
		glEnd();

		glBegin(GL_LINES);
		glVertex2i(w1, h1);
		glVertex2i(w2, h2);
		glEnd();
	}
	glutSwapBuffers();
}

void MousePlot(GLint button, GLint action, GLint xMouse, GLint yMouse) {
	//滑鼠函數
	//按下滑鼠左鍵繪制折線
	if (button == GLUT_LEFT_BUTTON && action == GLUT_DOWN) {
		if (iPointNum == 0) {
			w1 = xMouse; h1 = winHeight - yMouse;
			a[iPointNum] = w1; b[iPointNum] = h1;
			iPointNum++;
		}
		else {
			w2 = xMouse; h2 = winHeight - yMouse;
			a[iPointNum] = w2; b[iPointNum] = h2;
			w1 = w2; h1 = h2;
			iPointNum++;
			glutPostRedisplay();
		}
	}
	/*按下滑鼠右鍵結束繪制*/
	if (button == GLUT_RIGHT_BUTTON && action == GLUT_DOWN) {
		iPointNum = 0;
	}
	
}

void PassiveMouseMove(GLint xMouse, GLint yMouse) {
	//滑鼠移動函數
	//記錄滑鼠指針 的目前位置
	if (iPointNum) {
		w2 = xMouse;
		h2 = winHeight - yMouse;
		glutPostRedisplay();
	}
}

int main(int argc, char* argv[]) {
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
	glutInitWindowSize(400, 400);
	glutInitWindowPosition(100, 100);
	glutCreateWindow("橡皮筋技術 181203065 李詩雨");
	glutDisplayFunc(Display);

	glutReshapeFunc(ChangeSize);
	glutMouseFunc(MousePlot);//指定滑鼠響應函數
	glutPassiveMotionFunc(PassiveMouseMove);//指定滑鼠移動響應函數

	Initial();
	glutMainLoop();
	return 0;
}
           

繪制矩形

#include<gl/glut.h>
#include <iostream>
using namespace std;
int iPointNum = 0;
int w1, h1, w2, h2;
int winwidth = 400, winHeight = 300;
//變量的定義
void Initial() {
	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
}
void ChangeSize(int w, int h) {
	winwidth = w;
	winHeight = h;
	glViewport(0, 0, w, h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0.0, winwidth, 0.0, winHeight);
}

void Display() {
	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(1.0f, 0.0f, 0.0f);
	//繪制
	glBegin(GL_LINES);
	glVertex2i(w1, h1);
	glVertex2i(w2, h1);
	glEnd();
	glBegin(GL_LINES);
	glVertex2i(w2, h1);
	glVertex2i(w2, h2);
	glEnd();
	glBegin(GL_LINES);
	glVertex2i(w1, h1);
	glVertex2i(w1, h2);
	glEnd();
	glBegin(GL_LINES);
	glVertex2i(w1, h2);
	glVertex2i(w2, h2);
	glEnd();
	glutSwapBuffers();
}

void MousePlot(GLint button, GLint action, GLint xMouse, GLint yMouse) {
	//滑鼠函數
	//按下滑鼠左鍵繪制
	if (button == GLUT_LEFT_BUTTON && action == GLUT_DOWN) {
		if (iPointNum == 0||iPointNum==2) {
			iPointNum = 1;
			w1 = xMouse; h1 = winHeight - yMouse;
		}
		else {
			w2 = xMouse; h2 = winHeight - yMouse;
			iPointNum = 2;
			glutPostRedisplay();
		}
	}
	
}

void PassiveMouseMove(GLint xMouse, GLint yMouse) {
	//滑鼠移動函數
	//記錄滑鼠指針 的目前位置
	if (iPointNum==1) {
		w2 = xMouse;
		h2 = winHeight - yMouse;
		glutPostRedisplay();
	}
}

int main(int argc, char* argv[]) {
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
	glutInitWindowSize(400, 400);
	glutInitWindowPosition(100, 100);
	glutCreateWindow("橡皮筋技術 181203065 李詩雨");
	glutDisplayFunc(Display);

	glutReshapeFunc(ChangeSize);
	glutMouseFunc(MousePlot);//指定滑鼠響應函數
	glutPassiveMotionFunc(PassiveMouseMove);//指定滑鼠移動響應函數

	Initial();
	glutMainLoop();
	return 0;
}
           

模型函數繪制示例(菜單)

#include <GL/glut.h>

static GLsizei iMode = 1;
//x,y 方向旋轉參數
static GLfloat xRot = 0.0f;
static GLfloat yRot = 0.0f;

void Initial() {
	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
	glColor3f(0.0f, 0.0f, 0.0f);
}

void ChangeSize(int w, int h) {
	glViewport(0, 0, w, h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(-1.5f, 1.5f, -1.5f, 1.5f);
}

void Display() {
	glClear(GL_COLOR_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	//繞x軸旋轉
	//繞y軸旋轉
	glRotatef(xRot, 1.0f, 0.0f, 0.0f);
	glRotatef(yRot, 0.0f, 1.0f, 0.0f);

     /*指定要繪制的圖元*/
	switch (iMode)
	{
	case 1:
		/*繪制線框正四面體*/
		glutWireTetrahedron(); break;
	case 2:
		/*繪制實體正四面體*/
		glutSolidTetrahedron(); break;
	case 3:
		/*繪制線框正八面體*/
		glutWireOctahedron(); break;
	case 4:
		/*繪制實體正八面體*/
		glutSolidOctahedron(); break;
	case 5:
		/*繪制線框球面*/
		glutWireSphere(1.0f,15,15); break;
	case 6:
		/*繪制實體球面*/
		glutSolidSphere(1.0f, 15, 15); break;
	case 7:
		/*繪制線框茶壺*/
		glutWireTeapot(1.0f); break;
	case 8:
		/*繪制實體茶壺*/
		glutSolidTeapot(1.0f); break;
	default:break;
	}
	glFlush();
}

void ProcessMenu(int value) {
	//選擇繪制模式
	iMode = value;
	glutPostRedisplay();
}

//鍵盤繪制函數
void SpecialKeys(int key, int x, int y) {
	//繞x軸旋轉的角度變化
	if (key == GLUT_KEY_UP) xRot -= 0.5f;
	if (key == GLUT_KEY_DOWN) xRot += 0.5f;

	//繞y軸旋轉的角度的變化
	if (key == GLUT_KEY_LEFT) yRot -= 0.5f;
	if (key == GLUT_KEY_RIGHT) yRot += 0.5f;

	if (xRot > 356.0f) xRot = 0.0f;
	if (xRot < -1.0f) xRot = 355.0f;

	if (yRot > 356.0f) yRot = 0.0f;
	if (yRot < -1.0f) yRot = 355.0f;
	glutPostRedisplay();
}

int main(int argc, char* argv[]) {
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
	glutInitWindowSize(400, 400);
	glutInitWindowPosition(100, 100);
	glutCreateWindow("openGl模型繪制函數示例 181203065 李詩雨");
	/*建立菜單并定義菜單的回調函數*/
	/*創造GLUT多面體繪制菜單*/
	int nGLutPolyMenu = glutCreateMenu(ProcessMenu);
	glutAddMenuEntry("線框正四面體", 1);
	glutAddMenuEntry("實體正四面體", 2);
	glutAddMenuEntry("線框正八面體", 3);
	glutAddMenuEntry("實體正八面體", 4);
	/*建立GLUT曲面繪制菜單*/
	int nGLutCurveMenu = glutCreateMenu(ProcessMenu);;
	glutAddMenuEntry("線框球面", 5);
	glutAddMenuEntry("實體球面", 6);
	glutAddMenuEntry("線框茶壺", 7);
	glutAddMenuEntry("實體茶壺", 8);

	/*建立主菜單*/
	int nMainMenu = glutCreateMenu(ProcessMenu);
	glutAddSubMenu("GLUT多面體繪制", nGLutPolyMenu);
	glutAddSubMenu("GLUT曲面繪制", nGLutCurveMenu);
	/*單擊右鍵顯示菜單*/
	glutAttachMenu(GLUT_RIGHT_BUTTON);



	glutDisplayFunc(Display);
	glutReshapeFunc(ChangeSize);
	glutSpecialFunc(SpecialKeys);

	Initial();
	glutMainLoop();
	return 0;
}
           

動畫:日地月模型

#include <GL/glut.h>

float fsunangle;
float fearthangle;

void Initial() {
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
	GLfloat diffuse[] = { 1.0f,1.0f,0.0f,1.0f };
	GLfloat position[] = { 0.0f,0.0f,-250.0f,1.0f };
	glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
	glLightfv(GL_LIGHT1, GL_POSITION, position);
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT1);    //黃色光
	glEnable(GL_DEPTH_TEST);
}

void Display() {
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//清除顔色和深度緩沖區
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glTranslatef(0.0f, 0.0f, -250.0f); //将圖形沿z軸負方向移動

	//太陽
	GLfloat mat_diffuse[] = { 0.2f,0.8f,1.0f,1.0f };
	glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
	GLfloat mat_emission1[] = { 0.98,0.25,0.12,1.0 };
	glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission1);//設定太陽顔色為紅
	glutSolidSphere(30.0f, 40, 50);
	glEnable(GL_LIGHTING);

	//earth
	GLfloat mat_diffuse2[] = { 0.8,0.8,0.8,1.0 };
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse2);
	GLfloat mat_emission2[] = { 0.0,0.0,1.0,1.0 };
	glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mat_emission2);//地球顔色設定為藍色

	glRotatef(fsunangle, 0.0f, 1.0f, 0.0f);//繞y軸旋轉--地球繞太陽轉
	glTranslatef(100.f, 0.0f, 0.0f);//平移一段距離
	glutSolidSphere(8.0f, 40, 50);//draw earth

	//moon
	GLfloat mat_diffuse3[] = { 0.4, 0.4, 0.4, 1.0 };
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse3);
	GLfloat mat_emission3[] = { 0.25,0.25,0.25,1.0 };
	glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mat_emission3);
	
	glRotatef(fearthangle, 0.0f, 1.0f, 1.0f);//繞斜軸旋轉
	glTranslatef(20.f, 0.0f, 0.0f);//在地球的基礎上再往外平移一段距離
	glutSolidSphere(4.0f, 40, 50);//draw moon

	fsunangle += 4.0f;//地球旋轉步長
	fearthangle += 36.0f;//月球旋轉步長
	if (fsunangle > 360.0f) {
		fsunangle = 4.0f;
	}
	if (fearthangle > 360.0f) {
		fearthangle = 36.0f;
	}

	glutSwapBuffers();
}

void ChangeSize(int w, int h) {
	GLfloat nRange = 80.f;
	if (h == 0) h = 1;
	glViewport(0, 0, w, h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0f, (GLfloat)w / (GLfloat)h, 1.0f, 1000.0f);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

void TimerFunc(int value) {
	glutPostRedisplay();
	glutTimerFunc(80, TimerFunc, 1);//80 ms restart
}

int main(int argc, char* argv[]) {
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
	glutInitWindowSize(400, 400);
	glutInitWindowPosition(100, 100);
	glutCreateWindow("日地月模型 181203065 李詩雨");
	glutDisplayFunc(Display);
	glutReshapeFunc(ChangeSize);
	glutTimerFunc(500,TimerFunc,1);

	Initial();
	glutMainLoop();
	return 0;
}
           

繼續閱讀