Small Tips : 如何整合3DS模型中的Obj

  lib3ds大家看了园子里发过的Tutorial后可能都会使用了,这里我展示了一个小小的优化技巧,把一个3DS文件中所有Objects的顶点、纹理坐标、向量都捆绑在一个Batch里进行渲染。局限是,如果你的3DS文件使用了多个贴图,那么还是无法使用这个技巧。或者你如同John Camark一样,发明那个MetaTexture技术,把多个贴图放到一个纹理中。
  我对比过STL版本的和C版本的代码,STL慢了不止一秒,而C代码使用了最快速与直接的memcpy,效率当然比STL容器高的多,不过代价是,调试非常麻烦,动不动就出错。
  关键是把所有的索引Index放在一起,正确的组合所有的顶点。代码如下,有些脏:

 1 None.gif static   void  InitModel()
 2 ExpandedBlockStart.gifContractedBlock.gif dot.gif {
 3InBlock.gif    Lib3dsFile* file = 0;
 4InBlock.gif    file = lib3ds_file_load("E:\\MyModels\\ELEPHANT\\ELEPHANT.3DS");
 5InBlock.gif
 6InBlock.gif    deque<GLfloat> _V;
 7InBlock.gif    deque<GLfloat> _T;
 8InBlock.gif    deque<GLushort> _I;
 9InBlock.gif    deque<GLfloat> _N;
10InBlock.gif
11InBlock.gif    deque<GLushort> _n;
12InBlock.gif    _n.push_front(0);
13InBlock.gif    _n.pop_back();
14ExpandedSubBlockStart.gifContractedSubBlock.gif    for(deque<ushort>::reverse_iterator r_itr = _n.rbegin();r_itr!=_n.rend();r_itr++)dot.gif{
15InBlock.gif        for( deque<ushort>::reverse_iterator f_itr = r_itr + 1; f_itr != _n.rend() ;f_itr++)
16InBlock.gif            *r_itr += *f_itr;
17InBlock.gif        //printf("%d\n",*r_itr);
18ExpandedSubBlockEnd.gif    }

19InBlock.gif    //Get All meshes information
20InBlock.gif    Lib3dsMesh *= 0;
21InBlock.gif    int VerNum = 0,TexNum = 0,TriNum = 0,IdxNum=0;
22InBlock.gif
23InBlock.gif    int MeshNum = 0;
24ExpandedSubBlockStart.gifContractedSubBlock.gif    for( m=file->meshes; m!=0; m=m->next)dot.gif{
25InBlock.gif        VerNum += m->points;
26InBlock.gif        TexNum += m->texels;
27InBlock.gif        TriNum += m->faces;
28InBlock.gif        IdxNum += m->faces*3;
29InBlock.gif        MeshNum++;
30InBlock.gif        _n.push_back(m->points);
31ExpandedSubBlockEnd.gif    }
;
32InBlock.gif    VerticesPtr = new GLfloat[VerNum * 3];
33InBlock.gif    TexCoordsPtr = new GLfloat[TexNum * 2];
34InBlock.gif    NormalPtr = new GLfloat[VerNum * 3];
35InBlock.gif    //NormalPtr = new GLfloat[TriNum * 3 * 3];
36InBlock.gif    IndexPtr = new GLushort[IdxNum];
37InBlock.gif    IndexNum = IdxNum;
38InBlock.gif    
39InBlock.gif
40InBlock.gif    printf("<---   mesh num : %d,tri,pointsNum : %d  --->\n",MeshNum,VerNum);
41InBlock.gif
42InBlock.gif    _n.push_front(0);
43InBlock.gif    _n.pop_back();
44ExpandedSubBlockStart.gifContractedSubBlock.gif    for(deque<ushort>::reverse_iterator r_itr = _n.rbegin();r_itr!=_n.rend();r_itr++)dot.gif{
45InBlock.gif        for( deque<ushort>::reverse_iterator f_itr = r_itr + 1; f_itr != _n.rend() ;f_itr++)
46InBlock.gif            *r_itr += *f_itr;
47InBlock.gif        //printf("%d\n",*r_itr);
48ExpandedSubBlockEnd.gif    }

49InBlock.gif
50ExpandedSubBlockStart.gifContractedSubBlock.gif    int offset[4= dot.gif{0,0,0,0};
51InBlock.gif    int j = 0;
52ExpandedSubBlockStart.gifContractedSubBlock.gif    for( m=file->meshes; m!=0; m=m->next)dot.gif{
53InBlock.gif        //copy VerticesPtr
54ExpandedSubBlockStart.gifContractedSubBlock.gif        forint i = 0;i<m->points;i++ )dot.gif{
55InBlock.gif            memcpy(&(VerticesPtr[offset[0]*3]),&(m->pointL[i].pos[0]),sizeof(float)*3);
56InBlock.gif            offset[0]++;
57ExpandedSubBlockEnd.gif        }
;
58InBlock.gif        //copy Texcoords
59ExpandedSubBlockStart.gifContractedSubBlock.gif        forint i=0;i<m->texels;i++ )dot.gif{
60InBlock.gif            memcpy(&(TexCoordsPtr[offset[1]*2]),&(m->texelL[i][0]),sizeof(float)*2);
61InBlock.gif            offset[1]++;
62ExpandedSubBlockEnd.gif        }
;
63InBlock.gif
64InBlock.gif        Lib3dsVector* normalL = (Lib3dsVector*)malloc(3*sizeof(Lib3dsVector)*m->faces);
65InBlock.gif        lib3ds_mesh_calculate_normals(m,normalL);
66InBlock.gif
67ExpandedSubBlockStart.gifContractedSubBlock.gif        forint i=0;i<m->faces;i++ )dot.gif{
68InBlock.gif            ushort _0 = m->faceL[i].points[0+ _n[j];
69InBlock.gif            ushort _1 = m->faceL[i].points[1+ _n[j];
70InBlock.gif            ushort _2 = m->faceL[i].points[2+ _n[j];
71InBlock.gif
72InBlock.gif            IndexPtr[ offset[2] ] = _0;
73InBlock.gif            offset[2]++;
74InBlock.gif            IndexPtr[ offset[2] ] = _1;
75InBlock.gif            offset[2]++;
76InBlock.gif            IndexPtr[ offset[2] ] = _2;
77InBlock.gif            offset[2]++;
78InBlock.gif            memcpy(&(NormalPtr[ _0 ]),&(normalL[i*3 + 0]),sizeof(float)*3);
79InBlock.gif            memcpy(&(NormalPtr[ _1 ]),&(normalL[i*3 + 1]),sizeof(float)*3);
80InBlock.gif            memcpy(&(NormalPtr[ _2 ]),&(normalL[i*3 + 2]),sizeof(float)*3);
81ExpandedSubBlockEnd.gif        }
;
82InBlock.gif        printf("J : %d\t _n[j] : %d\n",j,_n[j]);
83InBlock.gif        j++;
84InBlock.gif
85InBlock.gif        free(normalL);
86ExpandedSubBlockEnd.gif    }
;
87InBlock.gif
88InBlock.gif    for(int i=0;i<10;i++)
89InBlock.gif        printf("%f %f %f\t",NormalPtr[i*3 + 0],NormalPtr[i*3 + 1],NormalPtr[i*3 + 2]);
90InBlock.gif        //printf("%d ",IndexPtr[i]);
91InBlock.gif    printf("IndexNum : %d\n",_I.size());
92InBlock.gif
93InBlock.gif    
94ExpandedBlockEnd.gif}
;

  解释一下思路。3DS文件如果有多个OBJ,那么每一个OBJ都会维护一个自己的索引Index,而且都是从0开始。如果我们仅仅把顶点放在一起,那么是没有意义的,无法得到完整的Mesh。所以我们就必须迭代计算前一个Obj有多少个顶点,并且把当前Obj的索引都加上前面的数据。举例如下。
    3个Obj:
    Obj          0      1      2
    顶点数 10    20    30
  三角形数目    5      8    14
  新索引起点    0      5    13

  deque容器我留在了代码中,如果你不放心可以使用它们来装载数据,看看速度究竟有多么的迟缓。

  如果每个Obj都有自己的纹理,那么就很麻烦了。在你的纹理加载代码中,需要额外的声明一个能够装得下所有纹理的“巨大纹理”,拷贝所有的图象数据到这个大纹理中,记得各自的位置。在整合模型的阶段,处理纹理坐标,根据各自的纹理所在“巨大纹理”图上的位置进行缩放。然后就OK了,还节省纹理通道,非常实用!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值