科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道第二人生的源码分析(十五)Mesh文件的读取

第二人生的源码分析(十五)Mesh文件的读取

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

从前面可以看到人物角色显示是比较重要的,也是比较复杂的。现在就来仔细地分析一下第二人生里的Mesh文件是怎么样读取的呢?可以显示出来如此逼真优秀的画面。

作者:第二人生 来源:bolg【原创】 2008年1月17日

关键字: C++ Second Life caimouse 第二人生 软件

  • 评论
  • 分享微博
  • 分享邮件

从前面可以看到人物角色显示是比较重要的,也是比较复杂的。现在就来仔细地分析一下第二人生里的Mesh文件是怎么样读取的呢?可以显示出来如此逼真优秀的画面。如下图所示:

蔡军生  2008/01/15 QQ:9073204 深圳

Mesh文件保存的格式里,最常用的有两种格式:文本格式和二进制格式。文本格式就是占用空间比较大,并且读取文件的数据也比较慢,但它便于查看。二进制格式是刚好相反的,在第二人生里使用的是二进制的文件格式。它的读取代码如下:

 

#001  BOOL LLPolyMeshSharedData::loadMesh( const char *fileName )

#002  {

#003       //-------------------------------------------------------------------------

#004       // Open the file

#005       //-------------------------------------------------------------------------

#006       if(!fileName)

#007       {

#008              llerrs << "Filename is Empty!" << llendl;

#009              return FALSE;

#010       }

上面判断文件名称是否有效。

 

#011       FILE* fp = LLFile::fopen(fileName, "rb");               /*Flawfinder: ignore*/

#012       if (!fp)

#013       {

#014              llerrs << "can't open: " << fileName << llendl;

#015              return FALSE;

#016       }

以只读的方式打开文件。

 

#017 

#018       //-------------------------------------------------------------------------

#019       // Read a chunk

#020       //-------------------------------------------------------------------------

#021       char header[128];              /*Flawfinder: ignore*/

#022       if (fread(header, sizeof(char), 128, fp) != 128)

#023       {

#024              llwarns << "Short read" << llendl;

#025       }

读取第一块数据,大小为128个字节。这里也就是读取文件头。

 

#026 

#027       //-------------------------------------------------------------------------

#028       // Check for proper binary header

#029       //-------------------------------------------------------------------------

#030       BOOL status = FALSE;

#031       if ( strncmp(header, HEADER_BINARY, strlen(HEADER_BINARY)) == 0 )      /*Flawfinder: ignore*/

#032       {

上面是判断文件的版本。

 

#033              lldebugs << "Loading " << fileName << llendl;

#034 

#035              //----------------------------------------------------------------

#036              // File Header (seek past it)

#037              //----------------------------------------------------------------

#038              fseek(fp, 24, SEEK_SET);

移动文件指针到合适的位置。

 

#039 

#040              //----------------------------------------------------------------

#041              // HasWeights

#042              //----------------------------------------------------------------

#043              U8 hasWeights;

#044              size_t numRead = fread(&hasWeights, sizeof(U8), 1, fp);

#045              if (numRead != 1)

#046              {

#047                     llerrs << "can't read HasWeights flag from " << fileName << llendl;

#048                     return FALSE;

#049              }

#050              if (!isLOD())

#051              {

#052                     mHasWeights = (hasWeights==0) ? FALSE : TRUE;

#053              }

读取重量标志。

 

#054 

#055              //----------------------------------------------------------------

#056              // HasDetailTexCoords

#057              //----------------------------------------------------------------

#058              U8 hasDetailTexCoords;

#059              numRead = fread(&hasDetailTexCoords, sizeof(U8), 1, fp);

#060              if (numRead != 1)

#061              {

#062                     llerrs << "can't read HasDetailTexCoords flag from " << fileName << llendl;

#063                     return FALSE;

#064              }

读取是否有详细纹理坐标。

 

#065 

#066              //----------------------------------------------------------------

#067              // Position

#068              //----------------------------------------------------------------

#069              LLVector3 position;

#070              numRead = fread(position.mV, sizeof(float), 3, fp);

#071              llendianswizzle(position.mV, sizeof(float), 3);

#072              if (numRead != 3)

#073              {

