home *** CD-ROM | disk | FTP | other *** search
- /*
- Copyright (C) Matthew 'pagan' Baranowski & Sander 'FireStorm' van Rossen
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
- #include "system.h"
- #include "ndictionary.h"
- #include "md3gl.h"
- #include "md3view.h"
- #include "targa.h"
- #include <math.h>
-
- /*
- sets up an orthogonal projection matrix
- */
- void set_windowSize( int x, int y )
- {
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- if (y > 0) gluPerspective( 90, (double)x/(double)y, NEAR_GL_PLANE, FAR_GL_PLANE );
- glViewport( 0, 0, x, y );
-
- glMatrixMode(GL_MODELVIEW);
- }
-
-
- /*
- initializes the opengl state for rendering
- */
- void initialize_glstate()
- {
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- glClearDepth(1.0);
- glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
- glEnable( GL_DEPTH_TEST );
- glDepthFunc( GL_LEQUAL );
- glShadeModel( GL_SMOOTH );
- oglStateShadedTextured();
- // glFrontFace( mdview.faceSide );
-
- float mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
- float mat_ambient[] = { 0.9f, 0.9f, 0.9f, 1.0 };
- float mat_diffuse[] = { 1, 1, 1, 1 };
- float mat_shininess[] = { 20.0 };
-
- float light_position[] = { 55.0, -50.0, -5.0, 0.0 };
-
- float light2_position[] = {-50.0, 45.0, 15.0, 0.0 };
- float mat2_diffuse[] = { 0.5f, 0.5f, 1, 1 };
-
- glShadeModel (GL_SMOOTH);
-
- glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
- glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
-
- glLightfv(GL_LIGHT0, GL_AMBIENT, mat_ambient);
- glLightfv(GL_LIGHT0, GL_DIFFUSE, mat2_diffuse);
- glLightfv(GL_LIGHT0, GL_POSITION, light_position);
-
- glLightfv(GL_LIGHT1, GL_POSITION, light2_position);
- glLightfv(GL_LIGHT1, GL_DIFFUSE, mat2_diffuse);
- glLightfv(GL_LIGHT1, GL_AMBIENT, mat_ambient);
-
- glEnable(GL_LIGHTING);
- glEnable(GL_LIGHT0);
- glEnable(GL_LIGHT1);
- glEnable( GL_LIGHTING );
-
- glEnable( GL_BLEND );
-
- glBlendFunc(GL_ONE, GL_ZERO);//bug fix
-
- glEnable( GL_POLYGON_SMOOTH );
- }
-
-
- /*
- set to wire frame mode
- */
- void oglStateFlatTextured()
- {
- glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
- glEnable( GL_TEXTURE_2D );
- glDisable( GL_LIGHTING );
- }
-
- /*
- set to wire frame mode
- */
- void oglStateShadedTextured()
- {
- glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
- glEnable( GL_TEXTURE_2D );
- glEnable( GL_LIGHTING );
- }
-
- /*
- set to wire frame mode
- */
- void oglStateShadedFlat()
- {
- glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
- glDisable( GL_TEXTURE_2D );
- glEnable( GL_LIGHTING );
- }
-
- /*
- set to wire frame mode
- */
- void oglStateWireframe()
- {
- glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
- glDisable( GL_TEXTURE_2D );
- glDisable( GL_LIGHTING );
- }
-
- /*
- computes vector cross product
- */
- void cross(Vec3 v1, Vec3 v2, Vec3 c)
- {
- c[0] = v1[1]*v2[2] - v1[2]*v2[1];
- c[1] = v1[2]*v2[0] - v1[0]*v2[2];
- c[2] = v1[0]*v2[1] - v1[1]*v2[0];
- }
-
- /*
- makes normal unit length
- */
- void normalize( Vec3 n )
- {
- int i;
- float length = 0.0f;
- for (i=0 ; i< 3 ; i++) length += n[i]*n[i];
- length = (float)sqrt(length);
- if (length == 0) return;
- for (i=0 ; i< 3 ; i++) n[i] /= length;
- }
-
-
- /* --------------------------------------- new gl code ------------------------------------------------- */
-
-
- void draw_gl_mesh( gl_mesh *mesh, Vec3 *vecs )
- {
- TriVec *tris;
- int tri_num, t, v;
- Vec3 v1, v2, normal;
- TexVec *tvecs;
-
- tris = mesh->triangles;
- tvecs = mesh->textureCoord;
- tri_num = mesh->triangleNum;
-
- glBegin( GL_TRIANGLES );
-
- for (t=0 ; t<tri_num ; t++) {
-
- for (v=0 ; v<3 ; v++) {
- v1[v] = vecs[tris[t][1]][v] - vecs[tris[t][0]][v];
- v2[v] = vecs[tris[t][2]][v] - vecs[tris[t][0]][v];
- }
- cross( v1, v2, normal );
- normalize( normal );
-
- glNormal3fv( normal );
- glTexCoord2fv( tvecs[tris[t][0]] ); glVertex3fv( vecs[tris[t][0]] );
- glTexCoord2fv( tvecs[tris[t][1]] ); glVertex3fv( vecs[tris[t][1]] );
- glTexCoord2fv( tvecs[tris[t][2]] ); glVertex3fv( vecs[tris[t][2]] );
- }
- glEnd();
- }
-
- void draw_interpolated_gl_mesh( gl_mesh *mesh, int i)
- {
- unsigned int sf=i, ef=i+1, v, vec_num, t;
- Vec3 *vecs1, *vecs2;
- Vec3 *vecsI;
- float frac=mdview.frameFrac, frac1=1.f-frac;
-
-
- // do not interpolate if this is the only frame, or the last frame
- if ((mesh->meshFrameNum < 2) || (ef == mesh->meshFrameNum)) {
- draw_gl_mesh( mesh, mesh->meshFrames[i] );
- return;
- }
-
- // calculate an array of interpolated floating point vertices
- vecs1 = mesh->meshFrames[sf];
- vecs2 = mesh->meshFrames[ef];
- vecsI = mesh->iterMesh;
- vec_num = mesh->vertexNum;
-
- for (t=0 ; t<vec_num ; t++) {
- for (v=0 ; v<3 ; v++) {
- vecsI[t][v] = vecs1[t][v]*frac1 + vecs2[t][v]*frac;
- }
- }
-
- draw_gl_mesh( mesh, vecsI );
- }
-
-
- /*
- renders the current frame
- */
-
-
- void widget_Axis();
-
- void draw_gl_model( gl_model *model )
- {
- //if ( (model == NULL) || (!ismd3(*mdview.model) ) ) return;
-
- gl_mesh *mesh;
- int i, mesh_num,bind_num,skin_num,frame_num;
- int cur_skin;
- GLenum error;
-
- mesh_num = model->meshNum;
-
- bind_num=0;
- for (i=0 ; i<mesh_num; i++)
- {
- mesh = &model->meshes[i];
- skin_num = mesh->skinNum;
- frame_num = mesh->meshFrameNum;
- cur_skin = mesh->bindings[0];
-
- //disabled for now, cuz incorrect
- //bind_num+(int)((skin_num/(float)frame_num)*mdview.frames[i]);
- //glBindTexture( GL_TEXTURE_2D, mdview.glmdl->textureBinds[i] )
-
- glColor3f( 1, 1, 1 );
- glBindTexture( GL_TEXTURE_2D, cur_skin );
- error = glGetError();
-
- if (mdview.interpolate) {
- draw_interpolated_gl_mesh( mesh, model->currentFrame );
- }
- else {
- draw_gl_mesh( mesh, mesh->meshFrames[model->currentFrame] );
- }
- }
-
- }
-
- void draw_view()
- {
- NodePosition pos;
- gl_model *model;
-
- glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
- glLoadIdentity ();
- glTranslatef ( 0.0 , 0.0 , mdview.zPos );
- glScalef ( (float)0.05 , (float)0.05, (float)0.05 );
- glRotatef ( mdview.rotAngleX, 1.0 , 0.0 , 0.0 );
- glRotatef ( mdview.rotAngleY, 0.0 , 1.0 , 0.0 );
- glRotatef ( -90.f , 1.0 , 0.0 , 0.0 );
-
- for (pos=mdview.modelList->first() ; pos!=NULL ; pos=mdview.modelList->after(pos)) {
- model = (gl_model *)pos->element();
- draw_gl_model( model );
- }
- }
-
-
- /* ------------------------------ new skeletal drawing code ---------------------------------------------- */
-
-
- /*
- creates a matrix froma quaternion, accepts a ptr to 16 float 4x4 matrix array and a ptr to a 4 float quat array
- */
-
- #define MAT( p, row, col ) (p)[((col)*3)+(row)]
- #define MATGL( p, row, col ) (p)[((row)*3)+(col)]
- #define X 0
- #define Y 1
- #define Z 2
- #define W 3
- #define DELTA 0.1
- void matrix_from_quat( float *m, float *quat )
- {
- float wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2;
- // calculate coefficients
- x2 = quat[X] + quat[X];
- y2 = quat[Y] + quat[Y];
- z2 = quat[Z] + quat[Z];
- xx = quat[X] * x2; xy = quat[X] * y2; xz = quat[X] * z2;
- yy = quat[Y] * y2; yz = quat[Y] * z2; zz = quat[Z] * z2;
- wx = quat[W] * x2; wy = quat[W] * y2; wz = quat[W] * z2;
-
- MAT(m,0,0) = 1.f - (yy + zz); MAT(m,0,1) = xy - wz;
- MAT(m,0,2) = xz + wy; //MAT(m,0,3) = 0.0;
-
- MAT(m,1,0) = xy + wz; MAT(m,1,1) = 1.f - (xx + zz);
- MAT(m,1,2) = yz - wx; //MAT(m,1,3) = 0.0;
-
- MAT(m,2,0) = xz - wy; MAT(m,2,1) = yz + wx;
- MAT(m,2,2) = 1.f - (xx + yy); //MAT(m,2,3) = 0.f;
-
-
- //MAT(m,3,0) = 0; MAT(m,3,1) = 0;
- //MAT(m,3,2) = 0; MAT(m,3,3) = 1.f;
- }
-
- /*
- creates a quaternion from a matrix, parameters like above but reversed
- */
-
- void quat_from_matrix( float *quat, float *m )
- {
- float tr, s, q[4];
- int i, j, k;
- int nxt[3] = {1, 2, 0};
-
- tr = MAT(m, 0, 0) + MAT(m, 1, 1) + MAT(m, 2, 2);
-
- // check the diagonal
- if (tr > 0.0) {
- s = (float)sqrt (tr + 1.f);
- quat[W] = s / 2.0f;
- s = 0.5f / s;
- quat[X] = (MAT(m,1,2) - MAT(m,2,1)) * s;
- quat[Y] = (MAT(m,2,0) - MAT(m,0,2)) * s;
- quat[Z] = (MAT(m,0,1) - MAT(m,1,0)) * s;
- } else {
- // diagonal is negative
- i = 0;
- if (MAT(m,1,1) > MAT(m,0,0)) i = 1;
- if (MAT(m,2,2) > MAT(m,i,i)) i = 2;
- j = nxt[i];
- k = nxt[j];
-
- s = (float)sqrt ((MAT(m,i,i) - (MAT(m,j,j) + MAT(m,k,k))) + 1.0);
-
- q[i] = s * (float)0.5;
-
- if (s != 0.0f) s = 0.5f / s;
-
- q[3] = (MAT(m,j,k) - MAT(m,k,j)) * s;
- q[j] = (MAT(m,i,j) + MAT(m,j,i)) * s;
- q[k] = (MAT(m,i,k) + MAT(m,k,i)) * s;
-
- quat[X] = q[0];
- quat[Y] = q[1];
- quat[Z] = q[2];
- quat[W] = q[3];
- }
- }
-
-
- /*
- interpolate quaternions along unit 4d sphere
- */
-
- void quat_slerp(float *from, float *to, float t, float *res)
- {
- float to1[4];
- float omega, cosom, sinom, scale0, scale1;
-
- // calc cosine
- cosom = from[X]*to[X] +
- from[Y]*to[Y] +
- from[Z]*to[Z] +
- from[W]*to[W];
-
- // adjust signs (if necessary)
- if ( cosom <0.0 ) {
- cosom = -cosom;
- to1[0] = - to[X];
- to1[1] = - to[Y];
- to1[2] = - to[Z];
- to1[3] = - to[W];
- } else {
- to1[0] = to[X];
- to1[1] = to[Y];
- to1[2] = to[Z];
- to1[3] = to[W];
- }
-
- // calculate coefficients
- if ( (1.0 - cosom) > DELTA ) {
- // standard case (slerp)
- omega = (float)acos(cosom);
- sinom = (float)sin(omega);
- scale0 = (float)sin((1.0 - t) * omega) / sinom;
- scale1 = (float)sin(t * omega) / sinom;
-
- } else {
- // "from" and "to" quaternions are very close
- // ... so we can do a linear interpolation
- scale0 = 1.0f - t;
- scale1 = t;
- }
- // calculate final values
- res[X] = scale0 * from[X] + scale1 * to1[0];
- res[Y] = scale0 * from[Y] + scale1 * to1[1];
- res[Z] = scale0 * from[Z] + scale1 * to1[2];
- res[W] = scale0 * from[W] + scale1 * to1[3];
- }
-
-
- /*
- draws a node of the skeleton, setting up the transformation for its child nodes
- */
- void draw_skeleton( gl_model *model )
- {
- // draw this model
- draw_gl_model( model );
-
- // draw its children
- Tag *tag, *tag2;
- float m[16], quat1[4], quat2[4], resQuat[4], fm[9], *matrix;
- //float m1[9], m2[9];
- gl_model *child;
- float *position; //, *matrix;
- Vec3 interPos;
- unsigned int j,v;
- float frac=mdview.frameFrac, frac1=1.f-frac;
- unsigned int sf=model->currentFrame, ef=model->currentFrame+1;
- bool doInterpolate = false;
-
-
- // check if we can do interpolation
- if ((model->frameNum > 1) && (ef != model->frameNum) && (mdview.interpolate)) {
- doInterpolate = true;
- }
-
-
- // draw all the attached child models
- for (j=0; j<model->tagNum ; j++) {
- child = model->linkedModels[j];
- if (!child) continue;
-
- tag = &model->tags[sf][j];
-
- // if interpolating then calculate in between values
- if (doInterpolate) {
- tag2 = &model->tags[ef][j];
- // interpoalte position
- for (v=0 ; v<3 ; v++) interPos[v] = tag->Position[v]*frac1 + tag2->Position[v]*frac;
- position = interPos;
-
- // interpolate rotation matrix
- quat_from_matrix( quat1, &tag->Matrix[0][0] );
- quat_from_matrix( quat2, &tag2->Matrix[0][0] );
- quat_slerp( quat1, quat2, frac, resQuat );
- matrix_from_quat( fm, resQuat );
- matrix = fm;
-
- // quaternion code is column based, so use transposed matrix when spitting out to gl
- m[0] = MAT(matrix,0,0); m[4] = MAT(matrix,0,1); m[8] = MAT(matrix,0,2); m[12] = position[0];
- m[1] = MAT(matrix,1,0); m[5] = MAT(matrix,1,1); m[9] = MAT(matrix,1,2); m[13] = position[1];
- m[2] = MAT(matrix,2,0); m[6] = MAT(matrix,2,1); m[10]= MAT(matrix,2,2); m[14] = position[2];
- m[3] = 0; m[7] = 0; m[11]= 0; m[15] = 1;
- }
- else {
- // otherwise stay with last frame
- position = tag->Position;
- matrix = &tag->Matrix[0][0];
-
- m[0] = MATGL(matrix,0,0); m[4] = MATGL(matrix,0,1); m[8] = MATGL(matrix,0,2); m[12] = position[0];
- m[1] = MATGL(matrix,1,0); m[5] = MATGL(matrix,1,1); m[9] = MATGL(matrix,1,2); m[13] = position[1];
- m[2] = MATGL(matrix,2,0); m[6] = MATGL(matrix,2,1); m[10]= MATGL(matrix,2,2); m[14] = position[2];
- m[3] = 0; m[7] = 0; m[11]= 0; m[15] = 1;
- }
-
- // build transformation matrix
- glPushMatrix();
- glMultMatrixf( m );
- draw_skeleton( child );
- glPopMatrix();
- }
- }
-
- /*
- draws the entire scene starting with mdview.baseModel
- */
- void draw_viewSkeleton()
- {
- if (!mdview.baseModel) return;
-
- glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
- glLoadIdentity ();
- glTranslatef ( 0.0 , 0.0 , mdview.zPos );
- glScalef ( (float)0.05 , (float)0.05, (float)0.05 );
- glRotatef ( mdview.rotAngleX, 1.0 , 0.0 , 0.0 );
- glRotatef ( mdview.rotAngleY, 0.0 , 1.0 , 0.0 );
- glRotatef ( -90.f , 1.0 , 0.0 , 0.0 );
-
- draw_skeleton( mdview.baseModel );
- }
-
-