My Project
AnnPhysicsEngine.cpp
Go to the documentation of this file.
1 // This is an open source non-commercial project. Dear PVS-Studio, please check it.
2 // PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
3 
4 #include "AnnPhysicsEngine.hpp"
5 #include "AnnPlayerBody.hpp"
6 #include "AnnLogger.hpp"
7 #include "AnnGetter.hpp"
8 #include "AnnException.hpp"
9 
10 using namespace Annwvyn;
11 using std::make_unique;
12 
13 AnnPhysicsEngine::AnnPhysicsEngine(Ogre::SceneNode* rootNode,
14  AnnPlayerBodyPtr player) :
15  AnnSubSystem("PhysicsEngie"),
16  Broadphase(nullptr),
17  CollisionConfiguration(nullptr),
18  Solver(nullptr),
19  DynamicsWorld(nullptr),
20  debugDrawer(nullptr),
21  playerRigidBodyState(nullptr),
22  playerObject(player),
23  defaultGravity(0, -9.81f, 0)
24 {
25  AnnDebug(Log::Important) << "Initializing bullet version " << getBulletVersion();
26 
27  //Initialize the Bullet world
28  Broadphase = make_unique<btDbvtBroadphase>();
29  CollisionConfiguration = make_unique<btDefaultCollisionConfiguration>();
30  Dispatcher = make_unique<btCollisionDispatcher>(CollisionConfiguration.get());
31  Solver = make_unique<btSequentialImpulseConstraintSolver>();
32  DynamicsWorld = make_unique<btDiscreteDynamicsWorld>(Dispatcher.get(), Broadphase.get(), Solver.get(), CollisionConfiguration.get());
33  AnnDebug() << "btDiscreteDynamicsWorld instantiated";
34 
35  //Set gravity vector
37  AnnDebug() << "Gravity vector " << defaultGravity;
38 
39  debugPhysics = false; //by default
40  debugDrawer = make_unique<BtOgre::DebugDrawer>(rootNode, DynamicsWorld.get(), AnnGetEngine()->getSceneManager());
41  DynamicsWorld->setDebugDrawer(debugDrawer.get());
42  debugDrawer->setUnlitDiffuseMultiplier(16.0f);
43 }
44 
46 {
47 }
48 
50 {
51  DynamicsWorld->addRigidBody(playerObject->getBody(), Player, General);
52 }
53 
55 {
56  AnnDebug() << "createPlayerPhysicalVirtualBody";
57 
58  //Create (new) a rigid body state through BtOgre
60  playerRigidBodyState = new BtOgre::RigidBodyState(node);
61 
62  //Get inertia vector
63  btVector3 inertia;
64  const auto playerShape = playerObject->getShape();
65  const auto playerMass = playerObject->getMass();
66  playerShape->calculateLocalInertia(playerMass, inertia);
67 
68  //Set the body to the player
69  const auto body = new btRigidBody {
70  playerMass,
72  playerShape,
73  inertia
74  };
75 
76  playerObject->setBody(body);
77 }
78 
80 {
81  //remove the diameter of the two half sphere on top and bottom of the capsule
82  playerObject->setShape(new btCapsuleShape { radius, playerObject->getEyesHeight() - 2 * radius });
83 }
84 
85 btDiscreteDynamicsWorld* AnnPhysicsEngine::getWorld() const
86 {
87  return DynamicsWorld.get();
88 }
89 
90 void AnnPhysicsEngine::step(float delta) const
91 {
92  DynamicsWorld->stepSimulation(delta, 10, 1.0f / 240.0f);
93 }
94 
96 {
97  if(debugPhysics)
98  debugDrawer->step();
99 }
100 
102 {
103  const auto nbManifold = DynamicsWorld->getDispatcher()->getNumManifolds();
104  for(auto i { 0 }; i < nbManifold; ++i)
105  {
106  const auto contactManifold = DynamicsWorld->getDispatcher()->getManifoldByIndexInternal(i);
107  if(contactManifold->getNumContacts() > 0)
108  AnnGetEventManager()->detectedCollision(
109  contactManifold->getBody0()->getUserPointer(),
110  contactManifold->getBody1()->getUserPointer(),
111  contactManifold->getContactPoint(0).getPositionWorldOnB(),
112  contactManifold->getContactPoint(0).m_normalWorldOnB);
113  }
114 }
115 
116 void AnnPhysicsEngine::removeRigidBody(btRigidBody* body) const
117 {
118  AnnDebug() << "Removing " << body << " Form physics simulation";
119  if(body)
120  DynamicsWorld->removeRigidBody(body);
121 }
122 
124 {
125  if(state)
126  {
127  debugDrawer->setDebugMode(btIDebugDraw::DBG_DrawWireframe
128  | btIDebugDraw::DBG_FastWireframe
129  | btIDebugDraw::DBG_DrawContactPoints);
130  }
131  else
132  {
133  debugDrawer->setDebugMode(0);
134  }
135 
136  debugPhysics = state;
137  debugDrawer->step();
138 }
139 
141 {
142  DynamicsWorld->setGravity(gravity.getBtVector());
143 }
144 
146 {
148 }
149 
151 {
152  stepDebugDrawer();
153  step(float(AnnGetEngine()->getFrameTime()));
155 }
156 
158 {
160 }
161 
162 void AnnPhysicsEngine::initPlayerRoomscalePhysics(Ogre::SceneNode* playerAnchorNode) const
163 {
164  playerObject->setMode(ROOMSCALE);
165  AnnDebug() << "Initializing player's physics in RoomScale mode";
166 
167  btCollisionShape* sphere = new btSphereShape(0.25f);
168  auto body = new btRigidBody(0, nullptr, sphere);
169 
170  playerObject->setShape(sphere);
171  playerObject->setBody(body);
172 
173  playerObject->setRoomRefNode(playerAnchorNode);
174  playerObject->resetPlayerPhysics(); //this will properly put the player at it's intended position and will put it inside the dynamics world.
175 }
176 
178 {
179  playerObject->setMode(STANDING);
180  AnnDebug() << "Player's Capsule RigidBody : " << playerObject->getMass() << "Kg" << playerObject->getEyesHeight();
184 }
185 
187 {
188  debugDrawer->setUnlitDiffuseMultiplier(value);
189 }
190 
192 {
193  BtOgre::StaticMeshToShapeConverter converter(obj->getItem());
194 
195  btCollisionShape* Shape;
196 
197  switch(type)
198  {
199  case boxShape:
200  Shape = converter.createBox();
201  break;
202  case cylinderShape:
203  Shape = converter.createCylinder();
204  break;
205  case capsuleShape:
206  Shape = converter.createCapsule();
207  break;
208  case convexShape:
209  Shape = converter.createConvex();
210  break;
211  case staticShape:
212  Shape = converter.createTrimesh();
213  break;
214  case sphereShape:
215  Shape = converter.createSphere();
216  break;
217  default:
218  //non valid;
219  AnnDebug(Log::Important) << "Error: Requested shape is invalid";
221  }
222  return Shape;
223 }
std::unique_ptr< btDiscreteDynamicsWorld > DynamicsWorld
Bullet Dynamics World.
std::unique_ptr< btBroadphaseInterface > Broadphase
Bullet Broadphase.
AnnEngine * AnnGetEngine()
Get the current instance of AnnEngine.
Definition: AnnGetter.cpp:10
void initPlayerRoomscalePhysics(Ogre::SceneNode *playerAnchorNode) const
Init the "room-scale" physics model where the controls don't break when the player move is ass in the...
void resetGravity() const
Restore the default gravity.
~AnnPhysicsEngine()
Destroy the physics engine.
std::string getName() const
Return the name of the object.
void toggleDebugPhysics()
Toggle the debug physics overlay.
void setDebugDrawerColorMultiplier(float value) const
Set the color multiplier to convert raw color to HDR light value.
std::unique_ptr< btDefaultCollisionConfiguration > CollisionConfiguration
Bullet Default Collision Configuration.
A 3D Vector.
Definition: AnnVect3.hpp:16
bool debugPhysics
Should use the debug drawer.
void changeGravity(AnnVect3 gravity) const
Change the gravity vector.
Namespace containing the totality of Annwvyn components.
Definition: AnnGetter.cpp:8
btVector3 getBtVector() const
Return as bullet vector.
Definition: AnnVect3.cpp:44
btCollisionShape * _getGameObjectShape(AnnGameObject *obj, phyShapeType type)
advanced : functions called to setup physics by game objects
class that represent the player
void update() override
Update by steeping simulation by one frame time. Should be called only once, and only by AnnEngine.
static std::string getBulletVersion()
An object that exist in the game. Graphically and Potentially Physically.
phyShapeType
Definition: AnnTypes.h:43
void initPlayerStandingPhysics(Ogre::SceneNode *playerAnchorNode)
Init the class "standing" designed for the Oculus physics where the player is not moving in the room ...
btDiscreteDynamicsWorld * getWorld() const
Pointer to the bullet's dynamics world.
Create a ostream to the Ogre logger.
Ogre::SceneManager * getSceneManager() const
Get ogre scene manager.
Definition: AnnEngine.cpp:331
std::unique_ptr< btCollisionDispatcher > Dispatcher
Bullet Collision Dispatcher.
BtOgre::RigidBodyState * playerRigidBodyState
Rigid body state from BtOgre for the Player object.
void createVirtualBodyShape(float radius=0.125f) const
Create player's body shape (a capsule)
Open an output stream to the engine log.
Definition: AnnLogger.hpp:23
AnnVect3 defaultGravity
Default value for gravity. Should be initialized to (0, -9.82f, 0) unless something is wrong with thi...
void addPlayerPhysicalBodyToDynamicsWorld() const
Add the player body to the dynamics world.
std::unique_ptr< BtOgre::DebugDrawer > debugDrawer
Debug drawer object from BtOgre.
void setDebugPhysics(bool state)
Set the debug drawer state.
void stepDebugDrawer() const
Step the debug drawing for the physical representation.
Exception regarding collision shape creation.
void removeRigidBody(btRigidBody *body) const
Remove a body from simulation.
T get(T... args)
Parent class of all Annwvyn SubSystem.
The Physics Engine handle the Bullet "dynamics world" where the simulation occurs....
AnnEventManagerPtr AnnGetEventManager()
Get the event manager.
Definition: AnnGetter.cpp:16
AnnPlayerBodyPtr playerObject
Shared pointer to the player.
void createPlayerPhysicalVirtualBody(Ogre::SceneNode *node)
Create player's rigid-body.
void step(float delta) const
void processCollisionTesting() const
Process the collision query system.
std::unique_ptr< btSequentialImpulseConstraintSolver > Solver
Bullet Sequential Impulse Constraint Solver.
AnnPhysicsEngine(Ogre::SceneNode *rootNode, AnnPlayerBodyPtr player)
Create the physics engine.
Ogre::Item * getItem() const
Get the item of this object.