#074                     llerrs << "can't read Position from " << fileName << llendl;

#075                     return FALSE;

#076              }

#077              setPosition( position );

读取网格所在的位置。

 

#078 

#079              //----------------------------------------------------------------

#080              // Rotation

#081              //----------------------------------------------------------------

#082              LLVector3 rotationAngles;

#083              numRead = fread(rotationAngles.mV, sizeof(float), 3, fp);

#084              llendianswizzle(rotationAngles.mV, sizeof(float), 3);

#085              if (numRead != 3)

#086              {

#087                     llerrs << "can't read RotationAngles from " << fileName << llendl;

#088                     return FALSE;

#089              }

读取网格旋转的角度。

 

 

#090 

#091              U8 rotationOrder;

#092              numRead = fread(&rotationOrder, sizeof(U8), 1, fp);

#093 

#094              if (numRead != 1)

#095              {

#096                     llerrs << "can't read RotationOrder from " << fileName << llendl;

#097                     return FALSE;

#098              }

#099 

#100              rotationOrder = 0;

#101 

#102              setRotation( mayaQ(  rotationAngles.mV[0],

#103                                                 rotationAngles.mV[1],

#104                                                 rotationAngles.mV[2],

#105                                                 (LLQuaternion::Order)rotationOrder ) );

读取网格旋转顺序。

 

 

#106 

#107              //----------------------------------------------------------------

#108              // Scale

#109              //----------------------------------------------------------------

#110              LLVector3 scale;

#111              numRead = fread(scale.mV, sizeof(float), 3, fp);

#112              llendianswizzle(scale.mV, sizeof(float), 3);

#113              if (numRead != 3)

#114              {

#115                     llerrs << "can't read Scale from " << fileName << llendl;

#116                     return FALSE;

#117              }

#118              setScale( scale );

读取网格缩放的大小。

 

#119 

#120              //-------------------------------------------------------------------------

#121              // Release any existing mesh geometry

#122              //-------------------------------------------------------------------------

#123              freeMeshData();

#124 

#125              U16 numVertices = 0;

#126 

#127              //----------------------------------------------------------------

#128              // NumVertices

#129              //----------------------------------------------------------------

#130              if (!isLOD())

#131              {

#132                     numRead = fread(&numVertices, sizeof(U16), 1, fp);

#133                     llendianswizzle(&numVertices, sizeof(U16), 1);

#134                     if (numRead != 1)

#135                     {

#136                            llerrs << "can't read NumVertices from " << fileName << llendl;

#137                            return FALSE;

#138                     }

#139 

#140                     allocateVertexData( numVertices );

读取网格的顶点数量,并分配顶点保存数据的内存。

 

#141 

#142                     //----------------------------------------------------------------

#143                     // Coords

#144                     //----------------------------------------------------------------

#145                     numRead = fread(mBaseCoords, 3*sizeof(float), numVertices, fp);

#146                     llendianswizzle(mBaseCoords, sizeof(float), 3*numVertices);

#147                     if (numRead != numVertices)

#148                     {

#149                            llerrs << "can't read Coordinates from " << fileName << llendl;

#150                            return FALSE;

#151                     }

#152 

上面读取网格所有顶点的坐标值。每个坐标有三个浮点数组成。

 

#153                     //----------------------------------------------------------------

#154                     // Normals

#155                     //----------------------------------------------------------------

#156                     numRead = fread(mBaseNormals, 3*sizeof(float), numVertices, fp);

#157                     llendianswizzle(mBaseNormals, sizeof(float), 3*numVertices);

#158                     if (numRead != numVertices)

#159                     {

#160                            llerrs << " can't read Normals from " << fileName << llendl;

#161                            return FALSE;

#162                     }

读取网格的顶点法向量。

 

#163 

#164                     //----------------------------------------------------------------

#165                     // Binormals

#166                     //----------------------------------------------------------------

#167                     numRead = fread(mBaseBinormals, 3*sizeof(float), numVertices, fp);

#168                     llendianswizzle(mBaseBinormals, sizeof(float), 3*numVertices);

#169                     if (numRead != numVertices)

#170                     {

#171                            llerrs << " can't read Binormals from " << fileName << llendl;

#172                            return FALSE;

