home *** CD-ROM | disk | FTP | other *** search
/ Quark 3 / Quark3.iso / KATALOG / ARCHIV / TOOL / T001.ZIP / SOURCE.ZIP / md3gl.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-05-23  |  13.6 KB  |  508 lines

  1. /*
  2. Copyright (C) Matthew 'pagan' Baranowski & Sander 'FireStorm' van Rossen
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. GNU General Public License for more details.
  13.  
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17. */
  18.  
  19. #include "system.h"
  20. #include "ndictionary.h"
  21. #include "md3gl.h"
  22. #include "md3view.h"
  23. #include "targa.h"
  24. #include <math.h>
  25.  
  26. /*
  27. sets up an orthogonal projection matrix
  28. */
  29. void set_windowSize( int x, int y )
  30. {
  31.     glMatrixMode(GL_PROJECTION); 
  32.     glLoadIdentity();
  33.     if (y > 0) gluPerspective( 90, (double)x/(double)y, NEAR_GL_PLANE, FAR_GL_PLANE );
  34.     glViewport( 0, 0, x, y );
  35.     
  36.     glMatrixMode(GL_MODELVIEW);
  37. }
  38.  
  39.  
  40. /* 
  41. initializes the opengl state for rendering
  42. */
  43. void initialize_glstate()
  44. {
  45.     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
  46.     glClearDepth(1.0);                    
  47.     glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );    
  48.     glEnable( GL_DEPTH_TEST );     
  49.     glDepthFunc( GL_LEQUAL );
  50.     glShadeModel( GL_SMOOTH );
  51.     oglStateShadedTextured();
  52. //    glFrontFace( mdview.faceSide );
  53.   
  54.     float mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
  55.     float mat_ambient[] = { 0.9f, 0.9f, 0.9f, 1.0 };
  56.     float mat_diffuse[] = { 1, 1, 1, 1 };
  57.     float mat_shininess[] = { 20.0 };
  58.  
  59.     float light_position[] = { 55.0, -50.0, -5.0, 0.0 };
  60.  
  61.     float light2_position[] = {-50.0, 45.0, 15.0, 0.0 };
  62.     float mat2_diffuse[] = { 0.5f, 0.5f, 1, 1 };
  63.  
  64.     glShadeModel (GL_SMOOTH);
  65.  
  66.     glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
  67.     glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
  68.  
  69.     glLightfv(GL_LIGHT0, GL_AMBIENT, mat_ambient);
  70.     glLightfv(GL_LIGHT0, GL_DIFFUSE, mat2_diffuse);
  71.     glLightfv(GL_LIGHT0, GL_POSITION, light_position);
  72.  
  73.     glLightfv(GL_LIGHT1, GL_POSITION, light2_position);   
  74.     glLightfv(GL_LIGHT1, GL_DIFFUSE, mat2_diffuse);
  75.     glLightfv(GL_LIGHT1, GL_AMBIENT, mat_ambient);
  76.  
  77.     glEnable(GL_LIGHTING);
  78.     glEnable(GL_LIGHT0);
  79.     glEnable(GL_LIGHT1);
  80.     glEnable( GL_LIGHTING );
  81.  
  82.     glEnable( GL_BLEND );
  83.  
  84.     glBlendFunc(GL_ONE, GL_ZERO);//bug fix
  85.  
  86.     glEnable( GL_POLYGON_SMOOTH );
  87. }
  88.  
  89.  
  90. /*
  91. set to wire frame mode
  92. */
  93. void oglStateFlatTextured()
  94. {
  95.     glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
  96.     glEnable( GL_TEXTURE_2D );
  97.     glDisable( GL_LIGHTING );
  98. }
  99.  
  100. /*
  101. set to wire frame mode
  102. */
  103. void oglStateShadedTextured()
  104. {
  105.     glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
  106.     glEnable( GL_TEXTURE_2D );
  107.     glEnable( GL_LIGHTING );
  108. }
  109.  
  110. /*
  111. set to wire frame mode
  112. */
  113. void oglStateShadedFlat()
  114. {
  115.     glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
  116.     glDisable( GL_TEXTURE_2D );
  117.     glEnable( GL_LIGHTING );
  118. }
  119.  
  120. /*
  121. set to wire frame mode
  122. */
  123. void oglStateWireframe()
  124. {
  125.     glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
  126.     glDisable( GL_TEXTURE_2D );
  127.     glDisable( GL_LIGHTING );
  128. }
  129.  
  130. /*
  131. computes vector cross product
  132. */
  133. void cross(Vec3 v1, Vec3 v2, Vec3 c)
  134. {
  135.     c[0] = v1[1]*v2[2] - v1[2]*v2[1];
  136.     c[1] = v1[2]*v2[0] - v1[0]*v2[2];
  137.     c[2] = v1[0]*v2[1] - v1[1]*v2[0];
  138. }
  139.  
  140. /* 
  141. makes normal unit length
  142. */
  143. void normalize( Vec3 n )
  144. {
  145.     int i;
  146.     float length = 0.0f;
  147.     for (i=0 ; i< 3 ; i++) length += n[i]*n[i];
  148.     length = (float)sqrt(length);
  149.     if (length == 0) return;    
  150.     for (i=0 ; i< 3 ; i++) n[i] /= length;    
  151. }
  152.  
  153.  
  154. /* --------------------------------------- new gl code ------------------------------------------------- */
  155.  
  156.  
  157. void draw_gl_mesh( gl_mesh *mesh, Vec3 *vecs )
  158. {
  159.     TriVec    *tris;    
  160.     int tri_num, t, v;
  161.     Vec3 v1, v2, normal;
  162.     TexVec       *tvecs;
  163.  
  164.         tris    = mesh->triangles;
  165.         tvecs   = mesh->textureCoord;        
  166.         tri_num = mesh->triangleNum;                
  167.  
  168.         glBegin( GL_TRIANGLES );
  169.         
  170.         for (t=0 ; t<tri_num ; t++) {
  171.                     
  172.             for (v=0 ; v<3 ; v++) {
  173.                 v1[v] = vecs[tris[t][1]][v] - vecs[tris[t][0]][v];
  174.                 v2[v] = vecs[tris[t][2]][v] - vecs[tris[t][0]][v];
  175.             }
  176.             cross( v1, v2, normal );
  177.             normalize( normal );
  178.  
  179.             glNormal3fv( normal );
  180.             glTexCoord2fv( tvecs[tris[t][0]] ); glVertex3fv( vecs[tris[t][0]] );
  181.             glTexCoord2fv( tvecs[tris[t][1]] ); glVertex3fv( vecs[tris[t][1]] );
  182.             glTexCoord2fv( tvecs[tris[t][2]] ); glVertex3fv( vecs[tris[t][2]] );
  183.         }
  184.         glEnd();
  185. }
  186.  
  187. void draw_interpolated_gl_mesh( gl_mesh *mesh, int i)
  188. {
  189.     unsigned int sf=i, ef=i+1, v, vec_num, t;
  190.     Vec3 *vecs1, *vecs2;
  191.     Vec3 *vecsI;
  192.     float frac=mdview.frameFrac, frac1=1.f-frac;
  193.  
  194.  
  195.     // do not interpolate if this is the only frame, or the last frame
  196.     if ((mesh->meshFrameNum < 2) || (ef == mesh->meshFrameNum)) {
  197.         draw_gl_mesh( mesh, mesh->meshFrames[i] );
  198.         return;
  199.     }
  200.         
  201.     // calculate an array of interpolated floating point vertices
  202.     vecs1 = mesh->meshFrames[sf];
  203.     vecs2 = mesh->meshFrames[ef];
  204.     vecsI = mesh->iterMesh;
  205.     vec_num = mesh->vertexNum;
  206.     
  207.     for (t=0 ; t<vec_num ; t++) {                    
  208.         for (v=0 ; v<3 ; v++) {
  209.             vecsI[t][v] = vecs1[t][v]*frac1 + vecs2[t][v]*frac;        
  210.         }
  211.     }
  212.  
  213.     draw_gl_mesh( mesh, vecsI );
  214. }
  215.  
  216.  
  217. /*
  218. renders the current frame 
  219. */
  220.  
  221.  
  222. void widget_Axis();
  223.  
  224. void draw_gl_model( gl_model *model )
  225. {
  226.     //if ( (model == NULL) || (!ismd3(*mdview.model) ) ) return;
  227.  
  228.     gl_mesh        *mesh;
  229.     int i, mesh_num,bind_num,skin_num,frame_num;
  230.     int cur_skin;
  231.     GLenum error;
  232.         
  233.     mesh_num = model->meshNum;        
  234.     
  235.     bind_num=0;
  236.     for (i=0 ; i<mesh_num; i++) 
  237.     {        
  238.         mesh      = &model->meshes[i];
  239.         skin_num  = mesh->skinNum;
  240.         frame_num = mesh->meshFrameNum;
  241.         cur_skin  = mesh->bindings[0]; 
  242.  
  243.         //disabled for now, cuz incorrect
  244.         //bind_num+(int)((skin_num/(float)frame_num)*mdview.frames[i]);
  245.         //glBindTexture( GL_TEXTURE_2D, mdview.glmdl->textureBinds[i] )
  246.  
  247.         glColor3f( 1, 1, 1 );
  248.         glBindTexture( GL_TEXTURE_2D, cur_skin );
  249.         error = glGetError();
  250.     
  251.         if (mdview.interpolate) {             
  252.             draw_interpolated_gl_mesh( mesh, model->currentFrame );
  253.         }
  254.         else {
  255.             draw_gl_mesh( mesh, mesh->meshFrames[model->currentFrame] );
  256.         }        
  257.     }
  258.     
  259. }
  260.  
  261. void draw_view()
  262. {
  263.     NodePosition pos;
  264.     gl_model *model;
  265.  
  266.     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  267.     glLoadIdentity    ();     
  268.     glTranslatef    (       0.0 , 0.0 , mdview.zPos );
  269.     glScalef        (     (float)0.05 , (float)0.05, (float)0.05 );
  270.     glRotatef        ( mdview.rotAngleX, 1.0 ,  0.0 , 0.0 );
  271.      glRotatef        ( mdview.rotAngleY, 0.0 ,  1.0 , 0.0 );    
  272.     glRotatef        (    -90.f , 1.0 ,  0.0 , 0.0 );
  273.  
  274.     for (pos=mdview.modelList->first() ; pos!=NULL ; pos=mdview.modelList->after(pos)) {
  275.         model = (gl_model *)pos->element();
  276.         draw_gl_model( model );
  277.     }
  278. }
  279.  
  280.  
  281. /* ------------------------------ new skeletal drawing code ---------------------------------------------- */
  282.  
  283.  
  284. /*
  285. creates a matrix froma  quaternion, accepts a ptr to 16 float 4x4 matrix array and a ptr to a 4 float quat array
  286. */
  287.  
  288. #define MAT( p, row, col ) (p)[((col)*3)+(row)]
  289. #define MATGL( p, row, col ) (p)[((row)*3)+(col)]
  290. #define X 0
  291. #define Y 1
  292. #define Z 2
  293. #define W 3
  294. #define DELTA 0.1
  295. void matrix_from_quat( float *m, float *quat )
  296. {
  297.                    float wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2;
  298.                    // calculate coefficients
  299.                    x2 = quat[X] + quat[X]; 
  300.                    y2 = quat[Y] + quat[Y]; 
  301.                    z2 = quat[Z] + quat[Z];
  302.                    xx = quat[X] * x2;   xy = quat[X] * y2;   xz = quat[X] * z2;
  303.                    yy = quat[Y] * y2;   yz = quat[Y] * z2;   zz = quat[Z] * z2;
  304.                    wx = quat[W] * x2;   wy = quat[W] * y2;   wz = quat[W] * z2;
  305.  
  306.                    MAT(m,0,0) = 1.f - (yy + zz);    MAT(m,0,1) = xy - wz;
  307.                    MAT(m,0,2) = xz + wy;            //MAT(m,0,3) = 0.0;
  308.                   
  309.                    MAT(m,1,0) = xy + wz;            MAT(m,1,1) = 1.f - (xx + zz);
  310.                    MAT(m,1,2) = yz - wx;            //MAT(m,1,3) = 0.0;
  311.  
  312.                    MAT(m,2,0) = xz - wy;            MAT(m,2,1) = yz + wx;
  313.                    MAT(m,2,2) = 1.f - (xx + yy);    //MAT(m,2,3) = 0.f;
  314.  
  315.                    
  316.                    //MAT(m,3,0) = 0;                  MAT(m,3,1) = 0;
  317.                    //MAT(m,3,2) = 0;                  MAT(m,3,3) = 1.f;         
  318. }
  319.  
  320. /*
  321. creates a quaternion from a matrix, parameters like above but reversed
  322. */
  323.  
  324. void quat_from_matrix( float *quat, float *m )
  325. {
  326.   float  tr, s, q[4];
  327.   int    i, j, k;
  328.   int    nxt[3] = {1, 2, 0};  
  329.  
  330.   tr = MAT(m, 0, 0) + MAT(m, 1, 1) + MAT(m, 2, 2);
  331.  
  332.   // check the diagonal
  333.   if (tr > 0.0) {
  334.     s = (float)sqrt (tr + 1.f);
  335.     quat[W] = s / 2.0f;
  336.     s = 0.5f / s;
  337.     quat[X] = (MAT(m,1,2) - MAT(m,2,1)) * s;
  338.     quat[Y] = (MAT(m,2,0) - MAT(m,0,2)) * s;
  339.     quat[Z] = (MAT(m,0,1) - MAT(m,1,0)) * s;
  340.   } else {                
  341.     // diagonal is negative
  342.     i = 0;
  343.     if (MAT(m,1,1) > MAT(m,0,0)) i = 1;
  344.     if (MAT(m,2,2) > MAT(m,i,i)) i = 2;
  345.     j = nxt[i];
  346.     k = nxt[j];
  347.  
  348.     s = (float)sqrt ((MAT(m,i,i) - (MAT(m,j,j) + MAT(m,k,k))) + 1.0);
  349.                        
  350.     q[i] = s * (float)0.5;
  351.                              
  352.     if (s != 0.0f) s = 0.5f / s;
  353.  
  354.     q[3] = (MAT(m,j,k) - MAT(m,k,j)) * s;
  355.     q[j] = (MAT(m,i,j) + MAT(m,j,i)) * s;
  356.     q[k] = (MAT(m,i,k) + MAT(m,k,i)) * s;
  357.  
  358.     quat[X] = q[0];
  359.     quat[Y] = q[1];
  360.     quat[Z] = q[2];
  361.     quat[W] = q[3];
  362.   }
  363. }
  364.  
  365.  
  366. /*
  367. interpolate quaternions along unit 4d sphere
  368. */
  369.  
  370. void quat_slerp(float *from, float *to, float t, float *res)
  371. {
  372.   float           to1[4];
  373.   float        omega, cosom, sinom, scale0, scale1;
  374.  
  375.   // calc cosine
  376.   cosom = from[X]*to[X] + 
  377.           from[Y]*to[Y] + 
  378.           from[Z]*to[Z] +
  379.           from[W]*to[W];
  380.  
  381.   // adjust signs (if necessary)
  382.   if ( cosom <0.0 ) { 
  383.           cosom = -cosom; 
  384.           to1[0] = - to[X];
  385.           to1[1] = - to[Y];
  386.           to1[2] = - to[Z];
  387.           to1[3] = - to[W];
  388.   } else  {
  389.           to1[0] = to[X];
  390.           to1[1] = to[Y];
  391.           to1[2] = to[Z];
  392.           to1[3] = to[W];
  393.   }
  394.  
  395.  // calculate coefficients
  396.  if ( (1.0 - cosom) > DELTA ) {
  397.           // standard case (slerp)
  398.           omega = (float)acos(cosom);
  399.           sinom = (float)sin(omega);
  400.           scale0 = (float)sin((1.0 - t) * omega) / sinom;
  401.           scale1 = (float)sin(t * omega) / sinom;
  402.  
  403.   } else {        
  404.       // "from" and "to" quaternions are very close 
  405.       //  ... so we can do a linear interpolation
  406.           scale0 = 1.0f - t;
  407.           scale1 = t;
  408.   }
  409.   // calculate final values
  410.   res[X] = scale0 * from[X] + scale1 * to1[0];
  411.   res[Y] = scale0 * from[Y] + scale1 * to1[1];
  412.   res[Z] = scale0 * from[Z] + scale1 * to1[2];
  413.   res[W] = scale0 * from[W] + scale1 * to1[3];
  414. }    
  415.  
  416.  
  417. /* 
  418. draws a node of the skeleton, setting up the transformation for its child nodes
  419. */
  420. void draw_skeleton( gl_model *model )
  421. {
  422.     // draw this model
  423.     draw_gl_model( model );
  424.  
  425.     // draw its children    
  426.     Tag *tag, *tag2;
  427.     float m[16], quat1[4], quat2[4], resQuat[4], fm[9], *matrix;
  428.     //float m1[9], m2[9];
  429.     gl_model *child;
  430.     float *position; //, *matrix;
  431.     Vec3 interPos;
  432.     unsigned int j,v;
  433.     float frac=mdview.frameFrac, frac1=1.f-frac;
  434.     unsigned int sf=model->currentFrame, ef=model->currentFrame+1;
  435.     bool doInterpolate = false;
  436.  
  437.  
  438.     // check if we can do interpolation
  439.     if ((model->frameNum > 1) && (ef != model->frameNum) && (mdview.interpolate)) {
  440.         doInterpolate = true;
  441.     }
  442.  
  443.  
  444.     // draw all the attached child models
  445.     for (j=0; j<model->tagNum ; j++) {            
  446.         child = model->linkedModels[j];
  447.         if (!child) continue;
  448.  
  449.         tag = &model->tags[sf][j];        
  450.         
  451.         // if interpolating then calculate in between values
  452.         if (doInterpolate) {            
  453.             tag2 = &model->tags[ef][j];
  454.             // interpoalte position
  455.             for (v=0 ; v<3 ; v++) interPos[v] = tag->Position[v]*frac1 + tag2->Position[v]*frac;
  456.             position = interPos;
  457.  
  458.             // interpolate rotation matrix                        
  459.             quat_from_matrix( quat1, &tag->Matrix[0][0] );
  460.             quat_from_matrix( quat2, &tag2->Matrix[0][0] );
  461.             quat_slerp( quat1, quat2, frac, resQuat );
  462.             matrix_from_quat( fm, resQuat );
  463.             matrix = fm;
  464.             
  465.             // quaternion code is column based, so use transposed matrix when spitting out to gl
  466.             m[0] = MAT(matrix,0,0); m[4] = MAT(matrix,0,1); m[8] = MAT(matrix,0,2); m[12] = position[0];
  467.             m[1] = MAT(matrix,1,0); m[5] = MAT(matrix,1,1); m[9] = MAT(matrix,1,2); m[13] = position[1];
  468.             m[2] = MAT(matrix,2,0); m[6] = MAT(matrix,2,1); m[10]= MAT(matrix,2,2); m[14] = position[2];
  469.             m[3] = 0;               m[7] = 0;               m[11]= 0;               m[15] = 1;                
  470.         }
  471.         else {
  472.             // otherwise stay with last frame
  473.             position = tag->Position;
  474.             matrix = &tag->Matrix[0][0];
  475.  
  476.             m[0] = MATGL(matrix,0,0); m[4] = MATGL(matrix,0,1); m[8] = MATGL(matrix,0,2); m[12] = position[0];
  477.             m[1] = MATGL(matrix,1,0); m[5] = MATGL(matrix,1,1); m[9] = MATGL(matrix,1,2); m[13] = position[1];
  478.             m[2] = MATGL(matrix,2,0); m[6] = MATGL(matrix,2,1); m[10]= MATGL(matrix,2,2); m[14] = position[2];
  479.             m[3] = 0;               m[7] = 0;               m[11]= 0;               m[15] = 1;    
  480.         }
  481.  
  482.         // build transformation matrix        
  483.         glPushMatrix();
  484.         glMultMatrixf( m );
  485.         draw_skeleton( child );
  486.         glPopMatrix();
  487.     }    
  488. }
  489.  
  490. /*
  491. draws the entire scene starting with mdview.baseModel
  492. */
  493. void draw_viewSkeleton()
  494. {    
  495.     if (!mdview.baseModel) return;
  496.  
  497.     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  498.     glLoadIdentity    ();     
  499.     glTranslatef    (       0.0 , 0.0 , mdview.zPos );
  500.     glScalef        (     (float)0.05 , (float)0.05, (float)0.05 );
  501.     glRotatef        ( mdview.rotAngleX, 1.0 ,  0.0 , 0.0 );
  502.      glRotatef        ( mdview.rotAngleY, 0.0 ,  1.0 , 0.0 );    
  503.     glRotatef        (    -90.f , 1.0 ,  0.0 , 0.0 );
  504.  
  505.     draw_skeleton( mdview.baseModel );
  506. }
  507.  
  508.