【摘录】读取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, 0, sizeof(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, 1, sizeof(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.0, 0.0, 0.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
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, 0, sizeof(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, 1, sizeof(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.0, 0.0, 0.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) 编辑 收藏 举报