Overte C++ Documentation
PhysicsEngine.h
1 //
2 // PhysicsEngine.h
3 // libraries/physics/src
4 //
5 // Created by Andrew Meadows 2014.10.29
6 // Copyright 2014 High Fidelity, Inc.
7 //
8 // Distributed under the Apache License, Version 2.0.
9 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
10 //
11 
12 #ifndef hifi_PhysicsEngine_h
13 #define hifi_PhysicsEngine_h
14 
15 #include <stdint.h>
16 #include <set>
17 #include <vector>
18 
19 #include <QUuid>
20 #include <btBulletDynamicsCommon.h>
21 #include <BulletCollision/CollisionDispatch/btGhostObject.h>
22 
23 #include "BulletUtil.h"
24 #include "ContactInfo.h"
25 #include "ObjectMotionState.h"
26 #include "ThreadSafeDynamicsWorld.h"
27 #include "ObjectAction.h"
28 #include "ObjectConstraint.h"
29 
30 const float HALF_SIMULATION_EXTENT = 512.0f; // meters
31 
32 class CharacterController;
33 class PhysicsDebugDraw;
34 
35 // simple class for keeping track of contacts
36 class ContactKey {
37 public:
38  ContactKey() = delete;
39  ContactKey(void* a, void* b) : _a(a), _b(b) {}
40  bool operator<(const ContactKey& other) const { return _a < other._a || (_a == other._a && _b < other._b); }
41  bool operator==(const ContactKey& other) const { return _a == other._a && _b == other._b; }
42  void* _a; // ObjectMotionState pointer
43  void* _b; // ObjectMotionState pointer
44 };
45 
46 struct ContactTestResult {
47  ContactTestResult() = delete;
48 
49  ContactTestResult(const ContactTestResult& contactTestResult) :
50  foundID(contactTestResult.foundID),
51  testCollisionPoint(contactTestResult.testCollisionPoint),
52  foundCollisionPoint(contactTestResult.foundCollisionPoint),
53  collisionNormal(contactTestResult.collisionNormal) {
54  }
55 
56  ContactTestResult(const QUuid& foundID, const glm::vec3& testCollisionPoint, const glm::vec3& otherCollisionPoint, const glm::vec3& collisionNormal) :
57  foundID(foundID),
58  testCollisionPoint(testCollisionPoint),
59  foundCollisionPoint(otherCollisionPoint),
60  collisionNormal(collisionNormal) {
61  }
62 
63  QUuid foundID;
64  // The deepest point of an intersection within the volume of the test shape, in world space.
65  glm::vec3 testCollisionPoint;
66  // The deepest point of an intersection within the volume of the found object, in world space.
67  glm::vec3 foundCollisionPoint;
68  // The normal vector of this intersection
69  glm::vec3 collisionNormal;
70 };
71 
72 using ContactMap = std::map<ContactKey, ContactInfo>;
73 using CollisionEvents = std::vector<Collision>;
74 
75 class PhysicsEngine {
76 public:
77  using ContactAddedCallback = bool (*)(btManifoldPoint& cp,
78  const btCollisionObjectWrapper* colObj0Wrap, int partId0, int index0,
79  const btCollisionObjectWrapper* colObj1Wrap, int partId1, int index1);
80 
81  class Transaction {
82  public:
83  void clear() {
84  objectsToRemove.clear();
85  objectsToAdd.clear();
86  objectsToReinsert.clear();
87  activeStaticObjects.clear();
88  }
89  std::vector<ObjectMotionState*> objectsToRemove;
90  std::vector<ObjectMotionState*> objectsToAdd;
91  std::vector<ObjectMotionState*> objectsToReinsert;
92  std::vector<ObjectMotionState*> activeStaticObjects;
93  };
94 
95  PhysicsEngine(const glm::vec3& offset);
96  ~PhysicsEngine();
97  void init();
98 
99  uint32_t getNumSubsteps() const;
100  int32_t getNumCollisionObjects() const;
101 
102  void removeObjects(const VectorOfMotionStates& objects);
103  void removeSetOfObjects(const SetOfMotionStates& objects); // only called during teardown
104 
105  void addObjects(const VectorOfMotionStates& objects);
106  void changeObjects(const VectorOfMotionStates& objects);
107  void reinsertObject(ObjectMotionState* object);
108 
109  void processTransaction(Transaction& transaction);
110 
111  void stepSimulation();
112  void harvestPerformanceStats();
113  void printPerformanceStatsToFile(const QString& filename);
114  void updateContactMap();
115  void doOwnershipInfectionForConstraints();
116 
117  bool hasOutgoingChanges() const { return _hasOutgoingChanges; }
118 
120  const VectorOfMotionStates& getChangedMotionStates();
121  const VectorOfMotionStates& getDeactivatedMotionStates() const { return _dynamicsWorld->getDeactivatedMotionStates(); }
122 
124  const CollisionEvents& getCollisionEvents();
125 
127  void dumpStatsIfNecessary();
128 
130  void saveNextPhysicsStats(QString filename);
131 
133  void setOriginOffset(const glm::vec3& offset) { _originOffset = offset; }
134 
136  const glm::vec3& getOriginOffset() const { return _originOffset; }
137 
138  void setCharacterController(CharacterController* character);
139 
140  void dumpNextStats() { _dumpNextStats = true; }
141 
142  EntityDynamicPointer getDynamicByID(const QUuid& dynamicID) const;
143  bool addDynamic(EntityDynamicPointer dynamic);
144  void removeDynamic(const QUuid dynamicID);
145  void forEachDynamic(std::function<void(EntityDynamicPointer)> actor);
146 
147  void setShowBulletWireframe(bool value);
148  void setShowBulletAABBs(bool value);
149  void setShowBulletContactPoints(bool value);
150  void setShowBulletConstraints(bool value);
151  void setShowBulletConstraintLimits(bool value);
152 
153  // Function for getting colliding objects in the world of specified type
154  // See PhysicsCollisionGroups.h for mask flags.
155  std::vector<ContactTestResult> contactTest(uint16_t mask, const ShapeInfo& regionShapeInfo, const Transform& regionTransform, uint16_t group = USER_COLLISION_GROUP_DYNAMIC, float threshold = 0.0f) const;
156 
157  void setContactAddedCallback(ContactAddedCallback cb);
158 
159  btDiscreteDynamicsWorld* getDynamicsWorld() const { return _dynamicsWorld; }
160  void removeContacts(ObjectMotionState* motionState);
161 
162 private:
163  QList<EntityDynamicPointer> removeDynamicsForBody(btRigidBody* body);
164  void addObjectToDynamicsWorld(ObjectMotionState* motionState);
165 
167  void bumpAndPruneContacts(ObjectMotionState* motionState);
168 
169  void doOwnershipInfection(const btCollisionObject* objectA, const btCollisionObject* objectB);
170 
171  btClock _clock;
172  btDefaultCollisionConfiguration* _collisionConfig = NULL;
173  btCollisionDispatcher* _collisionDispatcher = NULL;
174  btBroadphaseInterface* _broadphaseFilter = NULL;
175  btSequentialImpulseConstraintSolver* _constraintSolver = NULL;
176  ThreadSafeDynamicsWorld* _dynamicsWorld = NULL;
177  btGhostPairCallback* _ghostPairCallback = NULL;
178  std::unique_ptr<PhysicsDebugDraw> _physicsDebugDraw;
179 
180  ContactMap _contactMap;
181  CollisionEvents _collisionEvents;
182  QHash<QUuid, EntityDynamicPointer> _objectDynamics;
183  QHash<btRigidBody*, QSet<QUuid>> _objectDynamicsByBody;
184  std::set<btRigidBody*> _activeStaticBodies;
185  QString _statsFilename;
186 
187  glm::vec3 _originOffset;
188 
189  CharacterController* _myAvatarController;
190 
191  uint32_t _numContactFrames { 0 };
192 
193  bool _dumpNextStats { false };
194  bool _saveNextStats { false };
195  bool _hasOutgoingChanges { false };
196 
197 };
198 
199 typedef std::shared_ptr<PhysicsEngine> PhysicsEnginePointer;
200 
201 #endif // hifi_PhysicsEngine_h