2 Cafu Engine, http://www.cafu.de/
3 Copyright (c) Carsten Fuchs and other contributors.
4 This project is licensed under the terms of the MIT license.
7 #include "PhysicsWorld.hpp"
10 #include "ClipSys/CollisionModel_base.hpp"
11 #include "ConsoleCommands/Console.hpp"
12 #include "Math3D/Polygon.hpp"
13 #include "TextParser/TextParser.hpp"
15 // #include <iostream> // For std::cout debug output
17 // Turn off bogus warnings that occur with VC11's static code analysis.
18 // (Should move this to a better place though, e.g. some `compat.h` file...)
19 #if defined(_WIN32) && defined(_MSC_VER)
20 // warning C28182: Dereferencing NULL pointer.
21 #pragma warning(disable:28182)
28 PhysicsWorldT::PhysicsWorldT(const cf::ClipSys::CollisionModelT
* WorldCollMdl
)
29 : m_CollisionConfiguration(NULL
),
35 m_CollisionConfiguration
=new btDefaultCollisionConfiguration();
36 m_Dispatcher
=new btCollisionDispatcher(m_CollisionConfiguration
);
37 m_Broadphase
=new btDbvtBroadphase();
38 m_Solver
=new btSequentialImpulseConstraintSolver();
39 m_PhysicsWorld
=new btDiscreteDynamicsWorld(m_Dispatcher
, m_Broadphase
, m_Solver
, m_CollisionConfiguration
);
41 m_PhysicsWorld
->setGravity(btVector3(0, 0, -9.81f
));
44 // Corresponding to the worlds CollisionModelT, use the related btCollisionShape
45 // for adding a btRigidBody (which "is a" btCollisionObject) to the PhysicsWorld.
46 // Note that entities other than the world add their rigid bodies theirselves upon their instantiation.
47 btCollisionShape
* WorldShape
=WorldCollMdl
->GetBulletAdapter();
48 btRigidBody
* WorldStaticBody
=new btRigidBody(btRigidBody::btRigidBodyConstructionInfo(0, NULL
/*myMotionState*/, WorldShape
, btVector3(0, 0, 0)));
50 WorldStaticBody
->setUserPointer(NULL
); // There is no BaseEntityT instance associated to this rigid body.
52 m_PhysicsWorld
->addRigidBody(WorldStaticBody
);
56 PhysicsWorldT::~PhysicsWorldT()
58 // Clean-up in the reverse order of creation/initialization.
59 // This assumes that all entities other than the world have already removed their stuff.
61 // Remove the rigid bodies from the dynamics world and delete them.
62 for (int CONr
=m_PhysicsWorld
->getNumCollisionObjects()-1; CONr
>=0; CONr
--)
64 btCollisionObject
* obj
=m_PhysicsWorld
->getCollisionObjectArray()[CONr
];
66 assert(btRigidBody::upcast(obj
)->getMotionState()==NULL
); // Only entities (but not the world) have a proper motion state.
67 assert(obj
->getUserPointer()==NULL
); // Only entities (but not the world) have a proper pointer to their instance.
69 m_PhysicsWorld
->removeCollisionObject(obj
);
73 delete m_PhysicsWorld
; m_PhysicsWorld
=NULL
;
74 delete m_Solver
; m_Solver
=NULL
;
75 delete m_Broadphase
; m_Broadphase
=NULL
;
76 delete m_Dispatcher
; m_Dispatcher
=NULL
;
77 delete m_CollisionConfiguration
; m_CollisionConfiguration
=NULL
;
81 void PhysicsWorldT::AddRigidBody(btRigidBody
* RigidBody
)
83 m_PhysicsWorld
->addRigidBody(RigidBody
);
87 void PhysicsWorldT::RemoveRigidBody(btRigidBody
* RigidBody
)
89 m_PhysicsWorld
->removeRigidBody(RigidBody
);
93 void PhysicsWorldT::TraceRay(const Vector3dT
& Origin
, const Vector3dT
& Ray
, RayResultT
& RayResult
) const
95 // We intentionally leave it to the user to convert from world units to meters here,
96 // so that the user code is more aware on the details...
97 RayResult
.m_rayFromWorld
=conv(Origin
);
98 RayResult
.m_rayToWorld
=conv(Origin
+Ray
);
100 m_PhysicsWorld
->rayTest(RayResult
.m_rayFromWorld
, RayResult
.m_rayToWorld
, RayResult
);
104 void PhysicsWorldT::TraceBoundingBox(const BoundingBox3T
<double>& BB
, const VectorT
& Origin
, const VectorT
& Dir
, ShapeResultT
& ShapeResult
) const
106 const double METERS_PER_WORLD_UNIT
= 0.0254;
108 btBoxShape
Shape(conv((BB
.Max
-BB
.Min
)/2.0 * METERS_PER_WORLD_UNIT
));
110 // The box shape equally centered around the origin point, whereas BB is possibly "non-uniformely displaced".
111 // In order to compensate, compute how far the BB center is away from the origin.
112 const Vector3dT Ofs
=BB
.GetCenter();
114 ShapeResult
.m_convexFromWorld
=conv((Origin
+Ofs
) * METERS_PER_WORLD_UNIT
);
115 ShapeResult
.m_convexToWorld
=conv((Origin
+Ofs
+Dir
) * METERS_PER_WORLD_UNIT
);
117 btTransform TransFrom
; TransFrom
.setIdentity(); TransFrom
.setOrigin(ShapeResult
.m_convexFromWorld
);
118 btTransform TransTo
; TransTo
.setIdentity(); TransTo
.setOrigin(ShapeResult
.m_convexToWorld
);
120 m_PhysicsWorld
->convexSweepTest(&Shape
, TransFrom
, TransTo
, ShapeResult
);
124 void PhysicsWorldT::TraceShape() const
130 void PhysicsWorldT::Think(float FrameTime
)
132 // std::cout << __FILE__ << " (" << __LINE__ << "): Think(), " << FrameTime << "\n";
133 m_PhysicsWorld
->stepSimulation(FrameTime
, 20);