利用opengl进行模型表现

利用OpenGL进行模型表现

 

这篇文章介绍一下用OpenGL来表现模型对象。比如用3DMAX等工具做好一个模型后,我们希望能够在自己的程序中使用它。一般使用这些工具的导出功能导出特定的文件,然后读取其中我们感兴趣的部分,再把这些感兴趣的数据在我们的程序中组织好就可以了。利用OpenGL来表现静态模型是很简单的。

 

这里为了简单起见,模型对象文件为txt文本,只包含了模型的顶点个数,面个数,顶点坐标,索引信息。当然在一些复杂的模型文件中,还包括法线,贴图坐标等等信息。重要的问题是,如果组织这些信息。

 

 

219483
435667
3.031209 1.875606 1.422974
3.030240 1.863352 1.404835
3.030240 1.863352 1.404835
3.021032 1.846390 1.404004
3.021032 1.846390 1.404004
3.050020 1.888645 1.389481
3.040140 1.883706 1.400404

.

.

.

2869 2977 2973
2973 2974 2869
2979 2978 2975
2980 2979 2976
2976 2979 2975
2982 3104 3101
3096 2983 2982
3094 2984 3096
2984 2983 3096
3094 2972 2984
2979 2873 2978
2979 2980 2988

.

.

.

 

如上面的信息一样,第一行数据为该模型的顶点个数,第二行数据为该模型的三角形面个数。后面的数据分别人顶点坐标和每一个面的顶点索引信息。很自然的,首先可以想到要在程序中表现该模型,需要vertex的数据类型,于是可以定义这样的结构体,可以包含顶点的坐标和法线信息。

[cpp]  view plain  copy
  1. struct Vertex  
  2. {  
  3.     double P[3];  
  4.     double N[3];  
  5. };  

这里的顶点结构包含了顶点坐标P和法线N。

 

然后就是面的数据类型

[cpp]  view plain  copy
  1. struct Face  
  2. {  
  3.     int Idx[3];  
  4. };  

一个面由3个顶点构成,只要有了顶点的索引就可以了。

 

最后就是模型的数据类型了

[cpp]  view plain  copy
  1. struct Model  
  2. {  
  3.     int vNum;  
  4.     int fNum;  
  5.     Vertex *VertList;  
  6.     Face *FaceList;  
  7. };  

 

这个数据类型包含了模型顶点数vNum,面数fNum,指向顶点列表的指针VertList和指向面列表的指针FaceList。

然后这样只要用Model来定义一个模型就可以了

 

Model MyModel;

 

下面来看看如果从文件中读取信息。可以把读取文件的部分写成一个函数,比如叫LoadModel,函数的参数只需要提供文件名就可以了。

 

