1) Fixed 'rescue bug', i.e. karts have now a proper

heading after being rescued
2) Partly fixed 'automatic rescue' bug: karts get
   rescued when touching a reset material (though it
   currently can take a bit before it happens).
3) Restructured code: track loading and converting
   is now done in the track object.
4) Fixed several warnings for windows.
   


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@1345 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2007-12-12 14:07:26 +00:00
parent d8dac4e85b
commit d0c1aa9e8c
11 changed files with 453 additions and 412 deletions

View File

@ -394,7 +394,6 @@ void Kart::reset()
world->m_track->spatialToTrack( m_curr_track_coords, m_curr_pos.xyz, world->m_track->spatialToTrack( m_curr_track_coords, m_curr_pos.xyz,
m_track_sector ); m_track_sector );
#ifdef BULLET
btTransform trans; btTransform trans;
trans.setIdentity(); trans.setIdentity();
// Set heading: // Set heading:
@ -414,7 +413,6 @@ void Kart::reset()
m_vehicle->updateWheelTransform(j, true); m_vehicle->updateWheelTransform(j, true);
} }
#endif
placeModel(); placeModel();
} // reset } // reset
@ -711,20 +709,15 @@ void Kart::update (float dt)
{ {
// Let the kart raise 2m in the 2 seconds of the rescue // Let the kart raise 2m in the 2 seconds of the rescue
const float rescue_time = 2.0f; const float rescue_time = 2.0f;
#ifdef BULLET
const float rescue_height = 2.0f; const float rescue_height = 2.0f;
#endif
if(m_attachment.getType() != ATTACH_TINYTUX) if(m_attachment.getType() != ATTACH_TINYTUX)
{ {
if(isPlayerKart()) sound_manager -> playSfx ( SOUND_BZZT ); if(isPlayerKart()) sound_manager -> playSfx ( SOUND_BZZT );
m_attachment.set( ATTACH_TINYTUX, rescue_time ) ; m_attachment.set( ATTACH_TINYTUX, rescue_time ) ;
#ifdef BULLET
m_rescue_pitch = m_curr_pos.hpr[1]; m_rescue_pitch = m_curr_pos.hpr[1];
m_rescue_roll = m_curr_pos.hpr[2]; m_rescue_roll = m_curr_pos.hpr[2];
world->getPhysics()->removeKart(this); world->getPhysics()->removeKart(this);
#endif
} }
#ifdef BULLET
m_curr_pos.xyz[2] += rescue_height*dt/rescue_time; m_curr_pos.xyz[2] += rescue_height*dt/rescue_time;
btTransform pos=m_body->getCenterOfMassTransform(); btTransform pos=m_body->getCenterOfMassTransform();
@ -735,13 +728,8 @@ void Kart::update (float dt)
-m_rescue_pitch*dt/rescue_time*M_PI/180.0f); -m_rescue_pitch*dt/rescue_time*M_PI/180.0f);
pos.setRotation(pos.getRotation()*q_roll*q_pitch); pos.setRotation(pos.getRotation()*q_roll*q_pitch);
m_body->setCenterOfMassTransform(pos); m_body->setCenterOfMassTransform(pos);
setTrans(pos); setTrans(pos);
//printf("Set %f %f %f\n",pos.getOrigin().x(),pos.getOrigin().y(),pos.getOrigin().z()); //printf("Set %f %f %f\n",pos.getOrigin().x(),pos.getOrigin().y(),pos.getOrigin().z());
#else
sgZeroVec3 ( m_velocity.xyz ) ;
sgZeroVec3 ( m_velocity.hpr ) ;
m_velocity.xyz[2] = 1.1f * GRAVITY * dt *10.0f;
#endif
} // if m_rescue } // if m_rescue
m_attachment.update(dt, &m_velocity); m_attachment.update(dt, &m_velocity);
@ -1058,7 +1046,7 @@ void Kart::endRescue()
world ->m_track -> trackToSpatial ( m_curr_pos.xyz, m_track_sector ) ; world ->m_track -> trackToSpatial ( m_curr_pos.xyz, m_track_sector ) ;
m_curr_pos.hpr[0] = world->m_track->m_angle[m_track_sector] ; m_curr_pos.hpr[0] = world->m_track->m_angle[m_track_sector] ;
m_rescue = false ; m_rescue = false ;
#ifdef BULLET
world->getPhysics()->addKart(this, m_vehicle); world->getPhysics()->addKart(this, m_vehicle);
m_body->setLinearVelocity (btVector3(0.0f,0.0f,0.0f)); m_body->setLinearVelocity (btVector3(0.0f,0.0f,0.0f));
m_body->setAngularVelocity(btVector3(0.0f,0.0f,0.0f)); m_body->setAngularVelocity(btVector3(0.0f,0.0f,0.0f));
@ -1070,10 +1058,10 @@ void Kart::endRescue()
btTransform pos=m_body->getCenterOfMassTransform(); btTransform pos=m_body->getCenterOfMassTransform();
pos.setOrigin(btVector3(m_curr_pos.xyz[0],m_curr_pos.xyz[1], pos.setOrigin(btVector3(m_curr_pos.xyz[0],m_curr_pos.xyz[1],
m_curr_pos.xyz[2]+0.5f*m_kart_height)); m_curr_pos.xyz[2]+0.5f*m_kart_height));
pos.setRotation(btQuaternion(btVector3(0.0f, 0.0f, 1.0f),
DEGREE_TO_RAD(world->m_track->m_angle[m_track_sector])));
m_body->setCenterOfMassTransform(pos); m_body->setCenterOfMassTransform(pos);
setTrans(pos); setTrans(pos);
#endif
} // endRescue } // endRescue

View File

@ -60,20 +60,20 @@ public:
int matches ( char *tx ) ; int matches ( char *tx ) ;
bool isIgnore () { return m_ignore ; } ssgSimpleState
bool isZipper () { return m_zipper ; } *getState () const { return m_state ; }
bool isSphereMap () { return m_sphere_map ; } bool isIgnore () const { return m_ignore; }
bool isCrashable () { return m_collideable ; } bool isZipper () const { return m_zipper; }
bool isReset () { return m_resetter ; } bool isSphereMap () const { return m_sphere_map; }
float getFriction() { return m_friction ; } bool isCrashable () const { return m_collideable; }
bool isReset () const { return m_resetter; }
float getFriction () const { return m_friction; }
char *getTexFname () const { return m_texname; }
int getIndex () const { return m_index; }
void apply () { m_state -> apply (); }
void applyToLeaf ( ssgLeaf *l ) ; void applyToLeaf ( ssgLeaf *l ) ;
ssgSimpleState *getState () { return m_state ; }
int getIndex () { return m_index ; }
void apply () { m_state -> apply () ; }
char *getTexFname () const { return m_texname ; }
} ; } ;

View File

