T3DLIB13.CPP
上传用户:husern
上传日期:2018-01-20
资源大小:42486k
文件大小:28k
源码类别:

游戏

开发平台:

Visual C++

  1. // T3DLIB13.CPP - Quake md2 model software, motion and collision
  2. // I N C L U D E S ///////////////////////////////////////////////////////////
  3. #define DEBUG_ON
  4. #define WIN32_LEAN_AND_MEAN  
  5. #include <windows.h>   // include important windows stuff
  6. #include <windowsx.h> 
  7. #include <mmsystem.h>
  8. #include <objbase.h>
  9. #include <iostream.h> // include important C/C++ stuff
  10. #include <conio.h>
  11. #include <stdlib.h>
  12. #include <malloc.h>
  13. #include <memory.h>
  14. #include <string.h>
  15. #include <stdarg.h>
  16. #include <stdio.h>
  17. #include <math.h>
  18. #include <io.h>
  19. #include <fcntl.h>
  20. #include <direct.h>
  21. #include <wchar.h>
  22. #include <limits.h>
  23. #include <float.h>
  24. #include <search.h>
  25. #include <ddraw.h>      // needed for defs in T3DLIB1.H 
  26. #include "T3DLIB1.H"
  27. #include "T3DLIB4.H"
  28. #include "T3DLIB5.H"
  29. #include "T3DLIB6.H"
  30. #include "T3DLIB7.H"
  31. #include "T3DLIB8.H"
  32. #include "T3DLIB9.H"
  33. #include "T3DLIB10.H"
  34. #include "T3DLIB11.H"
  35. #include "T3DLIB12.H"
  36. #include "T3DLIB13.H"
  37. // DEFINES //////////////////////////////////////////////////////////////////
  38. // EXTERNALS /////////////////////////////////////////////
  39. extern HWND main_window_handle; // save the window handle
  40. extern HINSTANCE main_instance; // save the instance
  41. // GLOBALS //////////////////////////////////////////////////////////////////
  42. // high speed timing functions
  43. INT64  lpFrequency;
  44. INT64  lpPerformanceCount;
  45. INT64  ticks_per_ms;
  46. // the animations, the frames, and timing look good on most
  47. // models, but tweak them to suit your needs OR create a table
  48. // for every character in your game to fine tune your animation
  49. MD2_ANIMATION md2_animations[NUM_MD2_ANIMATIONS]  = 
  50. {
  51. // format: start frame (0..197), end frame (0..197), 
  52. // interpolation rate (0..1, 1 for no interpolation), 
  53. // speed (0..10, 0 fastest, 1 fast, 2 medium, 3 slow...)
  54. {0,39,0.5,1},    // MD2_ANIM_STATE_STANDING_IDLE       0
  55. {40,45,0.5,2},   // MD2_ANIM_STATE_RUN                 1
  56. {46,53,0.5,1},   // MD2_ANIM_STATE_ATTACK              2 
  57. {54,57,0.5,1},   // MD2_ANIM_STATE_PAIN_1              3
  58. {58,61,0.5,1},   // MD2_ANIM_STATE_PAIN_2              4
  59. {62,65,0.5,1},   // MD2_ANIM_STATE_PAIN_3              5
  60. {66,71,0.5,1},   // MD2_ANIM_STATE_JUMP                6
  61. {72,83,0.5,1},   // MD2_ANIM_STATE_FLIP                7
  62. {84,94,0.5,1},   // MD2_ANIM_STATE_SALUTE              8
  63. {95,111,0.5,1},  // MD2_ANIM_STATE_TAUNT               9
  64. {112,122,0.5,1}, // MD2_ANIM_STATE_WAVE                10
  65. {123,134,0.5,1}, // MD2_ANIM_STATE_POINT               11 
  66. {135,153,0.5,1}, // MD2_ANIM_STATE_CROUCH_STAND        12 
  67. {154,159,0.5,1}, // MD2_ANIM_STATE_CROUCH_WALK         13
  68. {160,168,0.5,1}, // MD2_ANIM_STATE_CROUCH_ATTACK       14
  69. {169,172,0.5,1}, // MD2_ANIM_STATE_CROUCH_PAIN         15
  70. {173,177,0.25,0}, // MD2_ANIM_STATE_CROUCH_DEATH        16  
  71. {178,183,0.25,0}, // MD2_ANIM_STATE_DEATH_BACK          17
  72. {184,189,0.25,0}, // MD2_ANIM_STATE_DEATH_FORWARD       18
  73. {190,197,0.25,0}, // MD2_ANIM_STATE_DEATH_SLOW          19
  74. };
  75. // ASCII names for debugging
  76. char *md2_anim_strings[] = 
  77. {
  78. "MD2_ANIM_STATE_STANDING_IDLE ",
  79. "MD2_ANIM_STATE_RUN",
  80. "MD2_ANIM_STATE_ATTACK", 
  81. "MD2_ANIM_STATE_PAIN_1",
  82. "MD2_ANIM_STATE_PAIN_2",
  83. "MD2_ANIM_STATE_PAIN_3",
  84. "MD2_ANIM_STATE_JUMP",
  85. "MD2_ANIM_STATE_FLIP",
  86. "MD2_ANIM_STATE_SALUTE",
  87. "MD2_ANIM_STATE_TAUNT",
  88. "MD2_ANIM_STATE_WAVE",
  89. "MD2_ANIM_STATE_POINT",       
  90. "MD2_ANIM_STATE_CROUCH_STAND", 
  91. "MD2_ANIM_STATE_CROUCH_WALK ",
  92. "MD2_ANIM_STATE_CROUCH_ATTACK",
  93. "MD2_ANIM_STATE_CROUCH_PAIN",
  94. "MD2_ANIM_STATE_CROUCH_DEATH",  
  95. "MD2_ANIM_STATE_DEATH_BACK",
  96. "MD2_ANIM_STATE_DEATH_FORWARD",
  97. "MD2_ANIM_STATE_DEATH_SLOW",
  98. };
  99. // FUNCTIONS ////////////////////////////////////////////////////////////////
  100. int Set_Animation_MD2(MD2_CONTAINER_PTR md2_obj,     // md2 object 
  101.                       int anim_state,                // which animation to play
  102.                       int anim_mode = MD2_ANIM_LOOP) // mode of animation single/loop
  103. {
  104. // this function initializes an animation for play back
  105. md2_obj->anim_state   = anim_state; 
  106. md2_obj->anim_counter = 0;    
  107. md2_obj->anim_speed   = md2_animations[anim_state].anim_speed;
  108. md2_obj->anim_mode    = anim_mode; 
  109. // set initial frame 
  110. md2_obj->curr_frame   = md2_animations[anim_state].start_frame;
  111. // set animation complete flag
  112. md2_obj->anim_complete = 0;
  113. // return success
  114. return(1);
  115. } // end Set_Animation_MD2
  116. ///////////////////////////////////////////////////////////////////////////////
  117. int Animate_MD2(MD2_CONTAINER_PTR md2_obj) // md2 object
  118. {
  119. // animate the mesh to next frame based on state and interpolation values...
  120. // update animation counter
  121. if (++md2_obj->anim_counter >= md2_obj->anim_speed)
  122.    {
  123.    // reset counter
  124.    md2_obj->anim_counter = 0;
  125.    // animate mesh with interpolation, algorithm is straightforward interpolate
  126.    // from current frame in animation to next and blend vertex positions based  
  127.    // on interpolant ivalue in the md2_container class, couple tricky parts
  128.    // are to watch out for the endpost values of the animation, etc.
  129.    // if the interpolation rate irate=1.0 then there is no interpolation
  130.    // for all intent purposes...
  131.    // add interpolation rate to interpolation value, test for next frame
  132.    md2_obj->curr_frame+=md2_animations[md2_obj->anim_state].irate;
  133.    // test if sequence is complete?
  134.    if (md2_obj->curr_frame > md2_animations[md2_obj->anim_state].end_frame)
  135.       {
  136.       // test for one shot, if so then reset to last frame, if loop, the loop
  137.       if (md2_obj->anim_mode == MD2_ANIM_LOOP)
  138.          {
  139.          // loop animation back to starting frame
  140.          md2_obj->curr_frame = md2_animations[md2_obj->anim_state].start_frame;
  141.          } // end if
  142.       else
  143.          {
  144.          // MD2_ANIM_SINGLE_SHOT
  145.          md2_obj->curr_frame = md2_animations[md2_obj->anim_state].end_frame; 
  146.          // set complete flag incase outside wants to take action
  147.          md2_obj->anim_complete = 1;
  148.          } // end else
  149.       } // end if sequence complete
  150.    } // end if time to animate
  151. // return success
  152. return(1);
  153. } // end Animate_MD2
  154. ///////////////////////////////////////////////////////////////////////////////
  155. int Extract_MD2_Frame(OBJECT4DV2_PTR obj,        // pointer to destination object
  156.                       MD2_CONTAINER_PTR obj_md2) // md2 object to extract frame from
  157. {
  158. // this function extracts a single frame of animation from the md2 container and stores
  159. // in into the object4dv2 container, this is so we can leverage the library to transform,
  160. // light, etc. the mesh rather than writing new functions, granted the process of extraction
  161. // is an unneeded overhead, but since we will only have a few MD2 object running around 
  162. // the rendering swamps the time to extract by many orders of magnitude, so the extraction
  163. // is negligable
  164. // the function also interpolates frames; if the curr_frame value is non-intergral then
  165. // the function will blend frames together based on the decimal fraction 
  166. // test if frame number is greater than max frames allowable, some models are malformed
  167. int frame_0,   // starting frame to interpolate
  168.     frame_1;   // ending frame to interpolate
  169. // step 1: decide if this is an interpolated frame?
  170. float ivalue = obj_md2->curr_frame - (int)obj_md2->curr_frame;
  171. // test for integer?
  172. if (ivalue == 0.0)
  173.     {
  174.     // single frame, no interpolation
  175.     frame_0  = obj_md2->curr_frame;
  176.     // check for overflow?
  177.     if (frame_0 >= obj_md2->num_frames)
  178.         frame_0 = obj_md2->num_frames-1;
  179.     // copy vertex list for selected frame, vertex list begins at
  180.     // base index (obj_md2->num_verts * obj_md2->curr_frame)
  181.     int base_index = obj_md2->num_verts * frame_0;
  182.     // copy vertices now from base
  183.     for (int vindex = 0; vindex < obj_md2->num_verts; vindex++)
  184.         {
  185.         // copy the vertex
  186.         obj->vlist_local[vindex].x = obj_md2->vlist[vindex + base_index].x;
  187.         obj->vlist_local[vindex].y = obj_md2->vlist[vindex + base_index].y;
  188.         obj->vlist_local[vindex].z = obj_md2->vlist[vindex + base_index].z;
  189.         obj->vlist_local[vindex].w = 1;  
  190.         // every vertex has a point and texture attached, set that in the flags attribute
  191.         SET_BIT(obj->vlist_local[vindex].attr, VERTEX4DTV1_ATTR_POINT);
  192.         SET_BIT(obj->vlist_local[vindex].attr, VERTEX4DTV1_ATTR_TEXTURE);
  193.         } // end for vindex
  194.     } // end if
  195. else
  196.     {
  197.     // interpolate between curr_frame and curr_frame+1 based
  198.     // on ivalue
  199.     frame_0  = obj_md2->curr_frame;
  200.     frame_1  = obj_md2->curr_frame+1;
  201.     // check for overflow?
  202.     if (frame_0 >= obj_md2->num_frames)
  203.         frame_0 = obj_md2->num_frames-1;
  204.     // check for overflow?
  205.     if (frame_1 >= obj_md2->num_frames)
  206.         frame_1 = obj_md2->num_frames-1;
  207.     // interpolate vertex lists for selected frame(s), vertex list(s) begin at
  208.     // base index (obj_md2->num_verts * obj_md2->curr_frame)
  209.     int base_index_0 = obj_md2->num_verts * frame_0;
  210.     int base_index_1 = obj_md2->num_verts * frame_1;
  211.     // interpolate vertices now from base frame 0,1
  212.     for (int vindex = 0; vindex < obj_md2->num_verts; vindex++)
  213.         {
  214.         // interpolate the vertices
  215.         obj->vlist_local[vindex].x = ((1-ivalue)*obj_md2->vlist[vindex + base_index_0].x + ivalue*obj_md2->vlist[vindex + base_index_1].x);
  216.         obj->vlist_local[vindex].y = ((1-ivalue)*obj_md2->vlist[vindex + base_index_0].y + ivalue*obj_md2->vlist[vindex + base_index_1].y);
  217.         obj->vlist_local[vindex].z = ((1-ivalue)*obj_md2->vlist[vindex + base_index_0].z + ivalue*obj_md2->vlist[vindex + base_index_1].z);
  218.         obj->vlist_local[vindex].w = 1;  
  219.         // every vertex has a point and texture attached, set that in the flags attribute
  220.         SET_BIT(obj->vlist_local[vindex].attr, VERTEX4DTV1_ATTR_POINT);
  221.         SET_BIT(obj->vlist_local[vindex].attr, VERTEX4DTV1_ATTR_TEXTURE);
  222.         } // end for vindex
  223.     } // end if
  224. // return success
  225. return(1);
  226. } // end Extract_MD2_Frame
  227. ///////////////////////////////////////////////////////////////////////////////
  228. int Load_Object_MD2(MD2_CONTAINER_PTR obj_md2, // the loaded md2 file placed in container
  229.                     char *modelfile,    // the filename of the .MD2 model
  230.                     VECTOR4D_PTR scale, // initial scaling factors
  231.                     VECTOR4D_PTR pos,   // initial position
  232.                     VECTOR4D_PTR rot,   // initial rotations (not implemented)
  233.                     char *texturefile,  // the texture filename for the model
  234.                     int attr,           // the lighting/model attributes for the model
  235.                     int color,          // base color if no texturing
  236.                     int vertex_flags)   // control ordering etc.
  237. {
  238. // this function loads in an md2 file, extracts all the data and stores it in the 
  239. // container class which will be used later to load frames into a the standard object
  240. // type for rendering on the fly
  241. FILE *fp      = NULL;  // file pointer to model
  242. int   flength = -1;    // general file length
  243. UCHAR *buffer = NULL;  // used to buffer md2 file data
  244. MD2_HEADER_PTR md2_header;   // pointer to the md2 header
  245. // begin by loading in the .md2 model file
  246. if ((fp = fopen(modelfile, "rb"))==NULL)
  247.    {
  248.    Write_Error("nLoad_Object_MD2 - couldn't find file %s", modelfile);
  249.    return(0);
  250.    } // end if
  251. // find the length of the model file
  252. // seek to end of file
  253. fseek(fp, 0, SEEK_END);
  254. // where is the file pointer?
  255. flength = ftell(fp);
  256. // now read the md2 file into a buffer to analyze it
  257. // re-position file pointer to beginning of file
  258. fseek(fp, 0, SEEK_SET);
  259. // allocate memory to hold file
  260. buffer = (UCHAR *)malloc(flength+1);
  261. // load data into buffer
  262. int bytes_read = fread(buffer, sizeof(UCHAR), flength, fp);
  263. // the header is the first item in the buffer, so alias a pointer
  264. // to it, so we can start analyzing it and creating the model
  265. md2_header = (MD2_HEADER_PTR)buffer;
  266. Write_Error("nint identifier        = %d", md2_header->identifier);
  267. Write_Error("nint version           = %d", md2_header->version);
  268. Write_Error("nint skin_width        = %d", md2_header->skin_width);
  269. Write_Error("nint skin_height       = %d", md2_header->skin_height);
  270. Write_Error("nint framesize         = %d", md2_header->framesize);
  271. Write_Error("nint num_skins         = %d", md2_header->num_skins);
  272. Write_Error("nint num_verts         = %d", md2_header->num_verts);
  273. Write_Error("nint num_textcoords    = %d", md2_header->num_textcoords);
  274. Write_Error("nint num_polys         = %d", md2_header->num_polys);
  275. Write_Error("nint num_openGLcmds    = %d", md2_header->num_openGLcmds);
  276. Write_Error("nint num_frames        = %d", md2_header->num_frames);
  277. Write_Error("nint offset_skins      = %d", md2_header->offset_skins);
  278. Write_Error("nint offset_textcoords = %d", md2_header->offset_textcoords);
  279. Write_Error("nint offset_polys      = %d", md2_header->offset_polys);
  280. Write_Error("nint offset_frames     = %d", md2_header->offset_frames);
  281. Write_Error("nint offset_openGLcmds = %d", md2_header->offset_openGLcmds);
  282. Write_Error("nint offset_end        = %d", md2_header->offset_end);
  283. // test for valid file
  284. if (md2_header->identifier != MD2_MAGIC_NUM || md2_header->version != MD2_VERSION)
  285.    {
  286.    fclose(fp);
  287.    return(0);
  288.    } // end if
  289. // assign fields to container class
  290. obj_md2->state          = 0;                          // state of the model
  291. obj_md2->attr           = attr;                       // attributes of the model
  292. obj_md2->color          = color;                      // 
  293. obj_md2->num_frames     = md2_header->num_frames;     // number of frames in the model
  294. obj_md2->num_polys      = md2_header->num_polys;      // number of polygons
  295. obj_md2->num_verts      = md2_header->num_verts;      // number of vertices 
  296. obj_md2->num_textcoords = md2_header->num_textcoords; // number of texture coordinates
  297. obj_md2->curr_frame     = 0;                          // current frame in animation
  298. obj_md2->skin           = NULL;                       // pointer to texture skin for model
  299. obj_md2->world_pos      = *pos;                       // position object in world
  300. // allocate memory for mesh data
  301. obj_md2->polys = (MD2_POLY_PTR)malloc(md2_header->num_polys      * sizeof(MD2_POLY)); // pointer to polygon list
  302. obj_md2->vlist = (VECTOR3D_PTR)malloc(md2_header->num_frames     * md2_header->num_verts * sizeof(VECTOR3D)); // pointer to vertex coordinate list
  303. obj_md2->tlist = (VECTOR2D_PTR)malloc(md2_header->num_textcoords * sizeof(VECTOR2D)); // pointer to texture coordinate list
  304. #if (MD2_DEBUG==1)
  305. Write_Error("nTexture Coordinates:");
  306. #endif
  307. for (int tindex = 0; tindex < md2_header->num_textcoords; tindex++)
  308.     {
  309. #if (MD2_DEBUG==1)
  310.     Write_Error("ntextcoord[%d] = (%d, %d)", tindex,
  311.                                          ((MD2_TEXTCOORD_PTR)(buffer+md2_header->offset_textcoords))[tindex].u, 
  312.                                          ((MD2_TEXTCOORD_PTR)(buffer+md2_header->offset_textcoords))[tindex].v);
  313. #endif    
  314.     // insert texture coordinate into storage container
  315.     obj_md2->tlist[tindex].x = ((MD2_TEXTCOORD_PTR)(buffer+md2_header->offset_textcoords))[tindex].u;
  316.     obj_md2->tlist[tindex].y = ((MD2_TEXTCOORD_PTR)(buffer+md2_header->offset_textcoords))[tindex].v;
  317.     } // end for vindex
  318. #if (MD2_DEBUG==1)
  319. Write_Error("nVertex List:");
  320. #endif
  321. for (int findex = 0; findex < md2_header->num_frames; findex++)
  322.     {
  323. #if (MD2_DEBUG==1)
  324.     Write_Error("nn******************************************************************************");
  325.     Write_Error("nnF R A M E # %d", findex);
  326.     Write_Error("nn******************************************************************************n");
  327. #endif
  328.     MD2_FRAME_PTR frame_ptr = (MD2_FRAME_PTR)(buffer + md2_header->offset_frames + md2_header->framesize * findex);
  329.     // extract md2 scale and translate, additionally use sent scale and translate
  330.     float sx = frame_ptr->scale[0],
  331.           sy = frame_ptr->scale[1],
  332.           sz = frame_ptr->scale[2],
  333.           tx = frame_ptr->translate[0],  
  334.           ty = frame_ptr->translate[1],  
  335.           tz = frame_ptr->translate[2];
  336. #if (MD2_DEBUG==1)    
  337.     Write_Error("nScale: (%f, %f, %f)nTranslate: (%f, %f, %f)", sx, sy, sz, tx, ty, tz);  
  338. #endif
  339.     for (int vindex = 0; vindex < md2_header->num_verts; vindex++)
  340.         {
  341.         VECTOR3D v;
  342.         // scale and translate compressed vertex
  343.         v.x = (float)frame_ptr->vlist[vindex].v[0] * sx + tx;
  344.         v.y = (float)frame_ptr->vlist[vindex].v[1] * sy + ty;
  345.         v.z = (float)frame_ptr->vlist[vindex].v[2] * sz + tz;
  346.         // scale final point based on sent data
  347.         v.x = scale->x * v.x;
  348.         v.y = scale->y * v.y;
  349.         v.z = scale->z * v.z;
  350. float temp; // used for swaping
  351.         // test for vertex modifications to winding order etc.
  352.         if (vertex_flags & VERTEX_FLAGS_INVERT_X)
  353.            v.x = -v.x;
  354.         if (vertex_flags & VERTEX_FLAGS_INVERT_Y)
  355.            v.y = -v.y;
  356.         
  357.         if (vertex_flags & VERTEX_FLAGS_INVERT_Z)
  358.            v.z = -v.z;
  359.         if (vertex_flags & VERTEX_FLAGS_SWAP_YZ)
  360.            SWAP(v.y, v.z, temp);
  361.         if (vertex_flags & VERTEX_FLAGS_SWAP_XZ)
  362.            SWAP(v.x, v.z, temp);
  363.         if (vertex_flags & VERTEX_FLAGS_SWAP_XY)
  364.            SWAP(v.x, v.y, temp);
  365. #if (MD2_DEBUG==1)
  366.         Write_Error("nVertex #%d = (%f, %f, %f)", vindex, v.x, v.y, v.z);
  367. #endif
  368.         // insert vertex into vertex list which is laid out frame 0, frame 1,..., frame n 
  369.         // frame i: vertex 0, vertex 1,....vertex j
  370.         obj_md2->vlist[vindex + (findex * obj_md2->num_verts)] = v;
  371.         } // end vindex
  372.   } // end findex
  373. #if (MD2_DEBUG==1)
  374. Write_Error("nPolygon List:");
  375. #endif
  376. MD2_POLY_PTR poly_ptr = (MD2_POLY_PTR)(buffer + md2_header->offset_polys);
  377. for (int pindex = 0; pindex < md2_header->num_polys; pindex++)
  378.     {
  379.     // insert polygon into polygon list in container
  380.     if (vertex_flags & VERTEX_FLAGS_INVERT_WINDING_ORDER)
  381.        {
  382.        // inverted winding order
  383.        // vertices
  384.        obj_md2->polys[pindex].vindex[0] = poly_ptr[pindex].vindex[2];
  385.        obj_md2->polys[pindex].vindex[1] = poly_ptr[pindex].vindex[1];
  386.        obj_md2->polys[pindex].vindex[2] = poly_ptr[pindex].vindex[0];
  387.        // texture coordinates
  388.        obj_md2->polys[pindex].tindex[0] = poly_ptr[pindex].tindex[2];
  389.        obj_md2->polys[pindex].tindex[1] = poly_ptr[pindex].tindex[1];
  390.        obj_md2->polys[pindex].tindex[2] = poly_ptr[pindex].tindex[0];
  391.        } // end if
  392.     else
  393.        {
  394.        // normal winding order
  395.        // vertices
  396.        obj_md2->polys[pindex].vindex[0] = poly_ptr[pindex].vindex[0];
  397.        obj_md2->polys[pindex].vindex[1] = poly_ptr[pindex].vindex[1];
  398.        obj_md2->polys[pindex].vindex[2] = poly_ptr[pindex].vindex[2];
  399.        // texture coordinates
  400.        obj_md2->polys[pindex].tindex[0] = poly_ptr[pindex].tindex[0];
  401.        obj_md2->polys[pindex].tindex[1] = poly_ptr[pindex].tindex[1];
  402.        obj_md2->polys[pindex].tindex[2] = poly_ptr[pindex].tindex[2];
  403.        } // end if
  404. #if (MD2_DEBUG==1)
  405.    Write_Error("npoly %d: v(%d, %d, %d), t(%d, %d, %d)", pindex,
  406.                                                       obj_md2->polys[pindex].vindex[0], obj_md2->polys[pindex].vindex[1], obj_md2->polys[pindex].vindex[2],
  407.                                                       obj_md2->polys[pindex].tindex[0], obj_md2->polys[pindex].tindex[1], obj_md2->polys[pindex].tindex[2]);
  408. #endif
  409.     } // end for vindex
  410. // close the file
  411. fclose(fp);
  412. //////////////////////////////////////////////////////////////////////////////
  413. // load the texture from disk
  414. Load_Bitmap_File(&bitmap16bit, texturefile);
  415. // create a proper size and bitdepth bitmap
  416. obj_md2->skin = (BITMAP_IMAGE_PTR)malloc(sizeof(BITMAP_IMAGE));
  417. // initialize bitmap
  418. Create_Bitmap(obj_md2->skin,0,0,
  419.               bitmap16bit.bitmapinfoheader.biWidth,
  420.               bitmap16bit.bitmapinfoheader.biHeight,
  421.               bitmap16bit.bitmapinfoheader.biBitCount);
  422.                           
  423. // load the bitmap image
  424. Load_Image_Bitmap16(obj_md2->skin, &bitmap16bit,0,0,BITMAP_EXTRACT_MODE_ABS);
  425. // done, so unload the bitmap
  426. Unload_Bitmap_File(&bitmap16bit);
  427. // finally release the memory for the temporary buffer
  428. if (buffer)
  429.    free(buffer);
  430. // return success
  431. return(1);
  432. } // end Load_Object_MD2
  433. ///////////////////////////////////////////////////////////////////////////////
  434. int Prepare_OBJECT4DV2_For_MD2(OBJECT4DV2_PTR obj,        // pointer to destination object
  435.                                MD2_CONTAINER_PTR obj_md2) // md2 object to extract frame from
  436. {
  437. // this function prepares the OBJECT4DV2 to be used as a vessel to hold
  438. // frames from the md2 container, it allocated the memory needed, set fields
  439. // and pre-computes as much as possible since each new frame will change only
  440. // the vertex list
  441. Write_Error("nPreparing MD2_CONTAINER_PTR %x for OBJECT4DV2_PTR %x", obj_md2, obj);
  442. ///////////////////////////////////////////////////////////////////////////////
  443. // clear out the object and initialize it a bit
  444. memset(obj, 0, sizeof(OBJECT4DV2));
  445. // set state of object to active and visible
  446. obj->state = OBJECT4DV2_STATE_ACTIVE | OBJECT4DV2_STATE_VISIBLE;
  447. // set some information in object
  448. obj->num_frames   = 1;   // always set to 1
  449. obj->curr_frame   = 0;
  450. obj->attr         = OBJECT4DV2_ATTR_SINGLE_FRAME | OBJECT4DV2_ATTR_TEXTURES; 
  451. obj->num_vertices = obj_md2->num_verts;
  452. obj->num_polys    = obj_md2->num_polys;
  453. obj->texture      = obj_md2->skin;
  454. // set position of object
  455. obj->world_pos = obj_md2->world_pos;
  456. // allocate the memory for the vertices and number of polys
  457. // the call parameters are redundant in this case, but who cares
  458. if (!Init_OBJECT4DV2(obj,   
  459.                      obj->num_vertices, 
  460.                      obj->num_polys, 
  461.                      obj->num_frames))
  462.     {
  463.     Write_Error("n(can't allocate memory).");
  464.     } // end if
  465. ////////////////////////////////////////////////////////////////////////////////
  466. // compute average and max radius using the vertices from frame 0, this isn't
  467. // totally accurate, but the volume of the object hopefully does vary wildly 
  468. // during animation
  469. // reset incase there's any residue
  470. obj->avg_radius[0] = 0;
  471. obj->max_radius[0] = 0;
  472. // loop thru and compute radius
  473. for (int vindex = 0; vindex < obj_md2->num_verts; vindex++)
  474.     {
  475.     // update the average and maximum radius (use frame 0)
  476.     float dist_to_vertex = 
  477.           sqrt(obj_md2->vlist[vindex].x * obj_md2->vlist[vindex].x +
  478.                obj_md2->vlist[vindex].y * obj_md2->vlist[vindex].y +
  479.                obj_md2->vlist[vindex].z * obj_md2->vlist[vindex].z );
  480.     
  481.     // accumulate total radius
  482.     obj->avg_radius[0]+=dist_to_vertex;
  483.     // update maximum radius   
  484.     if (dist_to_vertex > obj->max_radius[0])
  485.        obj->max_radius[0] = dist_to_vertex; 
  486.  
  487.     } // end for vertex
  488. // finallize average radius computation
  489. obj->avg_radius[0]/=obj->num_vertices;
  490. Write_Error("nMax radius=%f, Avg. Radius=%f",obj->max_radius[0], obj->avg_radius[0]);
  491. Write_Error("nWriting texture coordinates...");
  492. ///////////////////////////////////////////////////////////////////////////////
  493. // copy texture coordinate list always the same
  494. for (int tindex = 0; tindex < obj_md2->num_textcoords; tindex++)
  495.     {
  496.     // now texture coordinates
  497.     obj->tlist[tindex].x = obj_md2->tlist[tindex].x;
  498.     obj->tlist[tindex].y = obj_md2->tlist[tindex].y;
  499.     } // end for tindex
  500. Write_Error("nWriting polygons...");
  501. // generate the polygon index list, always the same
  502. for (int pindex=0; pindex < obj_md2->num_polys; pindex++)
  503.     {
  504.     // set polygon indices
  505.     obj->plist[pindex].vert[0] = obj_md2->polys[pindex].vindex[0];
  506.     obj->plist[pindex].vert[1] = obj_md2->polys[pindex].vindex[1];
  507.     obj->plist[pindex].vert[2] = obj_md2->polys[pindex].vindex[2];
  508.  
  509.     // point polygon vertex list to object's vertex list
  510.     // note that this is redundant since the polylist is contained
  511.     // within the object in this case and its up to the user to select
  512.     // whether the local or transformed vertex list is used when building up
  513.     // polygon geometry, might be a better idea to set to NULL in the context
  514.     // of polygons that are part of an object
  515.     obj->plist[pindex].vlist   = obj->vlist_local; 
  516.     // set attributes of polygon with sent attributes
  517.     obj->plist[pindex].attr    = obj_md2->attr;
  518.     // set color of polygon
  519.     obj->plist[pindex].color   = obj_md2->color;
  520.     // apply texture to this polygon
  521.     obj->plist[pindex].texture = obj_md2->skin;
  522.     // assign the texture coordinates
  523.     obj->plist[pindex].text[0] = obj_md2->polys[pindex].tindex[0];
  524.     obj->plist[pindex].text[1] = obj_md2->polys[pindex].tindex[1];
  525.     obj->plist[pindex].text[2] = obj_md2->polys[pindex].tindex[2];
  526.     // set texture coordinate attributes
  527.     SET_BIT(obj->vlist_local[ obj->plist[pindex].vert[0] ].attr, VERTEX4DTV1_ATTR_TEXTURE); 
  528.     SET_BIT(obj->vlist_local[ obj->plist[pindex].vert[1] ].attr, VERTEX4DTV1_ATTR_TEXTURE); 
  529.     SET_BIT(obj->vlist_local[ obj->plist[pindex].vert[2] ].attr, VERTEX4DTV1_ATTR_TEXTURE); 
  530.     // set the material mode to ver. 1.0 emulation
  531.     SET_BIT(obj->plist[pindex].attr, POLY4DV2_ATTR_DISABLE_MATERIAL);
  532.     // finally set the polygon to active
  533.     obj->plist[pindex].state = POLY4DV2_STATE_ACTIVE;    
  534.     // point polygon vertex list to object's vertex list
  535.     // note that this is redundant since the polylist is contained
  536.     // within the object in this case and its up to the user to select
  537.     // whether the local or transformed vertex list is used when building up
  538.     // polygon geometry, might be a better idea to set to NULL in the context
  539.     // of polygons that are part of an object
  540.     obj->plist[pindex].vlist = obj->vlist_local; 
  541.     // set texture coordinate list, this is needed
  542.     obj->plist[pindex].tlist = obj->tlist;
  543.     // extract vertex indices
  544.     int vindex_0 = obj_md2->polys[pindex].vindex[0];
  545.     int vindex_1 = obj_md2->polys[pindex].vindex[1];
  546.     int vindex_2 = obj_md2->polys[pindex].vindex[2];
  547.     
  548.     // we need to compute the normal of this polygon face, and recall
  549.     // that the vertices are in cw order, u=p0->p1, v=p0->p2, n=uxv
  550.     VECTOR4D u, v, n;
  551.     // build u, v
  552.     //VECTOR4D_Build(&obj->vlist_local[ vindex_0 ].v, &obj->vlist_local[ vindex_1 ].v, &u);
  553.     //VECTOR4D_Build(&obj->vlist_local[ vindex_0 ].v, &obj->vlist_local[ vindex_2 ].v, &v);
  554.     u.x = obj_md2->vlist[vindex_1].x - obj_md2->vlist[vindex_0].x;
  555.     u.y = obj_md2->vlist[vindex_1].y - obj_md2->vlist[vindex_0].y;
  556.     u.z = obj_md2->vlist[vindex_1].z - obj_md2->vlist[vindex_0].z;
  557.     u.w = 1;
  558.     v.x = obj_md2->vlist[vindex_2].x - obj_md2->vlist[vindex_0].x;
  559.     v.y = obj_md2->vlist[vindex_2].y - obj_md2->vlist[vindex_0].y;
  560.     v.z = obj_md2->vlist[vindex_2].z - obj_md2->vlist[vindex_0].z;
  561.     v.w = 1;
  562.     
  563.     // compute cross product
  564.     VECTOR4D_Cross(&u, &v, &n);
  565.     // compute length of normal accurately and store in poly nlength
  566.     // +- epsilon later to fix over/underflows
  567.     obj->plist[pindex].nlength = VECTOR4D_Length(&n); 
  568.     } // end for poly
  569. // return success
  570. return(1);
  571. } // end Prepare_OBJECT4DV2_For_MD2
  572. /////////////////////////////////////////////////////////////////////////////
  573. void Start_Fast_Timer(void)
  574. {
  575. // call this function to start the timer
  576. static int first_time = 1;
  577. if (first_time)
  578.    {
  579.    QueryPerformanceFrequency((LARGE_INTEGER *)&lpFrequency);
  580.    ticks_per_ms = lpFrequency/1000;
  581.    first_time = 0;
  582.    }
  583. // get the current time and save it globally
  584. QueryPerformanceCounter((LARGE_INTEGER *)&lpPerformanceCount);
  585. } // end Start_Fast_Timer
  586. //////////////////////////////////////////////////////////////////////////////
  587. void Wait_Fast_Timer(int delay)
  588. {
  589. // call this function to delay a specific number of milliseconds
  590. INT64 lpCurrPerformanceCount;
  591. while(1)
  592.      {
  593.      // get current time
  594.      QueryPerformanceCounter((LARGE_INTEGER *)&lpCurrPerformanceCount);
  595.      // wait until delay
  596.      if ( (lpCurrPerformanceCount - lpPerformanceCount) > (delay*ticks_per_ms) ) 
  597.      break;
  598.      } // end if
  599. } // end Wait_Fast_Timer
  600. //////////////////////////////////////////////////////////////////////////////