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:
parent
d8dac4e85b
commit
d0c1aa9e8c
22
src/kart.cpp
22
src/kart.cpp
@ -394,7 +394,6 @@ void Kart::reset()
|
||||
world->m_track->spatialToTrack( m_curr_track_coords, m_curr_pos.xyz,
|
||||
m_track_sector );
|
||||
|
||||
#ifdef BULLET
|
||||
btTransform trans;
|
||||
trans.setIdentity();
|
||||
// Set heading:
|
||||
@ -414,7 +413,6 @@ void Kart::reset()
|
||||
m_vehicle->updateWheelTransform(j, true);
|
||||
}
|
||||
|
||||
#endif
|
||||
placeModel();
|
||||
} // reset
|
||||
|
||||
@ -711,20 +709,15 @@ void Kart::update (float dt)
|
||||
{
|
||||
// Let the kart raise 2m in the 2 seconds of the rescue
|
||||
const float rescue_time = 2.0f;
|
||||
#ifdef BULLET
|
||||
const float rescue_height = 2.0f;
|
||||
#endif
|
||||
if(m_attachment.getType() != ATTACH_TINYTUX)
|
||||
{
|
||||
if(isPlayerKart()) sound_manager -> playSfx ( SOUND_BZZT );
|
||||
m_attachment.set( ATTACH_TINYTUX, rescue_time ) ;
|
||||
#ifdef BULLET
|
||||
m_rescue_pitch = m_curr_pos.hpr[1];
|
||||
m_rescue_roll = m_curr_pos.hpr[2];
|
||||
world->getPhysics()->removeKart(this);
|
||||
#endif
|
||||
}
|
||||
#ifdef BULLET
|
||||
m_curr_pos.xyz[2] += rescue_height*dt/rescue_time;
|
||||
|
||||
btTransform pos=m_body->getCenterOfMassTransform();
|
||||
@ -735,13 +728,8 @@ void Kart::update (float dt)
|
||||
-m_rescue_pitch*dt/rescue_time*M_PI/180.0f);
|
||||
pos.setRotation(pos.getRotation()*q_roll*q_pitch);
|
||||
m_body->setCenterOfMassTransform(pos);
|
||||
setTrans(pos);
|
||||
//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
|
||||
setTrans(pos);
|
||||
//printf("Set %f %f %f\n",pos.getOrigin().x(),pos.getOrigin().y(),pos.getOrigin().z());
|
||||
} // if m_rescue
|
||||
m_attachment.update(dt, &m_velocity);
|
||||
|
||||
@ -1058,7 +1046,7 @@ void Kart::endRescue()
|
||||
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_rescue = false ;
|
||||
#ifdef BULLET
|
||||
|
||||
world->getPhysics()->addKart(this, m_vehicle);
|
||||
m_body->setLinearVelocity (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();
|
||||
pos.setOrigin(btVector3(m_curr_pos.xyz[0],m_curr_pos.xyz[1],
|
||||
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);
|
||||
setTrans(pos);
|
||||
|
||||
#endif
|
||||
|
||||
} // endRescue
|
||||
|
||||
|
@ -60,20 +60,20 @@ public:
|
||||
|
||||
int matches ( char *tx ) ;
|
||||
|
||||
bool isIgnore () { return m_ignore ; }
|
||||
bool isZipper () { return m_zipper ; }
|
||||
bool isSphereMap () { return m_sphere_map ; }
|
||||
bool isCrashable () { return m_collideable ; }
|
||||
bool isReset () { return m_resetter ; }
|
||||
float getFriction() { return m_friction ; }
|
||||
ssgSimpleState
|
||||
*getState () const { return m_state ; }
|
||||
bool isIgnore () const { return m_ignore; }
|
||||
bool isZipper () const { return m_zipper; }
|
||||
bool isSphereMap () const { return m_sphere_map; }
|
||||
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 ) ;
|
||||
|
||||
ssgSimpleState *getState () { return m_state ; }
|
||||
int getIndex () { return m_index ; }
|
||||
void apply () { m_state -> apply () ; }
|
||||
|
||||
char *getTexFname () const { return m_texname ; }
|
||||
|
||||
} ;
|
||||
|
||||
|
@ -240,6 +240,7 @@ void Moveable::ReadHistory(char* s, int kartNumber, int indx)
|
||||
|
||||
#define max(m,n) ((m)>(n) ? (m) : (n)) /* return highest number */
|
||||
|
||||
#ifndef BULLET
|
||||
//-----------------------------------------------------------------------------
|
||||
float Moveable::collectIsectData ( sgVec3 start, sgVec3 end )
|
||||
{
|
||||
@ -371,3 +372,4 @@ float Moveable::getIsectData ( sgVec3 start, sgVec3 end )
|
||||
return HOT ;
|
||||
} // getIsectData
|
||||
|
||||
#endif
|
||||
|
@ -56,14 +56,13 @@ protected:
|
||||
int m_crashed;
|
||||
sgVec3 m_surface_avoidance_vector ;
|
||||
int m_first_time ;
|
||||
|
||||
#ifndef BULLET
|
||||
float collectIsectData ( sgVec3 start, sgVec3 end ) ;
|
||||
#endif
|
||||
sgCoord* m_history_velocity;
|
||||
sgCoord* m_history_position;
|
||||
#ifdef BULLET
|
||||
btRigidBody* m_body;
|
||||
btDefaultMotionState* m_motion_state;
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
@ -94,8 +93,9 @@ public:
|
||||
// there is a 'reset' material under the moveable --> karts need to be
|
||||
// rescued, missiles should explode.
|
||||
virtual void OutsideTrack (int isReset) {}
|
||||
|
||||
#ifndef BULLET
|
||||
float getIsectData (sgVec3 start, sgVec3 end );
|
||||
#endif
|
||||
void WriteHistory (char* s, int kartNumber, int indx);
|
||||
void ReadHistory (char* s, int kartNumber, int indx);
|
||||
btRigidBody* getBody () const {return m_body; }
|
||||
|
146
src/physics.cpp
146
src/physics.cpp
@ -18,8 +18,6 @@
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
#ifdef BULLET
|
||||
|
||||
#include "bullet/Demos/OpenGL/GL_ShapeDrawer.h"
|
||||
|
||||
#include "physics.hpp"
|
||||
@ -34,10 +32,22 @@
|
||||
|
||||
/** 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;
|
||||
|
||||
Physics::Physics(float gravity) : btSequentialImpulseConstraintSolver()
|
||||
{
|
||||
// Set the contact handler for friction computation (and reset triggering)
|
||||
gContactAddedCallback = HandleTerrainFriction;
|
||||
|
||||
m_collision_conf = new btDefaultCollisionConfiguration();
|
||||
m_dispatcher = new btCollisionDispatcher(m_collision_conf);
|
||||
|
||||
@ -68,90 +78,6 @@ 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
|
||||
void Physics::addKart(const Kart *kart, btRaycastVehicle *vehicle)
|
||||
@ -357,15 +283,26 @@ float Physics::getHAT(btVector3 pos)
|
||||
{
|
||||
btVector3 to_pos(pos);
|
||||
to_pos.setZ(-100000.f);
|
||||
btCollisionWorld::ClosestRayResultCallback
|
||||
rayCallback(pos, to_pos);
|
||||
|
||||
btCollisionWorld::ClosestRayResultCallback rayCallback(pos, to_pos);
|
||||
m_dynamics_world->rayTest(pos, to_pos, rayCallback);
|
||||
if(!rayCallback.HasHit()) return NOHIT;
|
||||
|
||||
return pos.getZ()-rayCallback.m_hitPointWorld.getZ();
|
||||
} // 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)
|
||||
{
|
||||
btVector3 to_pos(pos);
|
||||
@ -380,6 +317,36 @@ bool Physics::getTerrainNormal(btVector3 pos, btVector3* normal)
|
||||
return true;
|
||||
} // 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()
|
||||
@ -415,6 +382,5 @@ void Physics::debugDraw(float m[16], btCollisionShape *s, const btVector3 color)
|
||||
} // debugDraw
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#endif
|
||||
/* EOF */
|
||||
|
||||
|
@ -85,7 +85,6 @@ private:
|
||||
void KartKartCollision(Kart *ka, Kart *kb);
|
||||
|
||||
public:
|
||||
void convertTrack (ssgEntity *track, sgMat4 m, btTriangleMesh* track_mesh);
|
||||
Physics (float gravity);
|
||||
~Physics ();
|
||||
void addKart (const Kart *k, btRaycastVehicle *v);
|
||||
@ -94,12 +93,12 @@ public:
|
||||
void removeBody (btRigidBody* b) {m_dynamics_world->removeRigidBody(b);}
|
||||
void update (float dt);
|
||||
void draw ();
|
||||
void setTrack (ssgEntity *track);
|
||||
btDynamicsWorld*
|
||||
getPhysicsWorld () const {return m_dynamics_world;}
|
||||
void debugDraw (float m[16], btCollisionShape *s, const btVector3 color);
|
||||
static const float NOHIT;
|
||||
float getHAT (btVector3 pos);
|
||||
float getHOT (btVector3 pos);
|
||||
bool getTerrainNormal(btVector3 pos, btVector3* normal);
|
||||
virtual btScalar solveGroup(btCollisionObject** bodies, int numBodies,
|
||||
btPersistentManifold** manifold,int numManifolds,
|
||||
|
@ -56,22 +56,22 @@ void PlayerKart::action(KartAction action, int value)
|
||||
case KA_BRAKE:
|
||||
if (value)
|
||||
m_accel_val = 0;
|
||||
m_controls.brake = value;
|
||||
m_controls.brake = (value!=0); // This syntax avoid visual c++ warning (when brake=value)
|
||||
break;
|
||||
case KA_WHEELIE:
|
||||
m_controls.wheelie = value;
|
||||
m_controls.wheelie = (value!=0);
|
||||
break;
|
||||
case KA_RESCUE:
|
||||
m_controls.rescue = value;
|
||||
m_controls.rescue = (value!=0);
|
||||
break;
|
||||
case KA_FIRE:
|
||||
m_controls.fire = value;
|
||||
m_controls.fire = (value!=0);
|
||||
break;
|
||||
case KA_LOOK_BACK:
|
||||
m_camera->setReverseHeading(value);
|
||||
m_camera->setReverseHeading(value!=0);
|
||||
break;
|
||||
case KA_JUMP:
|
||||
m_controls.jump = value;
|
||||
m_controls.jump = (value!=0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
342
src/track.cpp
342
src/track.cpp
@ -29,10 +29,21 @@
|
||||
#include "stk_config.hpp"
|
||||
#include "translation.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__)
|
||||
# define snprintf _snprintf
|
||||
#endif
|
||||
std::vector<const Material*>Track::m_triangleIndex2Material;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
Track::Track( std::string filename_, float w, float h, bool stretch )
|
||||
{
|
||||
m_filename = filename_;
|
||||
@ -53,6 +64,15 @@ Track::Track( std::string filename_, float w, float h, bool stretch )
|
||||
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.
|
||||
@ -122,27 +142,27 @@ void Track::findRoadSector( const sgVec3 XYZ, int *sector )const
|
||||
that forms each track segment.
|
||||
*/
|
||||
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 next;
|
||||
|
||||
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],
|
||||
m_right_driveline[next], m_left_driveline[next],
|
||||
XYZ );
|
||||
|
||||
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
|
||||
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 )
|
||||
{
|
||||
//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 )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
@ -242,7 +262,7 @@ int Track::findOutOfRoadSector
|
||||
int sector = UNKNOWN_SECTOR;
|
||||
float dist;
|
||||
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 end_sector = DRIVELINE_SIZE - 1;
|
||||
@ -324,7 +344,7 @@ int Track::spatialToTrack
|
||||
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 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]);
|
||||
dst[2] = m_path_width[p1]*(1-fraction)+fraction*m_path_width[p2];
|
||||
|
||||
return p1;
|
||||
return (int)p1;
|
||||
} // spatialToTrack
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -370,11 +390,6 @@ void Track::trackToSpatial ( sgVec3 xyz, const int SECTOR ) const
|
||||
sgCopyVec3 ( xyz, m_driveline [ SECTOR ] ) ;
|
||||
} // 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
|
||||
(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
|
||||
// lap! Therefor -1.5 is subtracted from the y position - which
|
||||
// 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;
|
||||
// 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;
|
||||
@ -394,10 +409,8 @@ void Track::getStartCoords(unsigned int pos, sgCoord* coords) const {
|
||||
coords->hpr[1] = 0.0f;
|
||||
coords->hpr[2] = 0.0f;
|
||||
|
||||
ssgLeaf *leaf;
|
||||
sgVec4* normal;
|
||||
const float hot = m_static_ssg->hot(coords->xyz, coords->xyz, &leaf, &normal);
|
||||
coords->xyz[2] = hot;
|
||||
btVector3 tmp_pos(coords->xyz[0],coords->xyz[1],coords->xyz[2]);
|
||||
coords->xyz[2] = world->getPhysics()->getHOT(tmp_pos);
|
||||
|
||||
} // getStartCoords
|
||||
|
||||
@ -413,8 +426,8 @@ bool Track::isShortcut(const int OLDSEC, const int NEWSEC) const
|
||||
unsigned int distance_sectors = abs(OLDSEC-NEWSEC);
|
||||
// Handle 'wrap around': if the distance is more than half the
|
||||
// number of driveline poins, assume it's a 'wrap around'
|
||||
if(2*distance_sectors > m_driveline.size())
|
||||
distance_sectors = m_driveline.size() - distance_sectors;
|
||||
if(2*distance_sectors > (unsigned int)m_driveline.size())
|
||||
distance_sectors = (unsigned int)m_driveline.size() - distance_sectors;
|
||||
return (distance_sectors>stk_config->m_shortcut_segments);
|
||||
} // isShortcut
|
||||
|
||||
@ -507,7 +520,7 @@ void Track::drawScaled2D(float x, float y, float w, float h) const
|
||||
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 );
|
||||
|
||||
@ -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
|
||||
{
|
||||
|
||||
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 );
|
||||
|
||||
@ -757,12 +770,12 @@ void Track::loadTrack(std::string filename_)
|
||||
m_fog_end = 1000.0f;
|
||||
m_gravity = 9.80665f;
|
||||
|
||||
sgSetVec3 ( m_sun_position, 0.4f, 0.4f, 0.4f );
|
||||
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_ambient_col , 0.5f, 0.5f, 0.5f, 1.0f );
|
||||
sgSetVec3 ( m_sun_position, 0.4f, 0.4f, 0.4f );
|
||||
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_ambient_col, 0.5f, 0.5f, 0.5f, 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;
|
||||
const lisp::Lisp* const ROOT = parser.parse(loader->getPath(m_filename));
|
||||
@ -815,7 +828,7 @@ Track::loadDriveline()
|
||||
{
|
||||
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);
|
||||
readDrivelineFromFile(m_right_driveline, ".drvr");
|
||||
|
||||
@ -970,5 +983,276 @@ Track::readDrivelineFromFile(std::vector<sgVec3Wrapper>& line, const std::string
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -33,21 +33,24 @@
|
||||
#include <plib/ssg.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "static_ssg.hpp"
|
||||
#include "btBulletDynamicsCommon.h"
|
||||
#include "material.hpp"
|
||||
|
||||
class Track
|
||||
{
|
||||
private:
|
||||
float m_gravity;
|
||||
std::string m_ident;
|
||||
std::string m_screenshot;
|
||||
std::string m_top_view;
|
||||
float m_gravity;
|
||||
std::string m_ident;
|
||||
std::string m_screenshot;
|
||||
std::string m_top_view;
|
||||
std::vector<std::string> m_music_filenames;
|
||||
std::vector<float> m_start_x, m_start_y, m_start_z, m_start_heading;
|
||||
std::string m_herring_style;
|
||||
std::string m_description;
|
||||
std::string m_filename;
|
||||
StaticSSG* m_static_ssg;
|
||||
std::string m_herring_style;
|
||||
std::string m_description;
|
||||
std::string m_filename;
|
||||
ssgBranch* m_model;
|
||||
btRigidBody* m_body;
|
||||
static std::vector<const Material*> m_triangleIndex2Material;
|
||||
|
||||
public:
|
||||
enum RoadSide{ RS_DONT_KNOW = -1, RS_LEFT = 0, RS_RIGHT = 1 };
|
||||
@ -136,7 +139,7 @@ public:
|
||||
Track (std::string filename,float w=100,
|
||||
float h=100, bool stretch=1);
|
||||
~Track ();
|
||||
|
||||
void cleanup ();
|
||||
void addDebugToScene (int type ) const;
|
||||
void draw2Dview (float x_offset,
|
||||
float y_offset ) const;
|
||||
@ -152,36 +155,34 @@ public:
|
||||
const sgVec2 POS,
|
||||
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;
|
||||
float getGravity () const {return m_gravity; }
|
||||
float getTrackLength () const {return m_total_distance;}
|
||||
const char* getIdent () const {return m_ident.c_str(); }
|
||||
const char* getName () const {return m_name.c_str(); }
|
||||
float getGravity () const {return m_gravity; }
|
||||
float getTrackLength () const {return m_total_distance; }
|
||||
const char* getIdent () const {return m_ident.c_str(); }
|
||||
const char* getName () const {return m_name.c_str(); }
|
||||
const std::string& getMusic () const;
|
||||
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& getDiffuseCol () const {return m_diffuse_col; }
|
||||
const sgVec4& getSpecularCol () const {return m_specular_col; }
|
||||
const bool& useFog () const {return m_use_fog; }
|
||||
const sgVec4& getFogColor () const {return m_fog_color; }
|
||||
const float& getFogDensity () const {return m_fog_density; }
|
||||
const float& getFogStart () const {return m_fog_start; }
|
||||
const float& getFogEnd () const {return m_fog_end; }
|
||||
const sgVec4& getSkyColor () const {return m_sky_color; }
|
||||
const std::string& getDescription () const {return m_description; }
|
||||
const std::string& getTopviewFile () const {return m_top_view; }
|
||||
const std::string& getScreenshotFile() const {return m_screenshot; }
|
||||
const bool& useFog () const {return m_use_fog; }
|
||||
const sgVec4& getFogColor () const {return m_fog_color; }
|
||||
const float& getFogDensity () const {return m_fog_density; }
|
||||
const float& getFogStart () const {return m_fog_start; }
|
||||
const float& getFogEnd () const {return m_fog_end; }
|
||||
const sgVec4& getSkyColor () const {return m_sky_color; }
|
||||
const std::string& getDescription () const {return m_description; }
|
||||
const std::string& getTopviewFile () const {return m_top_view; }
|
||||
const std::string& getScreenshotFile() const {return m_screenshot; }
|
||||
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; }
|
||||
void createHash (ssgEntity* track_branch, unsigned int n);
|
||||
void getStartCoords (unsigned int pos, sgCoord* coords) const;
|
||||
int Collision(sgSphere* s, AllHits *a) const
|
||||
{return m_static_ssg->collision(s,a); }
|
||||
float GetHOT(sgVec3 start, sgVec3 end,
|
||||
ssgLeaf** l, sgVec4** nrm) const
|
||||
{return m_static_ssg->hot(start, end, l, nrm);}
|
||||
static const Material* getMaterial (unsigned int n) {return m_triangleIndex2Material[n];}
|
||||
void createPhysicsModel ();
|
||||
void glVtx (sgVec2 v, float x_offset, float y_offset) const
|
||||
{
|
||||
glVertex2f(
|
||||
@ -191,9 +192,12 @@ public:
|
||||
|
||||
private:
|
||||
void loadTrack (std::string filename);
|
||||
void herring_command (sgVec3 *xyz, char htype, int bNeedHeight);
|
||||
void loadDriveline ();
|
||||
void readDrivelineFromFile (std::vector<sgVec3Wrapper>& line,
|
||||
const std::string& file_ext );
|
||||
void convertTrackToBullet (ssgEntity *track, sgMat4 m,
|
||||
btTriangleMesh* track_mesh);
|
||||
|
||||
float pointSideToLine( const sgVec2 L1, const sgVec2 L2,
|
||||
const sgVec2 P ) const;
|
||||
|
235
src/world.cpp
235
src/world.cpp
@ -37,7 +37,6 @@
|
||||
#include "loader.hpp"
|
||||
#include "player_kart.hpp"
|
||||
#include "auto_kart.hpp"
|
||||
#include "isect.hpp"
|
||||
#include "track.hpp"
|
||||
#include "kart_properties_manager.hpp"
|
||||
#include "track_manager.hpp"
|
||||
@ -47,7 +46,6 @@
|
||||
#include "history.hpp"
|
||||
#include "constants.hpp"
|
||||
#include "sound_manager.hpp"
|
||||
#include "ssg_help.hpp"
|
||||
#include "translation.hpp"
|
||||
#include "highscore_manager.hpp"
|
||||
#include "scene.hpp"
|
||||
@ -93,10 +91,6 @@ World::World(const RaceSetup& raceSetup_) : m_race_setup(raceSetup_)
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
|
||||
// Start building the scene graph
|
||||
m_track_branch = new ssgBranch ;
|
||||
scene->add ( m_track_branch ) ;
|
||||
|
||||
// Create the physics
|
||||
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
|
||||
// karts can be positioned properly on (and not in) the tracks.
|
||||
loadTrack ( ) ;
|
||||
|
||||
m_track->createHash(m_track_branch, 1000);
|
||||
loadTrack() ;
|
||||
|
||||
int pos = 0;
|
||||
int playerIndex = 0;
|
||||
@ -164,7 +156,7 @@ World::World(const RaceSetup& raceSetup_) : m_race_setup(raceSetup_)
|
||||
? Highscores::HST_TIMETRIAL_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_track->getName(),
|
||||
m_race_setup.m_num_laps);
|
||||
@ -205,7 +197,7 @@ World::~World()
|
||||
#ifdef HAVE_GHOST_REPLAY
|
||||
saveReplayHumanReadable( "test" );
|
||||
#endif
|
||||
|
||||
m_track->cleanup();
|
||||
// Clear all callbacks
|
||||
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();
|
||||
// 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
|
||||
// first delta would not be added .. that would cause a gap in
|
||||
// replay-recording
|
||||
m_clock += delta;
|
||||
m_clock += dt;
|
||||
|
||||
// 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.
|
||||
@ -311,8 +303,8 @@ void World::update(float delta)
|
||||
|
||||
// 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)
|
||||
unsigned int karts_to_enter = (m_race_setup.m_mode==RaceSetup::RM_TIME_TRIAL)
|
||||
? m_kart.size() : m_kart.size()-1;
|
||||
unsigned int karts_to_enter = (m_race_setup.m_mode==RaceSetup::RM_TIME_TRIAL)
|
||||
? (unsigned int)m_kart.size() : (unsigned int)m_kart.size()-1;
|
||||
for(unsigned int pos=0; pos<karts_to_enter; pos++)
|
||||
{
|
||||
// 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::HST_TIMETRIAL_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_track->getName(),
|
||||
k->getName(),
|
||||
@ -338,35 +330,15 @@ void World::update(float delta)
|
||||
pause();
|
||||
menu_manager->pushMenu(MENUID_RACERESULT);
|
||||
}
|
||||
|
||||
float inc = 0.05f;
|
||||
float dt = delta;
|
||||
while (dt>0.0)
|
||||
if(!user_config->m_replay_history) history->StoreDelta(dt);
|
||||
m_physics->update(dt);
|
||||
for ( Karts::size_type i = 0 ; i < m_kart.size(); ++i)
|
||||
{
|
||||
if(dt>=inc)
|
||||
{
|
||||
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
|
||||
m_kart[i]->update(dt) ;
|
||||
}
|
||||
|
||||
projectile_manager->update(delta);
|
||||
herring_manager->update(delta);
|
||||
projectile_manager->update(dt);
|
||||
herring_manager->update(dt);
|
||||
|
||||
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 */
|
||||
callback_manager->update(delta);
|
||||
callback_manager->update(dt);
|
||||
|
||||
// Check for traffic jam. The sound is played even if it's
|
||||
// not a player kart - a traffic jam happens rarely anyway.
|
||||
@ -621,23 +593,6 @@ void World::updateRacePosition ( int k )
|
||||
m_kart [ k ] -> setPosition ( p ) ;
|
||||
} // 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()
|
||||
@ -680,161 +635,7 @@ void World::loadTrack()
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
m_track->loadTrackModel();
|
||||
} // loadTrack
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -68,15 +68,13 @@ public:
|
||||
/** debug text that will be overlaid to the screen */
|
||||
std::string m_debug_text[10];
|
||||
|
||||
/** Reference to the track inside the scene */
|
||||
ssgBranch *m_track_branch ;
|
||||
|
||||
|
||||
World(const RaceSetup& raceSetup);
|
||||
virtual ~World();
|
||||
#ifndef BULLET
|
||||
float GetHOT(sgVec3 start, sgVec3 end, ssgLeaf** leaf, sgVec4** nrm)
|
||||
{return m_track->GetHOT(start, end, leaf, nrm);}
|
||||
int Collision(sgSphere* s, AllHits *a) const {return m_track->Collision(s,a); }
|
||||
#endif
|
||||
void draw();
|
||||
void update(float delta);
|
||||
void restartRace();
|
||||
@ -124,7 +122,6 @@ private:
|
||||
|
||||
void updateRacePosition( int k );
|
||||
void loadTrack();
|
||||
void herring_command(sgVec3* loc, char htype, int bNeedHeight);
|
||||
void checkRaceStatus();
|
||||
void resetAllKarts();
|
||||
Kart* loadRobot(const KartProperties *kart_properties, int position,
|
||||
|
Loading…
x
Reference in New Issue
Block a user