浅浅地学习到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居然会改变物体显示大小,视锥变了?