diff --git a/data/stk_config.data b/data/stk_config.data index ca2bf276f..0cbc88ff4 100644 --- a/data/stk_config.data +++ b/data/stk_config.data @@ -28,6 +28,8 @@ (shortcut-skipped-segments 5 ) ;; skipping more than this number of segments ;; is considered to be a shortcut (explosion-impulse 10000.0 ) ;; explosion impulse on not directly hit karts + (explosion-impulse-objects 500.0 ) ;; explosion impulse for physics objects (smaller + ;; else a cone e.g. will be pushed way too far) ;; Other kart relates values ;; ------------------------- diff --git a/src/callback.hpp b/src/callback.hpp index 0e7ff102f..846f8ccb5 100644 --- a/src/callback.hpp +++ b/src/callback.hpp @@ -20,12 +20,16 @@ #ifndef CALLBACK_H #define CALLBACK_H +#include "btBulletDynamicsCommon.h" + class Callback { public: - virtual ~Callback() {}; - virtual void update (float dt) = 0; - virtual void init () = 0; + virtual ~Callback() {}; + virtual void update (float dt) = 0; + virtual void init () = 0; + virtual void reset () {}; + virtual void handleExplosion(const btVector3& pos, bool directHit) {}; } ; // Callback diff --git a/src/callback_manager.cpp b/src/callback_manager.cpp index 647ccdd4b..cc3c5d288 100644 --- a/src/callback_manager.cpp +++ b/src/callback_manager.cpp @@ -106,6 +106,31 @@ void CallbackManager::initAll() const (*c)->init(); } // for i -} // update +} // initAll +//----------------------------------------------------------------------------- +// Called when restarting a race +void CallbackManager::reset() const +{ + for(int i=0; i::const_iterator c = m_allCallbacks[i].begin(); + c != m_allCallbacks[i].end(); c++) + (*c)->reset(); + } // for i + +} // initAll + +//----------------------------------------------------------------------------- +void CallbackManager::handleExplosion(const btVector3& pos, + const MovingPhysics* mp) const +{ + for(int i=0; i::const_iterator c = m_allCallbacks[i].begin(); + c != m_allCallbacks[i].end(); c++) + (*c)->handleExplosion(pos, mp==(*c)); + } // for i + +} // handleExplosion diff --git a/src/callback_manager.hpp b/src/callback_manager.hpp index 53e5a08bd..8a9ad71e2 100644 --- a/src/callback_manager.hpp +++ b/src/callback_manager.hpp @@ -21,7 +21,9 @@ #define CALLBACK_MANAGER_H #include +#include "btBulletDynamicsCommon.h" #include "callback.hpp" +#include "moving_physics.hpp" // It might actually be enough to have only two different values: track (which // get deleted and loaded more than one), and everything else, which only @@ -36,13 +38,14 @@ class CallbackManager std::vector m_allCallbacks[CB_MAX]; public: - CallbackManager(); - ~CallbackManager(); - - void update (float dt) const; - void initAll () const; - void clear (CallbackType cbType); - void addCallback(Callback *c, CallbackType t); + CallbackManager(); + ~CallbackManager(); + void update (float dt) const; + void initAll () const; + void reset () const; + void clear (CallbackType cbType); + void addCallback (Callback *c, CallbackType t); + void handleExplosion(const btVector3& pos, const MovingPhysics* mo) const; } ; // CallbackManager diff --git a/src/flyable.cpp b/src/flyable.cpp index 2eaf78708..efcf3a2a0 100644 --- a/src/flyable.cpp +++ b/src/flyable.cpp @@ -23,6 +23,7 @@ #include "world.hpp" #include "kart.hpp" #include "projectile_manager.hpp" +#include "callback_manager.hpp" #include "sound_manager.hpp" #include "scene.hpp" #include "ssg_help.hpp" @@ -92,7 +93,7 @@ void Flyable::createPhysics(float y_offset, const btVector3 velocity, m_shape = shape; createBody(m_mass, trans, m_shape); - m_user_pointer.set(UserPointer::UP_PROJECTILE, this); + m_user_pointer.set(this); world->getPhysics()->addBody(getBody()); // Simplified rockets: no gravity @@ -204,7 +205,7 @@ void Flyable::placeModel() } // placeModel // ----------------------------------------------------------------------------- -void Flyable::explode(Kart *kart_hit) +void Flyable::explode(Kart *kart_hit, MovingPhysics* moving_physics) { if(m_exploded) return; @@ -219,6 +220,7 @@ void Flyable::explode(Kart *kart_hit) m->removeAllKids(); scene->remove(m); + btVector3 pos(m_curr_pos.xyz[0],m_curr_pos.xyz[1],m_curr_pos.xyz[2]); world->getPhysics()->removeBody(getBody()); m_exploded=true; @@ -228,7 +230,7 @@ void Flyable::explode(Kart *kart_hit) // handle the actual explosion. Set a flag it if was a direct hit. kart->handleExplosion(m_curr_pos.xyz, kart==kart_hit); } - + callback_manager->handleExplosion(pos, moving_physics); } // explode /* EOF */ diff --git a/src/flyable.hpp b/src/flyable.hpp index 9fba6d8c8..9feda0e07 100644 --- a/src/flyable.hpp +++ b/src/flyable.hpp @@ -21,6 +21,7 @@ #define HEADER_FLYABLE_H #include "moveable.hpp" +#include "moving_physics.hpp" #include "kart.hpp" #include "terrain_info.hpp" @@ -67,7 +68,7 @@ public: void placeModel (); virtual void hitTrack () {}; - void explode (Kart* kart); + void explode (Kart* kart, MovingPhysics* moving_physics=NULL); bool hasHit () { return m_has_hit_something; } void reset () { Moveable::reset(); sgCopyCoord(&m_last_pos,&m_reset_pos ); } diff --git a/src/kart.cpp b/src/kart.cpp index bf606d90d..0d082d380 100644 --- a/src/kart.cpp +++ b/src/kart.cpp @@ -199,7 +199,7 @@ void Kart::createPhysics(ssgEntity *obj) btTransform trans; trans.setIdentity(); createBody(mass, trans, &m_kart_chassis); - m_user_pointer.set(UserPointer::UP_KART, this); + m_user_pointer.set(this); m_body->setDamping(m_kart_properties->getChassisLinearDamping(), m_kart_properties->getChassisAngularDamping() ); diff --git a/src/moveable.cpp b/src/moveable.cpp index a675bc4ec..1fab2579b 100644 --- a/src/moveable.cpp +++ b/src/moveable.cpp @@ -85,14 +85,15 @@ void Moveable::createBody(float mass, btTransform& trans, m_motion_state = new btDefaultMotionState(trans); btRigidBody::btRigidBodyConstructionInfo info(mass, m_motion_state, shape, inertia); + info.m_restitution=0.5f; // Then create a rigid body // ------------------------ m_body = new btRigidBody(info); - // This MUST actually be set from the actual class, otherwise this + // The value of user_pointer must be set from the actual class, otherwise this // is only a pointer to moveable, not to (say) kart, and virtual - // functions are not called correctly. - m_user_pointer.set(UserPointer::UP_UNDEF, 0); + // functions are not called correctly. So only init the pointer to zero. + m_user_pointer.zero(); m_body->setUserPointer(&m_user_pointer); } // createBody diff --git a/src/moving_physics.cpp b/src/moving_physics.cpp index 528175037..91b08f754 100644 --- a/src/moving_physics.cpp +++ b/src/moving_physics.cpp @@ -148,12 +148,6 @@ void MovingPhysics::init() } } // while - // printf("matrix: "); - // for(int i=0; i<4; i++) - // for(int j=0; j<4; j++) - // printf("%f ",pos[i][j]); - // printf("\n"); - // 3. Determine size of the object // ------------------------------- float x_min, x_max, y_min, y_max, z_min, z_max, radius; @@ -176,15 +170,19 @@ void MovingPhysics::init() // 4. Create the rigid object // -------------------------- - btTransform trans; - trans.setIdentity(); - trans.setOrigin(btVector3(pos[3][0],pos[3][1],pos[3][2]+m_half_height)); - m_motion_state = new btDefaultMotionState(trans); + + m_init_pos.setIdentity(); + m_init_pos.setOrigin(btVector3(pos[3][0],pos[3][1],pos[3][2]+m_half_height)); + m_motion_state = new btDefaultMotionState(m_init_pos); btVector3 inertia; m_shape->calculateLocalInertia(m_mass, inertia); btRigidBody::btRigidBodyConstructionInfo info(m_mass, m_motion_state, m_shape, inertia); - + + // Make sure that the cones stop rolling by defining angular friction != 0. + info.m_angularDamping = 0.5f; m_body = new btRigidBody(info); + m_user_pointer.set(this); + m_body->setUserPointer(&m_user_pointer); world->getPhysics()->addBody(m_body); } // init @@ -196,13 +194,45 @@ void MovingPhysics::update(float dt) float m[4][4]; t.getOpenGLMatrix((float*)&m); - // printf("%lx is %f %f %f\n",this, t.getOrigin().x(),t.getOrigin().y(),t.getOrigin().z()); // Transfer the new position and hpr to m_curr_pos sgCoord m_curr_pos; sgSetCoord(&m_curr_pos, m); setTransform(&m_curr_pos); } // update // ----------------------------------------------------------------------------- +void MovingPhysics::reset() +{ + m_body->setCenterOfMassTransform(m_init_pos); +} // reset +// ----------------------------------------------------------------------------- +void MovingPhysics::handleExplosion(const btVector3& pos, bool direct_hit) { + if(direct_hit) { + btVector3 impulse(0.0f, 0.0f, stk_config->m_explosion_impulse_objects); + m_body->applyCentralImpulse(impulse); + } + else // only affected by a distant explosion + { + btTransform t; + m_motion_state->getWorldTransform(t); + btVector3 diff=t.getOrigin()-pos; + + float len2=diff.length2(); + + // The correct formhale would be to first normalise diff, + // then apply the impulse (which decreases 1/r^2 depending + // on the distance r), so: + // diff/len(diff) * impulseSize/len(diff)^2 + // = diff*impulseSize/len(diff)^3 + // We use diff*impulseSize/len(diff)^2 here, this makes the impulse + // somewhat larger, which is actually more fun :) + btVector3 impulse=diff*stk_config->m_explosion_impulse_objects/len2; + m_body->applyCentralImpulse(impulse); + } + m_body->activate(); + +} // handleExplosion + +// ----------------------------------------------------------------------------- /* EOF */ diff --git a/src/moving_physics.hpp b/src/moving_physics.hpp index 44d2cbe42..6ee026e7a 100644 --- a/src/moving_physics.hpp +++ b/src/moving_physics.hpp @@ -19,10 +19,11 @@ #ifndef HEADER_MOVING_PHYSICS_H #define HEADER_MOVING_PHYSICS_H +#include #include #include "btBulletDynamicsCommon.h" #include "callback.hpp" -#include +#include "user_pointer.hpp" class MovingPhysics : public ssgTransform, public Callback { @@ -36,12 +37,16 @@ protected: btDefaultMotionState *m_motion_state; float m_half_height; float m_mass; + UserPointer m_user_pointer; + btTransform m_init_pos; public: MovingPhysics (const std::string data); ~MovingPhysics (); void update (float dt); void init (); + virtual void reset (); const char *getTypeName() {return "moving physics";} + virtual void handleExplosion(const btVector3& pos, bool directHit); }; // MovingPhysics #endif diff --git a/src/moving_texture.cpp b/src/moving_texture.cpp index b06721447..58caa923b 100644 --- a/src/moving_texture.cpp +++ b/src/moving_texture.cpp @@ -38,7 +38,7 @@ MovingTexture::MovingTexture(char *data, ssgBranch *branch) parseData(data); -} // Callback +} // MovingTexture //----------------------------------------------------------------------------- MovingTexture::~MovingTexture() diff --git a/src/physics.cpp b/src/physics.cpp index e490c422b..a4161bef7 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -112,6 +112,11 @@ void Physics::update(float dt) { p->a->getPointerFlyable()->hitTrack(); } + else if(p->b->is(UserPointer::UP_MOVING_PHYSICS)) + { + p->a->getPointerFlyable()->explode(NULL, p->b->getPointerMovingPhysics()); + + } else if(p->b->is(UserPointer::UP_KART)) // projectile hit kart { p->a->getPointerFlyable()->explode((Kart*)(p->b)); @@ -207,7 +212,7 @@ btScalar Physics::solveGroup(btCollisionObject** bodies, int numBodies, // ======================= if(upA->is(UserPointer::UP_TRACK)) { - if(upB->is(UserPointer::UP_PROJECTILE)) // 1.1 projectile hits track + if(upB->is(UserPointer::UP_FLYABLE)) // 1.1 projectile hits track m_all_collisions.push_back(upB, upA); else if(upB->is(UserPointer::UP_KART)) upB->getPointerKart()->crashed(); @@ -218,21 +223,29 @@ btScalar Physics::solveGroup(btCollisionObject** bodies, int numBodies, { if(upB->is(UserPointer::UP_TRACK)) upA->getPointerKart()->crashed(); // Kart hit track - else if(upB->is(UserPointer::UP_PROJECTILE)) + else if(upB->is(UserPointer::UP_FLYABLE)) m_all_collisions.push_back(upB, upA); // 2.1 projectile hits kart else if(upB->is(UserPointer::UP_KART)) m_all_collisions.push_back(upA, upB); // 2.2 kart hits kart } // 3) object is a projectile // ======================== - else if(upA->is(UserPointer::UP_PROJECTILE)) + else if(upA->is(UserPointer::UP_FLYABLE)) { - if(upB->is(UserPointer::UP_TRACK ) || // 3.1) projectile hits track - upB->is(UserPointer::UP_PROJECTILE) || // 3.2) projectile hits projectile - upB->is(UserPointer::UP_KART ) ) // 3.3) projectile hits kart + if(upB->is(UserPointer::UP_TRACK ) || // 3.1) projectile hits track + upB->is(UserPointer::UP_FLYABLE ) || // 3.2) projectile hits projectile + upB->is(UserPointer::UP_MOVING_PHYSICS) || // 3.3) projectile hits projectile + upB->is(UserPointer::UP_KART ) ) // 3.4) projectile hits kart { m_all_collisions.push_back(upA, upB); } + } + else if(upA->is(UserPointer::UP_MOVING_PHYSICS)) + { + if(upB->is(UserPointer::UP_FLYABLE)) + { + m_all_collisions.push_back(upB, upA); + } } else assert("Unknown user pointer"); // 4) Should never happen } // for iget("zipper-time", m_zipper_time ); lisp->get("zipper-force", m_zipper_force ); lisp->get("explosion-impulse", m_explosion_impulse ); + lisp->get("explosion-impulse-objects", m_explosion_impulse_objects); lisp->get("max-karts", m_max_karts ); lisp->get("grid-order", m_grid_order ); diff --git a/src/stk_config.hpp b/src/stk_config.hpp index 463f76d50..1960e1216 100644 --- a/src/stk_config.hpp +++ b/src/stk_config.hpp @@ -42,6 +42,7 @@ public: float m_shortcut_segments; // skipping more than this number of segments is // considered to be a shortcut float m_explosion_impulse; // impulse affecting each non-hit kart + float m_explosion_impulse_objects;// impulse of explosion on moving objects, e.g. road cones, ... int m_max_karts; // maximum number of karts int m_grid_order; // whether grand prix grid is in point order or reverse point order diff --git a/src/triangle_mesh.cpp b/src/triangle_mesh.cpp index 87f641b3a..32d46ab79 100644 --- a/src/triangle_mesh.cpp +++ b/src/triangle_mesh.cpp @@ -59,7 +59,7 @@ void TriangleMesh::createBody(btCollisionObject::CollisionFlags flags) m_body=new btRigidBody(info); world->getPhysics()->addBody(m_body); - m_user_pointer.set(UserPointer::UP_TRACK, this); + m_user_pointer.set(this); m_body->setUserPointer(&m_user_pointer); m_body->setCollisionFlags(m_body->getCollisionFlags() | flags | diff --git a/src/user_pointer.hpp b/src/user_pointer.hpp index 0ac547b61..3e09e67c8 100644 --- a/src/user_pointer.hpp +++ b/src/user_pointer.hpp @@ -27,25 +27,34 @@ class TriangleMesh; class Moveable; class Flyable; class Kart; +class MovingPhysics; class UserPointer { public: - enum UserPointerType {UP_UNDEF, UP_KART, UP_PROJECTILE, UP_TRACK}; + enum UserPointerType {UP_UNDEF, UP_KART, UP_FLYABLE, UP_TRACK, + UP_MOVING_PHYSICS}; private: void* m_pointer; UserPointerType m_user_pointer_type; public: - bool is(UserPointerType t) const {return m_user_pointer_type==t; } - TriangleMesh* getPointerTriangleMesh() const {return (TriangleMesh*)m_pointer;} - Moveable* getPointerMoveable() const {return (Moveable*)m_pointer; } - Flyable* getPointerFlyable() const {return (Flyable*)m_pointer; } - Kart* getPointerKart() const {return (Kart*)m_pointer; } - void set(UserPointerType t, void* p) - { m_user_pointer_type=t; - m_pointer =p; } - UserPointer(): m_pointer(NULL),m_user_pointer_type(UP_UNDEF) {}; - UserPointer(UserPointerType t, void* p) {set(t,p);} + bool is(UserPointerType t) const {return m_user_pointer_type==t; } + TriangleMesh* getPointerTriangleMesh() const {return (TriangleMesh*)m_pointer; } + Moveable* getPointerMoveable() const {return (Moveable*)m_pointer; } + Flyable* getPointerFlyable() const {return (Flyable*)m_pointer; } + Kart* getPointerKart() const {return (Kart*)m_pointer; } + MovingPhysics* getPointerMovingPhysics() const {return (MovingPhysics*)m_pointer; } + void set(MovingPhysics* p) { m_user_pointer_type=UP_MOVING_PHYSICS; + m_pointer =p; } + void set(Kart* p) { m_user_pointer_type=UP_KART; + m_pointer =p; } + void set(Flyable* p) { m_user_pointer_type=UP_FLYABLE; + m_pointer =p; } + void set(TriangleMesh* p) { m_user_pointer_type=UP_TRACK; + m_pointer =p; } + UserPointer() { zero(); } + void zero() { m_user_pointer_type=UP_UNDEF; + m_pointer = NULL; } }; #endif /* EOF */ diff --git a/src/world.cpp b/src/world.cpp index d28a41fd0..f5918f7d8 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -615,6 +615,7 @@ void World::restartRace() herring_manager->reset(); projectile_manager->cleanup(); race_manager->reset(); + callback_manager->reset(); #ifdef HAVE_GHOST_REPLAY m_replay_recorder.destroy();