| 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 | |
|---|
| 36 | class AbstractKart; |
|---|
| 37 | class STKDynamicsWorld; |
|---|
| 38 | class Vec3; |
|---|
| 39 | |
|---|
| 40 | /** |
|---|
| 41 | * \ingroup physics |
|---|
| 42 | */ |
|---|
| 43 | class Physics : public btSequentialImpulseConstraintSolver |
|---|
| 44 | { |
|---|
| 45 | private: |
|---|
| 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 | |
|---|
| 148 | public: |
|---|
| 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 |
|---|