#173                     }

读取网格的副法线向量。

 

#174 

#175 

#176                     //----------------------------------------------------------------

#177                     // TexCoords

#178                     //----------------------------------------------------------------

#179                     numRead = fread(mTexCoords, 2*sizeof(float), numVertices, fp);

#180                     llendianswizzle(mTexCoords, sizeof(float), 2*numVertices);

#181                     if (numRead != numVertices)

#182                     {

#183                            llerrs << "can't read TexCoords from " << fileName << llendl;

#184                            return FALSE;

#185                     }

读取每个顶点的纹理坐标值。

 

#186 

#187                     //----------------------------------------------------------------

#188                     // DetailTexCoords

#189                     //----------------------------------------------------------------

#190                     if (mHasDetailTexCoords)

#191                     {

#192                            numRead = fread(mDetailTexCoords, 2*sizeof(float), numVertices, fp);

#193                            llendianswizzle(mDetailTexCoords, sizeof(float), 2*numVertices);

#194                            if (numRead != numVertices)

#195                            {

#196                                   llerrs << "can't read DetailTexCoords from " << fileName << llendl;

#197                                   return FALSE;

#198                            }

#199                     }

读取详细纹理坐标值。

 

#200 

#201                     //----------------------------------------------------------------

#202                     // Weights

#203                     //----------------------------------------------------------------

#204                     if (mHasWeights)

#205                     {

#206                            numRead = fread(mWeights, sizeof(float), numVertices, fp);

#207                            llendianswizzle(mWeights, sizeof(float), numVertices);

#208                            if (numRead != numVertices)

#209                            {

#210                                   llerrs << "can't read Weights from " << fileName << llendl;

#211                                   return FALSE;

#212                            }

#213                     }

#214              }

读取每个顶点重量。

 

 

 

#215 

#216              //----------------------------------------------------------------

#217              // NumFaces

#218              //----------------------------------------------------------------

#219              U16 numFaces;

#220              numRead = fread(&numFaces, sizeof(U16), 1, fp);

#221              llendianswizzle(&numFaces, sizeof(U16), 1);

#222              if (numRead != 1)

#223              {

#224                     llerrs << "can't read NumFaces from " << fileName << llendl;

#225                     return FALSE;

#226              }

#227              allocateFaceData( numFaces );

读取网格的表面个数,并分配所有表面内存。

 

#228 

#229 

#230              //----------------------------------------------------------------

#231              // Faces

#232              //----------------------------------------------------------------

#233              U32 i;

#234              U32 numTris = 0;

#235              for (i = 0; i < numFaces; i++)

#236              {

#237                     S16 face[3];

#238                     numRead = fread(face, sizeof(U16), 3, fp);

#239                     llendianswizzle(face, sizeof(U16), 3);

#240                     if (numRead != 3)

#241                     {

#242                            llerrs << "can't read Face[" << i << "] from " << fileName << llendl;

#243                            return FALSE;

#244                     }

#245                     if (mReferenceData)

#246                     {

#247                            llassert(face[0] < mReferenceData->mNumVertices);

#248                            llassert(face[1] < mReferenceData->mNumVertices);

#249                            llassert(face[2] < mReferenceData->mNumVertices);

#250                     }

#251                    

#252                     if (isLOD())

#253                     {

#254                            // store largest index in case of LODs

#255                            for (S32 j = 0; j < 3; j++)

#256                            {

#257                                   if (face[j] > mNumVertices - 1)

#258                                   {

#259                                          mNumVertices = face[j] + 1;

#260                                   }

#261                            }

#262                     }

#263                     mFaces[i][0] = face[0];

#264                     mFaces[i][1] = face[1];

#265                     mFaces[i][2] = face[2];

#266 

#267  //                 S32 j;

#268  //                 for(j = 0; j < 3; j++)

#269  //                 {

#270  //                        LLDynamicArray<S32> *face_list = mVertFaceMap.getIfThere(face[j]);

#271  //                        if (!face_list)

#272  //                        {

#273  //                               face_list = new LLDynamicArray<S32>;

#274  //                               mVertFaceMap.addData(face[j], face_list);

#275  //                        }

#276  //                        face_list->put(i);

#277  //                 }

#278 

#279                     numTris++;

