IamEasy_Man

Filled With Confidence , And Never Say Give Up !

【摘录】读取MD2模型文件源码

 

  1 ///////////////////////////////////////MD2.H//////////////////////////////////////////////////
  2 #ifndef _MD2_H 
  3 #define _MD2_H 
  4  
  5 // These are the needed defines for the max values when loading .MD2 files 
  6 #define MD2_MAX_TRIANGLES        4096 
  7 #define MD2_MAX_VERTICES        2048 
  8 #define MD2_MAX_TEXCOORDS        2048 
  9 #define MD2_MAX_FRAMES            512 
 10 #define MD2_MAX_SKINS            32 
 11 #define MD2_MAX_FRAMESIZE        (MD2_MAX_VERTICES * 4 + 128) 
 12  
 13 // This holds the header information that is read in at the beginning of the file 
 14 struct tMd2Header 
 15 {  
 16    int magic;                    // This is used to identify the file 
 17    int version;                    // The version number of the file (Must be 8) 
 18    int skinWidth;                // The skin width in pixels 
 19    int skinHeight;                // The skin height in pixels 
 20    int frameSize;                // The size in bytes the frames are 
 21    int numSkins;                // The number of skins associated with the model 
 22    int numVertices;                // The number of vertices (constant for each frame) 
 23    int numTexCoords;            // The number of texture coordinates 
 24    int numTriangles;            // The number of faces (polygons) 
 25    int numGlCommands;            // The number of gl commands 
 26    int numFrames;                // The number of animation frames 
 27    int offsetSkins;                // The offset in the file for the skin data 
 28    int offsetTexCoords;            // The offset in the file for the texture data 
 29    int offsetTriangles;            // The offset in the file for the face data 
 30    int offsetFrames;            // The offset in the file for the frames data 
 31    int offsetGlCommands;        // The offset in the file for the gl commands data 
 32    int offsetEnd;                // The end of the file offset 
 33 }; 
 34  
 35  
 36 // This is used to store the vertices that are read in for the current frame 
 37 struct tMd2AliasTriangle 
 38 
 39    byte vertex[3]; 
 40    byte lightNormalIndex; 
 41 }; 
 42  
 43 // This stores the normals and vertices for the frames 
 44 struct tMd2Triangle 
 45 
 46    float vertex[3]; 
 47    float normal[3]; 
 48 }; 
 49  
 50 // This stores the indices into the vertex and texture coordinate arrays 
 51 struct tMd2Face 
 52 
 53    short vertexIndices[3]; 
 54    short textureIndices[3]; 
 55 }; 
 56  
 57 // This stores UV coordinates 
 58 struct tMd2TexCoord 
 59 
 60    short u, v; 
 61 }; 
 62  
 63 // This stores the animation scale, translation and name information for a frame, plus verts 
 64 struct tMd2AliasFrame 
 65 
 66    float scale[3]; 
 67    float translate[3]; 
 68    char name[16]; 
 69    tMd2AliasTriangle aliasVertices[1]; 
 70 }; 
 71  
 72 // This stores the frames vertices after they have been transformed 
 73 struct tMd2Frame 
 74 
 75    char strName[16]; 
 76    tMd2Triangle *pVertices; 
 77 }; 
 78  
 79 // This stores a skin name 
 80 typedef char tMd2Skin[64]; 
 81  
 82  
 83 // This class handles all of the loading code 
 84 class CLoadMD2 
 85 
 86  
 87 public
 88     CLoadMD2();                                // This inits the data members 
 89  
 90     // This is the function that you call to load the MD2 
 91     bool ImportMD2(t3DModel *pModel, char *strFileName, char *strTexture); 
 92  
 93 private
 94      
 95     // This reads in the data from the MD2 file and stores it in the member variables 
 96     void ReadMD2Data(); 
 97  
 98     // This converts the member variables to our pModel structure 
 99     void ConvertDataStructures(t3DModel *pModel); 
