home *** CD-ROM | disk | FTP | other *** search
/ Xentax forum attachments archive / xentax.7z / 8090 / ModelEdit.7z / gl_modelrender.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2006-03-08  |  53.2 KB  |  2,017 lines

  1. //  ----------------------------------------------------------------
  2. //  * setup gl rendering context
  3. //  * render the model using open gl
  4. //  * animation to mesh updates
  5. //  ----------------------------------------------------------------
  6. #include "precompile.h"
  7. #pragma warning (disable:4786)
  8.  
  9. #include "gl_modelrender.h"
  10. #include "model_ops.h"
  11. #include "pixelformat.h"
  12. #include "geomroutines.h"
  13. #include "transformmaker.h"
  14. #include "model_cleanup.h"
  15. #include <gl/gl.h>
  16. #include <gl/glu.h>
  17. #include <set>
  18. #include "ltascene.h"
  19. #include <winbase.h>
  20.  
  21.  
  22. using namespace std;
  23. // ------------------------------------------------------------------------
  24.  
  25. //  global ambient color ui definable global ambient color
  26. float g_GlobalAmbientColor[3] = { 0.2f , 0.2f , 0.2f };
  27.  
  28. #define    GLM_TRI_INDEX0    2
  29. #define    GLM_TRI_INDEX1    1
  30. #define    GLM_TRI_INDEX2    0
  31.  
  32. #define PRIMARY_TEXTURE 1
  33. #define SPECULAR_TEXTURE 0
  34. #define ENVIRONMENTAL_TEXTURE 0
  35.  
  36. #pragma comment(lib, "opengl32.lib")
  37. #pragma comment(lib, "glu32.lib")
  38.  
  39.  
  40.  
  41.  
  42. // ------------------------------------------------------------------------
  43. // StateSet
  44. // pushes and pops GL attribs ..
  45. // examp: 
  46. // StateSet zbuf( GL_DEPTH_TEST , FALSE );
  47. // constructor either enables or disables option, destructor does the opposite
  48. // ------------------------------------------------------------------------
  49. class StateSet
  50. {
  51.     int            m_Option;
  52.     int            m_OldVal;
  53.     
  54.     void glChooseEnable(int option, BOOL bEnable)
  55.     {
  56.         if(bEnable)
  57.             glEnable(option);
  58.         else
  59.             glDisable(option);
  60.     }
  61.  
  62. public:
  63.     StateSet(int option, BOOL bEnable)
  64.     {
  65.         m_Option = option;
  66.         m_OldVal = glIsEnabled(option);
  67.         glChooseEnable(option, bEnable);
  68.     }
  69.  
  70.     ~StateSet()
  71.     {
  72.         glChooseEnable(m_Option, m_OldVal);
  73.     }
  74. };
  75.  
  76.  
  77. // ------------------------------------------------------------------------
  78. // vertex blend ( result, a-vec, b-vec, interp )
  79. // ------------------------------------------------------------------------
  80. static inline
  81. void vertexLerp(float *res, float *a, float *b, float &t )
  82. {
  83.     res[0] =  a[0]  + ( (b[0] - a[0]) * t) ;
  84.     res[1] =  a[1]  + ( (b[1] - a[1]) * t) ;
  85.     res[2] =  a[2]  + ( (b[2] - a[2]) * t) ;
  86. }
  87.  
  88. //  ----------------------------------------------------------------
  89. //  TVert* UpdateVAModelPiece()
  90. // returns pointer to the current position in the vertertex draw buffer.
  91. //  
  92. //  ----------------------------------------------------------------
  93. TVert* UpdateVAModelPiece( Model      *pModel,
  94.                          ModelPiece *pModelPiece,
  95.                          AnimTimeRef*pAnimTimeRef   ,
  96.                          TVert      *pVertexBuffer ,
  97.                          const LTMatrix   *trans)
  98. {
  99.     PieceLOD  *pLOD = pModelPiece->GetLOD(uint32(0));
  100.     ModelAnim *pAnims[2];
  101.     NodeKeyFrame *pKeys[2];
  102.     AnimNode  *pAnimNodes[2] ;
  103.  
  104.     pAnims[0] = pModel->GetAnim( pAnimTimeRef->m_Prev.m_iAnim );
  105.     pAnims[1] = pModel->GetAnim( pAnimTimeRef->m_Cur.m_iAnim );
  106.     
  107.     pAnimNodes[0] = pAnims[0]->m_AnimNodes[ pModelPiece->m_vaAnimNodeIdx ];
  108.     pAnimNodes[1] = pAnims[1]->m_AnimNodes[ pModelPiece->m_vaAnimNodeIdx ];
  109.     
  110.     pKeys[0] = &pAnimNodes[0]->m_KeyFrames[pAnimTimeRef->m_Prev.m_iFrame];
  111.     pKeys[1] = &pAnimNodes[1]->m_KeyFrames[pAnimTimeRef->m_Cur.m_iFrame];
  112.     
  113.     // get vertex data from key.
  114.     // to do interp between frames ...
  115.     int iVBOffset = pModelPiece->m_VertOffset ;
  116.     int size      = pLOD->NumVerts() + iVBOffset ;
  117.                 
  118.     int v_cnt = 0 ;
  119.     CDefVertexLst *pDefVerts[2];
  120.     pDefVerts[0] = pKeys[0]->m_pDefVertexLst ;
  121.     pDefVerts[1] = pKeys[1]->m_pDefVertexLst ;
  122.     float percent = pAnimTimeRef->m_Percent ;
  123.  
  124.     if( pDefVerts[1] == NULL )
  125.         pDefVerts[1] = pDefVerts[0] ;
  126.     
  127.     // get the vertex animation  multiply it by current transforms
  128.     for( int i = iVBOffset ; i <  size ; i++, v_cnt++ )
  129.     {
  130.         float *prv_val = pDefVerts[0]->getValue( v_cnt ); 
  131.         float *cur_val = pDefVerts[1]->getValue( v_cnt ); 
  132.         float val[3] ;
  133.         vertexLerp( val, prv_val, cur_val, percent );
  134.         
  135.         LTVector vec( val[0], val[1], val[2] ) ;
  136.         LTVector res;
  137.         
  138.      
  139.         MatVMul( &res, trans, &vec );
  140.                 
  141.         (*pVertexBuffer).m_vPos = res ;
  142.         (*pVertexBuffer).m_vNormal = pLOD->m_Verts[v_cnt].m_Normal ;
  143.         pVertexBuffer++;
  144.     }    
  145.  
  146.     return pVertexBuffer ;
  147. }
  148.  
  149.  
  150. // ------------------------------------------------------------------------
  151. // 
  152. // ------------------------------------------------------------------------
  153. static CMoArray<DVector> g_TransformedVerts;
  154. static CMoArray<DVector*> g_PseudoIndices;
  155. static float g_tuAdd, g_tvAdd;
  156.  
  157. GLfloat viewMatrix[16];
  158.  
  159.  
  160. // ------------------------------------------------------------ //
  161. // Set up the pixel format for windoze
  162. // ------------------------------------------------------------ //
  163. BOOL SetDCPixelFormat(HDC hDC)
  164. {
  165.     int nPixelFormat;
  166.     PIXELFORMATDESCRIPTOR pfd = {
  167.         sizeof(PIXELFORMATDESCRIPTOR),
  168.         1, // Version
  169.         PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
  170.         PFD_TYPE_RGBA,
  171.         32, // Bit depth
  172.         0, 0, 0, 0, 0, 0,
  173.         0, 0,
  174.         0, 0, 0, 0, 0,
  175.         32, // ZBuffer size
  176.         0,
  177.         0,
  178.         PFD_MAIN_PLANE,
  179.         0,
  180.         0, 0, 0 };
  181.  
  182.     nPixelFormat = ChoosePixelFormat(hDC, &pfd);
  183.     if(nPixelFormat == 0)
  184.         return FALSE;
  185.         
  186.     return SetPixelFormat(hDC, nPixelFormat, &pfd);
  187. }
  188.  
  189. // ------------------------------------------------------------------------
  190. // SetupViewingParameters( GL-context, draw-structure )
  191. // sets up the camera view for the the gl-context, lights and stuff
  192. // ------------------------------------------------------------------------
  193. void SetupViewingParameters(GLMContext *pContext, DrawStruct * pDrawStruct )
  194. {
  195.     RECT rect;
  196.     float aspect;
  197.     GLfloat ambient[4], diffuse[4], lightPos[4];
  198.     int i;
  199.  
  200.     wglMakeCurrent(pContext->m_hDC, pContext->m_hglrc);
  201.  
  202.     GetClientRect(pContext->m_hWnd, &rect);
  203.     aspect = (float)(rect.right - rect.left) / (rect.bottom - rect.top);
  204.  
  205.     // Set the viewport.
  206.     glViewport(0, 0, rect.right, rect.bottom);
  207.  
  208.     // Setup the projection matrix.
  209.     glMatrixMode(GL_PROJECTION);
  210.     glLoadIdentity();
  211.     gluPerspective((GLdouble)(pDrawStruct->m_FOV), aspect, 0.1f, 5000.0f);
  212.  
  213.     // Setup the ModelView matrix.
  214.     glMatrixMode(GL_MODELVIEW);
  215.     glLoadIdentity();
  216.  
  217.     gluLookAt(EXPANDVEC(pDrawStruct->m_ViewerPos),
  218.         EXPANDVEC(pDrawStruct->m_LookAt), 0.0f, 1.0f, 0.0f);
  219.  
  220.     // This puts it in Lithtech's (left-handed) coordinate system.
  221.     glScalef(1.0f, 1.0f, -1.0f);    
  222.  
  223.  
  224.     glGetFloatv(GL_MODELVIEW_MATRIX, viewMatrix);
  225.     
  226.  
  227.  
  228.     // Clear the screen.
  229.     glClearColor(pContext->m_bgColor[0],pContext->m_bgColor[1],
  230.                  pContext->m_bgColor[2],0.0f);
  231.  
  232.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  233.  
  234.     
  235.     // Gouraud...
  236.     glShadeModel(GL_SMOOTH);
  237.  
  238.  
  239.     if(pDrawStruct->m_bWireframe)
  240.     {
  241.         glDisable(GL_LIGHTING);
  242.  
  243.         glDisable(GL_CULL_FACE);
  244.  
  245.         glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
  246.         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  247.  
  248.         // No ZBuffering..
  249.         glDisable(GL_DEPTH_TEST);
  250.     }
  251.     else
  252.     {
  253.         // Setup lighting.
  254.         glEnable(GL_LIGHTING);
  255.  
  256.         // Lights!
  257.         for(i=0; i < MAX_GLM_LIGHTS; i++)
  258.         {
  259.             if(i < pDrawStruct->m_nLights)
  260.             {
  261.                 ambient[0] = (pDrawStruct->m_LightColors[i].x / 255.0f) * 0.0f;
  262.                 ambient[1] = (pDrawStruct->m_LightColors[i].y / 255.0f) * 0.0f;
  263.                 ambient[2] = (pDrawStruct->m_LightColors[i].z / 255.0f) * 0.0f;
  264.                 ambient[0] = g_GlobalAmbientColor[0];
  265.                 ambient[1] = g_GlobalAmbientColor[1];
  266.                 ambient[2] = g_GlobalAmbientColor[2];
  267.             
  268.                 ambient[3] = 1.0f;
  269.  
  270.                 diffuse[0] = (pDrawStruct->m_LightColors[i].x / 255.0f) * 0.7f;
  271.                 diffuse[1] = (pDrawStruct->m_LightColors[i].y / 255.0f) * 0.7f;
  272.                 diffuse[2] = (pDrawStruct->m_LightColors[i].z / 255.0f) * 0.7f;
  273.     
  274.                 diffuse[3] = 1.0f;
  275.  
  276.                 lightPos[0] = pDrawStruct->m_LightPositions[i].x;
  277.                 lightPos[1] = pDrawStruct->m_LightPositions[i].y;
  278.                 lightPos[2] = -pDrawStruct->m_LightPositions[i].z;
  279.                 lightPos[3] = 1.0f;
  280.  
  281.                 glLightfv(GL_LIGHT0+i, GL_AMBIENT, ambient);
  282.                 glLightfv(GL_LIGHT0+i, GL_DIFFUSE, diffuse);
  283.                 glLightfv(GL_LIGHT0+i, GL_POSITION, lightPos);
  284.                 glEnable(GL_LIGHT0+i);
  285.             }
  286.             else
  287.             {
  288.                 glDisable(GL_LIGHT0+i);
  289.             }
  290.         }
  291.  
  292.  
  293.         // Cull faces.
  294.         glFrontFace(GL_CCW);
  295.         glEnable(GL_CULL_FACE);
  296.  
  297.         // Set the polygon mode.
  298.         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  299.  
  300.         // ZBuffering on.
  301.         glEnable(GL_DEPTH_TEST);
  302.     }
  303. }
  304.  
  305. // ------------------------------------------------------------ //
  306. // CreateGLMContext( anonymous-window )
  307. // Creates a GL-context from a window.
  308. // ------------------------------------------------------------ //
  309. GLM_CONTEXT CreateGLMContext(void *phWnd)
  310. {
  311.     GLMContext *pContext;
  312.     HDC hDC;
  313.     HWND hWnd;
  314.     char buffer[2048];
  315.  
  316.     // Set the pixel format.
  317.     hWnd = (HWND)phWnd;
  318.     hDC = GetDC(hWnd);
  319.     if(!SetDCPixelFormat(hDC))
  320.     {
  321.         ReleaseDC(hWnd, hDC);
  322.         return NULL;
  323.     }    
  324.  
  325.     pContext = new GLMContext;
  326.     pContext->m_hWnd = hWnd;
  327.     pContext->m_hDC = hDC;
  328.     pContext->m_hglrc = wglCreateContext(pContext->m_hDC);
  329.     pContext->m_nCurTexture = 0;
  330.     wglMakeCurrent(pContext->m_hDC, pContext->m_hglrc);
  331.  
  332.     sprintf( buffer, "OEM:\t\t%s  \n  Version:\t%s\n  Renderer:\t%s\n", glGetString( GL_VENDOR ), glGetString( GL_VERSION ), glGetString( GL_RENDERER ) );
  333.     return pContext;
  334. }
  335.  
  336. // ------------------------------------------------------------------------
  337. // Kill gl- context
  338. // ------------------------------------------------------------------------
  339. void DeleteGLMContext(GLM_CONTEXT hContext)
  340. {
  341.     GLMContext *pContext;
  342.  
  343.     pContext = (GLMContext*)hContext;
  344.  
  345.     // Delete the texture bindings
  346.     for (DWORD i = 0; i < pContext->m_Textures.GetSize(); i++)
  347.         if (pContext->m_Textures[i])
  348.             glDeleteTextures(1, &(pContext->m_Textures[i]));
  349.  
  350.     wglMakeCurrent(pContext->m_hDC, NULL);
  351.     wglDeleteContext(pContext->m_hglrc);
  352.     ReleaseDC(pContext->m_hWnd, pContext->m_hDC);
  353.  
  354.     delete pContext;
  355. }
  356.  
  357. // ------------------------------------------------------------------------
  358. // Get rid of all textures. Do this before loading a model to start 
  359. // fresh.. .
  360. // ------------------------------------------------------------------------
  361. void ReleaseAllTextures( GLM_CONTEXT hContext )
  362. {
  363.     GLMContext *pContext = (GLMContext*)hContext;
  364.  
  365.         // Delete the texture bindings
  366.     for (DWORD i = 0; i < pContext->m_Textures.GetSize(); i++)
  367.         if (pContext->m_Textures[i])
  368.             glDeleteTextures(1, &(pContext->m_Textures[i]));
  369.     pContext->m_Textures.Term();
  370. }
  371.  
  372. // ------------------------------------------------------------------------
  373. // DrawBox( color, min, max );
  374. // ------------------------------------------------------------------------
  375. void DrawBox (DVector *pColor, DVector *pMin, DVector *pMax)
  376. {
  377.     glDisable(GL_LIGHTING);
  378.     glDisable(GL_CULL_FACE);
  379.     glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
  380.     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  381.  
  382.     glColor3f (pColor->x, pColor->y, pColor->z);
  383.     glBegin (GL_LINES);
  384.         // top
  385.         glVertex3f (pMin->x, pMin->y, pMin->z);
  386.         glVertex3f (pMax->x, pMin->y, pMin->z);
  387.  
  388.         glVertex3f (pMax->x, pMin->y, pMin->z);
  389.         glVertex3f (pMax->x, pMin->y, pMax->z);
  390.  
  391.         glVertex3f (pMax->x, pMin->y, pMax->z);
  392.         glVertex3f (pMin->x, pMin->y, pMax->z);
  393.  
  394.         glVertex3f (pMin->x, pMin->y, pMax->z);
  395.         glVertex3f (pMin->x, pMin->y, pMin->z);
  396.  
  397.         // bottom
  398.         glVertex3f (pMax->x, pMax->y, pMax->z);
  399.         glVertex3f (pMin->x, pMax->y, pMax->z);
  400.         
  401.         glVertex3f (pMin->x, pMax->y, pMax->z);
  402.         glVertex3f (pMin->x, pMax->y, pMin->z);
  403.  
  404.         glVertex3f (pMin->x, pMax->y, pMin->z);
  405.         glVertex3f (pMax->x, pMax->y, pMin->z);
  406.  
  407.         glVertex3f (pMax->x, pMax->y, pMin->z);
  408.         glVertex3f (pMax->x, pMax->y, pMax->z);
  409.  
  410.         // sides
  411.  
  412.         glVertex3f (pMin->x, pMin->y, pMin->z);
  413.         glVertex3f (pMin->x, pMax->y, pMin->z);
  414.  
  415.         glVertex3f (pMax->x, pMin->y, pMin->z);
  416.         glVertex3f (pMax->x, pMax->y, pMin->z);
  417.  
  418.         glVertex3f (pMax->x, pMin->y, pMax->z);
  419.         glVertex3f (pMax->x, pMax->y, pMax->z);
  420.  
  421.         glVertex3f (pMin->x, pMin->y, pMax->z);
  422.         glVertex3f (pMin->x, pMax->y, pMax->z);
  423.  
  424.     glEnd();
  425. }
  426.  
  427. // ------------------------------------------------------------------------
  428. // DrawOriginLines()
  429. // draws coordinate system
  430. // ------------------------------------------------------------------------
  431. void DrawOriginLines()
  432. {
  433.     float size;
  434.  
  435.     size = 150.0f;
  436.  
  437.     glDisable(GL_LIGHTING);
  438.     glDisable(GL_CULL_FACE);
  439.     glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
  440.     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  441.     glBegin(GL_LINES);
  442.  
  443.         glColor3f(1.0f, 0.0f, 0.0f);
  444.         glVertex3f(-size, 0.0f, 0.0f);
  445.         glVertex3f( size, 0.0f, 0.0f);
  446.  
  447.         glColor3f(0.0f, 1.0f, 0.0f);
  448.         glVertex3f(0.0f, -size, 0.0f);
  449.         glVertex3f(0.0f,  size, 0.0f);
  450.  
  451.         glColor3f(0.0f, 0.0f, 1.0f);
  452.         glVertex3f(0.0f, 0.0f, -size);
  453.         glVertex3f(0.0f, 0.0f, size);
  454.     
  455.     glEnd();
  456.  
  457.     glPointSize(8.0f);
  458.     glBegin(GL_POINTS);
  459.         glVertex3f(size, 0.0f, 0.0f);
  460.         glVertex3f(0.0f, size, 0.0f);
  461.         glVertex3f(0.0f, 0.0f, size);
  462.     glEnd();
  463. }
  464.  
  465.  
  466. // ------------------------------------------------------------------------
  467. // Draw an LOD piece 
  468. // 
  469. // ------------------------------------------------------------------------
  470. static void DrawPiece(PieceLOD *pPiece, TVert *pVerts, DrawStruct* pStruct)
  471. {
  472.     DWORD count;
  473.     ModelTri *pCurTri;
  474.     DVector *v[3];
  475.     DVector normal, dir1, dir2;
  476.     int i;
  477.  
  478.     // Draw the tris.
  479.     pCurTri = pPiece->m_Tris.GetArray();
  480.     count = pPiece->m_Tris.GetSize();
  481.  
  482.     while(count)
  483.     {
  484.         count--;
  485.         
  486.         v[0] = &pVerts[pCurTri->m_Indices[GLM_TRI_INDEX0]].m_vPos;
  487.         v[1] = &pVerts[pCurTri->m_Indices[GLM_TRI_INDEX1]].m_vPos;
  488.         v[2] = &pVerts[pCurTri->m_Indices[GLM_TRI_INDEX2]].m_vPos;
  489.         
  490.         for(i=0; i < 3; i++){
  491.             glNormal3f(
  492.                 EXPANDVEC(pVerts[pCurTri->m_Indices[2-i]].m_vNormal));
  493.  
  494. #if PRIMARY_TEXTURE                
  495.             glTexCoord2f(
  496.                 pCurTri->m_UVs[2-i].tu + g_tuAdd,
  497.                 pCurTri->m_UVs[2-i].tv + g_tvAdd);
  498. #elif SPECULAR_TEXTURE
  499.  
  500. /* This could be interesting - but only if we wanted to play with the
  501. specular texture, which would allow for toon shading, for
  502. instance. If all we're going to do is a linear shade, we might as
  503. well use hardware specular highlights.
  504.  
  505. As of 10/18/00, this isn't completely working. I suspect another
  506. left-handed coordinate system problem. -DWL
  507. */              
  508.  
  509.             // compute specular value
  510.             for (int lightNum=1;
  511.                  lightNum<2;
  512. //                     lightNum<pStruct->m_nLights;
  513.                  ++lightNum){
  514.                 
  515.                 DVector vertPos=*v[i];
  516.                 DVector lightDir=
  517.                     pStruct->m_LightPositions[lightNum]-
  518.                     vertPos;
  519.  
  520.                 lightDir.Normalize();
  521.                 DVector normal=
  522.                     pVerts[pCurTri->m_Indices[2-i]].m_vNormal;
  523.  
  524.                 DVector reflect=(2.0f*normal.Dot(lightDir)*normal)-
  525.                     lightDir;
  526.  
  527.                 DVector toViewer=pStruct->m_ViewerPos-vertPos;
  528.  
  529.                 toViewer.Normalize();
  530.                 
  531.                 float specularValue=
  532.                     _cpp_max(0.005f,reflect.Dot(toViewer));
  533.  
  534.                 specularValue=pow(specularValue,2.0f);
  535.                 
  536.                 glTexCoord2f(
  537.                     specularValue,
  538.                     0.5f);
  539.  
  540.                 static debugOut=0;
  541.  
  542.                 if (debugOut){
  543.                     char msg[80];
  544.                     sprintf(msg,"vPos: [%2.2f %2.2f %2.2f]\n",vertPos[0], vertPos[1], vertPos[2]);                        
  545.                     OutputDebugString(msg);
  546.                     sprintf(msg,"lite: [%2.2f %2.2f %2.2f]\n",lightDir[0], lightDir[1], lightDir[2]);
  547.                     OutputDebugString(msg);
  548.                     sprintf(msg,"norm: [%2.2f %2.2f %2.2f]\n",normal[0], normal[1], normal[2]);
  549.                     OutputDebugString(msg);
  550.                     sprintf(msg,"refl: [%2.2f %2.2f %2.2f]\n",reflect[0], reflect[1], reflect[2]);
  551.                     OutputDebugString(msg);
  552.                     sprintf(msg,"view: [%2.2f %2.2f %2.2f]\n\n",toViewer[0], toViewer[1], toViewer[2]);                    
  553.                     OutputDebugString(msg);
  554.                 }
  555.             }
  556.  
  557. #elif ENVIRONMENTAL_TEXTURE
  558.             
  559.             // compute environmental value
  560.  
  561.             DVector normal=
  562.                 pVerts[pCurTri->m_Indices[2-i]].m_vNormal;
  563.  
  564.             DVector normalInViewspace;
  565.  
  566.             for (int j=0;j<4;++j){
  567.                 normalInViewspace[j]=
  568.                     normal[0]*viewMatrix[j]+
  569.                     normal[1]*viewMatrix[j+4]+
  570.                     normal[2]*viewMatrix[j+8]+
  571.                     normal[3]*viewMatrix[j+12];
  572.             }
  573.             
  574.             glTexCoord2f(
  575.                 .5+normalInViewspace[0]*.5f,
  576.                 .5+normalInViewspace[1]*.5f);
  577. #endif
  578.             glVertex3f(EXPANDVEC(*v[i]));
  579.         }
  580.         
  581.         pCurTri++;
  582.     }
  583. }
  584.  
  585.  
  586. // ------------------------------------------------------------------------
  587. // Draw an LOD piece 
  588. // 
  589. // ------------------------------------------------------------------------
  590. static void DrawPieceVertexColors(PieceLOD *pPiece, TVert *pVerts, DrawStruct* pStruct)
  591. {
  592.     DWORD count;
  593.     ModelTri *pCurTri;
  594.     DVector *v[3], *c[3];
  595.     DVector normal, dir1, dir2;
  596.     int i;
  597.  
  598.     // Draw the tris.
  599.     pCurTri = pPiece->m_Tris.GetArray();
  600.     count = pPiece->m_Tris.GetSize();
  601.  
  602.     while(count)
  603.     {
  604.         count--;
  605.         
  606.         v[0] = &pVerts[pCurTri->m_Indices[GLM_TRI_INDEX0]].m_vPos;
  607.         v[1] = &pVerts[pCurTri->m_Indices[GLM_TRI_INDEX1]].m_vPos;
  608.         v[2] = &pVerts[pCurTri->m_Indices[GLM_TRI_INDEX2]].m_vPos;
  609.         c[0] = &pVerts[pCurTri->m_Indices[GLM_TRI_INDEX0]].m_vColor;
  610.         c[1] = &pVerts[pCurTri->m_Indices[GLM_TRI_INDEX1]].m_vColor;
  611.         c[2] = &pVerts[pCurTri->m_Indices[GLM_TRI_INDEX2]].m_vColor;
  612.         
  613.  
  614.         for(i=0; i < 3; i++){
  615.             glColor3fv( & (c[i]->x) );
  616.             glNormal3f(
  617.                 EXPANDVEC(pVerts[pCurTri->m_Indices[2-i]].m_vNormal));
  618.             glVertex3f(EXPANDVEC(*v[i]));
  619.         }
  620.         
  621.         pCurTri++;
  622.     }
  623. }                            
  624.  
  625. /*
  626. This uses an alternate (mathematically identical) method of setting up the 
  627. transforms that allows it to transform the normals and allows it to only
  628. use one base vertex position:
  629.  
  630. Current engine method:
  631. NG = node global transform
  632. VG = vertex in global space
  633. PNG = precalculated node global transform
  634. PVL = precalculated vertex in node local space
  635. PVG = precalculated vertex in global space
  636. PVL = ~PNG * PVG
  637.  
  638. To get a vertex's position.
  639. VG = (NG0 * PVL0) + (NG1 * PVL1)...
  640.  
  641. // To get away from needing PVL0, PVL1... as input:
  642. VG = NG * (~PNG * PVG) * w1 + NG2 * (~PNG2 * PVG) * w2
  643.  
  644. So in AlternateGetVertexPositions, we get rid of PVL's and use PVG.
  645.  
  646. If bNormals is TRUE, then it also transforms each vertex's normal and
  647. places that right after each vertex's position.
  648. */
  649.  
  650. BOOL AlternateGetVertexPositions(    Model *pModel,
  651.                                      GVPStruct *pStruct, 
  652.                                     BOOL bSetupTransforms,
  653.                                     BOOL bNormals,
  654.                                     BOOL bDrawOriginalModel,
  655.                                     BOOL bMovementEncoding,
  656.                                     void **pNextVert /*= NULL*/ )
  657. {
  658.     DWORD i, j, k;
  659.     ModelPiece *pPiece;
  660.     BYTE *pCurOut;
  661.     DVector *pNormalOut;
  662.     TransformMaker tMaker;
  663.     float vTemp[4];
  664.     ModelVert *pVert;
  665.     const LTMatrix *pTransforms;
  666.     NewVertexWeight *pWeight;
  667.     PieceLOD *pLOD;
  668.     float theVec[4];
  669.     
  670.     int bDoVertexAnim = FALSE ;
  671.  
  672.     pModel->ResetNodeEvalState();
  673.     pModel->SetupNodeEvalStateFromPieces(pStruct->m_CurrentLODDist);
  674.  
  675.     // Validate..
  676.     if(!pStruct->m_Vertices)
  677.         return FALSE;
  678.  
  679.     if(pStruct->m_nAnims > MAX_GVP_ANIMS)
  680.         return FALSE;
  681.  
  682.     // Copy the vertex positions over.
  683.     pCurOut = (BYTE*)pStruct->m_Vertices;
  684.  
  685.  
  686.     if(bSetupTransforms )
  687.     {
  688.         tMaker.SetupFromGVPStruct(pStruct);
  689.  
  690.         if(bMovementEncoding && !tMaker.SetupMovementEncoding())
  691.             return FALSE;
  692.         if(!tMaker.SetupTransforms())
  693.             return FALSE;
  694.     }
  695.  
  696.     // Apply the inverse global transform according to the equation above.
  697.     pTransforms = pModel->m_Transforms.GetArray();
  698.  
  699.  
  700.     for(i=0; i < pModel->NumPieces(); i++)
  701.     {
  702.         pPiece = pModel->GetPiece(i);
  703.         pLOD = pPiece->GetLOD(pStruct->m_CurrentLODDist );
  704.  
  705.         // if this piece is vertex animated update the output vertex buffer
  706.         // with new data.
  707.         if( pPiece->m_isVA  )
  708.         {
  709.             // if we're drawing the original model stuff the vertex into the 
  710.             // vertex buffer
  711.             if( bDrawOriginalModel )
  712.             {
  713.                 for( j=0 ; j < pLOD->m_Verts ; j++ )
  714.                 {
  715.                     pVert = &pLOD->m_Verts[j];
  716.                     ((DVector*)pCurOut)->Init();
  717.                     ((DVector*)pCurOut)->x = pVert->m_Vec.x ;
  718.                     ((DVector*)pCurOut)->y = pVert->m_Vec.y ;
  719.                     ((DVector*)pCurOut)->z = pVert->m_Vec.z ;
  720.  
  721.                     pNormalOut = (LTVector*)(pCurOut + sizeof(LTVector));
  722.                     pNormalOut->Init();
  723.                     pNormalOut->x=pVert->m_Normal.x;
  724.                     pNormalOut->y=pVert->m_Normal.y;
  725.                     pNormalOut->z=pVert->m_Normal.z;
  726.                     pCurOut += pStruct->m_VertexStride;
  727.                 }
  728.             }
  729.             else
  730.             {
  731.  
  732.                 // update the vertex in the model according to animation
  733.                 pCurOut = (BYTE*)UpdateVAModelPiece( pModel, pPiece, 
  734.                                                      &pStruct->m_Anims[0], 
  735.                                                      (TVert*)pCurOut, 
  736.                                                      &pTransforms[0]);
  737.                 
  738.                 
  739.             }
  740.         }
  741.         
  742.         // update draw vertex buffer using skeletal animation
  743.         if(!pPiece->m_isVA)
  744.         for(j=0; j < pLOD->m_Verts; j++)
  745.         {
  746.             pVert = &pLOD->m_Verts[j];
  747.  
  748.             // Apply all the weights. ( do skeletal deformation )            
  749.             if(pVert->m_nWeights > 0 && (bDrawOriginalModel == FALSE) && !pPiece->m_isVA)
  750.             {
  751.                 vTemp[0] = vTemp[1] = vTemp[2] = vTemp[3] = 0.0f;
  752.                 for(k=0; k < pVert->m_nWeights; k++)
  753.                 {
  754.                     pWeight = &pVert->m_Weights[k];
  755.                     ASSERT(pWeight->m_iNode < pModel->NumNodes());
  756.  
  757.                     // Regular method..
  758.                     MatVMul_Add(vTemp, &pTransforms[pWeight->m_iNode], pWeight->m_Vec);                    
  759.                     //memcpy(vTemp,pWeight->m_Vec,sizeof(float)*4);
  760.                 }
  761.  
  762.                 // Divide by w.
  763.                 vTemp[3] = 1.0f / vTemp[3];
  764.                 ((DVector*)pCurOut)->x = vTemp[0] * vTemp[3];
  765.                 ((DVector*)pCurOut)->y = vTemp[1] * vTemp[3];
  766.                 ((DVector*)pCurOut)->z = vTemp[2] * vTemp[3];
  767.  
  768.                 // Calculate normals
  769.                 if(bNormals)
  770.                 {
  771.                     vTemp[0] = vTemp[1] = vTemp[2] = vTemp[3] = 0.0f;
  772.  
  773.                     for(k=0; k < pVert->m_nWeights; k++)
  774.                     {
  775.                         pWeight = &pVert->m_Weights[k];
  776.                         ASSERT(pWeight->m_iNode < pModel->NumNodes());
  777.  
  778.                         theVec[0] = pVert->m_Normal.x * pWeight->m_Vec[3];
  779.                         theVec[1] = pVert->m_Normal.y * pWeight->m_Vec[3];
  780.                         theVec[2] = pVert->m_Normal.z * pWeight->m_Vec[3];
  781.  
  782.                         theVec[3] = 0 ; //pWeight->m_Vec[3];
  783.  
  784.                         // pTransforms[i] is the appropriate way to transform this from 
  785.                         // node-local coords, so we need to transform from world to local
  786.                         // which is done by premultiplying by the inverse global transform.
  787.  
  788.                         ModelNode *node=pModel->GetNode(pWeight->m_iNode);
  789.                         LTMatrix matrix=node->GetInvGlobalTransform();
  790.                         LTMatrix worldToPosed = pTransforms[pWeight->m_iNode] * matrix;
  791.  
  792.                         MatVMul_Add_3x3(vTemp, &worldToPosed, theVec);
  793.                     }
  794.  
  795.                     pNormalOut = (DVector*)(pCurOut + sizeof(DVector));
  796.  
  797.                     float oneOverLen = 1.0f/sqrtf( vTemp[0] * vTemp[0] + vTemp[1] * vTemp[1] + vTemp[2] * vTemp[2] );
  798.  
  799.                     vTemp[0] *= oneOverLen ;
  800.                     vTemp[1] *= oneOverLen ;
  801.                     vTemp[2] *= oneOverLen ;
  802.                     pNormalOut->x = vTemp[0] ;
  803.                     pNormalOut->y = vTemp[1] ;
  804.                     pNormalOut->z = vTemp[2] ;
  805.                 }
  806.  
  807.             }
  808.             else if(bDrawOriginalModel)// draworiginal model
  809.             {
  810.                 ((DVector*)pCurOut)->Init();
  811.                 ((DVector*)pCurOut)->x = pVert->m_Vec.x ;
  812.                 ((DVector*)pCurOut)->y = pVert->m_Vec.y ;
  813.                 ((DVector*)pCurOut)->z = pVert->m_Vec.z ;
  814.  
  815.                 pNormalOut = (DVector*)(pCurOut + sizeof(DVector));
  816.                 pNormalOut->Init();
  817.                 pNormalOut->x=pVert->m_Normal.x;
  818.                 pNormalOut->y=pVert->m_Normal.y;
  819.                 pNormalOut->z=pVert->m_Normal.z;
  820.             }
  821.         
  822.  
  823.             pCurOut += pStruct->m_VertexStride;
  824.         }// for every vertex
  825.     }
  826.  
  827.     if( pNextVert )
  828.         *pNextVert = pCurOut;
  829.  
  830.     return TRUE;
  831. }
  832.  
  833. // ------------------------------------------------------------------------
  834. // set-vertex-color-based-on-bone-weight( model, render-data, bone-index)
  835. // sets a grey intensity based on the vertex weight for bone index. 
  836. // ------------------------------------------------------------------------
  837. BOOL SetVertexColorBasedOnBoneWeight(Model     *pModel,
  838.                                       GVPStruct *pStruct, 
  839.                                      set<int> &requested_bones )
  840. {
  841.     DWORD       i, j, k;
  842.     ModelPiece *pPiece;
  843.     TVert      *pCurOut;
  844.     ModelVert  *pVert;
  845.     PieceLOD   *pLOD;
  846.     NewVertexWeight *pWeight;
  847.     
  848.     // was pstruct set up right?
  849.     if(!pStruct->m_Vertices)
  850.         return FALSE;
  851.  
  852.     // Copy the vertex positions over.
  853.     pCurOut = (TVert*)pStruct->m_Vertices;
  854.  
  855.  
  856.     for(i=0; i < pModel->NumPieces(); i++)
  857.     {
  858.         pPiece = pModel->GetPiece(i);
  859.         pLOD = pPiece->GetLOD(pStruct->m_CurrentLODDist);
  860.  
  861.         for(j=0; j < pLOD->m_Verts; j++)
  862.         {
  863.             pVert = &pLOD->m_Verts[j];
  864.             // Create Color based on vertex weight and selected bone        
  865.             if(pVert->m_nWeights > 0)
  866.             {
  867.                 pCurOut->m_vColor.Init(0.0f,0.0f,0.0f);
  868.  
  869.                 for(k=0; k < pVert->m_nWeights; k++)
  870.                 {
  871.                     pWeight = &pVert->m_Weights[k];
  872.                     ASSERT(pWeight->m_iNode < pModel->NumNodes());
  873.  
  874.                     // if the weight influence is in the requested bone set, create a color 
  875.                     // for it on the vertex. 
  876.                     if( requested_bones.find( pWeight->m_iNode ) != requested_bones.end())
  877.                     {    
  878.                         LTVector intensity(pWeight->m_Vec[3],pWeight->m_Vec[3],pWeight->m_Vec[3]);
  879.  
  880.                         // turn the vector red if weight is over one.
  881.                         if( pWeight->m_Vec[3] > 1.0 )
  882.                             intensity.y = intensity.z = 0.0f ;
  883.                         
  884.                         pCurOut->m_vColor += intensity;
  885.                     }
  886.                 }    
  887.             }
  888.             pCurOut ++ ;
  889.         }// for every vertex
  890.     }// for every piece
  891.  
  892.     return TRUE;
  893. }
  894.  
  895.  
  896.  
  897. // ------------------------------------------------------------------------
  898. // DrawModelPolies( )
  899. // ------------------------------------------------------------------------
  900. static void DrawModelPolies(GLM_CONTEXT hContext,
  901.                             AnimTracker **pTrackers,
  902.                             DWORD nTrackers, 
  903.                             BOOL bDrawBright,
  904.                             DMatrix *pRootTransform,
  905.                             BYTE *pSelectedPieces,
  906.                             BOOL bNormals,
  907.                             DWORD iLOD,
  908.                             BOOL bDrawOriginalModel,
  909.                             BOOL bTexture,
  910.                             DrawStruct* pStruct,
  911.                             bool bCalcRadius = false,
  912.                             float* pRadius = NULL,
  913.                             bool bCalcAndDraw = false )
  914. {
  915.     int node_cnt ;
  916.     DWORD i, j, nWantedVerts;
  917.     ModelPiece *pPiece;
  918.     GVPStruct gvp;
  919.     DVector v1, v2;
  920.     TVert *pCurVert;
  921.     PieceLOD *pLOD;
  922.     static CMoArray<TVert> tVerts;
  923.     Model *pModel;
  924.     GLMContext *pContext = (GLMContext *)hContext;
  925.  
  926.     float current_lod_dist = pStruct->m_CurrentLODDist ;
  927.  
  928.     if(nTrackers == 0 || !pTrackers[0]->m_TimeRef.m_pModel)
  929.         return;
  930.  
  931.     pModel = pTrackers[0]->m_TimeRef.m_pModel;
  932.     nTrackers = DMIN(nTrackers, MAX_GVP_ANIMS);
  933.  
  934.     // Size our list.
  935.     nWantedVerts = pModel->GetTotalNumVerts() * 2;
  936.     if(tVerts.GetSize() < nWantedVerts)
  937.     {
  938.         if(!tVerts.SetSize(nWantedVerts))
  939.             return;
  940.     }
  941.  
  942.     // Use the model code to setup the vertices.
  943.     gvp.m_nAnims = 0;
  944.     for(i=0; i < nTrackers; i++)
  945.     {
  946.         gvp.m_Anims[i] = pTrackers[i]->m_TimeRef;
  947.         gvp.m_nAnims++;
  948.     }
  949.  
  950.     gvp.m_VertexStride = sizeof(TVert);
  951.     gvp.m_Vertices = tVerts.GetArray();
  952.     gvp.m_BaseTransform = *pRootTransform;
  953.     gvp.m_iLOD = iLOD;
  954.     gvp.m_CurrentLODDist = pStruct->m_CurrentLODDist ;
  955.  
  956.     TVert* pEndVert;
  957.  
  958.     if(!AlternateGetVertexPositions(pModel, &gvp, TRUE, TRUE, bDrawOriginalModel, pStruct->m_bMovementEncoding, (void**)&pEndVert))
  959.         return;
  960.  
  961.     // calculate the radius of this rendered frame of the model
  962.     if( bCalcRadius && pRadius )
  963.     {
  964.         // get the inverse of the base transform
  965.         LTMatrix mInvBase = pRootTransform->MakeInverse();
  966.         // find the maximum magsqr of the vertex locations
  967.         *pRadius = 0.0f;
  968.         for( TVert* pCurVert = tVerts.GetArray(); pCurVert < pEndVert; ++pCurVert )
  969.         {
  970.             // put the vertex in world coords
  971.             LTVector vWorldPos;
  972.             mInvBase.Apply( pCurVert->m_vPos, vWorldPos );
  973.             float fCurMag = vWorldPos.MagSqr();
  974.             if( fCurMag > *pRadius )
  975.                 *pRadius = fCurMag;
  976.         }
  977.         // the sqrt of that is what we want
  978.         *pRadius = (float)sqrt( *pRadius );
  979.         if( !bCalcAndDraw )
  980.             return;
  981.     }
  982.  
  983.     if( pStruct->m_bDrawVertexWeights )
  984.     {
  985.         set<int> selected_nodes ;
  986.         // find first selected node 
  987.         for( node_cnt  = 0 ; node_cnt < (int)pModel->NumNodes() ; node_cnt ++ )
  988.         {
  989.             if( pStruct->m_SelectedNodes[ node_cnt ] )
  990.             {
  991.                 selected_nodes.insert( node_cnt );
  992.             }
  993.         }    
  994.  
  995.         SetVertexColorBasedOnBoneWeight(pModel, &gvp, selected_nodes  );
  996.     }
  997.  
  998.  
  999.     if(bDrawBright)
  1000.     {
  1001.         glDisable(GL_LIGHTING);
  1002.         glColor3f(1.0f, 1.0f, 1.0f);
  1003.     }
  1004.     else
  1005.     {
  1006.         glColor3f(0.0f, 1.0f, 0.0f);
  1007.     }    
  1008.  
  1009.  
  1010. // defaults 
  1011.     static GLfloat ambient[4] = {0.2f, 0.2f, 0.2f,1.0f} ;
  1012.     static GLfloat diffuse[4] = {0.8f, 0.8f, 0.8f,1.0f} ;
  1013.     static GLfloat spec[4]    = {0.0f, 0.0f, 0.0f,1.0f};
  1014.     static GLfloat emiss[4]   = {0.0f, 0.0f, 0.0f,1.0f}; 
  1015.     static GLfloat shine      = 0.0f;
  1016.  
  1017. //    glEnable( GL_COLOR_MATERIAL );
  1018.  
  1019.     pCurVert  = tVerts.GetArray() ;
  1020.     int NumPieces = pModel->NumPieces() ;
  1021.     
  1022.     // for every piece 
  1023.     for( int iPieceCnt = 0 ; iPieceCnt < NumPieces ; iPieceCnt++ )
  1024.     {
  1025.         pPiece = pModel->GetPiece( iPieceCnt );
  1026.  
  1027.         // get the current draw lod
  1028.         pLOD = pPiece->GetLOD( current_lod_dist );
  1029.  
  1030.         // swap in the texture if required
  1031.         if( pContext && bTexture && ((uint32)pLOD->m_iTextures[0] < pContext->m_Textures.GetSize()) )
  1032.         {
  1033.             GLuint pieceLODTexture = pContext->m_Textures[pLOD->m_iTextures[0]];
  1034.             if( pieceLODTexture && (pieceLODTexture != pContext->m_nCurTexture) )
  1035.             {
  1036.                 pContext->m_nCurTexture = pieceLODTexture;
  1037.                 glBindTexture( GL_TEXTURE_2D, pContext->m_nCurTexture );
  1038.             }
  1039.  
  1040.             // only turn on texturing if there is a valid texture
  1041.             if( pieceLODTexture )
  1042.                 glEnable( GL_TEXTURE_2D );
  1043.             else
  1044.                 glDisable( GL_TEXTURE_2D );
  1045.         }
  1046.         else
  1047.         {
  1048.             // no texture, turn off texturing
  1049.             glDisable( GL_TEXTURE_2D );
  1050.         }
  1051.  
  1052.         
  1053.  
  1054.         // ------------    ------------------------------------------------------------
  1055.         // If we want to draw the vertex weights instead of the effect of light on 
  1056.         // the model we turn off lights, and material.
  1057.         // ------------    ------------------------------------------------------------
  1058.         if( pStruct->m_bDrawVertexWeights )
  1059.         {
  1060.             glDisable(GL_LIGHTING);
  1061.             glDisable(GL_CULL_FACE);    
  1062.  
  1063.             glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
  1064.             glBegin( GL_TRIANGLES );
  1065.             DrawPieceVertexColors( pLOD, pCurVert, pStruct );
  1066.             glEnd();
  1067.         }else
  1068.         {
  1069.             // 
  1070.             glMaterialfv( GL_FRONT, GL_DIFFUSE, diffuse );
  1071.             glMaterialfv( GL_FRONT, GL_AMBIENT, ambient );
  1072.             glMaterialfv( GL_FRONT, GL_SPECULAR, spec );
  1073.             glMaterialfv( GL_FRONT, GL_SHININESS, &shine );
  1074.             glMaterialfv( GL_FRONT, GL_EMISSION, emiss );
  1075.             // draw the geometry normally
  1076.             glBegin( GL_TRIANGLES );
  1077.                 DrawPiece( pLOD, pCurVert, pStruct );
  1078.             glEnd();
  1079.         
  1080.         }
  1081.  
  1082.         // step on to the next lump
  1083.         pCurVert += pLOD->m_Verts.GetSize() ;
  1084.  
  1085.     }
  1086.  
  1087.     // Draw vertex normals.
  1088.     if(bNormals)
  1089.     {
  1090.         glDisable(GL_TEXTURE_2D);
  1091.         glDisable(GL_LIGHTING);
  1092.         glDisable(GL_CULL_FACE);
  1093.         glDisable(GL_DEPTH_TEST);
  1094.         glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
  1095.         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  1096.         glColor3f(0.0f, 1.0f, 0.0f);
  1097.  
  1098.         pCurVert = tVerts.GetArray();
  1099.         for(i=0; i < pModel->NumPieces(); i++)
  1100.         {
  1101.             pPiece = pModel->GetPiece(i);
  1102.             pLOD = pPiece->GetLOD( current_lod_dist );
  1103.             if( pLOD == NULL ) break ;
  1104.  
  1105.             for(j=0; j < pLOD->NumVerts(); j++)
  1106.             {
  1107.                 v1 = pCurVert->m_vPos;
  1108.                 v2 = v1 + pCurVert->m_vNormal * 5.0f;
  1109.  
  1110.                 glBegin(GL_LINES);
  1111.                     glVertex3f(EXPANDVEC(v1));
  1112.                     glVertex3f(EXPANDVEC(v2));
  1113.                 glEnd();
  1114.  
  1115.                 pCurVert++;
  1116.             }
  1117.         }
  1118.     }
  1119.  
  1120.  
  1121.     glDisable(GL_TEXTURE_2D);
  1122.     if(bDrawBright)
  1123.     {
  1124.         glColor3f(0.0f, 1.0f, 0.0f);
  1125.     }
  1126.  
  1127.  
  1128.     DrawOriginLines();
  1129.  
  1130.  
  1131.     // If there are any selections, draw those too.
  1132.     glDisable(GL_LIGHTING);
  1133.     glEnable(GL_CULL_FACE);
  1134.     glDisable(GL_DEPTH_TEST);
  1135.     glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
  1136.     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  1137.  
  1138.     if(pSelectedPieces)
  1139.     {
  1140.         glColor3f(1.0f, 1.0f, 0.0f);
  1141.         glBegin(GL_TRIANGLES);
  1142.  
  1143.             pCurVert = tVerts.GetArray();
  1144.             for(i=0; i < pModel->NumPieces(); i++)
  1145.             {
  1146.                 pPiece = pModel->GetPiece(i);
  1147.                 pLOD = pPiece->GetLOD( current_lod_dist);
  1148.                 
  1149.                 if(pSelectedPieces[i])
  1150.                 {
  1151.                     DrawPiece(pLOD, pCurVert, pStruct );
  1152.                 }
  1153.  
  1154.                 pCurVert += pLOD->m_Verts.GetSize();
  1155.             }
  1156.  
  1157.         glEnd();
  1158.     }
  1159. }
  1160.  
  1161. // ------------------------------------------------------------------------
  1162. // Draw a line 
  1163. // ------------------------------------------------------------------------
  1164. void DrawArrow(float r, float g, float b, DVector pos, DVector vec, float length)
  1165. {
  1166.     DVector pos2;
  1167.  
  1168.     glColor3f(r, g, b);
  1169.  
  1170.     pos2 = pos + vec*length;
  1171.     glBegin(GL_LINES);
  1172.         glVertex3f(VEC_EXPAND(pos));
  1173.         glVertex3f(VEC_EXPAND(pos2));
  1174.     glEnd();
  1175. }
  1176.  
  1177. // ------------------------------------------------------------------------
  1178. // DrawCoordSys
  1179. // draw the rotation basis at pos, r/g/b = X/Y/Z
  1180. // ------------------------------------------------------------------------
  1181. void DrawCoordSys(DMatrix *pMat, float arrowLength)
  1182. {
  1183.     DVector up, right, forward;
  1184.     DVector pos;
  1185.     StateSet stateTexture(GL_TEXTURE_2D, FALSE);
  1186.     StateSet stateDepthTest(GL_DEPTH_TEST, FALSE);
  1187.     StateSet Lighting( GL_LIGHTING, FALSE );
  1188.  
  1189.     Mat_GetBasisVectors(pMat, &right, &up, &forward);
  1190.     pos.x = pMat->m[0][3];
  1191.     pos.y = pMat->m[0][7];
  1192.     pos.z = pMat->m[0][11];
  1193.  
  1194.     DrawArrow(1.0f, 0.0f, 0.0f, pos, right, arrowLength);
  1195.     DrawArrow(0.0f, 1.0f, 0.0f, pos, up, arrowLength);
  1196.     DrawArrow(0.0f, 0.0f, 1.0f, pos, forward, arrowLength);
  1197. }
  1198.  
  1199. // ------------------------------------------------------------------------
  1200. // RecurseAndDrawSkeleton()
  1201. // ------------------------------------------------------------------------
  1202. void RecurseAndDrawSkeleton(DrawStruct *pStruct, 
  1203.                             ModelNode  *pNode, 
  1204.                             LTVector    curNodePos, 
  1205.                             BOOL       bChainStarted)
  1206. {
  1207.     DVector myPos;
  1208.     DWORD i;
  1209.     Model *pModel;
  1210.     BOOL bSelected;
  1211.     LTMatrix mat ;
  1212.     float fEvaledVal;
  1213.  
  1214.     pModel = pStruct->GetModel();
  1215.  
  1216.     // don't draw the movement node if we are rendering using movement encoding
  1217.     if( pStruct->m_bMovementEncoding && (pModel->GetMovementNode() == pNode) )
  1218.         return;
  1219.  
  1220.     // Transform the position.
  1221.     if( !pStruct->m_bDrawOriginalModel )
  1222.         mat = pModel->m_Transforms[pNode->GetNodeIndex()];
  1223.     else
  1224.         mat = pNode->GetGlobalTransform();
  1225.  
  1226.     mat.GetTranslation( myPos );
  1227.  
  1228.     if(bChainStarted)
  1229.     {
  1230.         // The chain has already started so draw a line.
  1231.         glBegin(GL_LINES);
  1232.             glColor3f(1.0f, 1.0f, 1.0f);
  1233.             glVertex3f(VEC_EXPAND(curNodePos));
  1234.             glColor3f(0.2f, 0.2f, 0.2f);
  1235.             glVertex3f(VEC_EXPAND(myPos));
  1236.         glEnd();
  1237.     }
  1238.  
  1239.     // Draw a point if node is selected
  1240.     bSelected = pStruct->m_SelectedNodes[pNode->GetNodeIndex()];
  1241.     fEvaledVal= pNode->m_EvalState == ModelNode::kIgnore ? 0.5f : 1.0f ;
  1242.  
  1243.     glPointSize(bSelected ? 8.0f : 4.0f);
  1244.     glBegin(GL_POINTS);
  1245.  
  1246.     if(bSelected)
  1247.     {
  1248.         // yellow
  1249.         glColor3f(fEvaledVal, 1.0f, 0.0f);
  1250.     }
  1251.     else
  1252.     {
  1253.         // not yellow
  1254.         glColor3f(0.0f, 1.0f, fEvaledVal);
  1255.     }
  1256.  
  1257.     glVertex3f(VEC_EXPAND(myPos));
  1258.  
  1259.     glEnd();
  1260.  
  1261.     if(bSelected)
  1262.         DrawCoordSys( &mat, 6.0f );
  1263.  
  1264.     bChainStarted = TRUE;
  1265.  
  1266.     // Go into the children.
  1267.     for(i=0; i < pNode->m_Children; i++)
  1268.     {
  1269.         RecurseAndDrawSkeleton(pStruct, pNode->m_Children[i], myPos, bChainStarted);
  1270.     }
  1271. }
  1272.  
  1273. void RecurseAndDrawOBB(DrawStruct *pStruct, ModelNode  *pNode     );
  1274.     
  1275. // ------------------------------------------------------------------------
  1276. // DrawSkeleton( draw-struct );
  1277. // recursively draws the skeleton, showing selected nodes with a large point and
  1278. // a coord-sys representation.
  1279. // ------------------------------------------------------------------------
  1280. void DrawSkeleton(DrawStruct *pStruct)
  1281. {
  1282.     LTVector curNodePos;
  1283.     
  1284.     glDisable(GL_LIGHTING);
  1285.     glDisable(GL_CULL_FACE);
  1286.     glDisable(GL_DEPTH_TEST);
  1287.     glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
  1288.     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  1289.     
  1290.     curNodePos.Init();
  1291.     RecurseAndDrawSkeleton(pStruct, pStruct->GetModel()->GetRootNode(), curNodePos, FALSE);
  1292.  
  1293.     if(pStruct->m_bDrawOBB)
  1294.         RecurseAndDrawOBB(pStruct, pStruct->GetModel()->GetRootNode());
  1295. }
  1296.  
  1297. // ------------------------------------------------------------------------
  1298. // ltmat_to_glmat( lt-mat in, gl-mat out)
  1299. //
  1300. // convert a lithtech mat to a gl mat. basically transposes the matrix.
  1301. // ------------------------------------------------------------------------
  1302. static void ltmat_to_glmat( LTMatrix &mat, float *gl_mat )
  1303. {
  1304.     int cnt = 0 ;
  1305.  
  1306.     for( int row = 0 ; row < 4 ; row ++ )
  1307.     for( int col = 0 ; col < 4 ; col++ )
  1308.     {
  1309.         gl_mat[cnt] = mat.El( col, row );
  1310.         cnt ++ ;
  1311.     }
  1312. }
  1313.  
  1314. // -----------------------------------------------------------------------
  1315. // draw_box( position, orientation, scale )
  1316. //
  1317. // draw the bounding box, position, orient and scale it.
  1318. // ------------------------------------------------------------------------
  1319. static void draw_box( const LTVector &offset, 
  1320.                      const LTRotation &orient, 
  1321.                      const LTVector & size                 )
  1322. {
  1323.  
  1324.  
  1325.     LTMatrix mat ;
  1326.     float gl_mat[16];
  1327.     LTVector vmin(-.5f,-.5f,-.5f), vmax(.5f,.5f,.5f);
  1328.     
  1329.  
  1330.     mat.Identity();
  1331.     orient.ConvertToMatrix(mat);
  1332.     
  1333.     ltmat_to_glmat(mat,gl_mat);
  1334.  
  1335.     // set up the box's local transform
  1336.     glPushMatrix();
  1337.     // do rotation
  1338.  
  1339.     glMultMatrixf( gl_mat );
  1340.     glTranslatef( offset.x, offset.y,offset.z );
  1341.     //glScalef( size.x, size.y, size.z );
  1342.     vmin = vmin * size ; vmax = vmax *size ;
  1343.     
  1344.     // line drawing of box
  1345.     glBegin(GL_LINES);
  1346.         // top
  1347.         glVertex3f (vmin.x, vmin.y, vmin.z);
  1348.         glVertex3f (vmax.x, vmin.y, vmin.z);
  1349.  
  1350.         glVertex3f (vmax.x, vmin.y, vmin.z);
  1351.         glVertex3f (vmax.x, vmin.y, vmax.z);
  1352.  
  1353.         glVertex3f (vmax.x, vmin.y, vmax.z);
  1354.         glVertex3f (vmin.x, vmin.y, vmax.z);
  1355.  
  1356.         glVertex3f (vmin.x, vmin.y, vmax.z);
  1357.         glVertex3f (vmin.x, vmin.y, vmin.z);
  1358.  
  1359.         // bottom
  1360.  
  1361.         glVertex3f (vmax.x, vmax.y, vmax.z);
  1362.         glVertex3f (vmin.x, vmax.y, vmax.z);
  1363.         
  1364.         glVertex3f (vmin.x, vmax.y, vmax.z);
  1365.         glVertex3f (vmin.x, vmax.y, vmin.z);
  1366.  
  1367.         glVertex3f (vmin.x, vmax.y, vmin.z);
  1368.         glVertex3f (vmax.x, vmax.y, vmin.z);
  1369.  
  1370.         glVertex3f (vmax.x, vmax.y, vmin.z);
  1371.         glVertex3f (vmax.x, vmax.y, vmax.z);
  1372.  
  1373.         // sides
  1374.  
  1375.         glVertex3f (vmin.x, vmin.y, vmin.z);
  1376.         glVertex3f (vmin.x, vmax.y, vmin.z);
  1377.  
  1378.         glVertex3f (vmax.x, vmin.y, vmin.z);
  1379.         glVertex3f (vmax.x, vmax.y, vmin.z);
  1380.  
  1381.         glVertex3f (vmax.x, vmin.y, vmax.z);
  1382.         glVertex3f (vmax.x, vmax.y, vmax.z);
  1383.  
  1384.         glVertex3f (vmin.x, vmin.y, vmax.z);
  1385.         glVertex3f (vmin.x, vmax.y, vmax.z);
  1386.  
  1387.     
  1388.     glEnd();
  1389.  
  1390.     glPopMatrix();
  1391.  
  1392. }
  1393.  
  1394. // ------------------------------------------------------------------------
  1395. // RecurseAndDrawOBB()
  1396. // ------------------------------------------------------------------------
  1397. void RecurseAndDrawOBB(DrawStruct *pStruct, 
  1398.                             ModelNode  *pNode                             )
  1399.  
  1400. {
  1401.     DVector myPos;
  1402.     DWORD i;
  1403.     Model *pModel;
  1404.     BOOL bSelected;
  1405.     LTMatrix mat ;
  1406.  
  1407.     pModel = pStruct->GetModel();
  1408.  
  1409.     // don't draw the movement node if we are rendering using movement encoding
  1410.     if( pStruct->m_bMovementEncoding && (pModel->GetMovementNode() == pNode) )
  1411.         return;
  1412.  
  1413.     // Transform the position.
  1414.     if( pStruct->m_bDrawOriginalModel )
  1415.         mat = pNode->GetGlobalTransform();    
  1416.     else
  1417.         mat = pModel->m_Transforms[pNode->GetNodeIndex()];
  1418.  
  1419.     mat.GetTranslation( myPos );
  1420.  
  1421.     // Draw a point if node is selected
  1422.     bSelected = pStruct->m_SelectedNodes[pNode->GetNodeIndex()];
  1423.  
  1424.     glPointSize(bSelected ? 8.0f : 4.0f);
  1425.     glBegin(GL_POINTS);
  1426.  
  1427.         if(bSelected)
  1428.         {
  1429.             glColor3f(1.0f, 1.0f, 0.0f);
  1430.         }
  1431.         else
  1432.         {
  1433.             glColor3f(0.0f, 1.0f, 1.0f);
  1434.         }
  1435.  
  1436.         glVertex3f(VEC_EXPAND(myPos));
  1437.  
  1438.     glEnd();
  1439.  
  1440.     if(bSelected)
  1441.     {
  1442.         DrawCoordSys( &mat, 6.0f );
  1443.     }
  1444.  
  1445.     LTRotation default_orient;
  1446.     default_orient.Init();
  1447.     const SOBB obb = pNode->GetOBB();
  1448.  
  1449.     // if node is selected draw one color else draw common color
  1450.     if(bSelected) glColor3f(1.0f, 1.0f, 0.0f); else glColor3f(0.0f, 1.0f, 1.0f);
  1451.  
  1452.     // apply the current transform into the current matrix stack.
  1453.     if( pNode->IsOBBEnabled() )
  1454.     {
  1455.         float gl_mat[16];
  1456.         ltmat_to_glmat( mat, gl_mat );
  1457.         // move the box into nodes' coordinate frame
  1458.  
  1459.         glPushMatrix();
  1460.         glMultMatrixf( gl_mat );
  1461.         draw_box( obb.m_Pos , obb.m_Orientation, obb.m_Size);
  1462.         glPopMatrix();
  1463.     }
  1464.  
  1465.     // Recure down tree.
  1466.     for(i=0; i < pNode->m_Children; i++)
  1467.     {
  1468.         RecurseAndDrawOBB(pStruct, pNode->m_Children[i]);
  1469.     }
  1470. }
  1471.  
  1472.  
  1473. void DrawSocket(DrawStruct *pStruct, ModelSocket *pSocket)
  1474. {
  1475.     LTMatrix socketTransform;
  1476.     Model *pModel;
  1477.  
  1478.     LTBOOL bSelected = pStruct->m_SelectedNodes[pSocket->m_iNode];
  1479.  
  1480.     if(!bSelected)
  1481.     {
  1482.         glLineStipple(2, 0x1111); // Dotted lines.
  1483.         glEnable(GL_LINE_STIPPLE);
  1484.     }
  1485.     else 
  1486.         glLineWidth(2.0f);
  1487.  
  1488.  
  1489.     pModel = pStruct->GetModel();
  1490.  
  1491.     if(pModel->GetSocketTransform(pSocket, &socketTransform))
  1492.     {
  1493.         DrawCoordSys(&socketTransform, 10.0f);
  1494.     }
  1495.  
  1496.     if(!bSelected) {
  1497.         glDisable(GL_LINE_STIPPLE);
  1498.         glLineStipple(1, 0xFFFF);
  1499.     }
  1500.     glLineWidth(1.0f);
  1501. }
  1502.  
  1503. // ------------------------------------------------------------------------
  1504. // DrawAttachement( model, socket-transform, lod-level, solid, draw-context )
  1505. // Draw the model attached to a socket.
  1506. // ------------------------------------------------------------------------
  1507. static void DrawAttachment(Model *pAttachment,
  1508.                            DMatrix *pTransform,
  1509.                            DWORD iLOD,
  1510.                            BOOL bSolid,
  1511.                            DrawStruct* pStruct)
  1512. {
  1513.     AnimTracker tracker, *pTracker;
  1514.     StateSet stateLighting(GL_LIGHTING, bSolid);
  1515.     StateSet stateCull(GL_CULL_FACE, bSolid);
  1516.     StateSet stateDepth(GL_DEPTH_TEST, bSolid);
  1517.     GLenum eOldPolyMode;
  1518.     glGetIntegerv(GL_POLYGON_MODE, (int *)&eOldPolyMode);
  1519.     glPolygonMode(GL_FRONT_AND_BACK, (bSolid) ? GL_FILL : GL_LINE);
  1520.  
  1521.     tracker.m_TimeRef.Init(pAttachment, 0, 0, 0, 0, 0.0f);
  1522.     pTracker = &tracker;
  1523.  
  1524.     DrawModelPolies(NULL,
  1525.                     &pTracker,
  1526.                     1,
  1527.                     FALSE,
  1528.                     pTransform,
  1529.                     NULL,
  1530.                     FALSE,
  1531.                     iLOD,
  1532.                     FALSE,
  1533.                     pStruct->m_bDrawTextures,
  1534.                     pStruct);
  1535.  
  1536.     glPolygonMode(GL_FRONT_AND_BACK, eOldPolyMode);
  1537. }
  1538.  
  1539.  
  1540. static void DrawSocketsAndAttachments(DrawStruct *pStruct)
  1541. {
  1542.     uint32 i;
  1543.     ModelSocket *pSocket;
  1544.     Model *pModel;
  1545.     TransformMaker tMaker;
  1546.     LTMatrix mSocket;
  1547.  
  1548.     //if( !pStruct->m_bDrawAttachments || !pStruct->m_bDrawSockets )
  1549.         //return ;
  1550.  
  1551.     pModel = pStruct->GetModel();
  1552.     pModel->ResetNodeEvalState();
  1553.  
  1554.     // tag the nodes to eval.
  1555.     for(i=0; i < pModel->NumSockets(); i++)
  1556.     {
  1557.         pSocket = pModel->GetSocket(i);
  1558.  
  1559.         pModel->SetupNodeEvalStateFromNode( pSocket->m_iNode );
  1560.     }
  1561.  
  1562.     // Setup transforms.  
  1563.     pStruct->SetupTransformMaker(&tMaker);
  1564.     
  1565.     if(pStruct->m_bMovementEncoding && !tMaker.SetupMovementEncoding())
  1566.         return;
  1567.     if(!tMaker.SetupTransforms())
  1568.         return;
  1569.  
  1570.     
  1571.     for(i=0; i < pModel->NumSockets(); i++)
  1572.     {
  1573.         pSocket = pModel->GetSocket(i);
  1574.         
  1575.         if(pStruct->m_bDrawAttachments && pSocket->m_pAttachment)
  1576.         {
  1577.             if(pModel->GetSocketTransform(pSocket, &mSocket))
  1578.             {
  1579.                 DrawAttachment(
  1580.                     pSocket->m_pAttachment, 
  1581.                     &mSocket, 
  1582.                     pStruct->m_iLOD, 
  1583.                     pStruct->m_bSolidAttachments,
  1584.                     pStruct);
  1585.             }
  1586.         }
  1587.  
  1588.         if(pStruct->m_bDrawSockets)
  1589.         {
  1590.             DrawSocket(
  1591.                 pStruct, 
  1592.                 pSocket);
  1593.         }
  1594.     }
  1595. }
  1596.  
  1597.  
  1598.  
  1599. // ------------------------------------------------------------------------
  1600. // DrawModel
  1601. // Entry point for rendering the model.
  1602. // ------------------------------------------------------------------------
  1603. void DrawModel(GLM_CONTEXT hContext, DrawStruct *pStruct)
  1604. {
  1605.     GLMContext *pContext;
  1606.     DMatrix baseTransform;
  1607.     DVector vMin, vMax;
  1608.     Model *pModel;
  1609.     uint32 renderTicksTGT = 0;
  1610.     LARGE_INTEGER Ticks;
  1611.     RECT rect;
  1612.     char str[256];
  1613.     uint64 startTime;
  1614.     uint64 stopTime;
  1615.     double renderTicks;
  1616.  
  1617.     LARGE_INTEGER Frequency;
  1618.     QueryPerformanceFrequency(&Frequency);
  1619.     double m_fPrecisionScaleMS = (Frequency.QuadPart == 0) ? 1.0 : 1000.0 / (double)(Frequency.QuadPart);
  1620.  
  1621.     QueryPerformanceCounter(&Ticks);
  1622.  
  1623.     startTime = Ticks.QuadPart;
  1624.  
  1625.     
  1626.     // Must have at least one valid AnimTracker (the first one is used for things
  1627.     // like dims).
  1628.     if(!pStruct->m_Times[0]->m_TimeRef.m_pModel)
  1629.         return;
  1630.  
  1631.     pModel = pStruct->GetModel();
  1632.     
  1633.     pContext = (GLMContext*)hContext;
  1634.  
  1635.  
  1636.     // Draw the model.
  1637.     renderTicks = 0;
  1638.  
  1639.     Mat_Identity(&baseTransform);
  1640.     
  1641.     DrawModelPolies(hContext,
  1642.                     pStruct->m_Times,
  1643.                     pStruct->NumValidTimes(),
  1644.                     pStruct->m_bDrawBright,
  1645.                     &baseTransform,
  1646.                     pStruct->m_SelectedPieces,
  1647.                     pStruct->m_bNormals,
  1648.                     pStruct->m_iLOD,
  1649.                     pStruct->m_bDrawOriginalModel,
  1650.                     pStruct->m_bDrawTextures,
  1651.                     pStruct,
  1652.                     pStruct->m_bCalcRadius,
  1653.                     &(pStruct->m_fModelRadius),
  1654.                     pStruct->m_bCalcAndDraw);
  1655.  
  1656.     // jump out if we're not actually drawing anything
  1657.     if( pStruct->m_bCalcRadius && !pStruct->m_bCalcAndDraw )
  1658.         return;
  1659.     
  1660.  
  1661.     if(pStruct->m_bDrawSkeleton)
  1662.     {
  1663.         DrawSkeleton(pStruct);
  1664.     }
  1665.  
  1666.     if (pStruct->m_bDims)
  1667.     {
  1668.         vMax = pModel->GetAnimInfo(pStruct->m_Times[0]->m_TimeRef.m_Prev.m_iAnim)->m_vDims;
  1669.         vMin = -vMax;
  1670.         DrawBox ((DVector*)&pStruct->m_DimsColor, &vMin, &vMax);
  1671.     }
  1672.  
  1673.  
  1674.     // Draw sockets.
  1675.     if(pStruct->m_bDrawAttachments || pStruct->m_bDrawSockets)
  1676.     {
  1677.         DrawSocketsAndAttachments(pStruct);
  1678.     }
  1679.  
  1680.  
  1681.     if (pStruct->m_bAnimBox)
  1682.     {
  1683.         vMax.x = vMax.y = vMax.z = pModel->m_GlobalRadius;
  1684.         vMin = -vMax;
  1685.         DrawBox ((DVector*)&pStruct->m_AnimBoxColor, &vMin, &vMax);
  1686.     }
  1687.  
  1688.     // Draw some status stuff..
  1689.     if(pStruct->m_bProfile)
  1690.     {
  1691.         QueryPerformanceCounter(&Ticks);
  1692.  
  1693.         stopTime = Ticks.QuadPart;
  1694.     
  1695.         renderTicks = ( ( stopTime-startTime) * m_fPrecisionScaleMS);
  1696.  
  1697.         rect.left = rect.top = 0;
  1698.         rect.right = 1000;
  1699.         rect.bottom = 100;
  1700.         sprintf(str, "Tris: %d, Ticks: %f", pModel->CalcNumTris(pStruct->m_CurrentLODDist), renderTicks);
  1701.         DrawText(pContext->m_hDC, str, strlen(str), &rect, DT_LEFT);
  1702.     }
  1703. }
  1704.  
  1705.  
  1706. BOOL SetGLMTexture(GLM_CONTEXT hContext, TextureData *pTexture, DWORD nTextureNum)
  1707. {
  1708.     BYTE *p32BitTexture;
  1709.     FormatMgr formatMgr;
  1710.     PFormat srcFormat, destFormat;
  1711.     ConvertRequest request;
  1712.     DRESULT dResult;
  1713.     TextureMipData *pMip;
  1714.     DWORD err;
  1715.     GLMContext *pContext;
  1716.  
  1717.  
  1718.     if(!(pContext = (GLMContext*)hContext))
  1719.         return FALSE;
  1720.  
  1721.     wglMakeCurrent(pContext->m_hDC, pContext->m_hglrc);
  1722.     pMip = &pTexture->m_Mips[0];
  1723.  
  1724.     // Convert to 32-bit.
  1725.     p32BitTexture = new BYTE[pMip->m_Width * pMip->m_Height * 4];
  1726.     if(!p32BitTexture)
  1727.         return FALSE;
  1728.  
  1729.     dtx_SetupDTXFormat(pTexture, &srcFormat);
  1730.     destFormat.Init(BPP_32, 0xFF000000, 0x000000FF, 0x0000FF00, 0x00FF0000);
  1731.  
  1732.     request.m_pSrcFormat = &srcFormat;
  1733.     request.m_pSrc = pTexture->m_Mips[0].m_Data;
  1734.     request.m_SrcPitch = pMip->m_Pitch;
  1735.     request.m_pDestFormat = &destFormat;
  1736.     request.m_pDest = p32BitTexture;
  1737.     request.m_DestPitch = pMip->m_Width * 4;
  1738.     request.m_Width = pMip->m_Width;
  1739.     request.m_Height = pMip->m_Height;
  1740.     request.m_Flags = 0;
  1741.  
  1742.     //! we need to set the pallete for BPP_32P
  1743.     if (pTexture->m_Header.GetBPPIdent() == BPP_32P)
  1744.     {
  1745.         // find the pallete section
  1746.         DtxSection* pSection = dtx_FindSection(pTexture, "PALLETE32");
  1747.  
  1748.         if (pSection)
  1749.         {
  1750.             request.m_pSrcPalette = (RPaletteColor*)pSection->m_Data;  
  1751.         }
  1752.     }
  1753.  
  1754.     dResult = formatMgr.ConvertPixels(&request);
  1755.     if(dResult != LT_OK)
  1756.         return FALSE;
  1757.  
  1758.     // Clear the error state
  1759.     err = glGetError();
  1760.  
  1761.     while (pContext->m_Textures.GetSize() <= nTextureNum)
  1762.         pContext->m_Textures.Append(0);
  1763.  
  1764.     // Free the texture channel if it's already allocated
  1765.     if (pContext->m_Textures[nTextureNum])
  1766.     {
  1767.         glDeleteLists(pContext->m_Textures[nTextureNum], 1);
  1768.         err = glGetError();
  1769.     }
  1770.  
  1771.     // Create a texture binding for the texture
  1772.     GLuint nTextureID;
  1773.     glGenTextures(1, &nTextureID);
  1774.     pContext->m_Textures[nTextureNum] = nTextureID;
  1775.     glBindTexture(GL_TEXTURE_2D, nTextureID);
  1776.     err = glGetError();
  1777.  
  1778.     glDisable(GL_TEXTURE_1D);
  1779.     err = glGetError();
  1780.  
  1781.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  1782.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  1783.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  1784.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  1785.  
  1786.     glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
  1787.     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
  1788.     glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
  1789.     glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
  1790.  
  1791.     glTexImage2D(GL_TEXTURE_2D, 0, 4, pMip->m_Width, pMip->m_Height, 0, 
  1792.         GL_RGBA, GL_UNSIGNED_BYTE, p32BitTexture);
  1793.     err = glGetError();
  1794.  
  1795.     delete p32BitTexture;
  1796.  
  1797.     // Adjust for bilinear filtering.
  1798.     g_tuAdd = 0.5f / (float)pMip->m_Width;
  1799.     g_tvAdd = 0.5f / (float)pMip->m_Height;
  1800.     return TRUE;
  1801. }
  1802.  
  1803. // ----------------------------------------------------------
  1804. // SetGLMBackgroundColor( gl-context, COLORREF )
  1805. // ----------------------------------------------------------
  1806. void SetGLMBackgroundColor( GLM_CONTEXT hContext, COLORREF win_color )
  1807. {
  1808.     GLMContext *pContext ;
  1809.     unsigned char *pColDecomp = (unsigned char*)&win_color;
  1810.  
  1811.     if(!(pContext = (GLMContext*)hContext))
  1812.     {
  1813.         ASSERT( pContext != NULL ); // let windows deal with this error.
  1814.         return ;
  1815.     }
  1816.  
  1817.     // unitize
  1818.     pContext->m_bgColor[0] = pColDecomp[0]/255.0f;
  1819.     pContext->m_bgColor[1] = pColDecomp[1]/255.0f;
  1820.     pContext->m_bgColor[2] = pColDecomp[2]/255.0f;
  1821.  
  1822. }
  1823.  
  1824.  
  1825. // ----------------------------------------------------------
  1826. // SetGLMBackgroundColor( gl-context, COLORREF )
  1827. // ----------------------------------------------------------
  1828. void SetGLMBackgroundColor( GLM_CONTEXT hContext, float *color )
  1829. {
  1830.     GLMContext *pContext ;
  1831.     if(!(pContext = (GLMContext*)hContext))
  1832.     {
  1833.         ASSERT( pContext != NULL ); // let windows deal with this error.
  1834.         return ;
  1835.     }
  1836.  
  1837.     pContext->m_bgColor[0] = color[0];
  1838.     pContext->m_bgColor[1] = color[1];
  1839.     pContext->m_bgColor[2] = color[2];
  1840.  
  1841. }
  1842.  
  1843.  
  1844.  
  1845.  
  1846. BOOL DrawStruct::SetupTransformMaker(TransformMaker *pMaker)
  1847. {
  1848.     DWORD i;
  1849.  
  1850.     pMaker->m_nAnims = 0;
  1851.     for(i=0; i < NUM_ANIM_INFOS && pMaker->m_nAnims < MAX_GVP_ANIMS; i++)
  1852.     {
  1853.         if(m_Times[i]->m_TimeRef.m_pModel)
  1854.         {
  1855.             pMaker->m_Anims[pMaker->m_nAnims] = m_Times[i]->m_TimeRef;
  1856.             pMaker->m_nAnims++;
  1857.         }
  1858.     }
  1859.  
  1860.     return pMaker->m_nAnims > 0;
  1861. }
  1862.  
  1863.  
  1864. DWORD DrawStruct::NumValidTimes()
  1865. {
  1866.     DWORD i, nTimes;
  1867.  
  1868.     nTimes = 0;
  1869.     for(i=0; i < NUM_ANIM_INFOS; i++)
  1870.     {
  1871.         if(!m_Times[i]->m_TimeRef.m_pModel)
  1872.             break;
  1873.  
  1874.         ++nTimes;
  1875.     }
  1876.  
  1877.     return nTimes;
  1878. }
  1879.  
  1880. // ------------------------------------------------------------------------
  1881. // 
  1882. // ------------------------------------------------------------------------
  1883. void DrawWorldCoordSys() 
  1884. {
  1885.     static GLuint mGrid = 0;
  1886.     static float mGridSize = 120;
  1887.     static float d;
  1888.  
  1889.     if(mGrid)
  1890.       glCallList( mGrid );
  1891.     else {
  1892.      mGrid = glGenLists( 1 );
  1893.       if( mGrid == 0 )
  1894.       {
  1895.             return ;    
  1896.       }
  1897.       
  1898.       glNewList(mGrid, GL_COMPILE);
  1899.       glPushAttrib(GL_LIGHTING_BIT|GL_DEPTH_BUFFER_BIT );
  1900.       glDisable(GL_LIGHTING);
  1901.       glDisable(GL_DEPTH_TEST);
  1902.       
  1903.       glColor3f(.3f,.3f,.3f);
  1904.       glLineWidth( 5.0f );
  1905.  
  1906.       glBegin(GL_LINES);
  1907.       
  1908.       // draw axis 
  1909.       glColor3f( .3f, 0.0f,0.0f);
  1910.       glVertex3f(-mGridSize, 0.0f, 0.0f);
  1911.       glVertex3f(      0.0f, 0.0f, 0.0f);
  1912.       glColor3f( 1.0f, 0.0f,0.0f);
  1913.       glVertex3f( mGridSize, 0.0f, 0.0f);
  1914.       glVertex3f(      0.0f, 0.0f, 0.0f);
  1915.       
  1916.       d = 0.0f ;
  1917.       glColor3f( 0.0f, 0.0f,.3f);
  1918.       glVertex3f(d, 0.0f, -mGridSize);
  1919.       glVertex3f(d, 0.0f, -0.0f);
  1920.       glColor3f( 0.0f, 0.0f,1.0f);
  1921.       glVertex3f(d, 0.0f,  mGridSize);
  1922.       glVertex3f(d, 0.0f, -0.0f);
  1923.      // glEnd();
  1924.  
  1925.        d = 0.0f ;
  1926.       glColor3f( 0.0f, 0.2f,0.0f);
  1927.       glVertex3f(d,  -mGridSize,0.0f);
  1928.       glVertex3f(d, 0.0f, -0.0f);
  1929.       glColor3f( 0.0f, 1.0f,0.0f);
  1930.       glVertex3f(d, mGridSize,0.0f);
  1931.       glVertex3f(d, 0.0f, -0.0f);
  1932.  
  1933.  
  1934.       glEnd();
  1935.  
  1936.       glLineWidth(1.0f);
  1937.  
  1938.       glPopAttrib();
  1939.       
  1940.       glEndList();
  1941.       
  1942.     }
  1943.   }
  1944.  
  1945. #if(0)
  1946. // ray obb collision 
  1947. // returns false on ray rejection.
  1948. bool ray_obb( const LTVector &o, const LTVector &d, const SOBB &obb, float &t )
  1949. {
  1950.     float tmin = -HUGE;
  1951.     float tmax = HUGE;
  1952.  
  1953.     LTVector p = obb.m_Pos - o ;
  1954.     float e ;
  1955.     float f;
  1956.     float hi;
  1957.     float t1,t2;
  1958.     LTVector X = obb.m_Orientation.Right();
  1959.     LTVector Y = obb.m_Orientation.Up();
  1960.     LTVector Z = obb.m_Orientation.Forward();
  1961.     // x
  1962.     e = X.Dot(p);
  1963.     f = X.Dot(d);
  1964.     hi= obb.m_Size.x /2.0f ;
  1965.     if( fabs(f) > 0.0015 )
  1966.     {
  1967.         t1 = ( e + hi ) / f ;
  1968.         t2 = ( e - hi ) / f ;
  1969.         if( t1 > t2 ) {float v = t2 ; t2 = t1 ; t1 = v ; }
  1970.         if(t1 > tmin ) tmin = t1 ;
  1971.         if(t2 > tmin ) tmin = t2 ;
  1972.         if(tmin > tmax ) { t = 0 ; return false ; }
  1973.         if(tmax < 0  ) { t = 0 ; return false ; }
  1974.         if( ((-e - hi) > 0 ) || ( (-e + hi) < 0 )) { t = 0 ; return false ; }
  1975.  
  1976.     }
  1977.  
  1978.     e = Y.Dot(p);
  1979.     f = Y.Dot(d);
  1980.     hi= obb.m_Size.y /2.0f ;
  1981.     if( fabs(f) > 0.0015 )
  1982.     {
  1983.         t1 = ( e + hi ) / f ;
  1984.         t2 = ( e - hi ) / f ;
  1985.         if( t1 > t2 ) {float v = t2 ; t2 = t1 ; t1 = v ; }
  1986.         if(t1 > tmin ) tmin = t1 ;
  1987.         if(t2 > tmin ) tmin = t2 ;
  1988.         if(tmin > tmax ) { t = 0 ; return false ; }
  1989.         if(tmax < 0    ) { t = 0 ; return false ; }
  1990.         if( ((-e - hi) > 0 ) || ( (-e + hi) < 0 )) { t = 0 ; return false ; }
  1991.  
  1992.     }
  1993.  
  1994.     e = Z.Dot(p);
  1995.     f = Z.Dot(d);
  1996.     hi= obb.m_Size.z /2.0f ;
  1997.     if( fabs(f) > 0.0015 )
  1998.     {
  1999.         t1 = ( e + hi ) / f ;
  2000.         t2 = ( e - hi ) / f ;
  2001.         if( t1 > t2 ) {float v = t2 ; t2 = t1 ; t1 = v ; }
  2002.         if(t1 > tmin ) tmin = t1 ;
  2003.         if(t2 > tmin ) tmin = t2 ;
  2004.         if(tmin > tmax ) { t = 0 ; return false ; }
  2005.         if(tmax < 0    ) { t = 0 ; return false ; }
  2006.         if( ((-e - hi) > 0 ) || ( (-e + hi) < 0 )) { t = 0 ; return false ; }
  2007.  
  2008.     }
  2009.     
  2010.     if( tmin > 0 ) { t = tmin ; return true ;}
  2011.     if( tmax > 0 ) { t = tmax ; return true ;}
  2012. }
  2013. #endif
  2014.  
  2015. //bool obb_obb( const SOBB &A, const SOBB &B , float &t)
  2016.  
  2017.