From a3094590d61ff124e3019b1df56547016564ce7c Mon Sep 17 00:00:00 2001 From: hikerstk Date: Tue, 5 Feb 2008 11:56:21 +0000 Subject: [PATCH] 1) Improved handling of 'moving' or 'physical' objects (e.g. road cone). You can now shoot them, and they will be pushed aside by a close-by explosions. 2) Bugfix: Physical objects are now reset to the correct starting location. 3) Physical objects have now angular friction defined, preventing them from rotating endlessly. 4) Karts have now some 'restitution', which adds a bit of bouncing to collisions. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@1445 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- data/stk_config.data | 2 ++ src/callback.hpp | 10 +++++--- src/callback_manager.cpp | 27 +++++++++++++++++++- src/callback_manager.hpp | 17 +++++++------ src/flyable.cpp | 8 +++--- src/flyable.hpp | 3 ++- src/kart.cpp | 2 +- src/moveable.cpp | 7 +++--- src/moving_physics.cpp | 54 +++++++++++++++++++++++++++++++--------- src/moving_physics.hpp | 7 +++++- src/moving_texture.cpp | 2 +- src/physics.cpp | 25 ++++++++++++++----- src/stk_config.cpp | 5 +++- src/stk_config.hpp | 1 + src/triangle_mesh.cpp | 2 +- src/user_pointer.hpp | 31 +++++++++++++++-------- src/world.cpp | 1 + 17 files changed, 152 insertions(+), 52 deletions(-) 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();