OpengGL繪製立方體的三種方法

以下爲繪製立方體的三種方法:

第一種方法爲最爲傳統的,也是各個圖形學書上的方法。

第二種方法爲1.1新加入的 頂點數組,該繪製程序也能運行在OpenGL ES1.1上

第三種方法是第二種方法的改進,用索引數組代替了法向量。

先介紹這幾種方法吧,以後在添加新的方法:

第一種方法:立即模式

void draw1(GLdouble dSize)
{
	double size = dSize * 0.5;
	glEnable(GL_DEPTH_TEST);//深度測試消除隱藏面
	glBegin(GL_QUADS);
	//上
	glColor4f(1.0, 0.0, 0.0, 1.0);
	glNormal3d(0.0, 0.0, 1.0); //上
	glVertex3d(dSize, dSize, dSize);
	glVertex3d(-dSize, dSize, dSize);
	glVertex3d(-dSize, -dSize, dSize);
	glVertex3d(dSize, -dSize, dSize);
	//下
	glColor4f(0.0, 1.0, 0.0, 1.0);
	glNormal3d(0.0, 0.0, -1.0);//下
	glVertex3d(dSize, dSize, -dSize);
	glVertex3d(-dSize, dSize, -dSize);
	glVertex3d(-dSize, -dSize, -dSize);
	glVertex3d(dSize, -dSize, -dSize);
	//前
	glColor4f(1.0, 1.0, 0.0, 1.0);
	glNormal3d(1.0, 0.0, 0.0);//前
	glVertex3d(dSize, dSize, dSize);
	glVertex3d(dSize, -dSize, dSize);
	glVertex3d(dSize, -dSize, -dSize);
	glVertex3d(dSize, dSize, -dSize);
	//後
	glColor4f(0.0, 0.0, 1.0, 1.0);
	glNormal3d(-1.0, 0.0, 0.0);//後
	glVertex3d(-dSize, dSize, dSize);
	glVertex3d(-dSize, dSize, -dSize);
	glVertex3d(-dSize, -dSize, -dSize);
	glVertex3d(-dSize, -dSize, dSize);
	//左
	glColor4f(0.0, 1.0, 0.5, 1.0);
	glNormal3d(0.0, -1.0, 0.0);//左
	glVertex3d(dSize, -dSize, dSize);
	glVertex3d(dSize, -dSize, -dSize);
	glVertex3d(-dSize, -dSize, -dSize);
	glVertex3d(-dSize, -dSize, dSize);
	//右
	glColor4f(0.5, 1.0, 0.5, 1.0);
	glNormal3d(0.0, 1.0, 0.0);//右
	glVertex3d(dSize, dSize,dSize);
	glVertex3d(dSize, dSize, -dSize);
	glVertex3d(-dSize, dSize, -dSize);
	glVertex3d(-dSize, dSize, dSize);//右
	glEnd();
}


第二種方法:頂點數組+法向量

void draw2(GLdouble dSize)
{
	double size = dSize * 0.5;
	GLdouble dVertexes[][3] = {
		{ dSize, dSize, dSize },{ -dSize, dSize, dSize },{ -dSize, -dSize, dSize },	{ dSize, -dSize, dSize },
		{ dSize, dSize, -dSize },{ -dSize, dSize, -dSize},{ -dSize, -dSize, -dSize },{ dSize, -dSize, -dSize },
		{ dSize, dSize, dSize },{ dSize, -dSize, dSize },{ dSize, -dSize, -dSize },	{ dSize, dSize, -dSize },
		{ -dSize, dSize, dSize },{ -dSize, dSize, -dSize },	{ -dSize, -dSize, -dSize }, { -dSize, -dSize, dSize },
		{ dSize, -dSize, dSize },{ dSize, -dSize, -dSize },	{ -dSize, -dSize, -dSize }, { -dSize, -dSize, dSize },
		{ dSize, dSize, dSize },{ dSize, dSize, -dSize },	{ -dSize, dSize, -dSize },	{ -dSize, dSize, dSize }
	};
	GLdouble dVertexNormals[][3] = {
		{ 0.0, 0.0, 1.0 },//上
		{ 0.0, 0.0, -1.0 },//下
		{ 1.0, 0.0, 0.0 },//前
		{ -1.0, 0.0, 0.0 },//後
		{ 0.0, -1.0, 0.0 },//左
		{ 0.0, 1.0, 0.0 }//右
	};
	glEnable(GL_DEPTH_TEST);//深度測試消除隱藏面
	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_NORMAL_ARRAY);
	glNormalPointer(GL_FLOAT, 0, dVertexNormals);
	glVertexPointer(3, GL_DOUBLE, 0, dVertexes);

	glColor4f(1.0, 0.0, 0.0, 1.0);
	glDrawArrays(GL_QUADS, 0, 4);
	glColor4f(0.0, 1.0, 0.0, 1.0);
	glDrawArrays(GL_QUADS, 4, 4);
	glColor4f(0.0, 0.0, 1.0, 1.0);
	glDrawArrays(GL_QUADS, 8, 4);
	glColor4f(1.0, 1.0, 0.0, 1.0);
	glDrawArrays(GL_QUADS, 12, 4);
	glColor4f(0.0, 1.0, 0.5, 1.0);
	glDrawArrays(GL_QUADS, 16, 4);
	glColor4f(0.5, 1.0, 0.5, 1.0);
	glDrawArrays(GL_QUADS, 20, 4);
}

