Back to index

extremetuxracer  0.5beta
model_hndl.cpp
Go to the documentation of this file.
00001 /* 
00002  * ETRacer 
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 
00024 #include "lights.h"
00025 #include "hier_cb.h"
00026 #include "hier.h"
00027 #include "gl_util.h"
00028 #include "game_config.h"
00029 #include "string_util.h"
00030 
00031 #include "course_mgr.h"
00032 
00033 #include "ppgltk/alg/defs.h"
00034 
00035 
00036 #define MAX_ARM_ANGLE 30.0
00037 #define MAX_PADDLING_ANGLE 35.0
00038 #define MAX_EXT_PADDLING_ANGLE 30.0
00039 #define MAX_KICK_PADDLING_ANGLE 20.0
00040 
00041 bool          model_hndl::tuxLoaded = false;
00042 char*     model_hndl::tuxRootNode;
00043 char*     model_hndl::tuxLeftShoulderJoint;
00044 char*     model_hndl::tuxRightShoulderJoint;
00045 char*     model_hndl::tuxLeftHipJoint;
00046 char*     model_hndl::tuxRightHipJoint;
00047 char*     model_hndl::tuxLeftKneeJoint;
00048 char*     model_hndl::tuxRightKneeJoint;
00049 char*     model_hndl::tuxLeftAnkleJoint;
00050 char*     model_hndl::tuxRightAnkleJoint;
00051 char*     model_hndl::tuxTailJoint;
00052 char*     model_hndl::tuxNeck;
00053 char*     model_hndl::tuxHead;
00054 
00055 
00056 model_hndl* ModelHndl=NULL;
00057 
00058 void
00059 model_hndl::adjust_tux_joints( double turnFact, bool isBraking, 
00060                      double paddling_factor, double speed,
00061                      pp::Vec3d net_force, double flap_factor )
00062 {
00063     double turning_angle[2] = {0., 0.};
00064     double paddling_angle = 0.;
00065     double ext_paddling_angle = 0.;  /* arm extension during paddling */
00066     double kick_paddling_angle = 0.;  /* leg kicking during paddling */
00067     double braking_angle = 0.;
00068     double force_angle = 0.; /* amount that legs move because of force */
00069     double turn_leg_angle = 0.; /* amount legs move when turning */
00070     double flap_angle = 0.;
00071 
00072     /* move arms */
00073     reset_scene_node( tuxLeftShoulderJoint );
00074     reset_scene_node( tuxRightShoulderJoint );
00075 
00076     if ( isBraking ) {
00077        braking_angle = MAX_ARM_ANGLE;
00078     }
00079 
00080     paddling_angle = MAX_PADDLING_ANGLE * sin(paddling_factor * M_PI);
00081     ext_paddling_angle = MAX_EXT_PADDLING_ANGLE * sin(paddling_factor * M_PI);
00082     kick_paddling_angle = MAX_KICK_PADDLING_ANGLE * 
00083        sin(paddling_factor * M_PI * 2.0);
00084 
00085     turning_angle[0] = MAX(-turnFact,0.0) * MAX_ARM_ANGLE;
00086     turning_angle[1] = MAX(turnFact,0.0) * MAX_ARM_ANGLE;
00087 
00088     flap_angle = MAX_ARM_ANGLE * (0.5 + 0.5*sin(M_PI*flap_factor*6-M_PI/2));
00089 
00090     /* Adjust arms for turning */
00091     rotate_scene_node( tuxLeftShoulderJoint, 'z', 
00092                      MIN( braking_angle + paddling_angle + turning_angle[0],
00093                          MAX_ARM_ANGLE ) + flap_angle );
00094     rotate_scene_node( tuxRightShoulderJoint, 'z',
00095                      MIN( braking_angle + paddling_angle + turning_angle[1], 
00096                          MAX_ARM_ANGLE ) + flap_angle );
00097 
00098 
00099     /* Adjust arms for paddling */
00100     rotate_scene_node( tuxLeftShoulderJoint, 'y', -ext_paddling_angle );
00101     rotate_scene_node( tuxRightShoulderJoint, 'y', ext_paddling_angle );
00102 
00103     force_angle = MAX( -20.0, MIN( 20.0, -net_force.z / 300.0 ) );
00104     turn_leg_angle = turnFact * 10;
00105     
00106        /* Adjust hip joints */
00107     reset_scene_node( tuxLeftHipJoint );
00108     rotate_scene_node( tuxLeftHipJoint, 'z', -20 + turn_leg_angle
00109                      + force_angle );
00110     reset_scene_node( tuxRightHipJoint );
00111     rotate_scene_node( tuxRightHipJoint, 'z', -20 - turn_leg_angle
00112                      + force_angle );
00113        
00114     /* Adjust knees */
00115     reset_scene_node( tuxLeftKneeJoint );
00116     rotate_scene_node( tuxLeftKneeJoint, 'z', -10 + turn_leg_angle
00117                      - MIN( 35, speed ) + kick_paddling_angle
00118                      + force_angle );
00119     reset_scene_node( tuxRightKneeJoint );
00120     rotate_scene_node( tuxRightKneeJoint, 'z', -10 - turn_leg_angle
00121                      - MIN( 35, speed ) - kick_paddling_angle 
00122                      + force_angle );
00123 
00124     /* Adjust ankles */
00125     reset_scene_node( tuxLeftAnkleJoint );
00126     rotate_scene_node( tuxLeftAnkleJoint, 'z', -20 + MIN(50, speed ) );
00127     reset_scene_node( tuxRightAnkleJoint );
00128     rotate_scene_node( tuxRightAnkleJoint, 'z', -20 + MIN(50, speed ) );
00129 
00130        /* Turn tail */
00131     reset_scene_node( tuxTailJoint );
00132     rotate_scene_node( tuxTailJoint, 'z', turnFact * 20 );
00133 
00134        /* Adjust head and neck */
00135     reset_scene_node( tuxNeck );
00136     rotate_scene_node( tuxNeck, 'z', -50 );
00137     reset_scene_node( tuxHead );
00138     rotate_scene_node( tuxHead, 'z', -30 );
00139 
00140        /* Turn head when turning */
00141     rotate_scene_node( tuxHead, 'y', -turnFact * 70 );
00142 
00143 }
00144 
00145 void
00146 model_hndl::draw_tux()
00147 {
00148     GLfloat dummyColor[]  = { 0.0, 0.0, 0.0, 1.0 };
00149 
00150     /* XXX: For some reason, inserting this call here makes Tux render
00151      * with correct lighting under Mesa 3.1. I'm guessing it's a Mesa bug.
00152      */
00153     glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, dummyColor );
00154 
00155     set_gl_options( TUX );
00156 
00157     /* Turn on lights
00158      */
00159     setup_course_lighting();
00160 
00161     draw_scene_graph( tuxRootNode );
00162 } 
00163 
00164 model_hndl::model_hndl() {
00165        cur_model=0;
00166        num_models=0;
00167 }
00168 
00169 void model_hndl::init_models() {
00170        //Load modellist from data/models.tcl
00171        char buff[BUFF_LEN];
00172      
00173        sprintf(buff, "%s/models.tcl", getparam_data_dir());
00174                      
00175        registerHierCallbacks( tclInterp );
00176      register_tux_callbacks( tclInterp );
00177      
00178        if ( Tcl_EvalFile( tclInterp , buff ) != TCL_OK) {
00179               std::cerr << " error evalating model list file " << buff
00180                             << " : " << Tcl_GetStringResult (tclInterp ) << std::endl;
00181        }
00182        
00183        /*
00184        *Debug stuff:
00185        for(std::list<model_t>::iterator it=l_models.begin();it!=l_models.end();++it) {
00186               std::cout<<(*it).name<<": "<<(*it).filename<<std::endl;
00187        }
00188        */
00189 }
00190 
00191 void
00192 model_hndl::load_model() 
00193 {
00194        tuxLoaded=false;
00195        load_model(cur_model);
00196 }
00197 
00198 void
00199 model_hndl::load_model(int model=0)
00200 {      
00201     //Loads a model.
00202     char cwd[BUFF_LEN];
00203     char buff[BUFF_LEN];
00204 
00205 
00206     std::list<model_t>::iterator c_model=l_models.begin();
00207     if(model!=0) {
00208        for(int i=0;i<model;i++) {
00209               c_model++;
00210        }
00211     }
00212 
00213 
00214     if ( tuxLoaded == true && cur_model==model) 
00215         return;
00216     cur_model=model;
00217     tuxLoaded = true;
00218     initialize_scene_graph();
00219 
00220     if ( getcwd( cwd, BUFF_LEN ) == NULL ) {
00221        handle_system_error( 1, "getcwd failed" );
00222     }
00223     if ( chdir( getparam_data_dir() ) != 0 ) {
00224        /* Print a more informative warning since this is a common error */
00225        handle_system_error( 
00226            1, "Can't find the etracer data "
00227            "directory.  Please check the\nvalue of `data_dir' in "
00228            "~/.etracer/options and set it to the location where you\n"
00229            "installed the etracer-data files.\n\n"
00230            "Couldn't chdir to %s", getparam_data_dir() );
00231        /*
00232         handle_system_error( 1, "couldn't chdir to %s", getparam_data_dir() );
00233        */
00234     } 
00235     
00236     
00237     //std::cout<<"Loading model "<< (*c_model).name<<std::endl;
00238     if ( Tcl_EvalFile( tclInterp, (*c_model).filename.c_str()) == TCL_ERROR ) {
00239         handle_error( 1, "error evalating %s/%s: %s\n"
00240                     "Please check the value of `data_dir' in ~/.etracer/options "
00241                     "and make sure it\npoints to the location of the "
00242                     "latest version of the etracer-data files.", 
00243                     getparam_data_dir(),(*c_model).filename.c_str(),
00244                     Tcl_GetStringResult( tclInterp ) );
00245     } 
00246     check_assertion( !Tcl_InterpDeleted( tclInterp ),
00247                    "Tcl interpreter deleted" );
00248 
00249     if ( chdir( cwd ) != 0 ) {
00250        handle_system_error( 1, "couldn't chdir to %s", cwd );
00251     } 
00252 } 
00253 
00254 static int
00255 head_cb ( ClientData cd, Tcl_Interp *ip, int argc, CONST84 char *argv[]) 
00256 {
00257     if ( argc != 2 ) {
00258         Tcl_AppendResult(ip, argv[0], ": invalid number of arguments\n", 
00259                          "Usage: ", argv[0], " <head joint>",
00260                       (char *)0 );
00261         return TCL_ERROR;
00262     } 
00263 
00264     ModelHndl->tuxHead = string_copy( argv[1] );
00265 
00266     return TCL_OK;
00267 } 
00268 
00269 static int
00270 neck_cb ( ClientData cd, Tcl_Interp *ip, 
00271                    int argc, CONST84 char *argv[]) 
00272 {
00273 
00274     if ( argc != 2 ) {
00275         Tcl_AppendResult(ip, argv[0], ": invalid number of arguments\n", 
00276                       "Usage: ", argv[0], " <neck joint>",
00277                       (char *)0 );
00278         return TCL_ERROR;
00279     } 
00280 
00281     ModelHndl->tuxNeck = string_copy( argv[1] );
00282 
00283     return TCL_OK;
00284 } 
00285 
00286 static int
00287 root_node_cb ( ClientData cd, Tcl_Interp *ip, 
00288                        int argc, CONST84 char *argv[]) 
00289 {
00290     if ( argc != 2 ) {
00291         Tcl_AppendResult(ip, argv[0], ": invalid number of arguments\n", 
00292                       "Usage: ", argv[0], " <root node>",
00293                       (char *)0 );
00294         return TCL_ERROR;
00295     } 
00296 
00297     ModelHndl->tuxRootNode = string_copy( argv[1] );
00298 
00299     return TCL_OK;
00300 } 
00301 
00302 static int
00303 left_shoulder_cb ( ClientData cd, Tcl_Interp *ip, 
00304                            int argc, CONST84 char *argv[]) 
00305 {
00306 
00307     if ( argc != 2 ) {
00308         Tcl_AppendResult(ip, argv[0], ": invalid number of arguments\n", 
00309                       "Usage: ", argv[0], " <left shoulder joint>",
00310                       (char *)0 );
00311         return TCL_ERROR;
00312     } 
00313 
00314     ModelHndl->tuxLeftShoulderJoint = string_copy( argv[1] );
00315 
00316     return TCL_OK;
00317 } 
00318 
00319 static int
00320 right_shoulder_cb ( ClientData cd, Tcl_Interp *ip, 
00321                             int argc, CONST84 char *argv[]) 
00322 {
00323 
00324     if ( argc != 2 ) {
00325         Tcl_AppendResult(ip, argv[0], ": invalid number of arguments\n", 
00326                       "Usage: ", argv[0], " <right shoulder joint>",
00327                       (char *)0 );
00328         return TCL_ERROR;
00329     } 
00330 
00331     ModelHndl->tuxRightShoulderJoint = string_copy( argv[1] );
00332 
00333     return TCL_OK;
00334 } 
00335 
00336 static int
00337 left_hip_cb ( ClientData cd, Tcl_Interp *ip, 
00338                       int argc, CONST84 char *argv[]) 
00339 {
00340 
00341     if ( argc != 2 ) {
00342         Tcl_AppendResult(ip, argv[0], ": invalid number of arguments\n", 
00343                       "Usage: ", argv[0], " <left hip joint>",
00344                       (char *)0 );
00345         return TCL_ERROR;
00346     } 
00347 
00348     ModelHndl->tuxLeftHipJoint = string_copy( argv[1] );
00349 
00350     return TCL_OK;
00351 } 
00352 
00353 static int
00354 right_hip_cb ( ClientData cd, Tcl_Interp *ip, 
00355                        int argc, CONST84 char *argv[]) 
00356 {
00357 
00358     if ( argc != 2 ) {
00359         Tcl_AppendResult(ip, argv[0], ": invalid number of arguments\n", 
00360                       "Usage: ", argv[0], " <right hip joint>",
00361                       (char *)0 );
00362         return TCL_ERROR;
00363     } 
00364 
00365     ModelHndl->tuxRightHipJoint = string_copy( argv[1] );
00366 
00367     return TCL_OK;
00368 } 
00369 
00370 static int
00371 left_knee_cb ( ClientData cd, Tcl_Interp *ip, 
00372                        int argc, CONST84 char *argv[]) 
00373 {
00374 
00375     if ( argc != 2 ) {
00376         Tcl_AppendResult(ip, argv[0], ": invalid number of arguments\n", 
00377                       "Usage: ", argv[0], " <left knee joint>",
00378                       (char *)0 );
00379         return TCL_ERROR;
00380     } 
00381 
00382     ModelHndl->tuxLeftKneeJoint = string_copy( argv[1] );
00383 
00384     return TCL_OK;
00385 } 
00386 
00387 static int
00388 right_knee_cb ( ClientData cd, Tcl_Interp *ip, 
00389                         int argc, CONST84 char *argv[]) 
00390 {
00391 
00392     if ( argc != 2 ) {
00393         Tcl_AppendResult(ip, argv[0], ": invalid number of arguments\n", 
00394                       "Usage: ", argv[0], " <right knee joint>",
00395                       (char *)0 );
00396         return TCL_ERROR;
00397     } 
00398 
00399     ModelHndl->tuxRightKneeJoint = string_copy( argv[1] );
00400 
00401     return TCL_OK;
00402 } 
00403 
00404 static int
00405 left_ankle_cb ( ClientData cd, Tcl_Interp *ip, 
00406                         int argc, CONST84 char *argv[]) 
00407 {
00408 
00409     if ( argc != 2 ) {
00410         Tcl_AppendResult(ip, argv[0], ": invalid number of arguments\n", 
00411                       "Usage: ", argv[0], " <left ankle joint>",
00412                       (char *)0 );
00413         return TCL_ERROR;
00414     } 
00415 
00416     ModelHndl->tuxLeftAnkleJoint = string_copy( argv[1] );
00417 
00418     return TCL_OK;
00419 } 
00420 
00421 static int
00422 right_ankle_cb ( ClientData cd, Tcl_Interp *ip, 
00423                          int argc, CONST84 char *argv[]) 
00424 {
00425 
00426     if ( argc != 2 ) {
00427         Tcl_AppendResult(ip, argv[0], ": invalid number of arguments\n", 
00428                       "Usage: ", argv[0], " <right ankle joint>",
00429                       (char *)0 );
00430         return TCL_ERROR;
00431     } 
00432 
00433     ModelHndl->tuxRightAnkleJoint = string_copy( argv[1] );
00434 
00435     return TCL_OK;
00436 } 
00437 
00438 static int
00439 tail_cb ( ClientData cd, Tcl_Interp *ip, 
00440                    int argc, CONST84 char *argv[]) 
00441 {
00442 
00443     if ( argc != 2 ) {
00444         Tcl_AppendResult(ip, argv[0], ": invalid number of arguments\n", 
00445                       "Usage: ", argv[0], " <tail joint>",
00446                       (char *)0 );
00447         return TCL_ERROR;
00448     } 
00449 
00450     ModelHndl->tuxTailJoint = string_copy( argv[1] );
00451 
00452     return TCL_OK;
00453 } 
00454 
00455 static int
00456 tux_add_model_cb ( ClientData cd, Tcl_Interp *ip, 
00457                    int argc, CONST84 char *argv[]) 
00458 {
00459     if ( argc != 3 ) {
00460         Tcl_AppendResult(ip, argv[0], ": invalid number of arguments\n", 
00461                       "Usage: ", argv[0], " <model file> <model name>",
00462                       (char *)0 );
00463         return TCL_ERROR;
00464     }
00465  
00466     model_t tmp_model;
00467     tmp_model.name = _(string_copy( argv[2] ));
00468     tmp_model.filename = string_copy( argv[1] );
00469     tmp_model.id = ModelHndl->num_models++;
00470     ModelHndl->l_models.push_back(tmp_model);
00471  
00472     return TCL_OK;
00473 }
00474 
00475 
00476 static void register_tux_callbacks( Tcl_Interp *ip )
00477 {
00478     Tcl_CreateCommand (ip, "tux_root_node", root_node_cb,   0,0);
00479     Tcl_CreateCommand (ip, "tux_left_shoulder",  left_shoulder_cb,   0,0);
00480     Tcl_CreateCommand (ip, "tux_right_shoulder",  right_shoulder_cb,   0,0);
00481     Tcl_CreateCommand (ip, "tux_left_hip",  left_hip_cb,   0,0);
00482     Tcl_CreateCommand (ip, "tux_right_hip",  right_hip_cb,   0,0);
00483     Tcl_CreateCommand (ip, "tux_left_knee",  left_knee_cb,   0,0);
00484     Tcl_CreateCommand (ip, "tux_right_knee",  right_knee_cb,   0,0);
00485     Tcl_CreateCommand (ip, "tux_left_ankle",  left_ankle_cb,   0,0);
00486     Tcl_CreateCommand (ip, "tux_right_ankle",  right_ankle_cb,   0,0);
00487     Tcl_CreateCommand (ip, "tux_neck",  neck_cb,   0,0);
00488     Tcl_CreateCommand (ip, "tux_head", head_cb,  0,0);
00489     Tcl_CreateCommand (ip, "tux_tail", tail_cb,  0,0);
00490     Tcl_CreateCommand (ip, "tux_add_model", tux_add_model_cb,  0,0);
00491 }
00492 
00493 /*
00494 static void register_tuxplayer_callbacks( Tcl_Interp *ip )
00495 {
00496     Tcl_CreateCommand (ip, "tux_root_node", root_node_cb,   0,0);
00497     Tcl_CreateCommand (ip, "tux_left_shoulder",  left_shoulder_cb,   0,0);
00498     Tcl_CreateCommand (ip, "tux_right_shoulder",  right_shoulder_cb,   0,0);
00499     Tcl_CreateCommand (ip, "tux_left_hip",  left_hip_cb,   0,0);
00500     Tcl_CreateCommand (ip, "tux_right_hip",  right_hip_cb,   0,0);
00501     Tcl_CreateCommand (ip, "tux_left_knee",  left_knee_cb,   0,0);
00502     Tcl_CreateCommand (ip, "tux_right_knee",  right_knee_cb,   0,0);
00503     Tcl_CreateCommand (ip, "tux_left_ankle",  left_ankle_cb,   0,0);
00504     Tcl_CreateCommand (ip, "tux_right_ankle",  right_ankle_cb,   0,0);
00505     Tcl_CreateCommand (ip, "tux_neck",  neck_cb,   0,0);
00506     Tcl_CreateCommand (ip, "tux_head", head_cb,  0,0);
00507     Tcl_CreateCommand (ip, "tux_tail", tail_cb,  0,0);
00508 }
00509 */