Improved handling of bullet user pointers, which should fix the problem

of rockets not exploding when hitting the track anymore. But there is
still a bug with homing missiles, which still don't explode :(


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@1425 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2008-01-30 05:30:10 +00:00
parent b75c9ec869
commit c3d3f3ab19
9 changed files with 82 additions and 107 deletions

View File

@ -53,7 +53,6 @@ Flyable::Flyable(Kart *kart, CollectableType type) : Moveable(false)
m_shape = NULL;
m_mass = 1.0f;
setUserPointerType(UP_PROJECTILE);
// Add the graphical model
ssgTransform *m = getModelTransform();
m->addKid(m_st_model[type]);
@ -92,7 +91,8 @@ void Flyable::createPhysics(float y_offset, const btVector3 velocity,
trans *= offset_transform;
m_shape = shape;
createBody(m_mass, trans, m_shape, UserPointer::UP_PROJECTILE);
createBody(m_mass, trans, m_shape);
m_user_pointer.set(UserPointer::UP_PROJECTILE, this);
world->getPhysics()->addBody(getBody());
// Simplified rockets: no gravity
@ -106,7 +106,7 @@ void Flyable::createPhysics(float y_offset, const btVector3 velocity,
m_body->setLinearVelocity(v);
m_body->setAngularFactor(0.0f); // prevent rotations
}
m_body->setCollisionFlags(btCollisionObject::CF_NO_CONTACT_RESPONSE);
// m_body->setCollisionFlags(btCollisionObject::CF_NO_CONTACT_RESPONSE);
// FIXME: for now it is necessary to synch the graphical position with the
// physical position, since 'hot' computation is done using the

View File

@ -198,8 +198,8 @@ void Kart::createPhysics(ssgEntity *obj)
// --------------------
btTransform trans;
trans.setIdentity();
createBody(mass, trans, &m_kart_chassis, UserPointer::UP_KART);
createBody(mass, trans, &m_kart_chassis);
m_user_pointer.set(UserPointer::UP_KART, this);
m_body->setDamping(m_kart_properties->getChassisLinearDamping(),
m_kart_properties->getChassisAngularDamping() );

View File

@ -78,8 +78,7 @@ void Moveable::reset ()
//-----------------------------------------------------------------------------
void Moveable::createBody(float mass, btTransform& trans,
btCollisionShape *shape,
UserPointer::UserPointerType t) {
btCollisionShape *shape) {
btVector3 inertia;
shape->calculateLocalInertia(mass, inertia);
@ -89,8 +88,11 @@ void Moveable::createBody(float mass, btTransform& trans,
// ------------------------
m_body = new btRigidBody(mass, m_motion_state,
shape, inertia);
m_body->setUserPointer(this);
setUserPointerType(t);
// This MUST actually 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);
m_body->setUserPointer(&m_user_pointer);
} // createBody
//-----------------------------------------------------------------------------

View File

@ -32,11 +32,12 @@
#define MAX_HERRING_EATEN 20
class Moveable : public UserPointer
class Moveable
{
private:
btVector3 m_velocityLC; /* velocity in kart coordinates */
protected:
UserPointer m_user_pointer;
sgCoord m_reset_pos; /* Where to start in case of a reset */
sgCoord m_curr_pos; /* current position */
sgVec4* m_normal_hot; /* plane on which HOT was computed */
@ -47,9 +48,6 @@ 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;
btRigidBody* m_body;
@ -58,9 +56,6 @@ protected:
public:
/* start - New Physics */
Moveable (bool bHasHistory=false);
virtual ~Moveable();
@ -80,9 +75,7 @@ public:
void ReadHistory (char* s, int kartNumber, int indx);
btRigidBody* getBody () const {return m_body; }
void createBody(float mass, btTransform& trans,
btCollisionShape *shape,
UserPointer::UserPointerType t);
//void getTrans (btTransform& t) const {m_motion_state->getWorldTransform(t);}
btCollisionShape *shape);
const btTransform& getTrans() const {return m_transform;}
void setTrans (btTransform& t){m_transform=t;m_motion_state->setWorldTransform(t);}
}

View File

@ -103,26 +103,23 @@ void Physics::update(float dt)
std::vector<CollisionPair>::iterator p;
for(p=m_all_collisions.begin(); p!=m_all_collisions.end(); ++p)
{
if(p->type_a==UserPointer::UP_KART) { // kart-kart collision
Kart *kartA = (Kart*)(p->a);
Kart *kartB = (Kart*)(p->b);
KartKartCollision(kartA, kartB);
if(p->a->is(UserPointer::UP_KART)) { // kart-kart collision
KartKartCollision(p->a->getPointerKart(), p->b->getPointerKart());
} // if kart-kart collision
else // now the first object must be a projectile
{
if(p->type_b==UserPointer::UP_TRACK) // must be projectile hit track
if(p->b->is(UserPointer::UP_TRACK)) // must be projectile hit track
{
((Flyable*)(p->a))->hitTrack();
p->a->getPointerFlyable()->hitTrack();
}
else if(p->type_b==UserPointer::UP_KART) // projectile hit kart
else if(p->b->is(UserPointer::UP_KART)) // projectile hit kart
{
Flyable *f=(Flyable*)(p->a);
f->explode((Kart*)(p->b));
p->a->getPointerFlyable()->explode((Kart*)(p->b));
}
else // projectile hits projectile
{
((Flyable*)(p->a))->explode(NULL);
((Flyable*)(p->b))->explode(NULL);
p->a->getPointerFlyable()->explode(NULL);
p->b->getPointerFlyable()->explode(NULL);
}
}
} // for all p in m_all_collisions
@ -199,76 +196,41 @@ btScalar Physics::solveGroup(btCollisionObject** bodies, int numBodies,
int numContacts = contactManifold->getNumContacts();
if(!numContacts) continue; // no real collision
Moveable *movA = static_cast<Moveable*>(objA->getUserPointer());
Moveable *movB = static_cast<Moveable*>(objB->getUserPointer());
UserPointer *upA = (UserPointer*)(objA->getUserPointer());
UserPointer *upB = (UserPointer*)(objB->getUserPointer());
// 1) object A is a track
// =======================
if(!movA)
if(upA->is(UserPointer::UP_TRACK))
{
if(movB && movB->getUserPointerType()==UserPointer::UP_PROJECTILE)
{ // 1.1 projectile hits track
// -------------------------
m_all_collisions.push_back(CollisionPair(movB, UserPointer::UP_PROJECTILE,
NULL, UserPointer::UP_TRACK ));
}
else if(movB && movB->getUserPointerType()==UserPointer::UP_KART)
{
((Kart*)movB)->crashed();
}
if(upB->is(UserPointer::UP_PROJECTILE)) // 1.1 projectile hits track
m_all_collisions.push_back(upB, upA);
else if(upB->is(UserPointer::UP_KART))
upB->getPointerKart()->crashed();
}
// 2) object a is a kart
// =====================
else if(movA->getUserPointerType()==UserPointer::UP_KART)
else if(upA->is(UserPointer::UP_KART))
{
if(!movB)
{ // The casts here are important, otherwise re-casting the
// pointers later in kart-kart does not work as expected.
((Kart*)movA)->crashed();
}
else if(movB && movB->getUserPointerType()==UserPointer::UP_PROJECTILE)
{ // 2.1 projectile hits kart
// -------------------------
m_all_collisions.push_back(CollisionPair(movB, UserPointer::UP_PROJECTILE,
(Kart*)movA, UserPointer::UP_KART ));
}
else if(movB && movB->getUserPointerType()==UserPointer::UP_KART)
{ // 2.2 kart hits kart
// ------------------
m_all_collisions.push_back(CollisionPair((Kart*)movA, UserPointer::UP_KART,
(Kart*)movB, UserPointer::UP_KART ));
}
if(upB->is(UserPointer::UP_TRACK))
upA->getPointerKart()->crashed(); // Kart hit track
else if(upB->is(UserPointer::UP_PROJECTILE))
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(movA->getUserPointerType()==UserPointer::UP_PROJECTILE)
else if(upA->is(UserPointer::UP_PROJECTILE))
{
if(!movB)
{ // 3.1) projectile hits track
// --------------------------
m_all_collisions.push_back(CollisionPair(movA, UserPointer::UP_PROJECTILE,
NULL, UserPointer::UP_TRACK ));
}
else if(movB->getUserPointerType()==UserPointer::UP_PROJECTILE)
{ // 3.2 projectile hits projectile
// ------------------------------
m_all_collisions.push_back(CollisionPair(movA, UserPointer::UP_PROJECTILE,
movB, UserPointer::UP_PROJECTILE));
}
else if(movB->getUserPointerType()==UserPointer::UP_KART)
{ // 3.3 projectile hits kart
// ------------------------
m_all_collisions.push_back(CollisionPair(movA, UserPointer::UP_PROJECTILE,
(Kart*)movB, UserPointer::UP_KART ));
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
{
m_all_collisions.push_back(upA, upB);
}
}
// 4) Nothing else should happen
// =============================
else
{
assert("Unknown user pointer");
}
else assert("Unknown user pointer"); // 4) Should never happen
} // for i<numManifolds
return returnValue;

View File

@ -46,21 +46,21 @@ private:
// While this is a natural application of std::set, the set has some
// overhead (since it will likely use a tree to sort the entries).
// Considering that the number of collisions is usually rather small
// a simple list and linear search is being used here.
// a simple list and linear search is faster is is being used here.
class CollisionPair {
public:
void *a, *b;
UserPointer::UserPointerType type_a, type_b;
const UserPointer* a, *b;
// The entries in Collision Pairs are sorted: if a projectile
// is included, it's always 'a'. If only two karts are reported
// the first kart pointer is the smaller one
CollisionPair(void *a1, UserPointer::UserPointerType atype,
void *b1, UserPointer::UserPointerType btype) {
if(atype==Moveable::UP_KART && btype==Moveable::UP_KART && a1>b1) {
a=b1;b=a1; type_a=btype; type_b=atype;
CollisionPair(const UserPointer *a1, const UserPointer *b1) {
if(a1->is(UserPointer::UP_KART) &&
b1->is(UserPointer::UP_KART) && a1>b1) {
a=b1;b=a1;
} else {
a=a1; b=b1; type_a=atype; type_b=btype;
a=a1; b=b1;
}
}; // CollisionPair
bool operator==(const CollisionPair p) {
@ -71,14 +71,18 @@ private:
// This class is the list of collision objects, where each collision
// pair is stored as most once.
class CollisionList : public std::vector<CollisionPair> {
public:
void push_back(CollisionPair p) {
private:
void push_back(CollisionPair p) {
// only add a pair if it's not already in there
for(iterator i=begin(); i!=end(); i++) {
if((*i)==p) return;
}
std::vector<CollisionPair>::push_back(p);
}; // push_back
public:
void push_back(const UserPointer* a, const UserPointer*b) {
push_back(CollisionPair(a, b));
}
};
CollisionList m_all_collisions;

View File

@ -58,7 +58,8 @@ void TriangleMesh::createBody(btCollisionObject::CollisionFlags flags)
m_body=new btRigidBody(0.0f, m_motion_state, m_collision_shape);
world->getPhysics()->addBody(m_body);
m_body->setUserPointer(this);
m_user_pointer.set(UserPointer::UP_TRACK, this);
m_body->setUserPointer(&m_user_pointer);
m_body->setCollisionFlags(m_body->getCollisionFlags() |
flags |
btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);

View File

@ -28,15 +28,17 @@
/** A special class to store a triangle mesh with a separate material
* per triangle.
*/
class TriangleMesh : public UserPointer
class TriangleMesh
{
private:
UserPointer m_user_pointer;
std::vector<const Material*> m_triangleIndex2Material;
btRigidBody *m_body;
btTriangleMesh m_mesh;
btDefaultMotionState *m_motion_state;
btCollisionShape *m_collision_shape;
public:
TriangleMesh(): UserPointer(UserPointer::UP_TRACK), m_mesh() {};
TriangleMesh() : m_mesh() {};
~TriangleMesh();
void addTriangle(btVector3 t1, btVector3 t2, btVector3 t3,
const Material* m);

View File

@ -23,18 +23,29 @@
/** Some bullet objects store 'user pointers'. This is a base class
* that allows to easily determine the type of the user pointer.
*/
class TriangleMesh;
class Moveable;
class Flyable;
class Kart;
class UserPointer
{
public:
enum UserPointerType {UP_UNDEF, UP_KART, UP_PROJECTILE, UP_TRACK} ;
protected:
enum UserPointerType {UP_UNDEF, UP_KART, UP_PROJECTILE, UP_TRACK};
private:
void* m_pointer;
UserPointerType m_user_pointer_type;
public:
UserPointerType getUserPointerType() const {return m_user_pointer_type;}
void setUserPointerType(UserPointerType t)
{ m_user_pointer_type=t; }
UserPointer(): m_user_pointer_type(UP_UNDEF) {};
UserPointer(UserPointerType t): m_user_pointer_type(t) {};
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_user_pointer_type(UP_UNDEF),m_pointer(NULL) {};
UserPointer(UserPointerType t, void* p) {set(t,p);}
};
#endif
/* EOF */