/* * PlanetPenguin Racer * Copyright (C) 2004-2005 Volker Stroebel * * Copyright (C) 1999-2001 Jasmin F. Patry * * 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 "track_marks.h" #include "gl_util.h" #include "tux.h" #include "hier.h" #include "phys_sim.h" #include "course_render.h" #include "render_util.h" #include "course_mgr.h" #include "lights.h" #include "ppogl/base/defs.h" #include "ppogl/base/glwrappers.h" #include "game_mgr.h" #undef TRACK_TRIANGLES #define TRACK_WIDTH 0.7 #define MAX_CONTINUE_TRACK_DIST TRACK_WIDTH*4 #define MAX_CONTINUE_TRACK_TIME .1 #define SPEED_TO_START_TRENCH 0.0 #define SPEED_OF_DEEPEST_TRENCH 10 #define TRACK_HEIGHT 0.08 #define MAX_TRACK_DEPTH 0.7 extern TerrainTex terrain_texture[NUM_TERRAIN_TYPES]; extern unsigned int num_terrains; void TrackMarks::draw() { int current_quad, num_quads; int first_quad; TrackQuad *q, *qnext; ppogl::Color trackColor = ppogl::Color::white; set_gl_options( TRACK_MARKS ); gl::Color(ppogl::Color::black); gl::TexEnv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); set_material( ppogl::Color::white, ppogl::Color::black, 1.0 ); setup_course_lighting(); num_quads = MIN( current_mark, MAX_TRACK_MARKS - next_mark + current_mark ); first_quad = current_mark - num_quads; for ( current_quad = 0; current_quad < num_quads; current_quad++ ) { q = &quads[(first_quad + current_quad)%MAX_TRACK_MARKS]; trackColor.a() = q->alpha; set_material( trackColor, ppogl::Color::black, 1.0 ); switch (q->track_type){ case TRACK_HEAD: gl::BindTexture( GL_TEXTURE_2D, terrain_texture[q->terrain].trackmark.head); break; case TRACK_MARK: gl::BindTexture( GL_TEXTURE_2D, terrain_texture[q->terrain].trackmark.mark); break; case TRACK_TAIL: gl::BindTexture( GL_TEXTURE_2D, terrain_texture[q->terrain].trackmark.tail); break; default: gl::BindTexture( GL_TEXTURE_2D, terrain_texture[q->terrain].trackmark.mark); break; } if ((q->track_type == TRACK_HEAD) || (q->track_type == TRACK_TAIL)) { gl::Begin(GL_QUADS); gl::Normal( q->n1.x(), q->n1.y(), q->n1.z() ); gl::TexCoord( q->t1.x(), q->t1.y() ); gl::Vertex( q->v1.x(), q->v1.y(), q->v1.z() ); gl::Normal( q->n2.x(), q->n2.y(), q->n2.z() ); gl::TexCoord( q->t2.x(), q->t2.y() ); gl::Vertex( q->v2.x(), q->v2.y(), q->v2.z() ); gl::Normal( q->n4.x(), q->n4.y(), q->n4.z() ); gl::TexCoord( q->t4.x(), q->t4.y() ); gl::Vertex( q->v4.x(), q->v4.y(), q->v4.z() ); gl::Normal( q->n3.x(), q->n3.y(), q->n3.z() ); gl::TexCoord( q->t3.x(), q->t3.y() ); gl::Vertex( q->v3.x(), q->v3.y(), q->v3.z() ); gl::End(); } else { gl::Begin(GL_QUAD_STRIP); gl::Normal( q->n2.x(), q->n2.y(), q->n2.z() ); gl::TexCoord( q->t2.x(), q->t2.y() ); gl::Vertex( q->v2.x(), q->v2.y(), q->v2.z() ); gl::Normal( q->n1.x(), q->n1.y(), q->n1.z() ); gl::TexCoord( q->t1.x(), q->t1.y() ); gl::Vertex( q->v1.x(), q->v1.y(), q->v1.z() ); gl::Normal( q->n4.x(), q->n4.y(), q->n4.z() ); gl::TexCoord( q->t4.x(), q->t4.y() ); gl::Vertex( q->v4.x(), q->v4.y(), q->v4.z() ); gl::Normal( q->n3.x(), q->n3.y(), q->n3.z() ); gl::TexCoord( q->t3.x(), q->t3.y() ); gl::Vertex( q->v3.x(), q->v3.y(), q->v3.z() ); gl::End(); gl::Begin(GL_QUADS); qnext = &quads[(first_quad+current_quad+1)%MAX_TRACK_MARKS]; while (( qnext->track_type == TRACK_MARK ) && (current_quad+1 < num_quads)) { current_quad++; if (q->terrain != qnext->terrain){ gl::End(); gl::BindTexture( GL_TEXTURE_2D, terrain_texture[qnext->terrain].trackmark.mark); gl::Begin(GL_QUADS); } q = &quads[(first_quad+current_quad)%MAX_TRACK_MARKS]; trackColor.a() = qnext->alpha; set_material( trackColor, ppogl::Color::black, 1.0 ); gl::Normal( q->n1.x(), q->n1.y(), q->n1.z() ); gl::TexCoord( q->t1.x(), q->t1.y() ); gl::Vertex( q->v1.x(), q->v1.y(), q->v1.z() ); gl::Normal( q->n2.x(), q->n2.y(), q->n2.z() ); gl::TexCoord( q->t2.x(), q->t2.y() ); gl::Vertex( q->v2.x(), q->v2.y(), q->v2.z() ); gl::Normal( q->n4.x(), q->n4.y(), q->n4.z() ); gl::TexCoord( q->t4.x(), q->t4.y() ); gl::Vertex( q->v4.x(), q->v4.y(), q->v4.z() ); gl::Normal( q->n3.x(), q->n3.y(), q->n3.z() ); gl::TexCoord( q->t3.x(), q->t3.y() ); gl::Vertex( q->v3.x(), q->v3.y(), q->v3.z() ); qnext = &quads[(first_quad+current_quad+1)%MAX_TRACK_MARKS]; } gl::End(); } } } void TrackMarks::discontinue() { TrackQuad *qprev, *qprevprev; qprev = &quads[(current_mark-1)%MAX_TRACK_MARKS]; qprevprev = &quads[(current_mark-2)%MAX_TRACK_MARKS]; if (current_mark > 0) { qprev->track_type = TRACK_TAIL; qprev->t1 = ppogl::Vec2d(0.0, 0.0); qprev->t2 = ppogl::Vec2d(1.0, 0.0); qprev->t3 = ppogl::Vec2d(0.0, 1.0); qprev->t4 = ppogl::Vec2d(1.0, 1.0); qprevprev->t3.y() = MAX(int(qprevprev->t3.y()+0.5), int(qprevprev->t1.y()+1)); qprevprev->t4.y() = MAX(int(qprevprev->t3.y()+0.5), int(qprevprev->t1.y()+1)); } last_mark_time = -99999; last_mark_pos = ppogl::Vec3d(-9999, -9999, -9999); continuing_track = false; } void TrackMarks::update() { if(PPConfig.getBool("track_marks") == false) { return; } ppogl::Vec3d width_vector; ppogl::Vec3d left_vector; ppogl::Vec3d right_vector; float magnitude; TrackQuad *q, *qprev, *qprevprev; ppogl::Vec3d vel; float speed; ppogl::Vec3d left_wing, right_wing; float left_y, right_y; float dist_from_surface; pp::Plane surf_plane; float comp_depth; float tex_end; float terrain_weights[NUM_TERRAIN_TYPES]; float dist_from_last_mark; ppogl::Vec3d vector_from_last_mark; bool break_marks; float terrain_compression=0; float old_terrain_weight=0; unsigned int i; q = &quads[current_mark%MAX_TRACK_MARKS]; qprev = &quads[(current_mark-1)%MAX_TRACK_MARKS]; qprevprev = &quads[(current_mark-2)%MAX_TRACK_MARKS]; vector_from_last_mark = player->pos - last_mark_pos; dist_from_last_mark = vector_from_last_mark.normalize(); get_surface_type(player->pos.x(), player->pos.z(), terrain_weights); break_marks=true; for (i=0;i= 0.5) { if (old_terrain_weight < terrain_weights[i]) { break_marks=false; terrain_compression = get_compression_depth(i); q->terrain=i; old_terrain_weight = terrain_weights[i]; } } } } if (break_marks==true){ discontinue(); return; } vel = player->vel; speed = vel.normalize(); if (speed < SPEED_TO_START_TRENCH) { discontinue(); return; } width_vector = player->direction^ppogl::Vec3d( 0, 1, 0 ); magnitude = width_vector.normalize(); if ( magnitude == 0 ) { discontinue(); return; } left_vector = (TRACK_WIDTH/2.0)*width_vector; right_vector = (-TRACK_WIDTH/2.0)*width_vector; left_wing = player->pos - left_vector; right_wing = player->pos - right_vector; left_y = find_y_coord( left_wing.x(), left_wing.z() ); right_y = find_y_coord( right_wing.x(), right_wing.z() ); if (fabs(left_y-right_y) > MAX_TRACK_DEPTH) { discontinue(); return; } surf_plane = get_local_course_plane( player->pos ); dist_from_surface = surf_plane.distance( player->pos ); comp_depth = terrain_compression; if ( dist_from_surface >= (2*comp_depth) ) { discontinue(); return; } if (!continuing_track) { discontinue(); q->track_type = TRACK_HEAD; q->v1 = ppogl::Vec3d( left_wing.x(), left_y + TRACK_HEIGHT, left_wing.z() ); q->v2 = ppogl::Vec3d( right_wing.x(), right_y + TRACK_HEIGHT, right_wing.z() ); q->n1 = find_course_normal( q->v1.x(), q->v1.z()); q->n2 = find_course_normal( q->v2.x(), q->v2.z()); q->t1 = ppogl::Vec2d(0.0, 0.0); q->t2 = ppogl::Vec2d(1.0, 0.0); next_mark = current_mark + 1; } else { if ( next_mark == current_mark ) { q->v1 = qprev->v3; q->v2 = qprev->v4; q->n1 = qprev->n3; q->n2 = qprev->n4; q->t1 = qprev->t3; q->t2 = qprev->t4; if ( qprev->track_type != TRACK_HEAD ) { qprev->track_type = TRACK_MARK; } q->track_type = TRACK_MARK; } q->v3 = ppogl::Vec3d( left_wing.x(), left_y + TRACK_HEIGHT, left_wing.z() ); q->v4 = ppogl::Vec3d( right_wing.x(), right_y + TRACK_HEIGHT, right_wing.z() ); q->n3 = find_course_normal( q->v3.x(), q->v3.z()); q->n4 = find_course_normal( q->v4.x(), q->v4.z()); tex_end = speed*GameMgr::getInstance().getTimeStep()/TRACK_WIDTH; if (q->track_type == TRACK_HEAD) { q->t3= ppogl::Vec2d(0.0, 1.0); q->t4= ppogl::Vec2d(1.0, 1.0); } else { q->t3 = ppogl::Vec2d(0.0, q->t1.y() + tex_end); q->t4 = ppogl::Vec2d(1.0, q->t2.y() + tex_end); } current_mark++; next_mark = current_mark; } q->alpha = MIN( (2*comp_depth-dist_from_surface)/(4*comp_depth), 1.0 ); last_mark_time = GameMgr::getInstance().time; continuing_track = true; } void TrackMarks::init() { for(int i=0; i