从前面可以看到人物角色显示是比较重要的,也是比较复杂的。现在就来仔细地分析一下第二人生里的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 {