Md2.cpp
上传用户:mywjrx
上传日期:2008-01-23
资源大小:703k
文件大小:21k
源码类别:

射击游戏

开发平台:

Visual C++

  1. //***********************************************************************//
  2. //  //
  3. // - "Talk to me like I'm a 3 year old!" Programming Lessons -  //
  4. //                                                                       //
  5. // $Author: DigiBen digiben@gametutorials.com  //
  6. //  //
  7. // $Program: MD2 Loader  //
  8. //  //
  9. // $Description: Demonstrates how to load a Quake2 MD2 Model  //
  10. //  //
  11. // $Date: 2/6/02  //
  12. //  //
  13. //***********************************************************************//
  14. #include "main.h"
  15. #include "Md2.h"
  16. /////////////////////////////////////////////////////////////////////////
  17. //
  18. // This file holds the code to load the Quake2 models from a .Md2 format.
  19. // The .Md2 file is usually stored in a .zip file (don't let the extension
  20. // fool you, just rename it to .zip), depending on where you get the models
  21. // from.  The CLoadMD2 class handles the loading, but we draw the model
  22. // externally on our own in main.cpp.  I created a converter function
  23. // to convert to our already used model and object structures.  This way
  24. // eventually we can create a model library that can load any type of
  25. // model that we support, as well as use inheritance to create a new class
  26. // for each file format for the small things that each model format needs differently.
  27. // Like the other loading tutorials, we calculate our own vertex normals.
  28. // The .Md2 format is REALLY simple to load.  That is why I chose it.  The
  29. // next tutorial will show how to load and animate Md2 files.  Next, we
  30. // will move from key frame animation to skeletal animation with the Quake3
  31. // .Md3 files.  This is also a wonderfuly easy format to load and use.
  32. //
  33. //
  34. ///////////////////////////////// CLOAD MD2 \\\\\\\\\\\\\\\\*
  35. /////
  36. ///// This constructor initializes the md2 structures
  37. /////
  38. ///////////////////////////////// CLOAD MD2 \\\\\\\\\\\\\\\\*
  39. CLoadMD2::CLoadMD2()
  40. {
  41. // Here we initialize our structures to 0
  42. memset(&m_Header, 0, sizeof(tMd2Header));
  43. // Set the pointers to null
  44. m_pSkins=NULL;
  45. m_pTexCoords=NULL;
  46. m_pTriangles=NULL;
  47. m_pFrames=NULL;
  48. }
  49. ///////////////////////////////// IMPORT MD2 \\\\\\\\\\\\\\\\*
  50. /////
  51. ///// This is called by the client to open the .Md2 file, read it, then clean up
  52. /////
  53. ///////////////////////////////// IMPORT MD2 \\\\\\\\\\\\\\\\*
  54. bool CLoadMD2::ImportMD2(t3DModel *pModel, char *strFileName, char *strTexture)
  55. {
  56. char strMessage[255] = {0};
  57. // Open the MD2 file in binary
  58. m_FilePointer = fopen(strFileName, "rb");
  59. // Make sure we have a valid file pointer (we found the file)
  60. if(!m_FilePointer) 
  61. {
  62. // Display an error message and don't load anything if no file was found
  63. sprintf(strMessage, "Unable to find the file: %s!", strFileName);
  64. MessageBox(NULL, strMessage, "Error", MB_OK);
  65. return false;
  66. }
  67. // Just like most file formats, there is a header that needs to be read
  68. // from the .Md2 format.  If you look at the tMd2Header structure you will
  69. // find all the data that will be read in.  It's nice to know up front about
  70. // the data that we will be reading.  This makes it easy to just to large
  71. // binary reads using fread, instead of counting and reading chunks.
  72. // Read the header data and store it in our m_Header member variable
  73. fread(&m_Header, 1, sizeof(tMd2Header), m_FilePointer);
  74. // For some reason, .Md2 files MUST have a version of 8.  I am not sure why,
  75. // but if it doesn't there is something wrong and the header was read in
  76. // incorrectly, or perhaps the file format is bad.
  77. if(m_Header.version != 8)
  78. {
  79. // Display an error message for bad file format, then stop loading
  80. sprintf(strMessage, "Invalid file format (Version not 8): %s!", strFileName);
  81. MessageBox(NULL, strMessage, "Error", MB_OK);
  82. return false;
  83. }
  84. // Now that we made sure the header had correct data, we want to read in the
  85. // rest of the data.  Once the data is read in, we need to convert it to our structures.
  86. // Since we are only reading in the first frame of animation, there will only
  87. // be ONE object in our t3DObject structure, held within our pModel variable.
  88. ReadMD2Data();
  89. // Here we pass in our model structure to it can store the read Quake data
  90. // in our own model and object structure data
  91. ConvertDataStructures(pModel);
  92. // After we have read the whole MD2 file, we want to calculate our own vertex normals.
  93. ComputeNormals(pModel);
  94. // If there is a valid texture name passed in, we want to set the texture data
  95. if(strTexture)
  96. {
  97. // Create a local material info structure
  98. tMaterialInfo texture;
  99. // Copy the name of the file into our texture file name variable
  100. strcpy(texture.strFile, strTexture);
  101. // Since there is only one texture for a .Md2 file, the ID is always 0
  102. texture.texureId = 0;
  103. // The tile or scale for the UV's is 1 to 1 (but Quake saves off a 0-256 ratio)
  104. texture.uTile = texture.uTile = 1;
  105. // We only have 1 material for a model
  106. pModel->numOfMaterials = 1;
  107. // Add the local material info to our model's material list
  108. pModel->pMaterials.push_back(texture);
  109. }
  110. // Clean up after everything
  111. CleanUp();
  112. // Return a success
  113. return true;
  114. }
  115. ///////////////////////////////// READ MD2 DATA \\\\\\\\\\\\\\\\*
  116. /////
  117. ///// This function reads in all of the model's data, except the animation frames
  118. /////
  119. ///////////////////////////////// READ MD2 DATA \\\\\\\\\\\\\\\\*
  120. void CLoadMD2::ReadMD2Data()
  121. {
  122. // Create a larger buffer for the frames of animation (not fully used yet)
  123. unsigned char buffer[MD2_MAX_FRAMESIZE];
  124. int j = 0;
  125. // Here we allocate all of our memory from the header's information
  126. m_pSkins     = new tMd2Skin [m_Header.numSkins];
  127. m_pTexCoords = new tMd2TexCoord [m_Header.numTexCoords];
  128. m_pTriangles = new tMd2Face [m_Header.numTriangles];
  129. m_pFrames    = new tMd2Frame [m_Header.numFrames];
  130. // Next, we start reading in the data by seeking to our skin names offset
  131. fseek(m_FilePointer, m_Header.offsetSkins, SEEK_SET);
  132. // Depending on the skin count, we read in each skin for this model
  133. fread(m_pSkins, sizeof(tMd2Skin), m_Header.numSkins, m_FilePointer);
  134. // Move the file pointer to the position in the file for texture coordinates
  135. fseek(m_FilePointer, m_Header.offsetTexCoords, SEEK_SET);
  136. // Read in all the texture coordinates in one fell swoop
  137. fread(m_pTexCoords, sizeof(tMd2TexCoord), m_Header.numTexCoords, m_FilePointer);
  138. // Move the file pointer to the triangles/face data offset
  139. fseek(m_FilePointer, m_Header.offsetTriangles, SEEK_SET);
  140. // Read in the face data for each triangle (vertex and texCoord indices)
  141. fread(m_pTriangles, sizeof(tMd2Face), m_Header.numTriangles, m_FilePointer);
  142. // Move the file pointer to the vertices (frames)
  143. fseek(m_FilePointer, m_Header.offsetFrames, SEEK_SET);
  144. // Assign our alias frame to our buffer memory
  145. tMd2AliasFrame *pFrame = (tMd2AliasFrame *) buffer;
  146. // Allocate the memory for the first frame of animation's vertices
  147. m_pFrames[0].pVertices = new tMd2Triangle [m_Header.numVertices];
  148. // Read in the first frame of animation
  149. fread(pFrame, 1, m_Header.frameSize, m_FilePointer);
  150. // Copy the name of the animation to our frames array
  151. strcpy(m_pFrames[0].strName, pFrame->name);
  152. // After we have read in the data for the model, since there is animation,
  153. // This means that there are scale and translation values to be dealt with.
  154. // To apply the scale and translation values, we simply multiply the scale (x, y, z)
  155. // by the current vertex (x, y, z).  Also notice that we switch the Y and Z values
  156. // so that Y is faces up, NOT Z.
  157. // Store off a vertex array pointer to cut down large lines of code
  158. tMd2Triangle *pVertices = m_pFrames[0].pVertices;
  159. // Go through all of the number of vertices and assign the scale and translations.
  160. // Store the vertices in our current frame's vertex list array, while swapping Y and Z.
  161. // Notice we also negate the Z axis as well to make the swap correctly.
  162. for (j=0; j < m_Header.numVertices; j++)
  163. {
  164. pVertices[j].vertex[0] = pFrame->aliasVertices[j].vertex[0] * pFrame->scale[0] + pFrame->translate[0];
  165. pVertices[j].vertex[2] = -1 * (pFrame->aliasVertices[j].vertex[1] * pFrame->scale[1] + pFrame->translate[1]);
  166. pVertices[j].vertex[1] = pFrame->aliasVertices[j].vertex[2] * pFrame->scale[2] + pFrame->translate[2];
  167. }
  168. }
  169. ///////////////////////////////// CONVERT DATA STRUCTURES \\\\\\\\\\\\\\\\*
  170. /////
  171. ///// This function converts the .md2 structures to our own model and object structures
  172. /////
  173. ///////////////////////////////// CONVERT DATA STRUCTURES \\\\\\\\\\\\\\\\*
  174. void CLoadMD2::ConvertDataStructures(t3DModel *pModel)
  175. {
  176. int j = 0, i = 0;
  177. // Assign the number of objects, which is 1 since we only want 1 frame
  178. // of animation.  In the next tutorial each object will be a key frame
  179. // to interpolate between.
  180. pModel->numOfObjects = 1;
  181. // Create a local object to store the first frame of animation's data
  182. t3DObject currentFrame = {0};
  183. // Assign the vertex, texture coord and face count to our new structure
  184. currentFrame.numOfVerts   = m_Header.numVertices;
  185. currentFrame.numTexVertex = m_Header.numTexCoords;
  186. currentFrame.numOfFaces   = m_Header.numTriangles;
  187. // Allocate memory for the vertices, texture coordinates and face data.
  188. currentFrame.pVerts    = new CVector3 [currentFrame.numOfVerts];
  189. currentFrame.pTexVerts = new CVector2 [currentFrame.numTexVertex];
  190. currentFrame.pFaces    = new tFace [currentFrame.numOfFaces];
  191. // Go through all of the vertices and assign them over to our structure
  192. for (j=0; j < currentFrame.numOfVerts; j++)
  193. {
  194. currentFrame.pVerts[j].x = m_pFrames[0].pVertices[j].vertex[0];
  195. currentFrame.pVerts[j].y = m_pFrames[0].pVertices[j].vertex[1];
  196. currentFrame.pVerts[j].z = m_pFrames[0].pVertices[j].vertex[2];
  197. }
  198. // We can now free the old vertices stored in this frame of animation
  199. delete m_pFrames[0].pVertices;
  200. // Go through all of the uv coordinates and assign them over to our structure.
  201. // The UV coordinates are not normal uv coordinates, they have a pixel ratio of
  202. // 0 to 256.  We want it to be a 0 to 1 ratio, so we divide the u value by the
  203. // skin width and the v value by the skin height.  This gives us our 0 to 1 ratio.
  204. // For some reason also, the v coodinate is flipped upside down.  We just subtract
  205. // the v coordinate from 1 to remedy this problem.
  206. for (j=0; j < currentFrame.numTexVertex; j++)
  207. {
  208. currentFrame.pTexVerts[j].x = m_pTexCoords[j].u / float(m_Header.skinWidth);
  209. currentFrame.pTexVerts[j].y = 1 - m_pTexCoords[j].v / float(m_Header.skinHeight);
  210. }
  211. // Go through all of the face data and assign it over to OUR structure
  212. for(j=0; j < currentFrame.numOfFaces; j++)
  213. {
  214. // Assign the vertex indices to our face data
  215. currentFrame.pFaces[j].vertIndex[0] = m_pTriangles[j].vertexIndices[0];
  216. currentFrame.pFaces[j].vertIndex[1] = m_pTriangles[j].vertexIndices[1];
  217. currentFrame.pFaces[j].vertIndex[2] = m_pTriangles[j].vertexIndices[2];
  218. // Assign the texture coord indices to our face data
  219. currentFrame.pFaces[j].coordIndex[0] = m_pTriangles[j].textureIndices[0];
  220. currentFrame.pFaces[j].coordIndex[1] = m_pTriangles[j].textureIndices[1];
  221. currentFrame.pFaces[j].coordIndex[2] = m_pTriangles[j].textureIndices[2];
  222. }
  223. // Here we add the current object (or frame) to our list object list
  224. pModel->pObject.push_back(currentFrame);
  225. }
  226. ///////////////////////////////// CLEAN UP \\\\\\\\\\\\\\\\*
  227. /////
  228. ///// This function cleans up our allocated memory and closes the file
  229. /////
  230. ///////////////////////////////// CLEAN UP \\\\\\\\\\\\\\\\*
  231. void CLoadMD2::CleanUp()
  232. {
  233. // This just just the regular cleanup or our md2 model class.  We can free
  234. // all of this data because we already have it stored in our own structures.
  235. fclose(m_FilePointer); // Close the current file pointer
  236. if(m_pSkins)  delete [] m_pSkins; // Free the skins data
  237. if(m_pTexCoords) delete m_pTexCoords; // Free the texture coord data
  238. if(m_pTriangles) delete m_pTriangles; // Free the triangle face data
  239. if(m_pFrames)  delete m_pFrames; // Free the frames of animation
  240. }
  241. // *Note* 
  242. //
  243. // Below are some math functions for calculating vertex normals.  We want vertex normals
  244. // because it makes the lighting look really smooth and life like.  You probably already
  245. // have these functions in the rest of your engine, so you can delete these and call
  246. // your own.  I wanted to add them so I could show how to calculate vertex normals.
  247. ////////////////////////////// Math Functions  ////////////////////////////////*
  248. // This computes the magnitude of a normal.   (magnitude = sqrt(x^2 + y^2 + z^2)
  249. #define Mag(Normal) (sqrt(Normal.x*Normal.x + Normal.y*Normal.y + Normal.z*Normal.z))
  250. // This calculates a vector between 2 points and returns the result
  251. CVector3 Vector(CVector3 vPoint1, CVector3 vPoint2)
  252. {
  253. CVector3 vVector; // The variable to hold the resultant vector
  254. vVector.x = vPoint1.x - vPoint2.x; // Subtract point1 and point2 x's
  255. vVector.y = vPoint1.y - vPoint2.y; // Subtract point1 and point2 y's
  256. vVector.z = vPoint1.z - vPoint2.z; // Subtract point1 and point2 z's
  257. return vVector; // Return the resultant vector
  258. }
  259. // This adds 2 vectors together and returns the result
  260. CVector3 AddVector(CVector3 vVector1, CVector3 vVector2)
  261. {
  262. CVector3 vResult; // The variable to hold the resultant vector
  263. vResult.x = vVector2.x + vVector1.x; // Add Vector1 and Vector2 x's
  264. vResult.y = vVector2.y + vVector1.y; // Add Vector1 and Vector2 y's
  265. vResult.z = vVector2.z + vVector1.z; // Add Vector1 and Vector2 z's
  266. return vResult; // Return the resultant vector
  267. }
  268. // This divides a vector by a single number (scalar) and returns the result
  269. CVector3 DivideVectorByScaler(CVector3 vVector1, float Scaler)
  270. {
  271. CVector3 vResult; // The variable to hold the resultant vector
  272. vResult.x = vVector1.x / Scaler; // Divide Vector1's x value by the scaler
  273. vResult.y = vVector1.y / Scaler; // Divide Vector1's y value by the scaler
  274. vResult.z = vVector1.z / Scaler; // Divide Vector1's z value by the scaler
  275. return vResult; // Return the resultant vector
  276. }
  277. // This returns the cross product between 2 vectors
  278. CVector3 Cross(CVector3 vVector1, CVector3 vVector2)
  279. {
  280. CVector3 vCross; // The vector to hold the cross product
  281. // Get the X value
  282. vCross.x = ((vVector1.y * vVector2.z) - (vVector1.z * vVector2.y));
  283. // Get the Y value
  284. vCross.y = ((vVector1.z * vVector2.x) - (vVector1.x * vVector2.z));
  285. // Get the Z value
  286. vCross.z = ((vVector1.x * vVector2.y) - (vVector1.y * vVector2.x));
  287. return vCross; // Return the cross product
  288. }
  289. // This returns the normal of a vector
  290. CVector3 Normalize(CVector3 vNormal)
  291. {
  292. double Magnitude; // This holds the magitude
  293. Magnitude = Mag(vNormal); // Get the magnitude
  294. vNormal.x /= (float)Magnitude; // Divide the vector's X by the magnitude
  295. vNormal.y /= (float)Magnitude; // Divide the vector's Y by the magnitude
  296. vNormal.z /= (float)Magnitude; // Divide the vector's Z by the magnitude
  297. return vNormal; // Return the normal
  298. }
  299. ///////////////////////////////// COMPUTER NORMALS \\\\\\\\\\\\\\\\*
  300. /////
  301. ///// This function computes the normals and vertex normals of the objects
  302. /////
  303. ///////////////////////////////// COMPUTER NORMALS \\\\\\\\\\\\\\\\*
  304. void CLoadMD2::ComputeNormals(t3DModel *pModel)
  305. {
  306. CVector3 vVector1, vVector2, vNormal, vPoly[3];
  307. // If there are no objects, we can skip this part
  308. if(pModel->numOfObjects <= 0)
  309. return;
  310. // What are vertex normals?  And how are they different from other normals?
  311. // Well, if you find the normal to a triangle, you are finding a "Face Normal".
  312. // If you give OpenGL a face normal for lighting, it will make your object look
  313. // really flat and not very round.  If we find the normal for each vertex, it makes
  314. // the smooth lighting look.  This also covers up blocky looking objects and they appear
  315. // to have more polygons than they do.    Basically, what you do is first
  316. // calculate the face normals, then you take the average of all the normals around each
  317. // vertex.  It's just averaging.  That way you get a better approximation for that vertex.
  318. // Go through each of the objects to calculate their normals
  319. for(int index = 0; index < pModel->numOfObjects; index++)
  320. {
  321. // Get the current object
  322. t3DObject *pObject = &(pModel->pObject[index]);
  323. // Here we allocate all the memory we need to calculate the normals
  324. CVector3 *pNormals = new CVector3 [pObject->numOfFaces];
  325. CVector3 *pTempNormals = new CVector3 [pObject->numOfFaces];
  326. pObject->pNormals = new CVector3 [pObject->numOfVerts];
  327. // Go though all of the faces of this object
  328. for(int i=0; i < pObject->numOfFaces; i++)
  329. {
  330. // To cut down LARGE code, we extract the 3 points of this face
  331. vPoly[0] = pObject->pVerts[pObject->pFaces[i].vertIndex[0]];
  332. vPoly[1] = pObject->pVerts[pObject->pFaces[i].vertIndex[1]];
  333. vPoly[2] = pObject->pVerts[pObject->pFaces[i].vertIndex[2]];
  334. // Now let's calculate the face normals (Get 2 vectors and find the cross product of those 2)
  335. vVector1 = Vector(vPoly[0], vPoly[2]); // Get the vector of the polygon (we just need 2 sides for the normal)
  336. vVector2 = Vector(vPoly[2], vPoly[1]); // Get a second vector of the polygon
  337. vNormal  = Cross(vVector1, vVector2); // Return the cross product of the 2 vectors (normalize vector, but not a unit vector)
  338. pTempNormals[i] = vNormal; // Save the un-normalized normal for the vertex normals
  339. vNormal  = Normalize(vNormal); // Normalize the cross product to give us the polygons normal
  340. pNormals[i] = vNormal; // Assign the normal to the list of normals
  341. }
  342. //////////////// Now Get The Vertex Normals /////////////////
  343. CVector3 vSum = {0.0, 0.0, 0.0};
  344. CVector3 vZero = vSum;
  345. int shared=0;
  346. for (i = 0; i < pObject->numOfVerts; i++) // Go through all of the vertices
  347. {
  348. for (int j = 0; j < pObject->numOfFaces; j++) // Go through all of the triangles
  349. { // Check if the vertex is shared by another face
  350. if (pObject->pFaces[j].vertIndex[0] == i || 
  351. pObject->pFaces[j].vertIndex[1] == i || 
  352. pObject->pFaces[j].vertIndex[2] == i)
  353. {
  354. vSum = AddVector(vSum, pTempNormals[j]);// Add the un-normalized normal of the shared face
  355. shared++; // Increase the number of shared triangles
  356. }
  357. }      
  358. // Get the normal by dividing the sum by the shared.  We negate the shared so it has the normals pointing out.
  359. pObject->pNormals[i] = DivideVectorByScaler(vSum, float(-shared));
  360. // Normalize the normal for the final vertex normal
  361. pObject->pNormals[i] = Normalize(pObject->pNormals[i]);
  362. vSum = vZero; // Reset the sum
  363. shared = 0; // Reset the shared
  364. }
  365. // Free our memory and start over on the next object
  366. delete [] pTempNormals;
  367. delete [] pNormals;
  368. }
  369. }
  370. /////////////////////////////////////////////////////////////////////////////////
  371. //
  372. // * QUICK NOTES * 
  373. //
  374. // Pretty simple huh?  This is probably the easiest 3D file format I have ever
  375. // worked with, so good job Carmack!  Once again, the next Md2 tutorial will cover
  376. // the key frame animation that is associated with these models.  Then you can 
  377. // actually say you have worked with real quake characters and know how they did
  378. // their animation.  Let's go over a brief explanation of this loader:
  379. //
  380. // The structures MUST be the same size and data types in order to load the
  381. // Quake2 data.  First we load the Header information.  This tells us everything
  382. // about the file and it's contents.
  383. // 
  384. // After the header is loaded, we need to check if the ID is 8.  This is a must.
  385. // Don't ask me why it's 8, ask John Carmack!  If the version ID checks out, then
  386. // we can start loading the data.
  387. // 
  388. // For each set of data you want to load is, we use an fseek() to move the file
  389. // pointer to that location in the file that is given in the header.
  390. //
  391. // After you load the data, you can then convert the data structures to your own
  392. // format, that way you don't have ot be stuck with theirs.  I decided to make it
  393. // like the other loaders for future purposes.  We also compute our own normals.
  394. //
  395. // There is one thing I didn't mention that was NOT loaded in.  There is an array
  396. // of OpenGL commands that allow you to render the vertices in triangle strips and
  397. // a triangle fan.  This is the ugliest code I have ever seen to implement it, so
  398. // I left it out :)
  399. //
  400. // I would like to thank Daniel E. Schoenblum <dansch@hops.cs.jhu.edu> for help
  401. // with explaining the file format.
  402. //
  403. // Let me know if this helps you out!
  404. // 
  405. // 
  406. // Ben Humphrey (DigiBen)
  407. // Game Programmer
  408. // DigiBen@GameTutorials.com
  409. // Co-Web Host of www.GameTutorials.com
  410. //
  411. // The Quake2 .Md2 file format is owned by ID Software.  This tutorial is being used 
  412. // as a teaching tool to help understand model loading and animation.  This should
  413. // not be sold or used under any way for commercial use with out written conset
  414. // from ID Software.
  415. //
  416. // Quake and Quake2 are trademarks of id Software.
  417. // All trademarks used are properties of their respective owners. 
  418. //
  419. //