@ -240,6 +240,7 @@ void Moveable::ReadHistory(char* s, int kartNumber, int indx)
#define max(m,n) ((m)>(n) ? (m) : (n)) /* return highest number */ #define max(m,n) ((m)>(n) ? (m) : (n)) /* return highest number */
#ifndef BULLET
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
float Moveable::collectIsectData ( sgVec3 start, sgVec3 end ) float Moveable::collectIsectData ( sgVec3 start, sgVec3 end )
{ {
@ -371,3 +372,4 @@ float Moveable::getIsectData ( sgVec3 start, sgVec3 end )
return HOT ; return HOT ;
} // getIsectData } // getIsectData
#endif

View File

@ -56,14 +56,13 @@ protected:
int m_crashed; int m_crashed;
sgVec3 m_surface_avoidance_vector ; sgVec3 m_surface_avoidance_vector ;
int m_first_time ; int m_first_time ;
#ifndef BULLET
float collectIsectData ( sgVec3 start, sgVec3 end ) ; float collectIsectData ( sgVec3 start, sgVec3 end ) ;
#endif
sgCoord* m_history_velocity; sgCoord* m_history_velocity;
sgCoord* m_history_position; sgCoord* m_history_position;
#ifdef BULLET
btRigidBody* m_body; btRigidBody* m_body;
btDefaultMotionState* m_motion_state; btDefaultMotionState* m_motion_state;
#endif
public: public:
@ -94,8 +93,9 @@ public:
// there is a 'reset' material under the moveable --> karts need to be // there is a 'reset' material under the moveable --> karts need to be
// rescued, missiles should explode. // rescued, missiles should explode.
virtual void OutsideTrack (int isReset) {} virtual void OutsideTrack (int isReset) {}
#ifndef BULLET
float getIsectData (sgVec3 start, sgVec3 end ); float getIsectData (sgVec3 start, sgVec3 end );
#endif
void WriteHistory (char* s, int kartNumber, int indx); void WriteHistory (char* s, int kartNumber, int indx);
void ReadHistory (char* s, int kartNumber, int indx); void ReadHistory (char* s, int kartNumber, int indx);
btRigidBody* getBody () const {return m_body; } btRigidBody* getBody () const {return m_body; }

View File

@ -18,8 +18,6 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifdef BULLET
#include "bullet/Demos/OpenGL/GL_ShapeDrawer.h" #include "bullet/Demos/OpenGL/GL_ShapeDrawer.h"
#include "physics.hpp" #include "physics.hpp"
@ -34,10 +32,22 @@
/** Initialise physics. */ /** Initialise physics. */
// ----------------------------------------------------------------------------
// Handling of triangle specific friction and special attributes (e.g. reset,
// zipper).
extern ContactAddedCallback gContactAddedCallback;
bool HandleTerrainFriction(btManifoldPoint& cp,
const btCollisionObject* colObj0,int partId0,int index0,
const btCollisionObject* colObj1,int partId1,int index1);
// ----------------------------------------------------------------------------
float const Physics::NOHIT=-99999.9f; float const Physics::NOHIT=-99999.9f;
Physics::Physics(float gravity) : btSequentialImpulseConstraintSolver() Physics::Physics(float gravity) : btSequentialImpulseConstraintSolver()
{ {
// Set the contact handler for friction computation (and reset triggering)
gContactAddedCallback = HandleTerrainFriction;
m_collision_conf = new btDefaultCollisionConfiguration(); m_collision_conf = new btDefaultCollisionConfiguration();
m_dispatcher = new btCollisionDispatcher(m_collision_conf); m_dispatcher = new btCollisionDispatcher(m_collision_conf);
@ -68,90 +78,6 @@ Physics::~Physics()
} // ~Physics } // ~Physics
// -----------------------------------------------------------------------------
//* Convert the ssg track tree into its physics equivalents.
void Physics::setTrack(ssgEntity* track)
{
if(!track) return;
sgMat4 mat;
sgMakeIdentMat4(mat);
btTriangleMesh *track_mesh = new btTriangleMesh();
// Collect all triangles in the track_mesh
convertTrack(track, mat, track_mesh);
// Now convert the triangle mesh into a static rigid body
btCollisionShape *mesh_shape = new btBvhTriangleMeshShape(track_mesh, true);
btTransform startTransform;
startTransform.setIdentity();
btDefaultMotionState *myMotionState = new btDefaultMotionState(startTransform);
btRigidBody *body=new btRigidBody(0.0f, myMotionState, mesh_shape);
// FIXME: can the mesh_shape and or track_mesh be deleted now?
m_dynamics_world->addRigidBody(body);
body->setUserPointer(0);
} // setTrack
// -----------------------------------------------------------------------------
//* Convert the ssg track tree into its physics equivalents.
void Physics::convertTrack(ssgEntity *track, sgMat4 m, btTriangleMesh* track_mesh)
{
if(!track) return;
MovingPhysics *mp = dynamic_cast<MovingPhysics*>(track);
if(mp)
{
// If the track contains obect of type MovingPhysics,
// these objects will be real rigid body and are already
// part of the world. So these objects must not be converted
// to triangle meshes.
}
else if(track->isAKindOf(ssgTypeLeaf()))
{
ssgLeaf *leaf = (ssgLeaf*)(track);
Material *mat = material_manager->getMaterial(leaf);
// Don't convert triangles with material that is ignored (e.g. fuzzy_sand)
if(!mat || mat->isIgnore()) return;
for(int i=0; i<leaf->getNumTriangles(); i++)
{
short v1,v2,v3;
sgVec3 vv1, vv2, vv3;
leaf->getTriangle(i, &v1, &v2, &v3);
sgXformPnt3 ( vv1, leaf->getVertex(v1), m );
sgXformPnt3 ( vv2, leaf->getVertex(v2), m );
sgXformPnt3 ( vv3, leaf->getVertex(v3), m );
btVector3 vb1(vv1[0],vv1[1],vv1[2]);
btVector3 vb2(vv2[0],vv2[1],vv2[2]);
btVector3 vb3(vv3[0],vv3[1],vv3[2]);
track_mesh->addTriangle(vb1, vb2, vb3);
}
} // if(track isAKindOf leaf)
else if(track->isAKindOf(ssgTypeTransform()))
{
ssgBaseTransform *t = (ssgBaseTransform*)(track);
sgMat4 tmpT, tmpM;
t->getTransform(tmpT);
sgCopyMat4(tmpM, m);
sgPreMultMat4(tmpM,tmpT);
for(ssgEntity *e = t->getKid(0); e!=NULL; e=t->getNextKid())
{
convertTrack(e, tmpM, track_mesh);
} // for i
}
else if (track->isAKindOf(ssgTypeBranch()))
{
ssgBranch *b =(ssgBranch*)track;
for(ssgEntity* e=b->getKid(0); e!=NULL; e=b->getNextKid()) {
convertTrack(e, m, track_mesh);
} // for i<getNumKids
}
else
{
assert(!"Unkown ssg type in convertTrack");
}
} // convertTrack
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
//* Adds a kart to the physics engine //* Adds a kart to the physics engine
void Physics::addKart(const Kart *kart, btRaycastVehicle *vehicle) void Physics::addKart(const Kart *kart, btRaycastVehicle *vehicle)
@ -357,15 +283,26 @@ float Physics::getHAT(btVector3 pos)
{ {
btVector3 to_pos(pos); btVector3 to_pos(pos);
to_pos.setZ(-100000.f); to_pos.setZ(-100000.f);
btCollisionWorld::ClosestRayResultCallback btCollisionWorld::ClosestRayResultCallback rayCallback(pos, to_pos);
rayCallback(pos, to_pos);
m_dynamics_world->rayTest(pos, to_pos, rayCallback); m_dynamics_world->rayTest(pos, to_pos, rayCallback);
if(!rayCallback.HasHit()) return NOHIT; if(!rayCallback.HasHit()) return NOHIT;
return pos.getZ()-rayCallback.m_hitPointWorld.getZ(); return pos.getZ()-rayCallback.m_hitPointWorld.getZ();
} // getHAT } // getHAT
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
float Physics::getHOT(btVector3 pos)
{
btVector3 to_pos(pos);
to_pos.setZ(-100000.f);
btCollisionWorld::ClosestRayResultCallback rayCallback(pos, to_pos);
m_dynamics_world->rayTest(pos, to_pos, rayCallback);
if(!rayCallback.HasHit()) return NOHIT;
return rayCallback.m_hitPointWorld.getZ();
} // getHOT
// -----------------------------------------------------------------------------
bool Physics::getTerrainNormal(btVector3 pos, btVector3* normal) bool Physics::getTerrainNormal(btVector3 pos, btVector3* normal)
{ {
btVector3 to_pos(pos); btVector3 to_pos(pos);
@ -380,6 +317,36 @@ bool Physics::getTerrainNormal(btVector3 pos, btVector3* normal)
return true; return true;
} // getTerrainNormal } // getTerrainNormal
// -----------------------------------------------------------------------------
bool HandleTerrainFriction(btManifoldPoint& cp,
const btCollisionObject* colObj0,int partId0,int index0,
const btCollisionObject* colObj1,int partId1,int index1)
{
const btCollisionObject* obj0 = static_cast<const btCollisionObject*>(colObj0);
const btCollisionObject* obj1 = static_cast<const btCollisionObject*>(colObj1);
Moveable *mov0 = static_cast<Moveable*>(obj0->getUserPointer());
Moveable *mov1 = static_cast<Moveable*>(obj1->getUserPointer());
// make sure that indeed one of the two objects is the track, i.e. has no user pointer
assert(mov0==0 || mov1==0);
Moveable *other;
other = (mov0==0) ? mov1 : mov0; // get the non-track object.
// This can happen when moving_physics objects exist
if(!other) return false;
int indx = (mov0==0) ? index0 : index1; // get the track index
// Don't do anything if a projectile (or any other non-kart object) hit sthe track
if(other->getMoveableType()!=Moveable::MOV_KART) return false;
const Material *mat= Track::getMaterial(indx);
if(mat->isReset())
{
((Kart*)other)->forceRescue();
}
cp.m_combinedFriction = mat->getFriction();
return true;
} // CustomTriangleHandler
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
//* //*
void Physics::draw() void Physics::draw()
@ -415,6 +382,5 @@ void Physics::debugDraw(float m[16], btCollisionShape *s, const btVector3 color)
} // debugDraw } // debugDraw
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#endif
/* EOF */ /* EOF */

View File

@ -85,7 +85,6 @@ private:
void KartKartCollision(Kart *ka, Kart *kb); void KartKartCollision(Kart *ka, Kart *kb);
public: public:
void convertTrack (ssgEntity *track, sgMat4 m, btTriangleMesh* track_mesh);
Physics (float gravity); Physics (float gravity);
~Physics (); ~Physics ();
void addKart (const Kart *k, btRaycastVehicle *v); void addKart (const Kart *k, btRaycastVehicle *v);
@ -94,12 +93,12 @@ public:
void removeBody (btRigidBody* b) {m_dynamics_world->removeRigidBody(b);} void removeBody (btRigidBody* b) {m_dynamics_world->removeRigidBody(b);}
void update (float dt); void update (float dt);
void draw (); void draw ();
void setTrack (ssgEntity *track);
btDynamicsWorld* btDynamicsWorld*
getPhysicsWorld () const {return m_dynamics_world;} getPhysicsWorld () const {return m_dynamics_world;}
void debugDraw (float m[16], btCollisionShape *s, const btVector3 color); void debugDraw (float m[16], btCollisionShape *s, const btVector3 color);
static const float NOHIT; static const float NOHIT;
float getHAT (btVector3 pos); float getHAT (btVector3 pos);
float getHOT (btVector3 pos);
bool getTerrainNormal(btVector3 pos, btVector3* normal); bool getTerrainNormal(btVector3 pos, btVector3* normal);
virtual btScalar solveGroup(btCollisionObject** bodies, int numBodies, virtual btScalar solveGroup(btCollisionObject** bodies, int numBodies,
btPersistentManifold** manifold,int numManifolds, btPersistentManifold** manifold,int numManifolds,

View File

@ -56,22 +56,22 @@ void PlayerKart::action(KartAction action, int value)
case KA_BRAKE: case KA_BRAKE:
if (value) if (value)
m_accel_val = 0; m_accel_val = 0;
m_controls.brake = value; m_controls.brake = (value!=0); // This syntax avoid visual c++ warning (when brake=value)
break; break;
case KA_WHEELIE: case KA_WHEELIE:
m_controls.wheelie = value; m_controls.wheelie = (value!=0);
break; break;
case KA_RESCUE: case KA_RESCUE:
m_controls.rescue = value; m_controls.rescue = (value!=0);
break; break;
case KA_FIRE: case KA_FIRE:
m_controls.fire = value; m_controls.fire = (value!=0);
break; break;
case KA_LOOK_BACK: case KA_LOOK_BACK:
m_camera->setReverseHeading(value); m_camera->setReverseHeading(value!=0);
break; break;
case KA_JUMP: case KA_JUMP:
m_controls.jump = value; m_controls.jump = (value!=0);
break; break;
} }
} }

View File

@ -29,10 +29,21 @@
#include "stk_config.hpp" #include "stk_config.hpp"
#include "translation.hpp" #include "translation.hpp"
#include "scene.hpp" #include "scene.hpp"
#include "moving_physics.hpp"
#include "world.hpp"
#include "material_manager.hpp"
#include "isect.hpp"
#include "ssg_help.hpp"
#include "user_config.hpp"
#include "herring.hpp"
#include "herring_manager.hpp"
#if defined(WIN32) && !defined(__CYGWIN__) #if defined(WIN32) && !defined(__CYGWIN__)
# define snprintf _snprintf # define snprintf _snprintf
#endif #endif
std::vector<const Material*>Track::m_triangleIndex2Material;
// ----------------------------------------------------------------------------
Track::Track( std::string filename_, float w, float h, bool stretch ) Track::Track( std::string filename_, float w, float h, bool stretch )
{ {
m_filename = filename_; m_filename = filename_;
@ -53,6 +64,15 @@ Track::Track( std::string filename_, float w, float h, bool stretch )
Track::~Track() Track::~Track()
{ {
} // ~Track } // ~Track
//-----------------------------------------------------------------------------
/** Removes the physical body from the world.
* Called at the end of a race.
*/
void Track::cleanup()
{
world->getPhysics()->removeBody(m_body);
delete m_body;
} // ~Track
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Finds on which side of the line segment a given point is. /** Finds on which side of the line segment a given point is.
@ -122,27 +142,27 @@ void Track::findRoadSector( const sgVec3 XYZ, int *sector )const
that forms each track segment. that forms each track segment.
*/ */
std::vector <SegmentTriangle> possible_segment_tris; std::vector <SegmentTriangle> possible_segment_tris;
const unsigned int DRIVELINE_SIZE = m_left_driveline.size(); const unsigned int DRIVELINE_SIZE = (unsigned int)m_left_driveline.size();
int triangle; int triangle;
int next; int next;
for( size_t i = 0; i < DRIVELINE_SIZE ; ++i ) for( size_t i = 0; i < DRIVELINE_SIZE ; ++i )
{ {
next = i + 1 < DRIVELINE_SIZE ? i + 1 : 0; next = (unsigned int)i + 1 < DRIVELINE_SIZE ? (int)i + 1 : 0;
triangle = pointInQuad( m_left_driveline[i], m_right_driveline[i], triangle = pointInQuad( m_left_driveline[i], m_right_driveline[i],
m_right_driveline[next], m_left_driveline[next], m_right_driveline[next], m_left_driveline[next],
XYZ ); XYZ );
if (triangle != QUAD_TRI_NONE && ((XYZ[2]-m_left_driveline[i][2]) < 1.0f)) if (triangle != QUAD_TRI_NONE && ((XYZ[2]-m_left_driveline[i][2]) < 1.0f))
{ {
possible_segment_tris.push_back(SegmentTriangle(i, triangle)); possible_segment_tris.push_back(SegmentTriangle((int)i, triangle));
} }
} }
/* Since xyz can be on more than one 2D track segment, we have to /* Since xyz can be on more than one 2D track segment, we have to
find on top of which one of the possible track segments it is. find on top of which one of the possible track segments it is.
*/ */
const int POS_SEG_SIZE = possible_segment_tris.size(); const int POS_SEG_SIZE = (int)possible_segment_tris.size();
if( POS_SEG_SIZE == 0 ) if( POS_SEG_SIZE == 0 )
{ {
//xyz is not on the road //xyz is not on the road
@ -164,7 +184,7 @@ void Track::findRoadSector( const sgVec3 XYZ, int *sector )const
for( int i = 0; i < POS_SEG_SIZE; ++i ) for( int i = 0; i < POS_SEG_SIZE; ++i )
{ {
segment = possible_segment_tris[i].segment; segment = possible_segment_tris[i].segment;
next = segment + 1 < DRIVELINE_SIZE ? segment + 1 : 0; next = segment + 1 < DRIVELINE_SIZE ? (int)segment + 1 : 0;
if( possible_segment_tris[i].triangle == QUAD_TRI_FIRST ) if( possible_segment_tris[i].triangle == QUAD_TRI_FIRST )
{ {
@ -242,7 +262,7 @@ int Track::findOutOfRoadSector
int sector = UNKNOWN_SECTOR; int sector = UNKNOWN_SECTOR;
float dist; float dist;
float nearest_dist = 99999; float nearest_dist = 99999;
const unsigned int DRIVELINE_SIZE = m_left_driveline.size(); const unsigned int DRIVELINE_SIZE = (unsigned int)m_left_driveline.size();
int begin_sector = 0; int begin_sector = 0;
int end_sector = DRIVELINE_SIZE - 1; int end_sector = DRIVELINE_SIZE - 1;
@ -324,7 +344,7 @@ int Track::spatialToTrack
return -1; return -1;
} }
const unsigned int DRIVELINE_SIZE = m_driveline.size(); const unsigned int DRIVELINE_SIZE = (unsigned int)m_driveline.size();
const size_t PREV = SECTOR == 0 ? DRIVELINE_SIZE - 1 : SECTOR - 1; const size_t PREV = SECTOR == 0 ? DRIVELINE_SIZE - 1 : SECTOR - 1;
const size_t NEXT = (size_t)SECTOR+1 >= DRIVELINE_SIZE ? 0 : SECTOR + 1; const size_t NEXT = (size_t)SECTOR+1 >= DRIVELINE_SIZE ? 0 : SECTOR + 1;
@ -361,7 +381,7 @@ int Track::spatialToTrack
/ (m_distance_from_start[p2]-m_distance_from_start[p1]); / (m_distance_from_start[p2]-m_distance_from_start[p1]);
dst[2] = m_path_width[p1]*(1-fraction)+fraction*m_path_width[p2]; dst[2] = m_path_width[p1]*(1-fraction)+fraction*m_path_width[p2];
return p1; return (int)p1;
} // spatialToTrack } // spatialToTrack
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -370,11 +390,6 @@ void Track::trackToSpatial ( sgVec3 xyz, const int SECTOR ) const
sgCopyVec3 ( xyz, m_driveline [ SECTOR ] ) ; sgCopyVec3 ( xyz, m_driveline [ SECTOR ] ) ;
} // trackToSpatial } // trackToSpatial
//-----------------------------------------------------------------------------
void Track::createHash(ssgEntity* track_branch, unsigned int n) {
m_static_ssg = new StaticSSG(track_branch, n);
} // createHash
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Returns the start coordinates for a kart on a given position pos /** Returns the start coordinates for a kart on a given position pos
(with 0<=pos). (with 0<=pos).
@ -385,7 +400,7 @@ void Track::getStartCoords(unsigned int pos, sgCoord* coords) const {
// This kart would not get any lap counting done in the first // This kart would not get any lap counting done in the first
// lap! Therefor -1.5 is subtracted from the y position - which // lap! Therefor -1.5 is subtracted from the y position - which
// is a somewhat arbitrary value. // is a somewhat arbitrary value.
coords->xyz[0] = pos<m_start_x.size() ? m_start_x[pos] : ((pos%2==0)?1.5:-1.5f); coords->xyz[0] = pos<m_start_x.size() ? m_start_x[pos] : ((pos%2==0)?1.5f:-1.5f);
coords->xyz[1] = pos<m_start_y.size() ? m_start_y[pos] : -1.5f*pos-1.5f; coords->xyz[1] = pos<m_start_y.size() ? m_start_y[pos] : -1.5f*pos-1.5f;
// height must be larger than the actual hight for which hot is computed. // height must be larger than the actual hight for which hot is computed.
coords->xyz[2] = pos<m_start_z.size() ? m_start_z[pos] : 1.0f; coords->xyz[2] = pos<m_start_z.size() ? m_start_z[pos] : 1.0f;
@ -394,10 +409,8 @@ void Track::getStartCoords(unsigned int pos, sgCoord* coords) const {
coords->hpr[1] = 0.0f; coords->hpr[1] = 0.0f;
coords->hpr[2] = 0.0f; coords->hpr[2] = 0.0f;
ssgLeaf *leaf; btVector3 tmp_pos(coords->xyz[0],coords->xyz[1],coords->xyz[2]);
sgVec4* normal; coords->xyz[2] = world->getPhysics()->getHOT(tmp_pos);
const float hot = m_static_ssg->hot(coords->xyz, coords->xyz, &leaf, &normal);
coords->xyz[2] = hot;
} // getStartCoords } // getStartCoords
@ -413,8 +426,8 @@ bool Track::isShortcut(const int OLDSEC, const int NEWSEC) const
unsigned int distance_sectors = abs(OLDSEC-NEWSEC); unsigned int distance_sectors = abs(OLDSEC-NEWSEC);
// Handle 'wrap around': if the distance is more than half the // Handle 'wrap around': if the distance is more than half the
// number of driveline poins, assume it's a 'wrap around' // number of driveline poins, assume it's a 'wrap around'
if(2*distance_sectors > m_driveline.size()) if(2*distance_sectors > (unsigned int)m_driveline.size())
distance_sectors = m_driveline.size() - distance_sectors; distance_sectors = (unsigned int)m_driveline.size() - distance_sectors;
return (distance_sectors>stk_config->m_shortcut_segments); return (distance_sectors>stk_config->m_shortcut_segments);
} // isShortcut } // isShortcut
@ -507,7 +520,7 @@ void Track::drawScaled2D(float x, float y, float w, float h) const
sy = sx; sy = sx;
} }
const unsigned int DRIVELINE_SIZE = m_driveline.size(); const unsigned int DRIVELINE_SIZE = (unsigned int)m_driveline.size();
glPushAttrib ( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_LINE_BIT ); glPushAttrib ( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_LINE_BIT );
@ -621,7 +634,7 @@ void Track::drawScaled2D(float x, float y, float w, float h) const
void Track::draw2Dview (float x_offset, float y_offset) const void Track::draw2Dview (float x_offset, float y_offset) const
{ {
const unsigned int DRIVELINE_SIZE = m_driveline.size(); const unsigned int DRIVELINE_SIZE = (unsigned int)m_driveline.size();
glPushAttrib ( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_LINE_BIT ); glPushAttrib ( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_LINE_BIT );
@ -757,12 +770,12 @@ void Track::loadTrack(std::string filename_)
m_fog_end = 1000.0f; m_fog_end = 1000.0f;
m_gravity = 9.80665f; m_gravity = 9.80665f;
sgSetVec3 ( m_sun_position, 0.4f, 0.4f, 0.4f ); sgSetVec3 ( m_sun_position, 0.4f, 0.4f, 0.4f );
sgSetVec4 ( m_sky_color , 0.3f, 0.7f, 0.9f, 1.0f ); sgSetVec4 ( m_sky_color, 0.3f, 0.7f, 0.9f, 1.0f );
sgSetVec4 ( m_fog_color , 0.3f, 0.7f, 0.9f, 1.0f ); sgSetVec4 ( m_fog_color, 0.3f, 0.7f, 0.9f, 1.0f );
sgSetVec4 ( m_ambient_col , 0.5f, 0.5f, 0.5f, 1.0f ); sgSetVec4 ( m_ambient_col, 0.5f, 0.5f, 0.5f, 1.0f );
sgSetVec4 ( m_specular_col, 1.0f, 1.0f, 1.0f, 1.0f ); sgSetVec4 ( m_specular_col, 1.0f, 1.0f, 1.0f, 1.0f );
sgSetVec4 ( m_diffuse_col , 1.0f, 1.0f, 1.0f, 1.0f ); sgSetVec4 ( m_diffuse_col, 1.0f, 1.0f, 1.0f, 1.0f );
lisp::Parser parser; lisp::Parser parser;
const lisp::Lisp* const ROOT = parser.parse(loader->getPath(m_filename)); const lisp::Lisp* const ROOT = parser.parse(loader->getPath(m_filename));
@ -815,7 +828,7 @@ Track::loadDriveline()
{ {
readDrivelineFromFile(m_left_driveline, ".drvl"); readDrivelineFromFile(m_left_driveline, ".drvl");
const unsigned int DRIVELINE_SIZE = m_left_driveline.size(); const unsigned int DRIVELINE_SIZE = (unsigned int)m_left_driveline.size();
m_right_driveline.reserve(DRIVELINE_SIZE); m_right_driveline.reserve(DRIVELINE_SIZE);
readDrivelineFromFile(m_right_driveline, ".drvr"); readDrivelineFromFile(m_right_driveline, ".drvr");
@ -970,5 +983,276 @@ Track::readDrivelineFromFile(std::vector<sgVec3Wrapper>& line, const std::string
} }
fclose ( fd ) ; fclose ( fd ) ;
} } // readDrivelineFromFile
// -----------------------------------------------------------------------------
//* Convert the ssg track tree into its physics equivalents.
void Track::createPhysicsModel()
{
if(!m_model) return;
sgMat4 mat;
sgMakeIdentMat4(mat);
btTriangleMesh *track_mesh = new btTriangleMesh();
m_triangleIndex2Material.clear();
// Collect all triangles in the track_mesh
convertTrackToBullet(m_model, mat, track_mesh);
// Now convert the triangle mesh into a static rigid body
btCollisionShape *mesh_shape = new btBvhTriangleMeshShape(track_mesh, true);
btTransform startTransform;
startTransform.setIdentity();
btDefaultMotionState *myMotionState = new btDefaultMotionState(startTransform);
m_body=new btRigidBody(0.0f, myMotionState, mesh_shape);
// FIXME: can the mesh_shape and or track_mesh be deleted now?
world->getPhysics()->addBody(m_body);
m_body->setUserPointer(0);
m_body->setCollisionFlags(m_body->getCollisionFlags() |
btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
} // createPhysicsModel
// -----------------------------------------------------------------------------
//* Convert the ssg track tree into its physics equivalents.
void Track::convertTrackToBullet(ssgEntity *track, sgMat4 m, btTriangleMesh* track_mesh)
{
if(!track) return;
MovingPhysics *mp = dynamic_cast<MovingPhysics*>(track);
if(mp)
{
// If the track contains obect of type MovingPhysics,
// these objects will be real rigid body and are already
// part of the world. So these objects must not be converted
// to triangle meshes.
}
else if(track->isAKindOf(ssgTypeLeaf()))
{
ssgLeaf *leaf = (ssgLeaf*)(track);
Material *mat = material_manager->getMaterial(leaf);
// Don't convert triangles with material that is ignored (e.g. fuzzy_sand)
if(!mat || mat->isIgnore()) return;
for(int i=0; i<leaf->getNumTriangles(); i++)
{
short v1,v2,v3;
sgVec3 vv1, vv2, vv3;
leaf->getTriangle(i, &v1, &v2, &v3);
sgXformPnt3 ( vv1, leaf->getVertex(v1), m );
sgXformPnt3 ( vv2, leaf->getVertex(v2), m );
sgXformPnt3 ( vv3, leaf->getVertex(v3), m );
btVector3 vb1(vv1[0],vv1[1],vv1[2]);
btVector3 vb2(vv2[0],vv2[1],vv2[2]);
btVector3 vb3(vv3[0],vv3[1],vv3[2]);
track_mesh->addTriangle(vb1, vb2, vb3);
m_triangleIndex2Material.push_back(mat);
}
} // if(track isAKindOf leaf)
else if(track->isAKindOf(ssgTypeTransform()))
{
ssgBaseTransform *t = (ssgBaseTransform*)(track);
sgMat4 tmpT, tmpM;
t->getTransform(tmpT);
sgCopyMat4(tmpM, m);
sgPreMultMat4(tmpM,tmpT);
for(ssgEntity *e = t->getKid(0); e!=NULL; e=t->getNextKid())
{
convertTrackToBullet(e, tmpM, track_mesh);
} // for i
}
else if (track->isAKindOf(ssgTypeBranch()))
{
ssgBranch *b =(ssgBranch*)track;
for(ssgEntity* e=b->getKid(0); e!=NULL; e=b->getNextKid()) {
convertTrackToBullet(e, m, track_mesh);
} // for i<getNumKids
}
else
{
assert(!"Unkown ssg type in convertTrackToBullet");
}
} // convertTrackToBullet
// ----------------------------------------------------------------------------
void Track::loadTrackModel()
{
std::string path = "data/";
path += getIdent();
path += ".loc";
path = loader->getPath(path.c_str());
FILE *fd = fopen (path.c_str(), "r" );
if ( fd == NULL )
{
char msg[MAX_ERROR_MESSAGE_LENGTH];
snprintf(msg, sizeof(msg),"Can't open track location file '%s'.\n",
path.c_str());
throw std::runtime_error(msg);
}
// Start building the scene graph
m_model = new ssgBranch ;
scene->add(m_model);
char s [ 1024 ] ;
while ( fgets ( s, 1023, fd ) != NULL )
{
if ( *s == '#' || *s < ' ' )
continue ;
int need_hat = false ;
int fit_skin = false ;
char fname [ 1024 ] ;
sgCoord loc ;
sgZeroVec3 ( loc.xyz ) ;
sgZeroVec3 ( loc.hpr ) ;
char htype = '\0' ;
if ( sscanf ( s, "%cHERRING,%f,%f,%f", &htype,
&(loc.xyz[0]), &(loc.xyz[1]), &(loc.xyz[2]) ) == 4 )
{
herring_command(&loc.xyz, htype, false) ;
}
else if ( sscanf ( s, "%cHERRING,%f,%f", &htype,
&(loc.xyz[0]), &(loc.xyz[1]) ) == 3 )
{
herring_command (&loc.xyz, htype, true) ;
}
else if ( s[0] == '\"' )
{
if ( sscanf ( s, "\"%[^\"]\",%f,%f,%f,%f,%f,%f",
fname, &(loc.xyz[0]), &(loc.xyz[1]), &(loc.xyz[2]),
&(loc.hpr[0]), &(loc.hpr[1]), &(loc.hpr[2]) ) == 7 )
{
/* All 6 DOF specified */
need_hat = false;
}
else if ( sscanf ( s, "\"%[^\"]\",%f,%f,{},%f,%f,%f",
fname, &(loc.xyz[0]), &(loc.xyz[1]),
&(loc.hpr[0]), &(loc.hpr[1]), &(loc.hpr[2])) == 6 )
{
/* All 6 DOF specified - but need height */
need_hat = true ;
}
else if ( sscanf ( s, "\"%[^\"]\",%f,%f,%f,%f",
fname, &(loc.xyz[0]), &(loc.xyz[1]), &(loc.xyz[2]),
&(loc.hpr[0]) ) == 5 )
{
/* No Roll/Pitch specified - assumed zero */
need_hat = false ;
}
else if ( sscanf ( s, "\"%[^\"]\",%f,%f,{},%f,{},{}",
fname, &(loc.xyz[0]), &(loc.xyz[1]),
&(loc.hpr[0]) ) == 3 )
{
/* All 6 DOF specified - but need height, roll, pitch */
need_hat = true ;
fit_skin = true ;
}
else if ( sscanf ( s, "\"%[^\"]\",%f,%f,{},%f",
fname, &(loc.xyz[0]), &(loc.xyz[1]),
&(loc.hpr[0]) ) == 4 )
{
/* No Roll/Pitch specified - but need height */
need_hat = true ;
}
else if ( sscanf ( s, "\"%[^\"]\",%f,%f,%f",
fname, &(loc.xyz[0]), &(loc.xyz[1]),
&(loc.xyz[2]) ) == 4 )
{
/* No Heading/Roll/Pitch specified - but need height */
need_hat = false ;
}
else if ( sscanf ( s, "\"%[^\"]\",%f,%f,{}",
fname, &(loc.xyz[0]), &(loc.xyz[1]) ) == 3 )
{
/* No Roll/Pitch specified - but need height */
need_hat = true ;
}
else if ( sscanf ( s, "\"%[^\"]\",%f,%f",
fname, &(loc.xyz[0]), &(loc.xyz[1]) ) == 3 )
{
/* No Z/Heading/Roll/Pitch specified */
need_hat = false ;
}
else if ( sscanf ( s, "\"%[^\"]\"", fname ) == 1 )
{
/* Nothing specified */
need_hat = false ;
}
else
{
fclose(fd);
char msg[MAX_ERROR_MESSAGE_LENGTH];
snprintf(msg, sizeof(msg), "Syntax error in '%s': %s",
path.c_str(), s);
throw std::runtime_error(msg);
}
if ( need_hat )
{
sgVec3 nrm ;
loc.xyz[2] = 1000.0f ;
loc.xyz[2] = getHeightAndNormal ( m_model, loc.xyz, nrm ) ;
if ( fit_skin )
{
float sy = sin ( -loc.hpr [ 0 ] * SG_DEGREES_TO_RADIANS ) ;
float cy = cos ( -loc.hpr [ 0 ] * SG_DEGREES_TO_RADIANS ) ;
loc.hpr[2] = SG_RADIANS_TO_DEGREES * atan2 ( nrm[0] * cy -
nrm[1] * sy, nrm[2] ) ;
loc.hpr[1] = -SG_RADIANS_TO_DEGREES * atan2 ( nrm[1] * cy +
nrm[0] * sy, nrm[2] ) ;
}
} // if need_hat
ssgEntity *obj = loader->load(fname, CB_TRACK);
createDisplayLists(obj);
ssgRangeSelector *lod = new ssgRangeSelector ;
ssgTransform *trans = new ssgTransform ( & loc ) ;
float r [ 2 ] = { -10.0f, 2000.0f } ;
lod -> addKid(obj );
trans -> addKid(lod );
m_model-> addKid(trans );
lod -> setRanges(r, 2);
if(user_config->m_track_debug)
addDebugToScene(user_config->m_track_debug);
}
else
{
// fclose(fd);
// char msg[MAX_ERROR_MESSAGE_LENGTH];
// snprintf(msg, sizeof(msg), "Syntax error in '%s': %s",
fprintf(stderr, "Warning: Syntax error in '%s': %s",
path.c_str(), s);
// throw std::runtime_error(msg);
}
} // while fgets
fclose ( fd ) ;
createPhysicsModel();
} // loadTrack
//-----------------------------------------------------------------------------
void Track::herring_command (sgVec3 *xyz, char htype, int bNeedHeight )
{
// if only 2d coordinates are given, let the herring fall from very heigh
if(bNeedHeight) (*xyz)[2] = 1000000.0f;
// Even if 3d data are given, make sure that the herring is on the ground
(*xyz)[2] = getHeight ( m_model, *xyz ) + 0.06f;
herringType type=HE_GREEN;
if ( htype=='Y' || htype=='y' ) { type = HE_GOLD ;}
if ( htype=='G' || htype=='g' ) { type = HE_GREEN ;}
if ( htype=='R' || htype=='r' ) { type = HE_RED ;}
if ( htype=='S' || htype=='s' ) { type = HE_SILVER ;}
herring_manager->newHerring(type, xyz);
} // herring_command

View File

@ -33,21 +33,24 @@
#include <plib/ssg.h> #include <plib/ssg.h>
#include <string> #include <string>
#include <vector> #include <vector>
#include "static_ssg.hpp" #include "btBulletDynamicsCommon.h"
#include "material.hpp"
class Track class Track
{ {
private: private:
float m_gravity; float m_gravity;
std::string m_ident; std::string m_ident;
std::string m_screenshot; std::string m_screenshot;
std::string m_top_view; std::string m_top_view;
std::vector<std::string> m_music_filenames; std::vector<std::string> m_music_filenames;
std::vector<float> m_start_x, m_start_y, m_start_z, m_start_heading; std::vector<float> m_start_x, m_start_y, m_start_z, m_start_heading;
std::string m_herring_style; std::string m_herring_style;
std::string m_description; std::string m_description;
std::string m_filename; std::string m_filename;
StaticSSG* m_static_ssg; ssgBranch* m_model;
btRigidBody* m_body;
static std::vector<const Material*> m_triangleIndex2Material;
public: public:
enum RoadSide{ RS_DONT_KNOW = -1, RS_LEFT = 0, RS_RIGHT = 1 }; enum RoadSide{ RS_DONT_KNOW = -1, RS_LEFT = 0, RS_RIGHT = 1 };
@ -136,7 +139,7 @@ public:
Track (std::string filename,float w=100, Track (std::string filename,float w=100,
float h=100, bool stretch=1); float h=100, bool stretch=1);
~Track (); ~Track ();
void cleanup ();
void addDebugToScene (int type ) const; void addDebugToScene (int type ) const;
void draw2Dview (float x_offset, void draw2Dview (float x_offset,
float y_offset ) const; float y_offset ) const;
@ -152,36 +155,34 @@ public:
const sgVec2 POS, const sgVec2 POS,
const int SECTOR ) const; const int SECTOR ) const;
void trackToSpatial (sgVec3 xyz, const int SECTOR) const; void trackToSpatial (sgVec3 xyz, const int SECTOR) const;
ssgBranch* getModel () const {return m_model;}
void loadTrackModel ();
bool isShortcut (const int OLDSEC, const int NEWSEC) const; bool isShortcut (const int OLDSEC, const int NEWSEC) const;
float getGravity () const {return m_gravity; } float getGravity () const {return m_gravity; }
float getTrackLength () const {return m_total_distance;} float getTrackLength () const {return m_total_distance; }
const char* getIdent () const {return m_ident.c_str(); } const char* getIdent () const {return m_ident.c_str(); }
const char* getName () const {return m_name.c_str(); } const char* getName () const {return m_name.c_str(); }
const std::string& getMusic () const; const std::string& getMusic () const;
const std::string& getFilename () const {return m_filename; } const std::string& getFilename () const {return m_filename; }
const sgVec3& getSunPos () const {return m_sun_position; } const sgVec3& getSunPos () const {return m_sun_position; }
const sgVec4& getAmbientCol () const {return m_ambient_col; } const sgVec4& getAmbientCol () const {return m_ambient_col; }
const sgVec4& getDiffuseCol () const {return m_diffuse_col; } const sgVec4& getDiffuseCol () const {return m_diffuse_col; }
const sgVec4& getSpecularCol () const {return m_specular_col; } const sgVec4& getSpecularCol () const {return m_specular_col; }
const bool& useFog () const {return m_use_fog; } const bool& useFog () const {return m_use_fog; }
const sgVec4& getFogColor () const {return m_fog_color; } const sgVec4& getFogColor () const {return m_fog_color; }
const float& getFogDensity () const {return m_fog_density; } const float& getFogDensity () const {return m_fog_density; }
const float& getFogStart () const {return m_fog_start; } const float& getFogStart () const {return m_fog_start; }
const float& getFogEnd () const {return m_fog_end; } const float& getFogEnd () const {return m_fog_end; }
const sgVec4& getSkyColor () const {return m_sky_color; } const sgVec4& getSkyColor () const {return m_sky_color; }
const std::string& getDescription () const {return m_description; } const std::string& getDescription () const {return m_description; }
const std::string& getTopviewFile () const {return m_top_view; } const std::string& getTopviewFile () const {return m_top_view; }
const std::string& getScreenshotFile() const {return m_screenshot; } const std::string& getScreenshotFile() const {return m_screenshot; }
const std::vector<sgVec3Wrapper>& getDriveline () const {return m_driveline;} const std::vector<sgVec3Wrapper>& getDriveline () const {return m_driveline;}
const std::vector<SGfloat>& getWidth() const {return m_path_width; } const std::vector<SGfloat>& getWidth() const {return m_path_width; }
const std::string& getHerringStyle () const {return m_herring_style; } const std::string& getHerringStyle () const {return m_herring_style; }
void createHash (ssgEntity* track_branch, unsigned int n);
void getStartCoords (unsigned int pos, sgCoord* coords) const; void getStartCoords (unsigned int pos, sgCoord* coords) const;
int Collision(sgSphere* s, AllHits *a) const static const Material* getMaterial (unsigned int n) {return m_triangleIndex2Material[n];}
{return m_static_ssg->collision(s,a); } void createPhysicsModel ();
float GetHOT(sgVec3 start, sgVec3 end,
ssgLeaf** l, sgVec4** nrm) const
{return m_static_ssg->hot(start, end, l, nrm);}
void glVtx (sgVec2 v, float x_offset, float y_offset) const void glVtx (sgVec2 v, float x_offset, float y_offset) const
{ {
glVertex2f( glVertex2f(
@ -191,9 +192,12 @@ public:
private: private:
void loadTrack (std::string filename); void loadTrack (std::string filename);
void herring_command (sgVec3 *xyz, char htype, int bNeedHeight);
void loadDriveline (); void loadDriveline ();
void readDrivelineFromFile (std::vector<sgVec3Wrapper>& line, void readDrivelineFromFile (std::vector<sgVec3Wrapper>& line,
const std::string& file_ext ); const std::string& file_ext );
void convertTrackToBullet (ssgEntity *track, sgMat4 m,
btTriangleMesh* track_mesh);
float pointSideToLine( const sgVec2 L1, const sgVec2 L2, float pointSideToLine( const sgVec2 L1, const sgVec2 L2,
const sgVec2 P ) const; const sgVec2 P ) const;

View File

@ -37,7 +37,6 @@
#include "loader.hpp" #include "loader.hpp"
#include "player_kart.hpp" #include "player_kart.hpp"
#include "auto_kart.hpp" #include "auto_kart.hpp"
#include "isect.hpp"
#include "track.hpp" #include "track.hpp"
#include "kart_properties_manager.hpp" #include "kart_properties_manager.hpp"
#include "track_manager.hpp" #include "track_manager.hpp"
@ -47,7 +46,6 @@
#include "history.hpp" #include "history.hpp"
#include "constants.hpp" #include "constants.hpp"
#include "sound_manager.hpp" #include "sound_manager.hpp"
#include "ssg_help.hpp"
#include "translation.hpp" #include "translation.hpp"
#include "highscore_manager.hpp" #include "highscore_manager.hpp"
#include "scene.hpp" #include "scene.hpp"
@ -93,10 +91,6 @@ World::World(const RaceSetup& raceSetup_) : m_race_setup(raceSetup_)
throw std::runtime_error(msg); throw std::runtime_error(msg);
} }
// Start building the scene graph
m_track_branch = new ssgBranch ;
scene->add ( m_track_branch ) ;
// Create the physics // Create the physics
m_physics = new Physics(getGravity()); m_physics = new Physics(getGravity());
@ -104,9 +98,7 @@ World::World(const RaceSetup& raceSetup_) : m_race_setup(raceSetup_)
// Load the track models - this must be done before the karts so that the // Load the track models - this must be done before the karts so that the
// karts can be positioned properly on (and not in) the tracks. // karts can be positioned properly on (and not in) the tracks.
loadTrack ( ) ; loadTrack() ;
m_track->createHash(m_track_branch, 1000);
int pos = 0; int pos = 0;
int playerIndex = 0; int playerIndex = 0;
@ -164,7 +156,7 @@ World::World(const RaceSetup& raceSetup_) : m_race_setup(raceSetup_)
? Highscores::HST_TIMETRIAL_OVERALL_TIME ? Highscores::HST_TIMETRIAL_OVERALL_TIME
: Highscores::HST_RACE_OVERALL_TIME; : Highscores::HST_RACE_OVERALL_TIME;
m_highscores = highscore_manager->getHighscores(hst, m_kart.size(), m_highscores = highscore_manager->getHighscores(hst, (int)m_kart.size(),
m_race_setup.m_difficulty, m_race_setup.m_difficulty,
m_track->getName(), m_track->getName(),
m_race_setup.m_num_laps); m_race_setup.m_num_laps);
@ -205,7 +197,7 @@ World::~World()
#ifdef HAVE_GHOST_REPLAY #ifdef HAVE_GHOST_REPLAY
saveReplayHumanReadable( "test" ); saveReplayHumanReadable( "test" );
#endif #endif
m_track->cleanup();
// Clear all callbacks // Clear all callbacks
callback_manager->clear(CB_TRACK); callback_manager->clear(CB_TRACK);
@ -275,16 +267,16 @@ void World::draw()
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void World::update(float delta) void World::update(float dt)
{ {
if(user_config->m_replay_history) delta=history->GetNextDelta(); if(user_config->m_replay_history) dt=history->GetNextDelta();
checkRaceStatus(); checkRaceStatus();
// this line was before checkRaceStatus. but m_clock is set to 0.0 in // this line was before checkRaceStatus. but m_clock is set to 0.0 in
// checkRaceStatus on start, so m_clock would not be synchron and the // checkRaceStatus on start, so m_clock would not be synchron and the
// first delta would not be added .. that would cause a gap in // first delta would not be added .. that would cause a gap in
// replay-recording // replay-recording
m_clock += delta; m_clock += dt;
// Count the number of collision in the next 'FRAMES_FOR_TRAFFIC_JAM' frames. // Count the number of collision in the next 'FRAMES_FOR_TRAFFIC_JAM' frames.
// If a kart has more than one hit, play 'traffic jam' noise. // If a kart has more than one hit, play 'traffic jam' noise.
@ -311,8 +303,8 @@ void World::update(float delta)
// Don't record the time for the last kart, since it didn't finish // Don't record the time for the last kart, since it didn't finish
// the race - unless it's timetrial (then there is only one kart) // the race - unless it's timetrial (then there is only one kart)
unsigned int karts_to_enter = (m_race_setup.m_mode==RaceSetup::RM_TIME_TRIAL) unsigned int karts_to_enter = (m_race_setup.m_mode==RaceSetup::RM_TIME_TRIAL)
? m_kart.size() : m_kart.size()-1; ? (unsigned int)m_kart.size() : (unsigned int)m_kart.size()-1;
for(unsigned int pos=0; pos<karts_to_enter; pos++) for(unsigned int pos=0; pos<karts_to_enter; pos++)
{ {
// Only record times for player karts // Only record times for player karts
@ -323,7 +315,7 @@ void World::update(float delta)
Highscores::HighscoreType hst = (m_race_setup.m_mode==RaceSetup::RM_TIME_TRIAL) Highscores::HighscoreType hst = (m_race_setup.m_mode==RaceSetup::RM_TIME_TRIAL)
? Highscores::HST_TIMETRIAL_OVERALL_TIME ? Highscores::HST_TIMETRIAL_OVERALL_TIME
: Highscores::HST_RACE_OVERALL_TIME; : Highscores::HST_RACE_OVERALL_TIME;
if(m_highscores->addData(hst, m_kart.size(), if(m_highscores->addData(hst, (int)m_kart.size(),
m_race_setup.m_difficulty, m_race_setup.m_difficulty,
m_track->getName(), m_track->getName(),
k->getName(), k->getName(),
@ -338,35 +330,15 @@ void World::update(float delta)
pause(); pause();
menu_manager->pushMenu(MENUID_RACERESULT); menu_manager->pushMenu(MENUID_RACERESULT);
} }
if(!user_config->m_replay_history) history->StoreDelta(dt);
float inc = 0.05f; m_physics->update(dt);
float dt = delta; for ( Karts::size_type i = 0 ; i < m_kart.size(); ++i)
while (dt>0.0)
{ {
if(dt>=inc) m_kart[i]->update(dt) ;
{ }
dt-=inc;
if(user_config->m_replay_history) delta=history->GetNextDelta();
}
else
{
inc=dt;
dt=0.0;
}
// The same delta is stored over and over again! This helps to use
// the same index in History:allDeltas, and the history* arrays here,
// and makes writing easier, since we had to write delta the first
// time, and then inc from then on.
if(!user_config->m_replay_history) history->StoreDelta(delta);
m_physics->update(inc);
for ( Karts::size_type i = 0 ; i < m_kart.size(); ++i)
{
m_kart[i]->update(inc) ;
}
} // while dt>0
projectile_manager->update(delta); projectile_manager->update(dt);
herring_manager->update(delta); herring_manager->update(dt);
for ( Karts::size_type i = 0 ; i < m_kart.size(); ++i) for ( Karts::size_type i = 0 ; i < m_kart.size(); ++i)
{ {
@ -375,7 +347,7 @@ void World::update(float delta)
} }
/* Routine stuff we do even when paused */ /* Routine stuff we do even when paused */
callback_manager->update(delta); callback_manager->update(dt);
// Check for traffic jam. The sound is played even if it's // Check for traffic jam. The sound is played even if it's
// not a player kart - a traffic jam happens rarely anyway. // not a player kart - a traffic jam happens rarely anyway.
@ -621,23 +593,6 @@ void World::updateRacePosition ( int k )
m_kart [ k ] -> setPosition ( p ) ; m_kart [ k ] -> setPosition ( p ) ;
} // updateRacePosition } // updateRacePosition
//-----------------------------------------------------------------------------
void World::herring_command (sgVec3 *xyz, char htype, int bNeedHeight )
{
// if only 2d coordinates are given, let the herring fall from very heigh
if(bNeedHeight) (*xyz)[2] = 1000000.0f;
// Even if 3d data are given, make sure that the herring is on the ground
(*xyz)[2] = getHeight ( m_track_branch, *xyz ) + 0.06f;
herringType type=HE_GREEN;
if ( htype=='Y' || htype=='y' ) { type = HE_GOLD ;}
if ( htype=='G' || htype=='g' ) { type = HE_GREEN ;}
if ( htype=='R' || htype=='r' ) { type = HE_RED ;}
if ( htype=='S' || htype=='s' ) { type = HE_SILVER ;}
herring_manager->newHerring(type, xyz);
} // herring_command
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void World::loadTrack() void World::loadTrack()
@ -680,161 +635,7 @@ void World::loadTrack()
} }
} }
FILE *fd = fopen (path.c_str(), "r" ); m_track->loadTrackModel();
if ( fd == NULL )
{
char msg[MAX_ERROR_MESSAGE_LENGTH];
snprintf(msg, sizeof(msg),"Can't open track location file '%s'.\n",
path.c_str());
throw std::runtime_error(msg);
}
char s [ 1024 ] ;
while ( fgets ( s, 1023, fd ) != NULL )
{
if ( *s == '#' || *s < ' ' )
continue ;
int need_hat = false ;
int fit_skin = false ;
char fname [ 1024 ] ;
sgCoord loc ;
sgZeroVec3 ( loc.xyz ) ;
sgZeroVec3 ( loc.hpr ) ;
char htype = '\0' ;
if ( sscanf ( s, "%cHERRING,%f,%f,%f", &htype,
&(loc.xyz[0]), &(loc.xyz[1]), &(loc.xyz[2]) ) == 4 )
{
herring_command(&loc.xyz, htype, false) ;
}
else if ( sscanf ( s, "%cHERRING,%f,%f", &htype,
&(loc.xyz[0]), &(loc.xyz[1]) ) == 3 )
{
herring_command (&loc.xyz, htype, true) ;
}
else if ( s[0] == '\"' )
{
if ( sscanf ( s, "\"%[^\"]\",%f,%f,%f,%f,%f,%f",
fname, &(loc.xyz[0]), &(loc.xyz[1]), &(loc.xyz[2]),
&(loc.hpr[0]), &(loc.hpr[1]), &(loc.hpr[2]) ) == 7 )
{
/* All 6 DOF specified */
need_hat = false;
}
else if ( sscanf ( s, "\"%[^\"]\",%f,%f,{},%f,%f,%f",
fname, &(loc.xyz[0]), &(loc.xyz[1]),
&(loc.hpr[0]), &(loc.hpr[1]), &(loc.hpr[2])) == 6 )
{
/* All 6 DOF specified - but need height */
need_hat = true ;
}
else if ( sscanf ( s, "\"%[^\"]\",%f,%f,%f,%f",
fname, &(loc.xyz[0]), &(loc.xyz[1]), &(loc.xyz[2]),
&(loc.hpr[0]) ) == 5 )
{
/* No Roll/Pitch specified - assumed zero */
need_hat = false ;
}
else if ( sscanf ( s, "\"%[^\"]\",%f,%f,{},%f,{},{}",
fname, &(loc.xyz[0]), &(loc.xyz[1]),
&(loc.hpr[0]) ) == 3 )
{
/* All 6 DOF specified - but need height, roll, pitch */
need_hat = true ;
fit_skin = true ;
}
else if ( sscanf ( s, "\"%[^\"]\",%f,%f,{},%f",
fname, &(loc.xyz[0]), &(loc.xyz[1]),
&(loc.hpr[0]) ) == 4 )
{
/* No Roll/Pitch specified - but need height */
need_hat = true ;
}
else if ( sscanf ( s, "\"%[^\"]\",%f,%f,%f",
fname, &(loc.xyz[0]), &(loc.xyz[1]),
&(loc.xyz[2]) ) == 4 )
{
/* No Heading/Roll/Pitch specified - but need height */
need_hat = false ;
}
else if ( sscanf ( s, "\"%[^\"]\",%f,%f,{}",
fname, &(loc.xyz[0]), &(loc.xyz[1]) ) == 3 )
{
/* No Roll/Pitch specified - but need height */
need_hat = true ;
}
else if ( sscanf ( s, "\"%[^\"]\",%f,%f",
fname, &(loc.xyz[0]), &(loc.xyz[1]) ) == 3 )
{
/* No Z/Heading/Roll/Pitch specified */
need_hat = false ;
}
else if ( sscanf ( s, "\"%[^\"]\"", fname ) == 1 )
{
/* Nothing specified */
need_hat = false ;
}
else
{
fclose(fd);
char msg[MAX_ERROR_MESSAGE_LENGTH];
snprintf(msg, sizeof(msg), "Syntax error in '%s': %s",
path.c_str(), s);
throw std::runtime_error(msg);
}
if ( need_hat )
{
sgVec3 nrm ;
loc.xyz[2] = 1000.0f ;
loc.xyz[2] = getHeightAndNormal ( m_track_branch, loc.xyz, nrm ) ;
if ( fit_skin )
{
float sy = sin ( -loc.hpr [ 0 ] * SG_DEGREES_TO_RADIANS ) ;
float cy = cos ( -loc.hpr [ 0 ] * SG_DEGREES_TO_RADIANS ) ;
loc.hpr[2] = SG_RADIANS_TO_DEGREES * atan2 ( nrm[0] * cy -
nrm[1] * sy, nrm[2] ) ;
loc.hpr[1] = -SG_RADIANS_TO_DEGREES * atan2 ( nrm[1] * cy +
nrm[0] * sy, nrm[2] ) ;
}
} // if need_hat
ssgEntity *obj = loader->load(fname, CB_TRACK);
createDisplayLists(obj);
ssgRangeSelector *lod = new ssgRangeSelector ;
ssgTransform *trans = new ssgTransform ( & loc ) ;
float r [ 2 ] = { -10.0f, 2000.0f } ;
lod -> addKid ( obj ) ;
trans -> addKid ( lod ) ;
m_track_branch -> addKid ( trans ) ;
lod -> setRanges ( r, 2 ) ;
if(user_config->m_track_debug)
m_track->addDebugToScene(user_config->m_track_debug);
}
else
{
// fclose(fd);
// char msg[MAX_ERROR_MESSAGE_LENGTH];
// snprintf(msg, sizeof(msg), "Syntax error in '%s': %s",
fprintf(stderr, "Warning: Syntax error in '%s': %s",
path.c_str(), s);
// throw std::runtime_error(msg);
}
} // while fgets
fclose ( fd ) ;
#ifdef BULLET
m_physics->setTrack(m_track_branch);
#endif
} // loadTrack } // loadTrack
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@ -68,15 +68,13 @@ public:
/** debug text that will be overlaid to the screen */ /** debug text that will be overlaid to the screen */
std::string m_debug_text[10]; std::string m_debug_text[10];
/** Reference to the track inside the scene */
ssgBranch *m_track_branch ;
World(const RaceSetup& raceSetup); World(const RaceSetup& raceSetup);
virtual ~World(); virtual ~World();
#ifndef BULLET
float GetHOT(sgVec3 start, sgVec3 end, ssgLeaf** leaf, sgVec4** nrm) float GetHOT(sgVec3 start, sgVec3 end, ssgLeaf** leaf, sgVec4** nrm)
{return m_track->GetHOT(start, end, leaf, nrm);} {return m_track->GetHOT(start, end, leaf, nrm);}
int Collision(sgSphere* s, AllHits *a) const {return m_track->Collision(s,a); } int Collision(sgSphere* s, AllHits *a) const {return m_track->Collision(s,a); }
#endif
void draw(); void draw();
void update(float delta); void update(float delta);
void restartRace(); void restartRace();
@ -124,7 +122,6 @@ private:
void updateRacePosition( int k ); void updateRacePosition( int k );
void loadTrack(); void loadTrack();
void herring_command(sgVec3* loc, char htype, int bNeedHeight);
void checkRaceStatus(); void checkRaceStatus();
void resetAllKarts(); void resetAllKarts();
Kart* loadRobot(const KartProperties *kart_properties, int position, Kart* loadRobot(const KartProperties *kart_properties, int position,