第三種方法:頂點數組+法向量

void draw3(GLdouble dSize)
{
	double size = dSize * 0.5;
	GLdouble dVertexes[][3] = {
		{ dSize, dSize, dSize },//0		第一象限點
		{ -dSize, dSize, dSize },//1	第二象限點
		{ -dSize, -dSize, dSize },//2	第三象限點
		{ dSize, -dSize, dSize },//3	第四象限點
		{ dSize, dSize, -dSize },//4	第五象限點
		{ -dSize, dSize, -dSize },//5	第六象限點
		{ -dSize, -dSize, -dSize },//6	第七象限點
		{ dSize, -dSize, -dSize }//7	第八象限點
	};

	//使用索引表示面,4個索引值表示組成面的四個頂點
	GLubyte dIndices[][4] = {
		{ 0, 1, 2, 3 },//上
		{ 4, 5, 6, 7 },//下
		{ 0, 3, 7, 4 },//前
		{ 1, 5, 6, 2 },//後
		{ 3, 7, 6, 2 },//左
		{ 0, 4, 5, 1 }//右
	};
	glEnable(GL_DEPTH_TEST);//深度測試消除隱藏面
	glEnableClientState(GL_VERTEX_ARRAY);
	glVertexPointer(3, GL_DOUBLE, 0, dVertexes);
	glColor4f(1.0, 0.0, 0.0, 1.0);
	glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, dIndices[0]);
	glColor4f(0.0, 1.0, 0.0, 1.0);
	glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, dIndices[1]);
	glColor4f(0.0, 0.0, 1.0, 1.0);
	glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, dIndices[2]);
	glColor4f(1.0, 0.0, 1.0, 1.0);
	glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, dIndices[3]);
	glColor4f(0.0, 1.0, 1.0, 1.0);
	glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, dIndices[4]);
	glColor4f(0.5, 0.5, 0.0, 1.0);
	glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, dIndices[5]);
	glDisable(GL_DEPTH_TEST);
	glDisableClientState(GL_VERTEX_ARRAY);
}


以下是完整的程序代碼,環境採用freeglut+glew來運行

#if ( (defined(__MACH__)) && (defined(__APPLE__)) )   
#include <stdlib.h>
#include <OpenGL/gl.h>
#include <GLUT/glut.h>
#include <OpenGL/glext.h>
#else
#include <stdlib.h>
#define GLEW_STATIC
#include <GL/glew.h>
#define FREEGLUT_STATIC
#include <GL/freeglut.h>
#include <GL/freeglut_ext.h>
#endif
#pragma comment(lib,"freeglut.lib")
#pragma comment(lib, "glew32s.lib")
#pragma comment(linker,"/NODEFAULTLIB:LiBCMT.lib")

