淺淺地學習到open gl 的3d觀察,對一些函數還不是理解的很透徹,但是還是用心地做了個小實驗——三維觀察小程序。
只要是用了心的程序,我就想好好在csdn整理下,或許日後會有用也說不定。這也是一種點滴的積累吧。
先看看what文件提供的數據格式吧(太多行,有11610個頂點座標,23216個三角形)
// 參考http://www.cnblogs.com/lizhengjin/archive/2010/09/23/1833580.html
// 參考http://blog.csdn.net/zzyoucan/article/details/8521823
#include<stdio.h>
#include "glut.h"
int countOfVertex;
int countOfTriangle;
GLfloat** vertex_list;
GLint** index_list;
// 從what數據文件讀取數據
void readData()
{
int i;
FILE *fp;
if((fp=fopen("what.txt","r"))==NULL)
{
printf("Can't open the file!\n");
exit(0);
}
fscanf(fp,"%d",&countOfVertex);
printf("%d\t",countOfVertex);
fscanf(fp,"%d",&countOfTriangle);
printf("%d",countOfTriangle);
// 接下來是難點,爲2個2維數組動態申請內存空間
///////////////////////////////////////////////////////////////////////////////////////////
vertex_list = new GLfloat*[countOfVertex];
for (i=0;i<countOfVertex;i++)
{
vertex_list[i]=new GLfloat[3];
}
index_list = new GLint*[countOfTriangle];
for (i=0;i<countOfTriangle;i++)
{
index_list[i]=new GLint[4];
}
////////////////////////////////////////////////////////////////////////////////////////////
for(i=0;i<countOfVertex;i++)
{
fscanf(fp,"%f%f%f",&vertex_list[i][0],&vertex_list[i][1],&vertex_list[i][2]);
}
for(i=0;i<countOfTriangle;i++)
{
fscanf(fp,"%d%d%d%d",&index_list[i][0],&index_list[i][1],&index_list[i][2],&index_list[i][3]);
}
fclose(fp);
}
static GLfloat theta[] = {0.0,0.0,0.0}; // 看來初始的旋轉角度爲0
static GLint axis = 2;
static GLdouble viewer[]= {0.0, 0.0, 5.0}; /* initial viewer location */
void display(void)
{
int i, j;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(viewer[0],viewer[1],viewer[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glRotatef(theta[0], 1.0, 0.0, 0.0);
glRotatef(theta[1], 0.0, 1.0, 0.0);
glRotatef(theta[2], 0.0, 0.0, 1.0);
// glBegin(GL_TRIANGLES);
for(i=0; i<countOfTriangle; i++)
{
glBegin(GL_LINE_LOOP);
for(j=1; j<=3; j++)
{
glVertex3fv(vertex_list[index_list[i][j]]);
}
glEnd();
}
glFlush();
glutSwapBuffers();
}
void mouse(int btn, int state, int x, int y) // 鼠標左中右鍵改變的都是旋轉角度
{
if(btn==GLUT_LEFT_BUTTON && state == GLUT_DOWN) axis = 0;
if(btn==GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) axis = 1;
if(btn==GLUT_RIGHT_BUTTON && state == GLUT_DOWN) axis = 2;
theta[axis] += 2.0;
if( theta[axis] > 360.0 ) theta[axis] -= 360.0;
display();
}
void keys(unsigned char key, int x, int y)
{
/* Use x, X, y, Y, z, and Z keys to move viewer */ // 鍵盤的xyz 改變眼睛的位置 viewer[0] viewer[1] viewer[2] 用在gluLookAt
if(key == 'x') viewer[0]-= 1.0;
if(key == 'X') viewer[0]+= 1.0;
if(key == 'y') viewer[1]-= 1.0;
if(key == 'Y') viewer[1]+= 1.0;
if(key == 'z') viewer[2]-= 1.0;
if(key == 'Z') viewer[2]+= 1.0;
display();
}
void myReshape(int w, int h)
{
glViewport(0, 0, w, h);
/* Use a perspective view */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(w<=h) glFrustum(-0.2, 0.2, -0.2 * (GLfloat) h/ (GLfloat) w, // 此時h/w >1 -0.2 ~ 0.2
0.2* (GLfloat) h / (GLfloat) w, 2.0, 40.0);
else glFrustum(-0.2, 0.2, -0.2 * (GLfloat) w/ (GLfloat) h, // 此時w/h >1
0.2* (GLfloat) w / (GLfloat) h, 2.0, 20.0);
/* Or we can use gluPerspective */
// gluPerspective(20.0, w/h, -0.1, 0.1);
glMatrixMode(GL_MODELVIEW); // 設置回模型矩陣
}
void
main(int argc, char **argv)
{
readData();
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(500, 500);
glutCreateWindow("牛");
glEnable(GL_DEPTH_TEST);
glutReshapeFunc(myReshape);
glutDisplayFunc(display);
glutMouseFunc(mouse);
glutKeyboardFunc(keys);
glutMainLoop();
// 這裏釋放這2個二維數組,其實不釋放也行,因爲進程結束了,自動回收內存
int i;
for(i=0;i<countOfVertex;i++)
{
delete [] vertex_list[i];
}
delete [] vertex_list;
for(i=0;i<countOfTriangle;i++)
{
delete [] index_list[i];
}
delete [] index_list;
}
效果:
// 收穫:1.直面了C++必須學會的動態創建多維數組
2.fscanf函數的使用,讀取文件數據
3.glFrustum函數前2個參數,調準近裁剪面的寬度越小如-0.2~0.2 =0.4 就很小,這樣顯示的物體就大,如果改爲-2~2,=4那麼會小的多。
4.glBegin(GL_LINE_LOOP);函數不等於glBegin(GL_LINES)。後者會以兩輛相連,顯然不適合用於畫一個獨立的三角形。
5.發現改變glFrustum函數的倒數第二個參數zNear居然會改變物體顯示大小,視錐變了?