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
This commit is contained in:
parent
5767b4f616
commit
a3094590d6
@ -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
|
||||
;; -------------------------
|
||||
|
@ -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
|
||||
|
||||
|
@ -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<CB_MAX; i++)
|
||||
{
|
||||
for(std::vector<Callback*>::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<CB_MAX; i++)
|
||||
{
|
||||
for(std::vector<Callback*>::const_iterator c = m_allCallbacks[i].begin();
|
||||
c != m_allCallbacks[i].end(); c++)
|
||||
(*c)->handleExplosion(pos, mp==(*c));
|
||||
} // for i
|
||||
|
||||
} // handleExplosion
|
||||
|
||||
|
@ -21,7 +21,9 @@
|
||||
#define CALLBACK_MANAGER_H
|
||||
|
||||
#include <vector>
|
||||
#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<Callback*> 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
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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 ); }
|
||||
|
@ -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() );
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -19,10 +19,11 @@
|
||||
|
||||
#ifndef HEADER_MOVING_PHYSICS_H
|
||||
#define HEADER_MOVING_PHYSICS_H
|
||||
#include <string>
|
||||
#include <plib/ssg.h>
|
||||
#include "btBulletDynamicsCommon.h"
|
||||
#include "callback.hpp"
|
||||
#include <string>
|
||||
#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
|
||||
|
@ -38,7 +38,7 @@ MovingTexture::MovingTexture(char *data, ssgBranch *branch)
|
||||
parseData(data);
|
||||
|
||||
|
||||
} // Callback
|
||||
} // MovingTexture
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
MovingTexture::~MovingTexture()
|
||||
|
@ -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 i<numManifolds
|
||||
|
@ -112,6 +112,7 @@ void STKConfig::load(const std::string filename)
|
||||
CHECK_NEG(m_suspension_rest, "suspension-rest" );
|
||||
CHECK_NEG(m_jump_velocity, "jump-velocity" );
|
||||
CHECK_NEG(m_explosion_impulse, "explosion-impulse" );
|
||||
CHECK_NEG(m_explosion_impulse_objects, "explosion-impulse-objects" );
|
||||
|
||||
} // load
|
||||
|
||||
@ -137,7 +138,8 @@ void STKConfig::init_defaults()
|
||||
m_wheelie_lean_recovery = m_wheelie_step = m_wheelie_balance_recovery =
|
||||
m_wheelie_power_boost = m_chassis_linear_damping = m_chassis_angular_damping =
|
||||
m_maximum_speed = m_brake_force = m_gravity_center_shift = m_suspension_rest =
|
||||
m_max_speed_reverse_ratio = m_explosion_impulse = m_jump_velocity = -99.9f;
|
||||
m_max_speed_reverse_ratio = m_explosion_impulse = m_jump_velocity =
|
||||
m_explosion_impulse_objects = -99.9f;
|
||||
|
||||
m_max_karts = -100;
|
||||
m_grid_order = -100;
|
||||
@ -166,6 +168,7 @@ void STKConfig::getAllData(const lisp::Lisp* lisp)
|
||||
lisp->get("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 );
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 |
|
||||
|
@ -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 */
|
||||
|
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user