GLfloat angle = 0.0; //set the angle of rotation
//第一種方法:立即模式
void draw1(GLdouble dSize)
{
	double size = dSize * 0.5;
	glEnable(GL_DEPTH_TEST);//深度測試消除隱藏面
	glBegin(GL_QUADS);
	//上
	glColor4f(1.0, 0.0, 0.0, 1.0);
	glNormal3d(0.0, 0.0, 1.0); //上
	glVertex3d(dSize, dSize, dSize);
	glVertex3d(-dSize, dSize, dSize);
	glVertex3d(-dSize, -dSize, dSize);
	glVertex3d(dSize, -dSize, dSize);
	//下
	glColor4f(0.0, 1.0, 0.0, 1.0);
	glNormal3d(0.0, 0.0, -1.0);//下
	glVertex3d(dSize, dSize, -dSize);
	glVertex3d(-dSize, dSize, -dSize);
	glVertex3d(-dSize, -dSize, -dSize);
	glVertex3d(dSize, -dSize, -dSize);
	//前
	glColor4f(1.0, 1.0, 0.0, 1.0);
	glNormal3d(1.0, 0.0, 0.0);//前
	glVertex3d(dSize, dSize, dSize);
	glVertex3d(dSize, -dSize, dSize);
	glVertex3d(dSize, -dSize, -dSize);
	glVertex3d(dSize, dSize, -dSize);
	//後
	glColor4f(0.0, 0.0, 1.0, 1.0);
	glNormal3d(-1.0, 0.0, 0.0);//後
	glVertex3d(-dSize, dSize, dSize);
	glVertex3d(-dSize, dSize, -dSize);
	glVertex3d(-dSize, -dSize, -dSize);
	glVertex3d(-dSize, -dSize, dSize);
	//左
	glColor4f(0.0, 1.0, 0.5, 1.0);
	glNormal3d(0.0, -1.0, 0.0);//左
	glVertex3d(dSize, -dSize, dSize);
	glVertex3d(dSize, -dSize, -dSize);
	glVertex3d(-dSize, -dSize, -dSize);
	glVertex3d(-dSize, -dSize, dSize);
	//右
	glColor4f(0.5, 1.0, 0.5, 1.0);
	glNormal3d(0.0, 1.0, 0.0);//右
	glVertex3d(dSize, dSize,dSize);
	glVertex3d(dSize, dSize, -dSize);
	glVertex3d(-dSize, dSize, -dSize);
	glVertex3d(-dSize, dSize, dSize);//右
	glEnd();
}
//方法二:頂點數組+法向量(OpenGL ES1.1兼容)
void draw2(GLdouble dSize)
{
	double size = dSize * 0.5;
	GLdouble dVertexes[][3] = {
		{ dSize, dSize, dSize },{ -dSize, dSize, dSize },{ -dSize, -dSize, dSize },	{ dSize, -dSize, dSize },
		{ dSize, dSize, -dSize },{ -dSize, dSize, -dSize},{ -dSize, -dSize, -dSize },{ dSize, -dSize, -dSize },
		{ dSize, dSize, dSize },{ dSize, -dSize, dSize },{ dSize, -dSize, -dSize },	{ dSize, dSize, -dSize },
		{ -dSize, dSize, dSize },{ -dSize, dSize, -dSize },	{ -dSize, -dSize, -dSize }, { -dSize, -dSize, dSize },
		{ dSize, -dSize, dSize },{ dSize, -dSize, -dSize },	{ -dSize, -dSize, -dSize }, { -dSize, -dSize, dSize },
		{ dSize, dSize, dSize },{ dSize, dSize, -dSize },	{ -dSize, dSize, -dSize },	{ -dSize, dSize, dSize }
	};
	GLdouble dVertexNormals[][3] = {
		{ 0.0, 0.0, 1.0 },//上
		{ 0.0, 0.0, -1.0 },//下
		{ 1.0, 0.0, 0.0 },//前
		{ -1.0, 0.0, 0.0 },//後
		{ 0.0, -1.0, 0.0 },//左
		{ 0.0, 1.0, 0.0 }//右
	};
	glEnable(GL_DEPTH_TEST);//深度測試消除隱藏面
	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_NORMAL_ARRAY);
	glNormalPointer(GL_FLOAT, 0, dVertexNormals);
	glVertexPointer(3, GL_DOUBLE, 0, dVertexes);

	glColor4f(1.0, 0.0, 0.0, 1.0);
	glDrawArrays(GL_QUADS, 0, 4);
	glColor4f(0.0, 1.0, 0.0, 1.0);
	glDrawArrays(GL_QUADS, 4, 4);
	glColor4f(0.0, 0.0, 1.0, 1.0);
	glDrawArrays(GL_QUADS, 8, 4);
	glColor4f(1.0, 1.0, 0.0, 1.0);
	glDrawArrays(GL_QUADS, 12, 4);
	glColor4f(0.0, 1.0, 0.5, 1.0);
	glDrawArrays(GL_QUADS, 16, 4);
	glColor4f(0.5, 1.0, 0.5, 1.0);
	glDrawArrays(GL_QUADS, 20, 4);
}