[cpp]  view plain  copy
  1. void LoadModel(char *fname)  
  2. {  
  3.     FILE *fp;  
  4.     fp = fopen(fname, "r");  
  5.   
  6.     fscanf(fp, "%d", &MyModel.vNum);  
  7.     fscanf(fp, "%d", &MyModel.fNum);  
  8.   
  9.     MyModel.VertList = new Vertex [MyModel.vNum];  
  10.     MyModel.FaceList = new Face [MyModel.fNum];  
  11.   
  12.     int vNum = MyModel.vNum;  
  13.     int fNum = MyModel.fNum;  
  14.   
  15.     for (int i = 0; i < vNum; ++i)  
  16.     {  
  17.         double x, y, z;  
  18.         fscanf(fp, "%lf %lf %lf", &x, &y, &z);  
  19.         MyModel.VertList[i].P[0] = x;  
  20.         MyModel.VertList[i].P[1] = y;  
  21.         MyModel.VertList[i].P[2] = z;  
  22.   
  23.         MyModel.VertList[i].N[0] = 0.0;  
  24.         MyModel.VertList[i].N[1] = 0.0;  
  25.         MyModel.VertList[i].N[2] = 0.0;  
  26.   
  27.     }  
  28.   
  29.     for (int i = 0; i < fNum; ++i)  
  30.     {  
  31.         int idx0, idx1, idx2;  
  32.         fscanf(fp, "%d %d %d", &idx0, &idx1, &idx2);  
  33.         MyModel.FaceList[i].Idx[0] = idx0;  
  34.         MyModel.FaceList[i].Idx[1] = idx1;  
  35.         MyModel.FaceList[i].Idx[2] = idx2;  
  36.   
  37.         double x0, y0, z0;  
  38.         double x1, y1, z1;  
  39.         double x2, y2, z2;  
  40.   
  41.         x0 = MyModel.VertList[idx0].P[0];  
  42.         y0 = MyModel.VertList[idx0].P[1];  
  43.         z0 = MyModel.VertList[idx0].P[2];  
  44.   
  45.         x1 = MyModel.VertList[idx1].P[0];  
  46.         y1 = MyModel.VertList[idx1].P[1];  
  47.         z1 = MyModel.VertList[idx1].P[2];  
  48.   
  49.         x2 = MyModel.VertList[idx2].P[0];  
  50.         y2 = MyModel.VertList[idx2].P[1];  
  51.         z2 = MyModel.VertList[idx2].P[2];  
  52.   
  53.         double ax, ay, az;  
  54.         double bx, by, bz;  
  55.         double nx, ny, nz;  
  56.         ax = x1 - x0;  
  57.         ay = y1 - y0;  
  58.         az = z1 - z0;  
  59.   
  60.         bx = x2 - x0;  
  61.         by = y2 - y0;  
  62.         bz = z2 - z0;  
  63.   
  64.         nx = ay * bz - az * by;  
  65.         ny = az * bx - ax * bz;  
  66.         nz = ax * by - ay * bx;  
  67.   
  68.         MyModel.VertList[idx0].N[0] += nx;  
  69.         MyModel.VertList[idx0].N[1] += ny;  
  70.         MyModel.VertList[idx0].N[2] += nz;  
  71.   
  72.         MyModel.VertList[idx1].N[0] += nx;  
  73.         MyModel.VertList[idx1].N[1] += ny;  
  74.         MyModel.VertList[idx1].N[2] += nz;  
  75.   
  76.         MyModel.VertList[idx2].N[0] += nx;  
  77.         MyModel.VertList[idx2].N[1] += ny;  
  78.         MyModel.VertList[idx2].N[2] += nz;  
  79.     }  
  80.   
  81.     for (int i = 0; i < vNum; ++i)  
  82.     {  
  83.         double nx, ny, nz;  
  84.         nx = MyModel.VertList[i].N[0];  
  85.         ny = MyModel.VertList[i].N[1];  
  86.         nz = MyModel.VertList[i].N[2];  
  87.   
  88.         double norm = sqrt(nx * nx + ny * ny + nz * nz);  
  89.   
  90.         MyModel.VertList[i].N[0] /= norm;  
  91.         MyModel.VertList[i].N[1] /= norm;  
  92.         MyModel.VertList[i].N[2] /= norm;  
  93.     }  
  94.   
  95.   
  96. }  

上面的代码比较长,但是内容很简单。首先打开文件,然后分别以整型的方式读取顶点个数和面个数,保存在结构体变量中。然后为顶点列表和面列表动态申请内存空间,在循环中分别读取每个数据。由于顶点包括法线信息,所以这里还进行了法线的计算。这里采用平均法线,即把一个顶点的多个法线加在一起,然后再进行单位化。由于一个顶点可能被用于多个面,所以该顶点的法线就是所有面的面法线的和。然后在程序初始化的时候,我们就可以调用这个函数来进行对模型的初始化。

 

最后就是里利用OpenGL来渲染模型了。有了上面的所有信息,要渲染模型就很简单了。我们只用利用画三角形的方法就可以了。

 

[cpp]  view plain  copy
  1. glBegin(GL_TRIANGLES);  
  2.     for (int i = 0; i < MyModel.fNum; ++i)  
  3.     {  
  4.         int idx0, idx1, idx2;  
  5.         idx0 = MyModel.FaceList[i].Idx[0];  
  6.         idx1 = MyModel.FaceList[i].Idx[1];  
  7.         idx2 = MyModel.FaceList[i].Idx[2];  
  8.   
  9.         glNormal3dv(MyModel.VertList[idx0].N);  
  10.         glVertex3dv(MyModel.VertList[idx0].P);  
  11.   
  12.         glNormal3dv(MyModel.VertList[idx1].N);  
  13.         glVertex3dv(MyModel.VertList[idx1].P);  
  14.   
  15.         glNormal3dv(MyModel.VertList[idx2].N);  
  16.         glVertex3dv(MyModel.VertList[idx2].P);  
  17.     }  
  18.     glEnd();  

 

可以看到,渲染部分很简单,就是在循环中依次访问面列表中每个面。并且给出每个面每个顶点的法线。 

(原地址:http://blog.csdn.net/zhangci226/article/details/5060634)

 

dragon








  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值