zoukankan      html  css  js  c++  java
  • Small Tips : 如何整合3DS模型中的Obj

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

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

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

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

      解释一下思路。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了,还节省纹理通道,非常实用!
  • 相关阅读:
    windows批处理
    网络设备巡检命令
    DOS笔记
    通过一台服务器ssh多台主机远程修改网卡ip
    DELL服务器PXE前期处理
    PXE推一半失败,HP服务器、曙光服务器删除数据
    IBM存储降级告警等一些服务器问题/dd/ethtool
    bond下改变网卡
    AndroidStudio 点9图片文件报错
    在AndroidStudio不能找到so文件问题:couldn't find libweibosdkcore.so
  • 原文地址:https://www.cnblogs.com/Jedimaster/p/743322.html
Copyright © 2011-2022 走看看