Back to index

extremetuxracer  0.5beta
keyframe.cpp
Go to the documentation of this file.
00001 /* 
00002  * PPRacer 
00003  * Copyright (C) 2004-2005 Volker Stroebel <volker@planetpenguin.de>
00004  *
00005  * Copyright (C) 1999-2001 Jasmin F. Patry
00006  * 
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  * 
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  * 
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00020  */
00021 
00022 #include "model_hndl.h"
00023 #include "phys_sim.h"
00024 #include "hier.h"
00025 #include "loop.h"
00026 
00027 #include "ppgltk/alg/defs.h"
00028 
00029 #define MAX_NUM_KEY_FRAMES 128
00030 
00031 static key_frame_t frames[MAX_NUM_KEY_FRAMES];
00032 static int numFrames = 0;
00033 static double keyTime;
00034 
00035 void get_key_frame_data( key_frame_t **fp, int *n )
00036 {
00037     *fp = frames;
00038     *n = numFrames;
00039 }
00040 
00041 void reset_key_frame()
00042 {
00043     keyTime = 0;
00044     numFrames = 0;
00045 } 
00046 
00047 void init_key_frame()
00048 {
00049     keyTime = frames[0].time;
00050 
00051     reset_scene_node( ModelHndl->get_tux_head() );
00052     reset_scene_node( ModelHndl->get_tux_neck() );
00053 } 
00054 
00055 double interp( double frac, double v1, double v2 ) 
00056 {
00057     return frac*v1 + (1.-frac)*v2;
00058 } 
00059 
00060 void update_key_frame( Player& plyr, double dt )
00061 {
00062     int idx;
00063     double frac;
00064     pp::Vec3d pos;
00065     double v;
00066     pp::Matrix cob_mat, rot_mat;
00067 
00068     char *root;
00069     char *lsh;
00070     char *rsh;
00071     char *lhp;
00072     char *rhp;
00073     char *lkn;
00074     char *rkn;
00075     char *lank;
00076     char *rank;
00077     char *head;
00078     char *neck;
00079     char *tail;
00080 
00081     root = ModelHndl->get_tux_root_node();
00082     lsh  = ModelHndl->get_tux_left_shoulder_joint();
00083     rsh  = ModelHndl->get_tux_right_shoulder_joint();
00084     lhp  = ModelHndl->get_tux_left_hip_joint();
00085     rhp  = ModelHndl->get_tux_right_hip_joint();
00086     lkn  = ModelHndl->get_tux_left_knee_joint();
00087     rkn  = ModelHndl->get_tux_right_knee_joint();
00088     lank = ModelHndl->get_tux_left_ankle_joint();
00089     rank = ModelHndl->get_tux_right_ankle_joint();
00090     head = ModelHndl->get_tux_head();
00091     neck = ModelHndl->get_tux_neck();
00092     tail = ModelHndl->get_tux_tail_joint();
00093 
00094     keyTime += dt;
00095 
00096     for (idx = 1; idx < numFrames; idx ++) {
00097         if ( keyTime < frames[idx].time )
00098             break;
00099     } 
00100 
00101     if ( idx == numFrames || numFrames == 0 ) {
00102         set_game_mode( RACING );
00103         return;
00104     } 
00105 
00106     reset_scene_node( root );
00107     reset_scene_node( lsh );
00108     reset_scene_node( rsh );
00109     reset_scene_node( lhp );
00110     reset_scene_node( rhp );
00111     reset_scene_node( lkn );
00112     reset_scene_node( rkn );
00113     reset_scene_node( lank );
00114     reset_scene_node( rank );
00115     reset_scene_node( head );
00116     reset_scene_node( neck );
00117     reset_scene_node( tail );
00118 
00119     check_assertion( idx > 0, "invalid keyframe index" );
00120 
00121     if ( fabs( frames[idx-1].time - frames[idx].time ) < EPS ) {
00122        frac = 1.;
00123     } else {
00124        frac = (keyTime - frames[idx].time) 
00125            / ( frames[idx-1].time - frames[idx].time );
00126     }
00127 
00128     pos.x = interp( frac, frames[idx-1].pos.x, frames[idx].pos.x );
00129     pos.z = interp( frac, frames[idx-1].pos.z, frames[idx].pos.z );
00130     pos.y = interp( frac, frames[idx-1].pos.y, frames[idx].pos.y );
00131     pos.y += find_y_coord( pos.x, pos.z );
00132 
00133     set_tux_pos( plyr, pos );
00134 
00135        cob_mat.makeIdentity();
00136 
00137     v = interp( frac, frames[idx-1].yaw, frames[idx].yaw );
00138     rotate_scene_node( root, 'y', v );
00139     rot_mat.makeRotation( v, 'y' );
00140     cob_mat=cob_mat*rot_mat;
00141 
00142     v = interp( frac, frames[idx-1].pitch, frames[idx].pitch );
00143     rotate_scene_node( root, 'x', v );
00144     rot_mat.makeRotation( v, 'x' );
00145     cob_mat=cob_mat*rot_mat;
00146 
00147     v = interp( frac, frames[idx-1].l_shldr, frames[idx].l_shldr );
00148     rotate_scene_node( lsh, 'z', v );
00149 
00150     v = interp( frac, frames[idx-1].r_shldr, frames[idx].r_shldr );
00151     rotate_scene_node( rsh, 'z', v );
00152 
00153     v = interp( frac, frames[idx-1].l_hip, frames[idx].l_hip );
00154     rotate_scene_node( lhp, 'z', v );
00155 
00156     v = interp( frac, frames[idx-1].r_hip, frames[idx].r_hip );
00157     rotate_scene_node( rhp, 'z', v );
00158 
00159     /* Set orientation */
00160     plyr.orientation = pp::Matrix( cob_mat); //make_quaternion_from_matrix( cob_mat );
00161     plyr.orientation_initialized = true;
00162 } 
00163 
00164 static int key_frame_cb ( ClientData cd, Tcl_Interp *ip, int argc, CONST84 char *argv[]) 
00165 {
00166     double tmp;
00167     key_frame_t frame;
00168     pp::Vec2d start_pt = get_start_pt();
00169 
00170     if (numFrames == MAX_NUM_KEY_FRAMES ) {
00171         print_warning( TCL_WARNING, 
00172                      "%s: max. num. of frames reached", argv[0] );
00173     } 
00174 
00175     if ( argc != 11 ) {
00176        print_warning( TCL_WARNING, "wrong number of args to %s", argv[0] );
00177         return TCL_ERROR;
00178     } 
00179 
00180     if ( Tcl_GetDouble( ip, argv[1], &tmp ) != TCL_OK ) {
00181         return TCL_ERROR;
00182     } else {
00183        frame.time = tmp;
00184     }
00185 
00186     if ( Tcl_GetDouble( ip, argv[2], &tmp ) != TCL_OK ) {
00187         return TCL_ERROR;
00188     } else {
00189        frame.pos.x = tmp + start_pt.x;
00190     }
00191 
00192     if ( Tcl_GetDouble( ip, argv[3], &tmp ) != TCL_OK ) {
00193         return TCL_ERROR;
00194     } else {
00195        frame.pos.z = -tmp + start_pt.y;
00196     }
00197     
00198     if ( Tcl_GetDouble( ip, argv[4], &tmp ) != TCL_OK ) {
00199         return TCL_ERROR;
00200     } else {
00201        frame.pos.y = tmp;
00202     }
00203 
00204     if ( Tcl_GetDouble( ip, argv[5], &tmp ) != TCL_OK ) {
00205         return TCL_ERROR;
00206     } else {
00207        frame.yaw = tmp;
00208     }
00209 
00210     if ( Tcl_GetDouble( ip, argv[6], &tmp ) != TCL_OK ) {
00211         return TCL_ERROR;
00212     } else {
00213        frame.pitch = tmp;
00214     }
00215 
00216     if ( Tcl_GetDouble( ip, argv[7], &tmp ) != TCL_OK ) {
00217         return TCL_ERROR;
00218     } else {
00219        frame.l_shldr = tmp;
00220     }
00221 
00222     if ( Tcl_GetDouble( ip, argv[8], &tmp ) != TCL_OK ) {
00223         return TCL_ERROR;
00224     } else {
00225        frame.r_shldr = tmp;
00226     }
00227 
00228     if ( Tcl_GetDouble( ip, argv[9], &tmp ) != TCL_OK ) {
00229         return TCL_ERROR;
00230     } else {
00231        frame.l_hip = tmp;
00232     }
00233 
00234     if ( Tcl_GetDouble( ip, argv[10], &tmp ) != TCL_OK ) {
00235         return TCL_ERROR;
00236     } else {
00237        frame.r_hip = tmp;
00238     }
00239 
00240     frames[numFrames] = frame;
00241     numFrames++;
00242 
00243     return TCL_OK;
00244 } 
00245 
00246 
00247 
00248 void register_key_frame_callbacks( Tcl_Interp *ip )
00249 {
00250     Tcl_CreateCommand (ip, "tux_key_frame", key_frame_cb,  0,0);
00251 }