Back to index

extremetuxracer  0.5beta
track_marks.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 "track_marks.h"
00023 #include "gl_util.h"
00024 #include "model_hndl.h"
00025 #include "hier.h"
00026 #include "phys_sim.h"
00027 #include "textures.h"
00028 #include "course_render.h"
00029 #include "render_util.h"
00030 #include "game_config.h"
00031 #include "course_mgr.h"
00032 
00033 #include "ppgltk/alg/defs.h"
00034 
00035 #include "game_mgr.h"
00036 
00037 
00038 #undef TRACK_TRIANGLES
00039 
00040 #define TRACK_WIDTH  0.7
00041 #define MAX_TRACK_MARKS 16000
00042 #define MAX_CONTINUE_TRACK_DIST TRACK_WIDTH*4
00043 #define MAX_CONTINUE_TRACK_TIME .1
00044 #define SPEED_TO_START_TRENCH 0.0
00045 #define SPEED_OF_DEEPEST_TRENCH 10
00046 
00047 #define MAX_CRACKS 100
00048 #define CRACK_MIN_FORCE 10000
00049 #define CRACK_SIZE_PER_FORCE 0.0001
00050 #define CRACK_MAX_SIZE 1.5
00051 #define CRACK_MAX_UNIFY_DISTANCE 0.5
00052 #define CRACK_HEIGHT 0.08
00053 #define MAX_CRACK_HEIGHT 0.2
00054 
00055 #ifdef TRACK_TRIANGLES
00056   #define TRACK_HEIGHT 0.1
00057   #define MAX_TRACK_DEPTH 10
00058   #define MAX_TRIS MAX_TRACK_MARKS
00059 #else
00060   #define TRACK_HEIGHT 0.08
00061   #define MAX_TRACK_DEPTH 0.7
00062 #endif
00063 
00064 typedef enum track_types_t {
00065     TRACK_HEAD,
00066     TRACK_MARK,
00067     TRACK_TAIL,
00068     NUM_TRACK_TYPES
00069 } track_types_t;
00070 
00071 typedef struct track_quad_t {
00072     pp::Vec3d v1, v2, v3, v4;
00073     pp::Vec2d t1, t2, t3, t4;
00074     pp::Vec3d n1, n2, n3, n4;
00075     track_types_t track_type;
00076        int terrain;
00077     double alpha;
00078 } track_quad_t;
00079 
00080 typedef struct track_marks_t {
00081     track_quad_t quads[MAX_TRACK_MARKS];
00082     int current_mark;
00083     int next_mark;
00084     double last_mark_time;
00085     pp::Vec3d last_mark_pos;
00086 } track_marks_t;
00087 
00088 static track_marks_t track_marks;
00089 static bool continuing_track;
00090 
00091 extern terrain_tex_t terrain_texture[NUM_TERRAIN_TYPES];
00092 extern unsigned int num_terrains;
00093 
00094 typedef struct crack_quad_t {
00095     pp::Vec3d v1, v2, v3, v4;
00096     pp::Vec2d t1, t2, t3, t4;
00097     pp::Vec3d n1, n2, n3, n4;
00098 } crack_quad_t;
00099 
00100 typedef struct cracks_t {
00101   crack_quad_t quads[MAX_CRACKS];
00102   int current_crack;
00103   double last_size;
00104   pp::Vec3d last_pos;
00105 } cracks_t;
00106 
00107 static cracks_t cracks;
00108 
00109 #ifdef TRACK_TRIANGLES
00110 typedef struct track_tris_t {
00111     triangle_t tri[MAX_TRIS];
00112     track_types_t *track_type[MAX_TRIS];
00113     double *alpha[MAX_TRIS];
00114     int first_mark;
00115     int next_mark;
00116     int current_start;
00117     int current_end;
00118     int num_tris;
00119 } track_tris_t;
00120 
00121 typedef struct track_tri_t {
00122     pp::Vec3d v1, v2, v3;
00123 } track_tri_t;
00124 
00125 static track_tris_t track_tris;
00126 
00127 static void draw_tri( triangle_t *tri, double alpha )
00128 {
00129     pp::Vec3d nml;
00130     GLfloat c[4] = {1.0, 0.0, 0.0, 1.0}; 
00131 
00132 /*    set_material_alpha( white, black, 1.0, alpha ); */
00133     set_material_alpha( white, black, 1.0, 1.0 );  
00134 
00135     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, c);
00136 
00137     glBegin(GL_TRIANGLES);
00138 
00139     nml = find_course_normal( tri->p[0].x, tri->p[0].z );
00140     glNormal3f( nml.x, nml.y, nml.z );
00141     glTexCoord2f( tri->t[0].x, tri->t[0].y );
00142     glVertex3f( tri->p[0].x, tri->p[0].y, tri->p[0].z );
00143     
00144     nml = find_course_normal( tri->p[1].x, tri->p[1].z );
00145     glNormal3f( nml.x, nml.y, nml.z );
00146     glTexCoord2f( tri->t[1].x, tri->t[1].y );
00147     glVertex3f( tri->p[1].x, tri->p[1].y, tri->p[1].z );
00148     
00149     nml = find_course_normal( tri->p[2].x, tri->p[2].z );
00150     glNormal3f( nml.x, nml.y, nml.z );
00151     glTexCoord2f( tri->t[2].x, tri->t[2].y );
00152     glVertex3f( tri->p[2].x, tri->p[2].y, tri->p[2].z );
00153 
00154     glEnd();
00155 }
00156 
00157 static void draw_tri_tracks( void )
00158 {
00159     GLuint texid[NUM_TRACK_TYPES];
00160     int i;
00161 
00162     set_gl_options( TRACK_MARKS ); 
00163 
00164     glColor4f( 0, 0, 0, 1);
00165 
00166     get_texture_binding( "track_head", &texid[TRACK_HEAD] );
00167     get_texture_binding( "track_mark", &texid[TRACK_MARK] );
00168     get_texture_binding( "track_tail", &texid[TRACK_TAIL] );
00169 
00170     glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
00171     set_material( white, black, 1.0 );
00172     setup_course_lighting();
00173 
00174     for( i = 0; i < track_tris.num_tris; i++ ) {
00175        glBindTexture( GL_TEXTURE_2D, 
00176                      texid[*track_tris.track_type[(track_tris.first_mark+i)%MAX_TRIS]] );
00177        draw_tri( &track_tris.tri[(track_tris.first_mark+i)%MAX_TRIS],
00178                 *track_tris.alpha[(track_tris.first_mark+i)%MAX_TRIS] );
00179     }
00180 }
00181 
00182 static void add_tri_tracks_from_tri( pp::Vec3d p1, pp::Vec3d p2, pp::Vec3d p3,
00183                                  pp::Vec2d t1, pp::Vec2d t2, pp::Vec2d t3,
00184                                  track_types_t *track_type, double *alpha )
00185 {
00186     double minx, maxx;
00187     double minz, maxz;
00188     int nx, nz;
00189     double width, length;
00190     int i, j, k;
00191     double xstep, zstep;
00192     line_t cut;
00193     int num_tris;
00194     int this_set_end;
00195     int num_new;
00196 
00197     /* Make 'em planar. Calculate y later anyway */
00198     p1.y = p2.y = p3.y = 0;
00199 
00200     get_course_divisions( &nx, &nz );
00201     get_course_dimensions( &width, &length );
00202     xstep = width/(nx-1);
00203     zstep = length/(nz-1);
00204 
00205     minx = min(min(p1.x, p2.x), p3.x);
00206     minz = min(min(p1.z, p2.z), p3.z);
00207     maxx = max(max(p1.x, p2.x), p3.x);
00208     maxz = max(max(p1.z, p2.z), p3.z);
00209 
00210     track_tris.current_start = track_tris.next_mark;
00211     track_tris.current_end = track_tris.next_mark;
00212 
00213     track_tris.tri[track_tris.next_mark].p[0] = p1;
00214     track_tris.tri[track_tris.next_mark].p[1] = p2;
00215     track_tris.tri[track_tris.next_mark].p[2] = p3;
00216     track_tris.tri[track_tris.next_mark].t[0] = t1;
00217     track_tris.tri[track_tris.next_mark].t[1] = t2;
00218     track_tris.tri[track_tris.next_mark].t[2] = t3; 
00219 
00220     /*
00221      * Make lengthwise cuts
00222      */
00223     for( i = (int)((minx/xstep)+0.9999); i < (int)(maxx/xstep); i++ ) {
00224        cut.pt = make_point( i*xstep, 0, 0 );
00225        cut.nml = make_vector( 1, 0, 0 );
00226        this_set_end = track_tris.current_end;
00227        for ( j = track_tris.current_start; j <= this_set_end; j++ ) {
00228            num_tris = cut_triangle( &track_tris.tri[j%MAX_TRIS],
00229                                  &track_tris.tri[(track_tris.current_end+1)%MAX_TRIS],
00230                                  &track_tris.tri[(track_tris.current_end+2)%MAX_TRIS],
00231                                  cut );
00232            track_tris.current_end = (track_tris.current_end + num_tris - 1)%MAX_TRIS;
00233        }
00234     }
00235     
00236     /*
00237      * Make cross cuts
00238      */
00239     for( i = (int)((minz/zstep)+0.9999); i < (int)(maxz/zstep); i++ ) {
00240        cut.pt = make_point( 0, 0, i*zstep );
00241        cut.nml = make_vector( 0, 0, 1 );
00242        this_set_end = track_tris.current_end;
00243        for ( j = track_tris.current_start; j <= this_set_end; j++ ) {
00244            num_tris = cut_triangle( &track_tris.tri[j%MAX_TRIS],
00245                                  &track_tris.tri[(track_tris.current_end+1)%MAX_TRIS],
00246                                  &track_tris.tri[(track_tris.current_end+2)%MAX_TRIS],
00247                                  cut );
00248            track_tris.current_end = (track_tris.current_end + num_tris - 1)%MAX_TRIS;
00249        }
00250     }
00251 
00252     /*
00253      * Make diagonal cuts
00254      */
00255     for( i = (int)((minx/xstep)+0.9999), j = (int)((minz/zstep)+0.9999);
00256         (i < (int)(maxx/xstep)) && (j < (int)(maxz/zstep));
00257         i++, j++) {
00258        if ( (i+j)%2 != 0 ) {
00259            i--;
00260        }
00261        cut.pt = make_point( i*xstep, 0, j*zstep );
00262        cut.nml = make_vector( 1, 0, 1 );
00263        cut.nml.normalize();
00264        for ( k = track_tris.current_start; k <= this_set_end; k++ ) {
00265            num_tris = cut_triangle( &track_tris.tri[k%MAX_TRIS],
00266                                  &track_tris.tri[(track_tris.current_end+1)%MAX_TRIS],
00267                                  &track_tris.tri[(track_tris.current_end+2)%MAX_TRIS],
00268                                  cut );
00269            track_tris.current_end = (track_tris.current_end + num_tris - 1)%MAX_TRIS;
00270        }
00271     }
00272 
00273     /*
00274      * Make other diagonal cuts
00275      */
00276     for( i = (int)((minx/xstep)+0.9999), j = (int)(maxz/zstep);
00277         (i < (int)(maxx/xstep)) && (j > (int)((minz/zstep) + 0.9999));
00278         i++, j--) {
00279        if ( (i+j)%2 != 0 ) {
00280            i--;
00281        }
00282        cut.pt = make_point( i*xstep, 0, j*zstep );
00283        cut.nml = make_vector( 1, 0, 1 );
00284        cut.nml.normalize();
00285        for ( k = track_tris.current_start; k <= this_set_end; k++ ) {
00286            num_tris = cut_triangle( &track_tris.tri[k%MAX_TRIS],
00287                                  &track_tris.tri[(track_tris.current_end+1)%MAX_TRIS],
00288                                  &track_tris.tri[(track_tris.current_end+2)%MAX_TRIS],
00289                                  cut );
00290            track_tris.current_end = (track_tris.current_end + num_tris - 1)%MAX_TRIS;
00291        }
00292     }
00293 
00294 
00295     /* Reset first, next and num_tris */
00296     if (track_tris.current_start <= track_tris.current_end) {
00297        num_new = track_tris.current_end - track_tris.current_start + 1;
00298        track_tris.num_tris = track_tris.num_tris + num_new;
00299        track_tris.next_mark = (track_tris.current_end+1)%MAX_TRIS;
00300        if ( ((track_tris.num_tris - num_new) > 0) &&
00301             (track_tris.first_mark >= track_tris.current_start) && 
00302             (track_tris.first_mark <= track_tris.current_end) ) {
00303            track_tris.num_tris = track_tris.num_tris - (track_tris.current_end - track_tris.first_mark + 1);
00304            track_tris.first_mark = track_tris.next_mark;
00305        }
00306 
00307     } else {
00308        num_new = (track_tris.current_end + 1) + (MAX_TRIS - track_tris.current_start);
00309        track_tris.num_tris = track_tris.num_tris + num_new;
00310        track_tris.next_mark = (track_tris.current_end+1)%MAX_TRIS;
00311        if (track_tris.first_mark >= track_tris.current_start) {
00312            track_tris.num_tris = track_tris.num_tris - (track_tris.current_end + 1) - 
00313               (MAX_TRIS - track_tris.first_mark);
00314            track_tris.first_mark = track_tris.next_mark;
00315        } else if (track_tris.first_mark <= track_tris.current_end) {
00316            track_tris.num_tris = track_tris.num_tris - (track_tris.current_end - track_tris.first_mark + 1);
00317            track_tris.first_mark = track_tris.next_mark;
00318        }
00319 
00320     }
00321 
00322     for ( i = 0; i < num_new; i++ ) {
00323        track_tris.alpha[(track_tris.current_start+i)%MAX_TRIS] = alpha;
00324        track_tris.track_type[(track_tris.current_start+i)%MAX_TRIS] = track_type;
00325        track_tris.tri[(track_tris.current_start+i)%MAX_TRIS].p[0].y = 
00326            find_y_coord( track_tris.tri[(track_tris.current_start+i)%MAX_TRIS].p[0].x, 
00327                        track_tris.tri[(track_tris.current_start+i)%MAX_TRIS].p[0].z ) +
00328            TRACK_HEIGHT; 
00329        track_tris.tri[(track_tris.current_start+i)%MAX_TRIS].p[1].y =
00330            find_y_coord( track_tris.tri[(track_tris.current_start+i)%MAX_TRIS].p[1].x, 
00331                        track_tris.tri[(track_tris.current_start+i)%MAX_TRIS].p[1].z ) +
00332            TRACK_HEIGHT; 
00333        track_tris.tri[(track_tris.current_start+i)%MAX_TRIS].p[2].y = 
00334            find_y_coord( track_tris.tri[(track_tris.current_start+i)%MAX_TRIS].p[2].x, 
00335                        track_tris.tri[(track_tris.current_start+i)%MAX_TRIS].p[2].z ) +
00336            TRACK_HEIGHT; 
00337     }
00338 
00339 }
00340 
00341 static void add_tri_tracks_from_quad( track_quad_t *q )
00342 {
00343     add_tri_tracks_from_tri( q->v1, q->v2, q->v3, q->t1, q->t2, q->t3,
00344                           &q->track_type, &q->alpha );
00345     add_tri_tracks_from_tri( q->v2, q->v4, q->v3, q->t2, q->t4, q->t3,
00346                           &q->track_type, &q->alpha );
00347 }
00348 
00349 #endif
00350 
00351 
00352 
00353 void init_track_marks(void)
00354 {
00355     if(gameMgr->doesRaceHaveToBeRetried()) {
00356     //do nothing, since we want to keep last try's tracks
00357     } else {
00358 
00359         track_marks.current_mark = 0;
00360         track_marks.next_mark = 0;
00361         track_marks.last_mark_time = -99999;
00362         track_marks.last_mark_pos = pp::Vec3d(-9999, -9999, -9999);
00363         continuing_track = false;
00364 #ifdef TRACK_TRIANGLES
00365         track_tris.first_mark = 0;
00366         track_tris.next_mark = 0;
00367         track_tris.num_tris = 0;
00368 #endif
00369         cracks.current_crack = 0;
00370         cracks.last_pos = pp::Vec3d(-9999, -9999, -9999);
00371     }
00372 }
00373 
00374 void draw_cracks(void) {
00375     int curr_crack;
00376     int first_crack;
00377     int num_cracks;
00378     GLuint texid;
00379 
00380     /* opengl-settings should still be ok from draw_track_marks() */
00381 //     set_gl_options( TRACK_MARKS );
00382 //
00383 //     glColor4f( 0, 0, 0, 1);
00384 //
00385 //     glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
00386 //     set_material( pp::Color::white, pp::Color::black, 1.0 );
00387 //     setup_course_lighting();
00388 
00389     get_texture_binding( "crack", &texid );
00390 
00391 
00392     num_cracks = MIN(cracks.current_crack, MAX_CRACKS);
00393 
00394     first_crack = cracks.current_crack - num_cracks;
00395 
00396     for (curr_crack = 0; curr_crack < num_cracks; curr_crack++) {
00397         crack_quad_t *q;
00398 
00399         q = &cracks.quads[(first_crack + curr_crack)%MAX_CRACKS];
00400 
00401         set_material( pp::Color::white, pp::Color::black, 1.0 );
00402 
00403         glBindTexture( GL_TEXTURE_2D, texid );
00404 
00405         glBegin(GL_QUADS);
00406 
00407         glNormal3f( q->n1.x, q->n1.y, q->n1.z );
00408         glTexCoord2f( q->t1.x, q->t1.y );
00409         glVertex3f( q->v1.x, q->v1.y, q->v1.z );
00410 
00411         glNormal3f( q->n2.x, q->n2.y, q->n2.z );
00412         glTexCoord2f( q->t2.x, q->t2.y );
00413         glVertex3f( q->v2.x, q->v2.y, q->v2.z );
00414 
00415         glNormal3f( q->n4.x, q->n4.y, q->n4.z );
00416         glTexCoord2f( q->t4.x, q->t4.y );
00417         glVertex3f( q->v4.x, q->v4.y, q->v4.z );
00418 
00419         glNormal3f( q->n3.x, q->n3.y, q->n3.z );
00420         glTexCoord2f( q->t3.x, q->t3.y );
00421         glVertex3f( q->v3.x, q->v3.y, q->v3.z );
00422 
00423         glEnd();
00424      }
00425  }
00426 
00427 
00428 void draw_track_marks(void)
00429 {
00430 #ifdef TRACK_TRIANGLES
00431     draw_tri_tracks();
00432 #else
00433     //GLuint texid[NUM_TRACK_TYPES];
00434     int current_quad, num_quads;
00435     int first_quad;
00436     track_quad_t *q, *qnext;
00437     pp::Color trackColor = pp::Color::white;
00438 
00439     if (getparam_track_marks() == false) {
00440               return;
00441     }
00442 
00443     set_gl_options( TRACK_MARKS ); 
00444 
00445     glColor4f( 0, 0, 0, 1);
00446 
00447     //get_texture_binding( "track_head", &texid[TRACK_HEAD] );
00448     //get_texture_binding( "track_mark", &texid[TRACK_MARK] );
00449     //get_texture_binding( "track_tail", &texid[TRACK_TAIL] );
00450 
00451     glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
00452     set_material( pp::Color::white, pp::Color::black, 1.0 );
00453     setup_course_lighting();
00454 
00455     num_quads = MIN( track_marks.current_mark, MAX_TRACK_MARKS -
00456                    track_marks.next_mark + track_marks.current_mark );
00457     first_quad = track_marks.current_mark - num_quads;
00458 
00459     for ( current_quad = 0;
00460          current_quad < num_quads;
00461          current_quad++ ) 
00462     {
00463        q = &track_marks.quads[(first_quad + current_quad)%MAX_TRACK_MARKS];
00464 
00465        trackColor.a = q->alpha;
00466        set_material( trackColor, pp::Color::black, 1.0 );
00467 
00468        //glBindTexture( GL_TEXTURE_2D, texid[q->track_type] );
00469        
00470        switch (q->track_type){
00471               case TRACK_HEAD:
00472                      glBindTexture( GL_TEXTURE_2D, terrain_texture[q->terrain].trackmark.head);
00473                      break;
00474               case TRACK_MARK:
00475                      glBindTexture( GL_TEXTURE_2D, terrain_texture[q->terrain].trackmark.mark);
00476                      break;
00477               case TRACK_TAIL:
00478                      glBindTexture( GL_TEXTURE_2D, terrain_texture[q->terrain].trackmark.tail);
00479                      break;        
00480               default:
00481                      glBindTexture( GL_TEXTURE_2D, terrain_texture[q->terrain].trackmark.mark);
00482                      break; 
00483        }
00484 
00485        if ((q->track_type == TRACK_HEAD) || (q->track_type == TRACK_TAIL)) { 
00486            glBegin(GL_QUADS);
00487            
00488            glNormal3f( q->n1.x, q->n1.y, q->n1.z );
00489            glTexCoord2f( q->t1.x, q->t1.y );
00490            glVertex3f( q->v1.x, q->v1.y, q->v1.z );
00491        
00492            glNormal3f( q->n2.x, q->n2.y, q->n2.z );
00493            glTexCoord2f( q->t2.x, q->t2.y );
00494            glVertex3f( q->v2.x, q->v2.y, q->v2.z );
00495 
00496            glNormal3f( q->n4.x, q->n4.y, q->n4.z );
00497            glTexCoord2f( q->t4.x, q->t4.y );
00498            glVertex3f( q->v4.x, q->v4.y, q->v4.z );
00499        
00500            glNormal3f( q->n3.x, q->n3.y, q->n3.z );
00501            glTexCoord2f( q->t3.x, q->t3.y );
00502            glVertex3f( q->v3.x, q->v3.y, q->v3.z );
00503        
00504            glEnd();
00505 
00506        } else {
00507              
00508            glBegin(GL_QUAD_STRIP);
00509 
00510            glNormal3f( q->n2.x, q->n2.y, q->n2.z );
00511            glTexCoord2f( q->t2.x, q->t2.y );
00512            glVertex3f( q->v2.x, q->v2.y, q->v2.z );
00513 
00514            glNormal3f( q->n1.x, q->n1.y, q->n1.z );
00515            glTexCoord2f( q->t1.x, q->t1.y );
00516            glVertex3f( q->v1.x, q->v1.y, q->v1.z );
00517 
00518            glNormal3f( q->n4.x, q->n4.y, q->n4.z );
00519            glTexCoord2f( q->t4.x, q->t4.y );
00520            glVertex3f( q->v4.x, q->v4.y, q->v4.z );
00521 
00522            glNormal3f( q->n3.x, q->n3.y, q->n3.z );
00523            glTexCoord2f( q->t3.x, q->t3.y );
00524            glVertex3f( q->v3.x, q->v3.y, q->v3.z );
00525               glEnd();
00526               glBegin(GL_QUADS);
00527               
00528            qnext = &track_marks.quads[(first_quad+current_quad+1)%MAX_TRACK_MARKS];
00529            while (( qnext->track_type == TRACK_MARK ) && (current_quad+1 < num_quads)) {
00530               current_quad++;
00531               
00532               if (q->terrain != qnext->terrain){
00533                      glEnd();
00534                      glBindTexture( GL_TEXTURE_2D, terrain_texture[qnext->terrain].trackmark.mark);
00535                      glBegin(GL_QUADS);          
00536               }
00537                             
00538               q = &track_marks.quads[(first_quad+current_quad)%MAX_TRACK_MARKS];
00539               trackColor.a = qnext->alpha;
00540               set_material( trackColor, pp::Color::black, 1.0 );
00541               
00542 
00543            glNormal3f( q->n1.x, q->n1.y, q->n1.z );
00544            glTexCoord2f( q->t1.x, q->t1.y );
00545            glVertex3f( q->v1.x, q->v1.y, q->v1.z );
00546               
00547               glNormal3f( q->n2.x, q->n2.y, q->n2.z );
00548            glTexCoord2f( q->t2.x, q->t2.y );
00549            glVertex3f( q->v2.x, q->v2.y, q->v2.z );     
00550               
00551               
00552                      
00553               glNormal3f( q->n4.x, q->n4.y, q->n4.z );
00554               glTexCoord2f( q->t4.x, q->t4.y );
00555               glVertex3f( q->v4.x, q->v4.y, q->v4.z );
00556 
00557               glNormal3f( q->n3.x, q->n3.y, q->n3.z );
00558               glTexCoord2f( q->t3.x, q->t3.y );
00559               glVertex3f( q->v3.x, q->v3.y, q->v3.z );
00560               
00561               qnext = &track_marks.quads[(first_quad+current_quad+1)%MAX_TRACK_MARKS];
00562            }
00563            glEnd();
00564        }
00565 
00566     }
00567 #endif
00568 
00569     draw_cracks();
00570 }
00571 
00572 void add_crack( Player& plyr )
00573 {
00574     crack_quad_t *q;
00575     //double terrain_weights[NumTerrains];
00576     pp::Vec3d normal_force;
00577     double force;
00578     double half_size;
00579     pp::Vec3d dist;
00580 
00581 
00582     /*
00583     get_surface_type(plyr.pos.x, plyr.pos.z, terrain_weights);
00584     if (terrain_weights[Snow] > 0.5) {
00585       return;
00586     }
00587     */
00588 
00589     normal_force = plyr.normal_force;
00590     force = normal_force.normalize();
00591 
00592     if (force < CRACK_MIN_FORCE)
00593       return;
00594 
00595     play_sound( "crack_ice_sound", 0 );
00596     half_size = force * CRACK_SIZE_PER_FORCE / 2.0;
00597    
00598     dist = plyr.pos - cracks.last_pos;
00599     if (dist.normalize() <= CRACK_MAX_UNIFY_DISTANCE) {
00600        cracks.current_crack--;
00601         half_size += cracks.last_size;
00602     }
00603 
00604     /* Too big cracks may hang around in the air, if the terrain is not plane */
00605     if (half_size > CRACK_MAX_SIZE / 2.0)
00606         half_size = CRACK_MAX_SIZE / 2.0;
00607 
00608     q = &cracks.quads[cracks.current_crack%MAX_TRACK_MARKS];
00609 
00610 
00611     q->v1 = pp::Vec3d( plyr.pos.x - half_size,
00612            find_y_coord(plyr.pos.x - half_size, plyr.pos.z - half_size) + CRACK_HEIGHT,
00613                                             plyr.pos.z - half_size  );
00614     q->v2 = pp::Vec3d( plyr.pos.x + half_size,
00615            find_y_coord(plyr.pos.x + half_size, plyr.pos.z - half_size) + CRACK_HEIGHT,
00616                                             plyr.pos.z - half_size  );
00617     q->v3 = pp::Vec3d( plyr.pos.x - half_size,
00618            find_y_coord(plyr.pos.x - half_size, plyr.pos.z + half_size) + CRACK_HEIGHT,
00619                                             plyr.pos.z + half_size  );
00620     q->v4 = pp::Vec3d( plyr.pos.x + half_size,
00621            find_y_coord(plyr.pos.x + half_size, plyr.pos.z + half_size) + CRACK_HEIGHT,
00622                                             plyr.pos.z + half_size  );
00623 
00624     /* Big cracks tended to hang around in the air. Reduce the probability that
00625        this happens: */
00626     double center_height = (q->v1.y + q->v2.y + q->v3.y + q->v4.y) / 4
00627                            - find_y_coord(plyr.pos.x, plyr.pos.z);
00628     if (center_height > MAX_CRACK_HEIGHT) {
00629         center_height -= MAX_CRACK_HEIGHT;
00630         q->v1.y -= center_height;
00631         q->v2.y -= center_height;
00632         q->v3.y -= center_height;
00633         q->v4.y -= center_height;
00634     }
00635    
00636     q->n1 = find_course_normal( q->v1.x, q->v1.z);
00637     q->n2 = find_course_normal( q->v2.x, q->v2.z);
00638     q->n3 = find_course_normal( q->v3.x, q->v3.z);
00639     q->n4 = find_course_normal( q->v4.x, q->v4.z);
00640     q->t1 = pp::Vec2d(0.0, 0.0);
00641     q->t2 = pp::Vec2d(1.0, 0.0);
00642     q->t3 = pp::Vec2d(0.0, 1.0);
00643     q->t4 = pp::Vec2d(1.0, 1.0);
00644     cracks.current_crack++;    
00645 
00646     cracks.last_pos = plyr.pos;
00647     cracks.last_size = half_size;
00648 }
00649 
00650 void break_track_marks( void )
00651 {
00652     track_quad_t *qprev, *qprevprev;
00653     qprev = &track_marks.quads[(track_marks.current_mark-1)%MAX_TRACK_MARKS];
00654     qprevprev = &track_marks.quads[(track_marks.current_mark-2)%MAX_TRACK_MARKS];
00655 
00656     if (track_marks.current_mark > 0) {
00657        qprev->track_type = TRACK_TAIL;
00658        qprev->t1 = pp::Vec2d(0.0, 0.0);
00659        qprev->t2 = pp::Vec2d(1.0, 0.0);
00660        qprev->t3 = pp::Vec2d(0.0, 1.0);
00661        qprev->t4 = pp::Vec2d(1.0, 1.0);
00662        qprevprev->t3.y = MAX((int)(qprevprev->t3.y+0.5), (int)(qprevprev->t1.y+1));
00663        qprevprev->t4.y = MAX((int)(qprevprev->t3.y+0.5), (int)(qprevprev->t1.y+1));
00664     }
00665     track_marks.last_mark_time = -99999;
00666     track_marks.last_mark_pos = pp::Vec3d(-9999, -9999, -9999);
00667     continuing_track = false;
00668 }
00669 
00670 void add_track_mark( Player& plyr )
00671 {
00672     pp::Vec3d width_vector;
00673     pp::Vec3d left_vector;
00674     pp::Vec3d right_vector;
00675     float magnitude;
00676     track_quad_t *q, *qprev, *qprevprev;
00677     pp::Vec3d vel;
00678     float speed;
00679     pp::Vec3d left_wing, right_wing;
00680     float left_y, right_y;
00681     float dist_from_surface;
00682     pp::Plane surf_plane;
00683     float comp_depth;
00684     float tex_end;
00685     float terrain_weights[NUM_TERRAIN_TYPES];
00686     float dist_from_last_mark;
00687     pp::Vec3d vector_from_last_mark;
00688        bool break_marks;
00689        float terrain_compression=0;
00690        float old_terrain_weight=0;
00691        unsigned int i;
00692 
00693     if (getparam_track_marks() == false) {
00694        return;
00695     }
00696     
00697     add_crack(plyr);
00698 
00699     q = &track_marks.quads[track_marks.current_mark%MAX_TRACK_MARKS];
00700     qprev = &track_marks.quads[(track_marks.current_mark-1)%MAX_TRACK_MARKS];
00701     qprevprev = &track_marks.quads[(track_marks.current_mark-2)%MAX_TRACK_MARKS];
00702 
00703     vector_from_last_mark = plyr.pos - track_marks.last_mark_pos;
00704     dist_from_last_mark = vector_from_last_mark.normalize();
00705        
00706        
00707     get_surface_type(plyr.pos.x, plyr.pos.z, terrain_weights);
00708     
00709        break_marks=true;
00710        for (i=0;i<num_terrains;i++){
00711               if (terrain_texture[i].trackmark.mark !=0){      
00712                      if (terrain_weights[i] >= 0.5) {
00713                             if (old_terrain_weight < terrain_weights[i]) {
00714                                    break_marks=false;
00715                                    terrain_compression = get_compression_depth(i);
00716                                    q->terrain=i;
00717                                    old_terrain_weight = terrain_weights[i];
00718                             }
00719               }
00720               }
00721        }
00722        
00723        if (break_marks==true){
00724               break_track_marks();
00725               return;
00726        }
00727 
00728     vel = plyr.vel;
00729     speed = vel.normalize();
00730     if (speed < SPEED_TO_START_TRENCH) {
00731        break_track_marks();
00732        return;
00733     }
00734 
00735     width_vector = plyr.direction^pp::Vec3d( 0, 1, 0 );
00736     magnitude = width_vector.normalize();
00737     if ( magnitude == 0 ) {
00738        break_track_marks();
00739        return;
00740     }
00741 
00742     left_vector = (TRACK_WIDTH/2.0)*width_vector;
00743     right_vector = (-TRACK_WIDTH/2.0)*width_vector;
00744     left_wing =  plyr.pos - left_vector;
00745     right_wing = plyr.pos - right_vector;
00746     left_y = find_y_coord( left_wing.x, left_wing.z );
00747     right_y = find_y_coord( right_wing.x, right_wing.z );
00748     if (fabs(left_y-right_y) > MAX_TRACK_DEPTH) {
00749        break_track_marks();
00750        return;
00751     }
00752 
00753     surf_plane = get_local_course_plane( plyr.pos );
00754     dist_from_surface = surf_plane.distance( plyr.pos );
00755     comp_depth = terrain_compression;
00756     if ( dist_from_surface >= (2*comp_depth) ) {
00757        break_track_marks();
00758        return;
00759     }
00760 
00761     if (!continuing_track) {
00762        break_track_marks();
00763        q->track_type = TRACK_HEAD;
00764        q->v1 = pp::Vec3d( left_wing.x, left_y + TRACK_HEIGHT, left_wing.z );
00765        q->v2 = pp::Vec3d( right_wing.x, right_y + TRACK_HEIGHT, right_wing.z );
00766        q->n1 = find_course_normal( q->v1.x, q->v1.z);
00767        q->n2 = find_course_normal( q->v2.x, q->v2.z);
00768        q->t1 = pp::Vec2d(0.0, 0.0);
00769        q->t2 = pp::Vec2d(1.0, 0.0);
00770        track_marks.next_mark = track_marks.current_mark + 1;
00771     } else {
00772        if ( track_marks.next_mark == track_marks.current_mark ) {
00773            q->v1 = qprev->v3;
00774            q->v2 = qprev->v4;
00775            q->n1 = qprev->n3;
00776            q->n2 = qprev->n4;
00777            q->t1 = qprev->t3; 
00778            q->t2 = qprev->t4;
00779            if ( qprev->track_type != TRACK_HEAD ) {
00780               qprev->track_type = TRACK_MARK;
00781            }
00782            q->track_type = TRACK_MARK;
00783        }
00784        q->v3 = pp::Vec3d( left_wing.x, left_y + TRACK_HEIGHT, left_wing.z );
00785        q->v4 = pp::Vec3d( right_wing.x, right_y + TRACK_HEIGHT, right_wing.z );
00786        q->n3 = find_course_normal( q->v3.x, q->v3.z);
00787        q->n4 = find_course_normal( q->v4.x, q->v4.z);
00788        tex_end = speed*gameMgr->getTimeStep()/TRACK_WIDTH;
00789        if (q->track_type == TRACK_HEAD) {
00790            q->t3= pp::Vec2d(0.0, 1.0);
00791            q->t4= pp::Vec2d(1.0, 1.0);
00792        } else {
00793            q->t3 = pp::Vec2d(0.0, q->t1.y + tex_end);
00794            q->t4 = pp::Vec2d(1.0, q->t2.y + tex_end);
00795        }
00796 
00797 #ifdef TRACK_TRIANGLES
00798        add_tri_tracks_from_quad(q);
00799 #endif
00800        track_marks.current_mark++;
00801        track_marks.next_mark = track_marks.current_mark;
00802     }
00803 
00804     q->alpha = MIN( (2*comp_depth-dist_from_surface)/(4*comp_depth), 1.0 );
00805               
00806     track_marks.last_mark_time = gameMgr->time;
00807     continuing_track = true;
00808 
00809 }