#280              }

#281 

#282              lldebugs << "verts: " << numVertices

#283                     << ", faces: "   << numFaces

#284                     << ", tris: "    << numTris

#285                     << llendl;

上面读取每个表面的索引值。

 

#286 

#287              //----------------------------------------------------------------

#288              // NumSkinJoints

#289              //----------------------------------------------------------------

#290              if (!isLOD())

#291              {

#292                     U16 numSkinJoints = 0;

#293                     if ( mHasWeights )

#294                     {

#295                            numRead = fread(&numSkinJoints, sizeof(U16), 1, fp);

#296                            llendianswizzle(&numSkinJoints, sizeof(U16), 1);

#297                            if (numRead != 1)

#298                            {

#299                                   llerrs << "can't read NumSkinJoints from " << fileName << llendl;

#300                                   return FALSE;

#301                            }

#302                            allocateJointNames( numSkinJoints );

#303                     }

读取有多少个联接名称。

 

#304 

#305                     //----------------------------------------------------------------

#306                     // SkinJoints

#307                     //----------------------------------------------------------------

#308                     for (i=0; i < numSkinJoints; i++)

#309                     {

#310                            char jointName[64+1];

#311                            numRead = fread(jointName, sizeof(jointName)-1, 1, fp);

#312                            jointName[sizeof(jointName)-1] = '\0'; // ensure nul-termination

#313                            if (numRead != 1)

#314                            {

#315                                   llerrs << "can't read Skin[" << i << "].Name from " << fileName << llendl;

#316                                   return FALSE;

#317                            }

#318 

#319                            std::string *jn = &mJointNames[i];

#320                            *jn = jointName;

#321                     }

#322 

读取联接名称。

 

 

#323                     //-------------------------------------------------------------------------

#324                     // look for morph section

#325                     //-------------------------------------------------------------------------

#326                     char morphName[64+1];

#327                     morphName[sizeof(morphName)-1] = '\0'; // ensure nul-termination

#328                     while(fread(&morphName, sizeof(char), 64, fp) == 64)

#329                     {

#330                            if (!strcmp(morphName, "End Morphs"))

#331                            {

#332                                   // we reached the end of the morphs

#333                                   break;

#334                            }

#335                            LLPolyMorphData* morph_data = new LLPolyMorphData(morphName);

#336 

#337                            BOOL result = morph_data->loadBinary(fp, this);

#338 

#339                            if (!result)

#340                            {

#341                                   delete morph_data;

#342                                   continue;

#343                            }

#344 

#345                            mMorphData.addData(morph_data);

#346                     }

#347 

#348                     S32 numRemaps;

#349                     if (fread(&numRemaps, sizeof(S32), 1, fp) == 1)

#350                     {

#351                            llendianswizzle(&numRemaps, sizeof(S32), 1);

#352                            for (S32 i = 0; i < numRemaps; i++)

#353                            {

#354                                   S32 remapSrc;

#355                                   S32 remapDst;

#356                                   if (fread(&remapSrc, sizeof(S32), 1, fp) != 1)

#357                                   {

#358                                          llerrs << "can't read source vertex in vertex remap data" << llendl;

#359                                          break;

#360                                   }

#361                                   if (fread(&remapDst, sizeof(S32), 1, fp) != 1)

#362                                   {

#363                                          llerrs << "can't read destination vertex in vertex remap data" << llendl;

#364                                          break;

#365                                   }

#366                                   llendianswizzle(&remapSrc, sizeof(S32), 1);

#367                                   llendianswizzle(&remapDst, sizeof(S32), 1);

#368 

#369                                   mSharedVerts[remapSrc] = remapDst;

#370                            }

#371                     }

#372              }

上面读取动画方面的数据。

 

#373 

#374              status = TRUE;

#375       }

#376       else

#377       {

#378              llerrs << "invalid mesh file header: " << fileName << llendl;

#379              status = FALSE;

#380       }

#381 

#382       if (0 == mNumJointNames)

#383       {

#384              allocateJointNames(1);

#385       }

#386 

#387       fclose( fp );

#388 

#389       return status;

#390  }

 原文链接:http://blog.csdn.net/caimouse/archive/2008/01/15/2046007.aspx

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章