以下爲繪製立方體的三種方法:
第一種方法爲最爲傳統的,也是各個圖形學書上的方法。
第二種方法爲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;
}