1. Summary
  2. Files
  3. Support
  4. Report Spam
  5. Create account
  6. Log in

root/main/trunk/src/physics/physics.hpp @ 11198

Revision 11198, 7.5 KB (checked in by hikerstk, 13 months ago)

Fixed #560: if a rigid body has more than one collision (and one collision can be
reported p to 4 times by bullet), a crash would be caused when the rigid body is
removed (meaning that all further collisions with this body are invalid/removed,
while the loop in physics still tries to access them).
This patches removes bodies only when it is safe to do so, i.e. after the collision
loop. Removals done in the loop will be stored and executed later.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1//
2//  SuperTuxKart - a fun racing game with go-kart
3//  Copyright (C) 2006 Joerg Henrichs
4//
5//  This program is free software; you can redistribute it and/or
6//  modify it under the terms of the GNU General Public License
7//  as published by the Free Software Foundation; either version 3
8//  of the License, or (at your option) any later version.
9//
10//  This program is distributed in the hope that it will be useful,
11//  but WITHOUT ANY WARRANTY; without even the implied warranty of
12//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13//  GNU General Public License for more details.
14//
15//  You should have received a copy of the GNU General Public License
16//  along with this program; if not, write to the Free Software
17//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19#ifndef HEADER_PHYSICS_HPP
20#define HEADER_PHYSICS_HPP
21
22/**
23  * \defgroup physics
24  * Contains various physics utilities.
25  */
26
27#include <set>
28#include <vector>
29
30#include "btBulletDynamicsCommon.h"
31
32#include "physics/irr_debug_drawer.hpp"
33#include "physics/stk_dynamics_world.hpp"
34#include "physics/user_pointer.hpp"
35
36class AbstractKart;
37class STKDynamicsWorld;
38class Vec3;
39
40/**
41  * \ingroup physics
42  */
43class Physics : public btSequentialImpulseConstraintSolver
44{
45private:
46    /** Bullet can report the same collision more than once (up to 4
47     *  contact points per collision. Additionally, more than one internal
48     *  substep might be taken, resulting in potentially even more
49     *  duplicates. To handle this, all collisions (i.e. pair of objects)
50     *  are stored in a vector, but only one entry per collision pair
51     *  of objects.
52     *  While this is a natural application of std::set, the set has some
53     *  overhead (since it will likely use a tree to sort the entries).
54     *  Considering that the number of collisions is usually rather small
55     *  a simple list and linear search is faster is is being used here. */
56    class CollisionPair {
57    private:
58        /** The user pointer of the objects involved in this collision. */
59        const UserPointer *m_up[2];
60
61        /** The contact point for each object (in local coordincates). */
62        Vec3               m_contact_point[2];
63    public:
64        /** The entries in Collision Pairs are sorted: if a projectile
65         * is included, it's always 'a'. If only two karts are reported
66         * the first kart pointer is the smaller one. */
67        CollisionPair(const UserPointer *a, const btVector3 &contact_point_a,
68                      const UserPointer *b, const btVector3 &contact_point_b) 
69        {
70            if(a->is(UserPointer::UP_KART) &&
71               b->is(UserPointer::UP_KART) && a>b) {
72                m_up[0]=b; m_contact_point[0] = contact_point_b;
73                m_up[1]=a; m_contact_point[1] = contact_point_a;
74            } else {
75                m_up[0]=a; m_contact_point[0] = contact_point_a;
76                m_up[1]=b; m_contact_point[1] = contact_point_b;
77            }
78        };  //    CollisionPair
79        // --------------------------------------------------------------------
80        /** Tests if two collision pairs involve the same objects. This test
81         *  is simplified (i.e. no test if p.b==a and p.a==b) since the
82         *  elements are sorted. */
83        bool operator==(const CollisionPair p)
84        {
85            return (p.m_up[0]==m_up[0] && p.m_up[1]==m_up[1]);
86        }   // operator==
87        // --------------------------------------------------------------------
88        const UserPointer *getUserPointer(unsigned int n) const 
89        {
90            assert(n>=0 && n<=1);
91            return m_up[n];
92        }   // getUserPointer
93        // --------------------------------------------------------------------
94        /** Returns the contact point of the collision in
95         *  car (local) coordinates. */
96        const Vec3 &getContactPointCS(unsigned int n) const 
97        {
98            assert(n>=0 && n<=1);
99            return m_contact_point[n];
100        }   // getContactPointCS
101    };  // CollisionPair
102
103    // ========================================================================
104    // This class is the list of collision objects, where each collision
105    // pair is stored as most once.
106    class CollisionList : public std::vector<CollisionPair> 
107    {
108    private:
109        void push_back(CollisionPair p) {
110            // only add a pair if it's not already in there
111            for(iterator i=begin(); i!=end(); i++) {
112                if((*i)==p) return;
113            }
114            std::vector<CollisionPair>::push_back(p);
115        };  // push_back
116    public:
117        /** Adds information about a collision to this vector. */
118        void push_back(const UserPointer *a, const btVector3 &contact_point_a,
119                       const UserPointer *b, const btVector3 &contact_point_b)
120        {
121            push_back(CollisionPair(a, contact_point_a, b, contact_point_b));
122        }
123    };  // CollisionList
124    // ========================================================================
125
126    /** This flag is set while bullets time step processing is taking
127    *  place. It is used to avoid altering data structures that might
128    *  be used (e.g. removing a kart while a loop over all karts is
129    *  taking place, as can happen in collision handling). */
130    bool               m_physics_loop_active;
131
132    /** If kart need to be removed from the physics world while physics
133    *  processing is taking place, store the pointers to the karts to
134    *  be removed here, and remove them once the physics processing
135    *  is finished. */
136    std::vector<const AbstractKart*> m_karts_to_delete;
137
138    /** Pointer to the physics dynamics world. */
139    STKDynamicsWorld                *m_dynamics_world;
140
141    /** Used in physics debugging to draw the physics world. */
142    IrrDebugDrawer                  *m_debug_drawer;
143    btCollisionDispatcher           *m_dispatcher;
144    btBroadphaseInterface           *m_axis_sweep;
145    btDefaultCollisionConfiguration *m_collision_conf;
146    CollisionList                    m_all_collisions;   
147
148public:
149          Physics          ();
150         ~Physics          ();
151    void  init             (const Vec3 &min_world, const Vec3 &max_world);
152    void  addKart          (const AbstractKart *k);
153    void  addBody          (btRigidBody* b) {m_dynamics_world->addRigidBody(b);}
154    void  removeKart       (const AbstractKart *k);
155    void  removeBody       (btRigidBody* b) {m_dynamics_world->removeRigidBody(b);}
156    void  KartKartCollision(AbstractKart *ka, const Vec3 &contact_point_a,
157                            AbstractKart *kb, const Vec3 &contact_point_b);
158    void  update           (float dt);
159    void  draw             ();
160    STKDynamicsWorld*
161          getPhysicsWorld  () const {return m_dynamics_world;}
162    /** Activates the next debug mode (or switches it off again).
163     */
164    void  nextDebugMode    () {m_debug_drawer->nextDebugMode(); }
165    /** Returns true if the debug drawer is enabled. */
166    bool  isDebug() const     {return m_debug_drawer->debugEnabled(); }
167    bool  projectKartDownwards(const AbstractKart *k);
168    virtual btScalar solveGroup(btCollisionObject** bodies, int numBodies,
169                                btPersistentManifold** manifold,int numManifolds,
170                                btTypedConstraint** constraints,int numConstraints,
171                                const btContactSolverInfo& info,
172                                btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,
173                                btDispatcher* dispatcher);
174};
175
176#endif // HEADER_PHYSICS_HPP
Note: See TracBrowser for help on using the browser.