100  
101     // This computes the vertex normals for the object (used for lighting) 
102     void ComputeNormals(t3DModel *pModel); 
103  
104     // This frees memory and closes the file 
105     void CleanUp(); 
106      
107     // The file pointer 
108     FILE *m_FilePointer; 
109  
110     // Member variables         
111  
112     tMd2Header                m_Header;            // The header data 
113     tMd2Skin                *m_pSkins;            // The skin data 
114     tMd2TexCoord            *m_pTexCoords;        // The texture coordinates 
115     tMd2Face                *m_pTriangles;        // Face index information 
116     tMd2Frame                *m_pFrames;            // The frames of animation (vertices) 
117 }; 
118  
119  
120 #endif 
121  
122  
123 ///////////////////////////////////////////////////////////////////////////////// 
124 // 
125 // * QUICK NOTES *  
126 //  
127 // This file holds all of the structure and class definitions needed to load 
128 // a MD2 Quake2 file. 
129 // 
130 //  
131 // Ben Humphrey (DigiBen) 
132 // Game Programmer 
133 // DigiBen@GameTutorials.com 
134 // Co-Web Host of www.GameTutorials.com 
135 // 
136 // The Quake2 .Md2 file format is owned by ID Software.  This tutorial is being used  
137 // as a teaching tool to help understand model loading and animation.  This should 
138 // not be sold or used under any way for commercial use with out written conset 
139 // from ID Software. 
140 // 
141 // Quake and Quake2 are trademarks of id Software. 
142 // All trademarks used are properties of their respective owners.  
143 // 
144 //  
145  
146  
147  
148  ///////////////////////////////////////MD2.CPP//////////////////////////////////////////////////
149  //***********************************************************************//   
150 //                                                                       //   
151 //      - "Talk to me like I'm a 3 year old!" Programming Lessons -      //   
152 //                                                                       //   
153 //      $Author:        DigiBen     digiben@gametutorials.com            //   
154 //                                                                       //   
155 //      $Program:       MD2 Loader                                       //   
156 //                                                                       //   
157 //      $Description:   Demonstrates how to load a Quake2 MD2 Model      //   
158 //                                                                       //   
159 //      $Date:          2/6/02                                           //   
160 //                                                                       //   
161 //***********************************************************************//   
162    
163    
164 #include "main.h"   
165 #include "Md2.h"   
166    
167    
168 /////////////////////////////////////////////////////////////////////////   
169 //   
170 // This file holds the code to load the Quake2 models from a .Md2 format.   
171 // The .Md2 file is usually stored in a .zip file (don't let the extension   
172 // fool you, just rename it to .zip), depending on where you get the models   
173 // from.  The CLoadMD2 class handles the loading, but we draw the model   
174 // externally on our own in main.cpp.  I created a converter function   
175 // to convert to our already used model and object structures.  This way   
176 // eventually we can create a model library that can load any type of   
177 // model that we support, as well as use inheritance to create a new class   
178 // for each file format for the small things that each model format needs differently.   
179 // Like the other loading tutorials, we calculate our own vertex normals.   
180 // The .Md2 format is REALLY simple to load.  That is why I chose it.  The   
181 // next tutorial will show how to load and animate Md2 files.  Next, we   
182 // will move from key frame animation to skeletal animation with the Quake3   
183 // .Md3 files.  This is also a wonderfuly easy format to load and use.   
184 //   
185 //   
186    
187    
188 ///////////////////////////////// CLOAD MD2 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*   
189 /////   
190 /////   This constructor initializes the md2 structures   
191 /////   
192 ///////////////////////////////// CLOAD MD2 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*   
193    
194 CLoadMD2::CLoadMD2()   
195 {   
196     // Here we initialize our structures to 0   
197     memset(&m_Header, 0sizeof(tMd2Header));   
198    
199     // Set the pointers to null   
200     m_pSkins=NULL;   
201     m_pTexCoords=NULL;   
202     m_pTriangles=NULL;   
203     m_pFrames=NULL;   
204 }   
205    
206    
207 ///////////////////////////////// IMPORT MD2 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*   
208 /////   
209 /////   This is called by the client to open the .Md2 file, read it, then clean up   
210 /////   
211 ///////////////////////////////// IMPORT MD2 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*   
212    
213 bool CLoadMD2::ImportMD2(t3DModel *pModel, char *strFileName, char *strTexture)   
214 {   
215     char strMessage[255= {0};   
216    
217     // Open the MD2 file in binary   
218     m_FilePointer = fopen(strFileName, "rb");   
219    
220     // Make sure we have a valid file pointer (we found the file)   
221     if(!m_FilePointer)    
222     {   
223         // Display an error message and don't load anything if no file was found   
224         sprintf(strMessage, "Unable to find the file: %s!", strFileName);   
225         MessageBox(NULL, strMessage, "Error", MB_OK);   
226         return false;   
227     }   
228        
229     // Just like most file formats, there is a header that needs to be read   
230     // from the .Md2 format.  If you look at the tMd2Header structure you will   
231     // find all the data that will be read in.  It's nice to know up front about   
232     // the data that we will be reading.  This makes it easy to just to large   
233     // binary reads using fread, instead of counting and reading chunks.   
234    
235     // Read the header data and store it in our m_Header member variable   
236     fread(&m_Header, 1sizeof(tMd2Header), m_FilePointer);   
237    
238     // For some reason, .Md2 files MUST have a version of 8.  I am not sure why,   
239     // but if it doesn't there is something wrong and the header was read in   
240     // incorrectly, or perhaps the file format is bad.   
241     if(m_Header.version != 8)   
242     {   
243         // Display an error message for bad file format, then stop loading   
244         sprintf(strMessage, "Invalid file format (Version not 8): %s!", strFileName);   
245         MessageBox(NULL, strMessage, "Error", MB_OK);   
246         return false;   
247     }   
248    
249     // Now that we made sure the header had correct data, we want to read in the   
250     // rest of the data.  Once the data is read in, we need to convert it to our structures.   
251     // Since we are only reading in the first frame of animation, there will only   
252     // be ONE object in our t3DObject structure, held within our pModel variable.   
253     ReadMD2Data();   
254        
255     // Here we pass in our model structure to it can store the read Quake data   
256     // in our own model and object structure data   
257     ConvertDataStructures(pModel);   
258    
259     // After we have read the whole MD2 file, we want to calculate our own vertex normals.   
260     ComputeNormals(pModel);   
261    
262     // If there is a valid texture name passed in, we want to set the texture data   
263     if(strTexture)   
264     {   
265         // Create a local material info structure   
266         tMaterialInfo texture;   
267    
268         // Copy the name of the file into our texture file name variable   
269         strcpy(texture.strFile, strTexture);   
270    
271         // Since there is only one texture for a .Md2 file, the ID is always 0   
272         texture.texureId = 0;   
273    
274         // The tile or scale for the UV's is 1 to 1 (but Quake saves off a 0-256 ratio)   
275         texture.uTile = texture.uTile = 1;   
276    
277         // We only have 1 material for a model   
278         pModel->numOfMaterials = 1;   
279    
280         // Add the local material info to our model's material list   
281         pModel->pMaterials.push_back(texture);   
282     }   
283    
284     // Clean up after everything   
285     CleanUp();   
286    
287     // Return a success   
288     return true;   
289 }   
290    
291    
292 ///////////////////////////////// READ MD2 DATA \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*   
293 /////   
294 /////   This function reads in all of the model's data, except the animation frames   
295 /////   
296 ///////////////////////////////// READ MD2 DATA \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*   
297    
298 void CLoadMD2::ReadMD2Data()   
299 {   
300     // Create a larger buffer for the frames of animation (not fully used yet)   
301     unsigned char buffer[MD2_MAX_FRAMESIZE];   
302     int j = 0;   
303    
304     // Here we allocate all of our memory from the header's information   
305     m_pSkins     = new tMd2Skin [m_Header.numSkins];   
306     m_pTexCoords = new tMd2TexCoord [m_Header.numTexCoords];   
307     m_pTriangles = new tMd2Face [m_Header.numTriangles];   
308     m_pFrames    = new tMd2Frame [m_Header.numFrames];   
309    
310     // Next, we start reading in the data by seeking to our skin names offset   
311     fseek(m_FilePointer, m_Header.offsetSkins, SEEK_SET);   
312        
313     // Depending on the skin count, we read in each skin for this model   
314     fread(m_pSkins, sizeof(tMd2Skin), m_Header.numSkins, m_FilePointer);   
315        
316     // Move the file pointer to the position in the file for texture coordinates   
317     fseek(m_FilePointer, m_Header.offsetTexCoords, SEEK_SET);   
318        
319     // Read in all the texture coordinates in one fell swoop   
320     fread(m_pTexCoords, sizeof(tMd2TexCoord), m_Header.numTexCoords, m_FilePointer);   
321    
322     // Move the file pointer to the triangles/face data offset   
323     fseek(m_FilePointer, m_Header.offsetTriangles, SEEK_SET);   
324        
325     // Read in the face data for each triangle (vertex and texCoord indices)   
326     fread(m_pTriangles, sizeof(tMd2Face), m_Header.numTriangles, m_FilePointer);   
327                
328     // Move the file pointer to the vertices (frames)   
329     fseek(m_FilePointer, m_Header.offsetFrames, SEEK_SET);   
330    
331     // Assign our alias frame to our buffer memory   
332     tMd2AliasFrame *pFrame = (tMd2AliasFrame *) buffer;   
333    
334     // Allocate the memory for the first frame of animation's vertices   
335     m_pFrames[0].pVertices = new tMd2Triangle [m_Header.numVertices];   
336    
337     // Read in the first frame of animation   
338     fread(pFrame, 1, m_Header.frameSize, m_FilePointer);   
339    
340     // Copy the name of the animation to our frames array   
341     strcpy(m_pFrames[0].strName, pFrame->name);   
342                
343     // After we have read in the data for the model, since there is animation,   
344     // This means that there are scale and translation values to be dealt with.   
345     // To apply the scale and translation values, we simply multiply the scale (x, y, z)   
346     // by the current vertex (x, y, z).  Also notice that we switch the Y and Z values   
347     // so that Y is faces up, NOT Z.   
348        
349     // Store off a vertex array pointer to cut down large lines of code   
350     tMd2Triangle *pVertices = m_pFrames[0].pVertices;   
351    
352     // Go through all of the number of vertices and assign the scale and translations.   
353     // Store the vertices in our current frame's vertex list array, while swapping Y and Z.   
354     // Notice we also negate the Z axis as well to make the swap correctly.   
355     for (j=0; j < m_Header.numVertices; j++)   
356     {   
357         pVertices[j].vertex[0= pFrame->aliasVertices[j].vertex[0* pFrame->scale[0+ pFrame->translate[0];   
358         pVertices[j].vertex[2= -1 * (pFrame->aliasVertices[j].vertex[1* pFrame->scale[1+ pFrame->translate[1]);   
359         pVertices[j].vertex[1= pFrame->aliasVertices[j].vertex[2* pFrame->scale[2+ pFrame->translate[2];   
360     }   
361 }   
362    
363    
364 ///////////////////////////////// CONVERT DATA STRUCTURES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*   
365 /////   
366 /////   This function converts the .md2 structures to our own model and object structures   
367 /////   
368 ///////////////////////////////// CONVERT DATA STRUCTURES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*   
369    
370 void CLoadMD2::ConvertDataStructures(t3DModel *pModel)   
371 {   
372     int j = 0, i = 0;   
373        
374     // Assign the number of objects, which is 1 since we only want 1 frame   
375     // of animation.  In the next tutorial each object will be a key frame   
376     // to interpolate between.   
377     pModel->numOfObjects = 1;   
378    
379     // Create a local object to store the first frame of animation's data   
380     t3DObject currentFrame = {0};   
381    
382     // Assign the vertex, texture coord and face count to our new structure   
383     currentFrame.numOfVerts   = m_Header.numVertices;   
384     currentFrame.numTexVertex = m_Header.numTexCoords;   
385     currentFrame.numOfFaces   = m_Header.numTriangles;   
386    
387     // Allocate memory for the vertices, texture coordinates and face data.   
388     currentFrame.pVerts    = new CVector3 [currentFrame.numOfVerts];   
389     currentFrame.pTexVerts = new CVector2 [currentFrame.numTexVertex];   
390     currentFrame.pFaces    = new tFace [currentFrame.numOfFaces];   
391    
392     // Go through all of the vertices and assign them over to our structure   
393     for (j=0; j < currentFrame.numOfVerts; j++)   
394     {   
395         currentFrame.pVerts[j].x = m_pFrames[0].pVertices[j].vertex[0];   
396         currentFrame.pVerts[j].y = m_pFrames[0].pVertices[j].vertex[1];   
397         currentFrame.pVerts[j].z = m_pFrames[0].pVertices[j].vertex[2];   
398     }   
399    
400     // We can now free the old vertices stored in this frame of animation   
401     delete m_pFrames[0].pVertices;   
402    
403     // Go through all of the uv coordinates and assign them over to our structure.   
404     // The UV coordinates are not normal uv coordinates, they have a pixel ratio of   
405     // 0 to 256.  We want it to be a 0 to 1 ratio, so we divide the u value by the   
406     // skin width and the v value by the skin height.  This gives us our 0 to 1 ratio.   
407     // For some reason also, the v coodinate is flipped upside down.  We just subtract   
408     // the v coordinate from 1 to remedy this problem.   
409     for (j=0; j < currentFrame.numTexVertex; j++)   
410     {   
411         currentFrame.pTexVerts[j].x = m_pTexCoords[j].u / float(m_Header.skinWidth);   
412         currentFrame.pTexVerts[j].y = 1 - m_pTexCoords[j].v / float(m_Header.skinHeight);   
413     }   
414    
415     // Go through all of the face data and assign it over to OUR structure   
416     for(j=0; j < currentFrame.numOfFaces; j++)   
417     {   
418         // Assign the vertex indices to our face data   
419         currentFrame.pFaces[j].vertIndex[0= m_pTriangles[j].vertexIndices[0];   
420         currentFrame.pFaces[j].vertIndex[1= m_pTriangles[j].vertexIndices[1];   
421         currentFrame.pFaces[j].vertIndex[2= m_pTriangles[j].vertexIndices[2];   
422    
423         // Assign the texture coord indices to our face data   
424         currentFrame.pFaces[j].coordIndex[0= m_pTriangles[j].textureIndices[0];   
425         currentFrame.pFaces[j].coordIndex[1= m_pTriangles[j].textureIndices[1];   
426         currentFrame.pFaces[j].coordIndex[2= m_pTriangles[j].textureIndices[2];   
427     }   
428    
429     // Here we add the current object (or frame) to our list object list   
430     pModel->pObject.push_back(currentFrame);   
431 }   
432    
433    
434 ///////////////////////////////// CLEAN UP \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*   
435 /////   
436 /////   This function cleans up our allocated memory and closes the file   
437 /////   
438 ///////////////////////////////// CLEAN UP \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*   
439    
440 void CLoadMD2::CleanUp()   
441 {   
442     // This just just the regular cleanup or our md2 model class.  We can free   
443     // all of this data because we already have it stored in our own structures.   
444    
445     fclose(m_FilePointer);                      // Close the current file pointer   
446    
447     if(m_pSkins)     delete [] m_pSkins;        // Free the skins data   
448     if(m_pTexCoords) delete m_pTexCoords;       // Free the texture coord data   
449     if(m_pTriangles) delete m_pTriangles;       // Free the triangle face data   
450     if(m_pFrames)    delete m_pFrames;          // Free the frames of animation   
451 }   
452    
453    
454    
455 // *Note*    
456 //   
457 // Below are some math functions for calculating vertex normals.  We want vertex normals   
458 // because it makes the lighting look really smooth and life like.  You probably already   
459 // have these functions in the rest of your engine, so you can delete these and call   
460 // your own.  I wanted to add them so I could show how to calculate vertex normals.   
461    
462 //////////////////////////////  Math Functions  ////////////////////////////////*   
463    
464 // This computes the magnitude of a normal.   (magnitude = sqrt(x^2 + y^2 + z^2)   
465 #define Mag(Normal) (sqrt(Normal.x*Normal.x + Normal.y*Normal.y + Normal.z*Normal.z))   
466    
467 // This calculates a vector between 2 points and returns the result   
468 CVector3 Vector(CVector3 vPoint1, CVector3 vPoint2)   
469 {   
470     CVector3 vVector;                           // The variable to hold the resultant vector   
471    
472     vVector.x = vPoint1.x - vPoint2.x;          // Subtract point1 and point2 x's   
473     vVector.y = vPoint1.y - vPoint2.y;          // Subtract point1 and point2 y's   
474     vVector.z = vPoint1.z - vPoint2.z;          // Subtract point1 and point2 z's   
475    
476     return vVector;                             // Return the resultant vector   
477 }   
478    
479 // This adds 2 vectors together and returns the result   
480 CVector3 AddVector(CVector3 vVector1, CVector3 vVector2)   
481 {   
482     CVector3 vResult;                           // The variable to hold the resultant vector   
483        
484     vResult.x = vVector2.x + vVector1.x;        // Add Vector1 and Vector2 x's   
485     vResult.y = vVector2.y + vVector1.y;        // Add Vector1 and Vector2 y's   
486     vResult.z = vVector2.z + vVector1.z;        // Add Vector1 and Vector2 z's   
487    
488     return vResult;                             // Return the resultant vector   
489 }   
490    
491 // This divides a vector by a single number (scalar) and returns the result   
492 CVector3 DivideVectorByScaler(CVector3 vVector1, float Scaler)   
493 {   
494     CVector3 vResult;                           // The variable to hold the resultant vector   
495        
496     vResult.x = vVector1.x / Scaler;            // Divide Vector1's x value by the scaler   
497     vResult.y = vVector1.y / Scaler;            // Divide Vector1's y value by the scaler   
498     vResult.z = vVector1.z / Scaler;            // Divide Vector1's z value by the scaler   
499    
500     return vResult;                             // Return the resultant vector   
501 }   
502    
503 // This returns the cross product between 2 vectors   
504 CVector3 Cross(CVector3 vVector1, CVector3 vVector2)   
505 {   
506     CVector3 vCross;                                // The vector to hold the cross product   
507                                                 // Get the X value   
508     vCross.x = ((vVector1.y * vVector2.z) - (vVector1.z * vVector2.y));   
509                                                 // Get the Y value   
510     vCross.y = ((vVector1.z * vVector2.x) - (vVector1.x * vVector2.z));   
511                                                 // Get the Z value   
512     vCross.z = ((vVector1.x * vVector2.y) - (vVector1.y * vVector2.x));   
513    
514     return vCross;                              // Return the cross product   
515 }   
516    
517 // This returns the normal of a vector   
518 CVector3 Normalize(CVector3 vNormal)   
519 {   
520     double Magnitude;                           // This holds the magitude             
521    
522     Magnitude = Mag(vNormal);                   // Get the magnitude   
523    
524     vNormal.x /= (float)Magnitude;              // Divide the vector's X by the magnitude   
525     vNormal.y /= (float)Magnitude;              // Divide the vector's Y by the magnitude   
526     vNormal.z /= (float)Magnitude;              // Divide the vector's Z by the magnitude   
527    
528     return vNormal;                             // Return the normal   
529 }   
530    
531 ///////////////////////////////// COMPUTER NORMALS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*   
532 /////   
533 /////   This function computes the normals and vertex normals of the objects   
534 /////   
535 ///////////////////////////////// COMPUTER NORMALS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*   
536    
537 void CLoadMD2::ComputeNormals(t3DModel *pModel)   
538 {   
539     CVector3 vVector1, vVector2, vNormal, vPoly[3];   
540    
541     // If there are no objects, we can skip this part   
542     if(pModel->numOfObjects <= 0)   
543         return;   
544    
545     // What are vertex normals?  And how are they different from other normals?   
546     // Well, if you find the normal to a triangle, you are finding a "Face Normal".   
547     // If you give OpenGL a face normal for lighting, it will make your object look   
548     // really flat and not very round.  If we find the normal for each vertex, it makes   
549     // the smooth lighting look.  This also covers up blocky looking objects and they appear   
550     // to have more polygons than they do.    Basically, what you do is first   
551     // calculate the face normals, then you take the average of all the normals around each   
552     // vertex.  It's just averaging.  That way you get a better approximation for that vertex.   
553    
554     // Go through each of the objects to calculate their normals   
555     for(int index = 0; index < pModel->numOfObjects; index++)   
556     {   
557         // Get the current object   
558         t3DObject *pObject = &(pModel->pObject[index]);   
559    
560         // Here we allocate all the memory we need to calculate the normals   
561         CVector3 *pNormals      = new CVector3 [pObject->numOfFaces];   
562         CVector3 *pTempNormals  = new CVector3 [pObject->numOfFaces];   
563         pObject->pNormals        = new CVector3 [pObject->numOfVerts];   
564    
565         // Go though all of the faces of this object   
566         for(int i=0; i < pObject->numOfFaces; i++)   
567         {                                                  
568             // To cut down LARGE code, we extract the 3 points of this face   
569             vPoly[0= pObject->pVerts[pObject->pFaces[i].vertIndex[0]];   
570             vPoly[1= pObject->pVerts[pObject->pFaces[i].vertIndex[1]];   
571             vPoly[2= pObject->pVerts[pObject->pFaces[i].vertIndex[2]];   
572    
573             // Now let's calculate the face normals (Get 2 vectors and find the cross product of those 2)   
574    
575             vVector1 = Vector(vPoly[0], vPoly[2]);      // Get the vector of the polygon (we just need 2 sides for the normal)   
576             vVector2 = Vector(vPoly[2], vPoly[1]);      // Get a second vector of the polygon   
577    
578             vNormal  = Cross(vVector1, vVector2);       // Return the cross product of the 2 vectors (normalize vector, but not a unit vector)   
579             pTempNormals[i] = vNormal;                  // Save the un-normalized normal for the vertex normals   
580             vNormal  = Normalize(vNormal);              // Normalize the cross product to give us the polygons normal   
581    
582             pNormals[i] = vNormal;                      // Assign the normal to the list of normals   
583         }   
584    
585         //////////////// Now Get The Vertex Normals /////////////////   
586    
587         CVector3 vSum = {0.00.00.0};   
588         CVector3 vZero = vSum;   
589         int shared=0;   
590    
591         for (i = 0; i < pObject->numOfVerts; i++)         // Go through all of the vertices   
592         {   
593             for (int j = 0; j < pObject->numOfFaces; j++// Go through all of the triangles   
594             {                                               // Check if the vertex is shared by another face   
595                 if (pObject->pFaces[j].vertIndex[0== i ||    
596                     pObject->pFaces[j].vertIndex[1== i ||    
597                     pObject->pFaces[j].vertIndex[2== i)   
598                 {   
599                     vSum = AddVector(vSum, pTempNormals[j]);// Add the un-normalized normal of the shared face   
600                     shared++;                               // Increase the number of shared triangles   
601                 }   
602             }         
603                
604             // Get the normal by dividing the sum by the shared.  We negate the shared so it has the normals pointing out.   
605             pObject->pNormals[i] = DivideVectorByScaler(vSum, float(-shared));   
606    
607             // Normalize the normal for the final vertex normal   
608             pObject->pNormals[i] = Normalize(pObject->pNormals[i]);      
609    
610             vSum = vZero;                                   // Reset the sum   
611             shared = 0;                                     // Reset the shared   
612         }   
613        
614         // Free our memory and start over on the next object   
615         delete [] pTempNormals;   
616         delete [] pNormals;   
617     }   
618 }   
619    
620    
621 /////////////////////////////////////////////////////////////////////////////////   
622 //   
623 // * QUICK NOTES *    
624 //   
625 // Pretty simple huh?  This is probably the easiest 3D file format I have ever   
626 // worked with, so good job Carmack!  Once again, the next Md2 tutorial will cover   
627 // the key frame animation that is associated with these models.  Then you can    
628 // actually say you have worked with real quake characters and know how they did   
629 // their animation.  Let's go over a brief explanation of this loader:   
630 //   
631 // The structures MUST be the same size and data types in order to load the   
632 // Quake2 data.  First we load the Header information.  This tells us everything   
633 // about the file and it's contents.   
634 //    
635 // After the header is loaded, we need to check if the ID is 8.  This is a must.   
636 // Don't ask me why it's 8, ask John Carmack!  If the version ID checks out, then   
637 // we can start loading the data.   
638 //    
639 // For each set of data you want to load is, we use an fseek() to move the file   
640 // pointer to that location in the file that is given in the header.   
641 //   
642 // After you load the data, you can then convert the data structures to your own   
643 // format, that way you don't have ot be stuck with theirs.  I decided to make it   
644 // like the other loaders for future purposes.  We also compute our own normals.   
645 //   
646 // There is one thing I didn't mention that was NOT loaded in.  There is an array   
647 // of OpenGL commands that allow you to render the vertices in triangle strips and   
648 // a triangle fan.  This is the ugliest code I have ever seen to implement it, so   
649 // I left it out :)   
650 //   
651 // I would like to thank Daniel E. Schoenblum <dansch@hops.cs.jhu.edu> for help   
652 // with explaining the file format.   
653 //   
654 // Let me know if this helps you out!   
655 //    
656 //    
657 // Ben Humphrey (DigiBen)   
658 // Game Programmer   
659 // DigiBen@GameTutorials.com   
660 // Co-Web Host of www.GameTutorials.com   
661 //   
662 // The Quake2 .Md2 file format is owned by ID Software.  This tutorial is being used    
663 // as a teaching tool to help understand model loading and animation.  This should   
664 // not be sold or used under any way for commercial use with out written conset   
665 // from ID Software.   
666 //   
667 // Quake and Quake2 are trademarks of id Software.   
668 // All trademarks used are properties of their respective owners.    
669 //   
670 //   
671  
672  

 

 

posted on 2010-03-17 20:41  IamEasy_Man  阅读(1127)  评论(0编辑  收藏  举报

导航