/*
* 方法二:頂點數組+索引數組
空間象限----第一象限 ++
第二象限 -+
第三象限 --
第四象限 +-
五,六,七,八象限與前面一致。但Z軸爲負
*/

void draw3(GLdouble dSize)
{
	double size = dSize * 0.5;
	GLdouble dVertexes[][3] = {
		{ dSize, dSize, dSize },//0		第一象限點
		{ -dSize, dSize, dSize },//1	第二象限點
		{ -dSize, -dSize, dSize },//2	第三象限點
		{ dSize, -dSize, dSize },//3	第四象限點
		{ dSize, dSize, -dSize },//4	第五象限點
		{ -dSize, dSize, -dSize },//5	第六象限點
		{ -dSize, -dSize, -dSize },//6	第七象限點
		{ dSize, -dSize, -dSize }//7	第八象限點
	};

	//使用索引表示面,4個索引值表示組成面的四個頂點
	GLubyte dIndices[][4] = {
		{ 0, 1, 2, 3 },//上
		{ 4, 5, 6, 7 },//下
		{ 0, 3, 7, 4 },//前
		{ 1, 5, 6, 2 },//後
		{ 3, 7, 6, 2 },//左
		{ 0, 4, 5, 1 }//右
	};
	glEnable(GL_DEPTH_TEST);//深度測試消除隱藏面
	glEnableClientState(GL_VERTEX_ARRAY);
	glVertexPointer(3, GL_DOUBLE, 0, dVertexes);
	glColor4f(1.0, 0.0, 0.0, 1.0);
	glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, dIndices[0]);
	glColor4f(0.0, 1.0, 0.0, 1.0);
	glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, dIndices[1]);
	glColor4f(0.0, 0.0, 1.0, 1.0);
	glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, dIndices[2]);
	glColor4f(1.0, 0.0, 1.0, 1.0);
	glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, dIndices[3]);
	glColor4f(0.0, 1.0, 1.0, 1.0);
	glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, dIndices[4]);
	glColor4f(0.5, 0.5, 0.0, 1.0);
	glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, dIndices[5]);
	glDisable(GL_DEPTH_TEST);
	glDisableClientState(GL_VERTEX_ARRAY);
}
void display(void) {
	//幾何變換和取景變換,都是取景矩陣
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	//設置取景矩陣
	gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);//設置取景矩陣
	//設置幾何矩陣
	glRotatef(angle, 1.0, 0.0, 0.0); //繞X軸旋轉
	glRotatef(angle, 0.0, 1.0, 0.0); //繞Y軸旋轉
	glRotatef(angle, 0.0, 0.0, 1.0); //繞Z軸旋轉

	//繪製模型
	glClearColor(0.0, 0.0, 0.0, 1.0);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	//drawSolidCube2(2);//繪製正方體
	draw3(1);
	glutSwapBuffers();
	angle += 0.01f;
}

void reshape(int w, int h) {
	//視區變換
	glViewport(0, 0, (GLsizei)w, (GLsizei)h);
	//投影變換
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(60, (GLfloat)w / (GLfloat)h, 1.0, 100.0);
}
int main(int argc, char **argv) {

	glutInit(&argc, argv);
	//創建窗口
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); //set up the double buffering
	glutInitWindowSize(500, 500);
	glutInitWindowPosition(100, 100);
	glutCreateWindow("A basic OpenGL Window");
	//初始化GLEW
	glewInit();
	//窗口回調函數
	glutReshapeFunc(reshape);//改變窗口後調用,也可以理解爲OpenGL的初始化,WM_SIZE,WM_CREATE
	glutDisplayFunc(display);//窗口顯示後調用,WM_PAINT
	glutIdleFunc(display);//空閒時調用
	glutMainLoop();
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章