CORGI
An open source project by FPL.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Groups Pages
physics.h
Go to the documentation of this file.
1 // Copyright 2015 Google Inc. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef CORGI_COMPONENT_LIBRARY_PHYSICS_H_
16 #define CORGI_COMPONENT_LIBRARY_PHYSICS_H_
17 
18 #include <memory>
19 #include <vector>
20 
21 #include "breadboard/event.h"
22 #include "corgi/component.h"
23 #include "flatbuffers/reflection.h"
24 #include "fplbase/asset_manager.h"
25 #include "fplbase/renderer.h"
26 #include "fplbase/shader.h"
27 #include "library_components_generated.h"
28 #include "mathfu/glsl_mappings.h"
29 
30 /// @cond COMPONENT_LIBRARY_INTERNAL
31 class btBroadphaseInterface;
32 class btCollisionDispatcher;
33 class btCollisionShape;
34 class btDefaultCollisionConfiguration;
35 class btDiscreteDynamicsWorld;
36 class btMotionState;
37 class btRigidBody;
38 class btSequentialImpulseConstraintSolver;
39 class btTriangleMesh;
40 
41 namespace corgi {
42 namespace component_library {
43 
44 BREADBOARD_DECLARE_EVENT(kCollisionEventId)
45 
46 class PhysicsComponent;
47 class PhysicsDebugDrawer;
48 /// @endcond
49 
50 /// @file
51 /// @addtogroup corgi_component_library
52 /// @{
53 
54 /// @var kMaxPhysicsBodies
55 ///
56 /// @brief The maximum number of physics bodies per Entity.
57 static const int kMaxPhysicsBodies = 5;
58 
59 /// @var kDefaultPhysicsGravity
60 ///
61 /// @brief The constant for gravity.
62 static const float kDefaultPhysicsGravity = -9.8f;
63 
64 /// @var kDefaultPhysicsMaxSteps
65 ///
66 /// @brief The default number of max steps to advance per frame.
67 static const int kDefaultPhysicsMaxSteps = 5;
68 
69 /// @struct CollisionData
70 ///
71 /// @brief Data describing which Entities were involed in a collision and where.
72 struct CollisionData {
73  /// @var this_entity
74  ///
75  /// @brief The first Entity involved in the collision.
77 
78  /// @var this_position
79  ///
80  /// @brief The position of the first Entity involved in the collision.
81  mathfu::vec3 this_position;
82 
83  /// @var this_tag
84  ///
85  /// @brief A std::string tag to identify the first Entity involved in the
86  /// collision.
87  std::string this_tag;
88 
89  /// @var other_entity
90  ///
91  /// @brief The second Entity involved in the collision.
93 
94  /// @var other_position
95  ///
96  /// @brief The position of the second Entity involved in the collision.
97  mathfu::vec3 other_position;
98 
99  /// @var other_tag
100  ///
101  /// @brief A std::string tag to identify the second Entity involved in the
102  /// collision.
103  std::string other_tag;
104 };
105 
106 /// @typedef CollisionCallback
107 ///
108 /// @brief A function pointer for the callback after a collision.
109 typedef void (*CollisionCallback)(CollisionData* collision_data,
110  void* user_data);
111 
112 /// @struct RigidBodyData
113 ///
114 /// @brief Data describing a single Bullet rigid body shape.
116  /// @brief Constructor for RigidBodyData.
117  RigidBodyData();
118  /// @brief Destructor for RigidBodyData.
119  ~RigidBodyData();
120 
121  /// @var offset
122  ///
123  /// @brief The position offset from the origin of the
124  /// TransformComponent to the center.
125  mathfu::vec3 offset;
126 
127  /// @var collision_type
128  ///
129  /// @brief A bit field determining what type of collision object this is.
131 
132  /// @var collides_with
133  ///
134  /// @brief A bit field determining what types of objects it can collide into.
136 
137  /// @var user_tag
138  ///
139  /// @brief A user-defined C-string tag to identify this rigid body.
140  std::string user_tag;
141 
142  /// @var shape
143  ///
144  /// @brief The btCollisionShape of the RigidBodyData.
145  std::unique_ptr<btCollisionShape> shape;
146 
147  /// @var motion_state
148  ///
149  /// @brief The btMotionState of the RigidBodyData.
150  std::unique_ptr<btMotionState> motion_state;
151 
152  /// @var rigid_body
153  ///
154  /// @brief The btRigidBody of the RigidBodyData.
155  std::unique_ptr<btRigidBody> rigid_body;
156 
157  /// @var should_export
158  ///
159  /// @brief Should the shape be included on export.
161 
162  /// @brief The move assignment operator for RigidBodyData.
163  ///
164  /// @param[in] src The other RigidBodyData to move into this RigidBodyData.
165  RigidBodyData& operator=(RigidBodyData&& src);
166 
167  private:
168  RigidBodyData& operator=(const RigidBodyData&);
170 };
171 
172 /// @struct PhysicsData
173 ///
174 /// @brief Data for scene object Components.
175 struct PhysicsData {
176  /// @cond COMPONENT_LIBRARY_INTERNAL
177  friend PhysicsComponent;
178  /// @endcond
179 
180  public:
181  /// @brief Constructor for PhysicsData.
182  PhysicsData();
183 
184  /// @brief Destructor for PhysicsData.
185  ~PhysicsData();
186 
187  /// @brief The move constructor for PhysicsData.
188  ///
189  /// @param[in] src The other PhysicsData to move into this PhysicsData.
190  PhysicsData(PhysicsData&& src);
191 
192  /// @brief The move assignment operator for PhysicsData.
193  ///
194  /// @param[in] src The other PhysicsData to move into this PhysicsData.
195  PhysicsData& operator=(PhysicsData&& src);
196 
197  /// @brief Get the velocity of the Entity.
198  ///
199  /// @return Returns the velocity of this Entity as a mathfu::vec3.
200  mathfu::vec3 Velocity() const;
201 
202  /// @brief Set the velocity of the Entity.
203  ///
204  /// @param[in] velocity A const mathfu::vec3 reference to the velocity
205  /// to set for this Entity.
206  void SetVelocity(const mathfu::vec3& velocity);
207 
208  /// @brief Get the angular velocity of the Entity.
209  ///
210  /// @return Returns the angular velocity of the Entity as a mathfu::vec3.
211  mathfu::vec3 AngularVelocity() const;
212 
213  /// @brief Set the angular velocity of the Entity.
214  ///
215  /// @param[in] velocity A const mathfu::vec3 reference to the angular velocity
216  /// to set for the Entity.
217  void SetAngularVelocity(const mathfu::vec3& velocity);
218 
219  /// @brief Get the index for the RigidBody for a given tag.
220  ///
221  /// @param[in] user_tag A const reference to a std::string of the tag for
222  /// the desired rigid body.
223  ///
224  /// @return Returns an int corresponding to the index of the rigid body.
225  int RigidBodyIndex(const std::string& user_tag) const;
226 
227  /// @brief Get the axis-aligned bounding box (AABB) of a rigid body at a given
228  /// index.
229  ///
230  /// @param[in] rigid_body_idx The index of the rigid body whose AABB should
231  /// be returned though `min` and `max`.
232  /// @param[out] min A mathfu::vec3 pointer that captures the output of the
233  /// mininum corner of the AABB.
234  /// @param[out] max A mathfu::vec3 pointer that captures the output of the
235  /// maximum corner of the AABB.
236  void GetAabb(int rigid_body_idx, mathfu::vec3* min, mathfu::vec3* max) const;
237 
238  /// @brief Check if this physics is enabled for this Entity.
239  ///
240  /// @return Returns `true` if the physics is enabled. Otherwise, return
241  /// `false`.
242  bool enabled() const { return enabled_; }
243 
244  /// @brief Get the number of physics shapes for this Entity.
245  ///
246  /// @return Returns an int corresponding to the body count.
247  int body_count() const { return body_count_; }
248 
249  private:
250  PhysicsData(const PhysicsData&);
251  PhysicsData& operator=(const PhysicsData&);
252 
253  // The rigid bodies associated with the entity. Note that only the first one
254  // can be set to not be kinematic, all subsequent ones are forced to be.
255  RigidBodyData rigid_bodies_[kMaxPhysicsBodies];
256  std::unique_ptr<btTriangleMesh> triangle_mesh_;
257  int body_count_;
258  bool enabled_;
259  float gravity_multiplier_;
260 };
261 
262 /// @class PhysicsComponent
263 ///
264 /// @brief The Component that manages the physics for every Entity
265 /// that registers with it.
266 class PhysicsComponent : public corgi::Component<PhysicsData> {
267  public:
268  /// @brief Constructor for the PhysicsComponent.
270 
271  /// @brief Destructor for the PhysicsComponent.
272  virtual ~PhysicsComponent();
273 
274  /// @brief Deserialize a flat binary buffer to create and populate an Entity
275  /// from raw data.
276  ///
277  /// @param[in,out] entity An EntityRef reference that points to an Entity that
278  /// is being added from the raw data.
279  /// @param[in] raw_data A void pointer to the raw FlatBuffer data.
280  virtual void AddFromRawData(corgi::EntityRef& entity, const void* raw_data);
281 
282  /// @brief Serializes a PhysicsComponent's data for a given Entity.
283  ///
284  /// @param[in] entity An EntityRef reference to an Entity whose corresponding
285  /// PhysicsData will be serialized.
286  ///
287  /// @return Returns a RawDataUniquePtr to the start of the raw data in a
288  /// flat binary buffer.
289  virtual RawDataUniquePtr ExportRawData(const corgi::EntityRef& entity) const;
290 
291  /// @brief Initializes the internal state of the variables for the
292  /// PhysicsComponent.
293  virtual void Init();
294 
295  /// @brief Adds an Entity to the TransformComponent.
296  ///
297  /// @note PhysicsComponents require that you have a TransformComponent.
298  virtual void InitEntity(corgi::EntityRef& /*entity*/);
299 
300  /// @brief Disables physics for the given Entity.
301  ///
302  /// @param[in] entity An EntityRef reference to the Entity that
303  /// should be cleaned up by having its physics disabled.
304  virtual void CleanupEntity(corgi::EntityRef& entity);
305 
306  /// @brief Update the physics data for all Entities registered with
307  /// this Component.
308  ///
309  /// @param[in] delta_time The time delta since the last call.
310  virtual void UpdateAllEntities(corgi::WorldTime delta_time);
311 
312  /// @brief Called after every Bullet frame update to handle all the
313  /// collisions.
314  void ProcessBulletTickCallback();
315 
316  /// @brief Update the physics world to match the transform for
317  /// a given Entity.
318  ///
319  /// @param[in] entity The Entity whose physics data should be updated
320  /// to match the transform data.
321  void UpdatePhysicsFromTransform(const corgi::EntityRef& entity);
322 
323  /// @brief Update the physics scale to match the transform for a
324  /// given Entity.
325  ///
326  /// @param[in] entity The Entity whose physics scale should be updated
327  /// to match the transform data.
328  void UpdatePhysicsScale(const corgi::EntityRef& entity);
329 
330  /// @brief Enables physics for a given Entity.
331  ///
332  /// @param[in] entity An EntityRef reference to the Entity whose
333  /// physics should be enabled.
334  void EnablePhysics(const corgi::EntityRef& entity);
335 
336  /// @brief Disables physics for a given Entity.
337  ///
338  /// @param[in] entity An EntityRef reference to the Entity whose
339  /// physics should be disabled.
340  void DisablePhysics(const corgi::EntityRef& entity);
341 
342  /// @brief Activate the rigid bodies for a given Entity to force reevaluation
343  /// within the scene.
344  ///
345  /// @param[in] entity An EntityRef reference to the Entity
346  /// whose rigid bodies should be activated.
347  void AwakenEntity(const corgi::EntityRef& entity);
348 
349  /// @brief Activates the rigid bodies in every Entity to force reevaluation
350  /// within the scene.
351  void AwakenAllEntities();
352 
353  /// @brief Initialize the data needed to generate a static mesh.
354  ///
355  /// Adds the entity to the PhysicsComponent, if necessary.
356  ///
357  /// @param[in] entity An EntityRef to the entity that should be added to the
358  /// PhysicsComponent, if necessary.
359  void InitStaticMesh(corgi::EntityRef& entity);
360 
361  /// @brief Add a triangle to the static mesh for the given entity.
362  ///
363  /// @note Note that `InitStaticMesh()` needs to be called beforehand.
364  ///
365  /// @param[in] entity An EntityRef to the Entity whose PhysicsData should
366  /// add the new static mesh.
367  /// @param[in] pt0 The first vertex for the triangle.
368  /// @param[in] pt1 The second vertex for the triangle.
369  /// @param[in] pt2 The third vertex for the triangle.
370  void AddStaticMeshTriangle(const corgi::EntityRef& entity,
371  const mathfu::vec3& pt0, const mathfu::vec3& pt1,
372  const mathfu::vec3& pt2);
373 
374  /// @brief Generates a static mesh shape and adds it to the world, based on
375  /// the previously added static mesh triangles.
376  ///
377  /// @param[in] entity An EntityRef to the Entity whose PhysicsData contains
378  /// the static mesh.
379  /// @param[in] collision_type A bit field determining the type of collision
380  /// for the rigid body.
381  /// @param[in] collides_with A bit field determining what type of objects
382  /// the rigid body can collide into.
383  /// @param[in] mass The mass of the rigid body.
384  /// @param[in] restitution The restitution for the rigid body.
385  /// @param[in] user_tag A C-string provided by the user to identify the
386  /// rigid body.
387  void FinalizeStaticMesh(const corgi::EntityRef& entity, short collision_type,
388  short collides_with, float mass, float restitution,
389  const std::string& user_tag);
390 
391  /// @brief Generate an AABB based on the rendermesh that collides with the
392  /// raycast layer.
393  ///
394  /// @note If the entity already collides with the raycast layer, no
395  /// change occurs. If there is no rendermesh, a unit cube is used instead.
396  ///
397  /// @param[in] entity An EntityRef to the Entity whose AABB should be
398  /// generated for raycasting.
399  /// @param[in] result_exportable A bool flag determining if the resulting
400  /// shape should be exported.
401  void GenerateRaycastShape(corgi::EntityRef& entity, bool result_exportable);
402 
403  /// @brief Performs a raycast into the world, returning the first Entity hit.
404  ///
405  /// @param[in] start The start point (origin) of the ray.
406  /// @param[in] end The end point of the ray.
407  ///
408  /// @return Returns an EntityRef to the first Entity that was hit.
409  corgi::EntityRef RaycastSingle(mathfu::vec3& start, mathfu::vec3& end);
410 
411  /// @brief Performs a raycast into the world, returning the first Entity hit.
412  ///
413  /// @param[in] start The start point (origin) of the ray.
414  /// @param[in] end The end point of the ray.
415  /// @param[in] layer_mask A bit field used to specify which layers the raycast
416  /// could hit.
417  ///
418  /// @return Returns an EntityRef to the first Entity that was hit.
419  corgi::EntityRef RaycastSingle(mathfu::vec3& start, mathfu::vec3& end,
420  short layer_mask);
421 
422  /// @brief Performs a raycast into the world, returning the first Entity hit.
423  ///
424  /// @param[in] start The start point (origin) of the ray.
425  /// @param[in] end The end point of the ray.
426  /// @param[out] hit_point Captures the output of the value where the ray hit
427  /// the Entity in world position, as a vec3.
428  ///
429  /// @return Returns an EntityRef to the first Entity that was hit.
430  corgi::EntityRef RaycastSingle(mathfu::vec3& start, mathfu::vec3& end,
431  mathfu::vec3* hit_point);
432 
433  /// @brief Performs a raycast into the world, returning the first Entity hit.
434  ///
435  /// @param[in] start The start point (origin) of the ray.
436  /// @param[in] end The end point of the ray.
437  /// @param[in] layer_mask A bit field used to specify which layers the raycast
438  /// could hit.
439  /// @param[out] hit_point Captures the output of the value where the ray hit
440  /// the Entity in world position, as a vec3.
441  ///
442  /// @return Returns an EntityRef to the first Entity that was hit.
443  corgi::EntityRef RaycastSingle(mathfu::vec3& start, mathfu::vec3& end,
444  short layer_mask, mathfu::vec3* hit_point);
445 
446  /// @brief Get the gravity value of the given Entity.
447  ///
448  /// @param[in] entity The Entity to get the custom gravity for.
449  /// @return The gravity value of the Entity.
450  float GravityForEntity(const corgi::EntityRef& entity) const;
451 
452  /// @brief Render the entire physics worlds using Bullet's default
453  /// debugging tools.
454  ///
455  /// @param[in] renderer A pointer to the fplbase::Renderer to handle the
456  /// rendering.
457  /// @param[in] camera_transform The camera transform for the view projection.
458  void DebugDrawWorld(fplbase::Renderer* renderer,
459  const mathfu::mat4& camera_transform);
460 
461  /// @brief Render a given Entity's physics using Bullet's default debugging
462  /// tools.
463  ///
464  /// @param[in] renderer A pointer to the fplbase::Renderer to handle the
465  /// rendering.
466  /// @param[in] camera_transform The camera transform for the view projection.
467  /// @param[in] entity The Entity whose physics should be rendered.
468  /// @param[in] color The color to draw the object in RGB.
469  void DebugDrawObject(fplbase::Renderer* renderer,
470  const mathfu::mat4& camera_transform,
471  const corgi::EntityRef& entity,
472  const mathfu::vec3& color);
473 
474  /// @brief Get the bullet world.
475  ///
476  /// @return Returns the bullet world as a pointer to
477  /// `btDiscreteDynamicsWorld`.
478  btDiscreteDynamicsWorld* bullet_world() { return bullet_world_.get(); }
479 
480  /// @brief Set the gravity value.
481  ///
482  /// @param[in] gravity A float to set as the new gravity value.
483  void set_gravity(float gravity) { gravity_ = gravity; }
484 
485  /// @brief Get the gravity value.
486  ///
487  /// @return Returns the gravity as a float.
488  float gravity() const { return gravity_; }
489 
490  /// @brief Set the max steps.
491  ///
492  /// @param[in] max_steps An int to set as the new max steps value.
493  void set_max_steps(int max_steps) { max_steps_ = max_steps; }
494 
495  /// @brief Get the max steps.
496  ///
497  /// @return Returns the max steps as an int.
498  int max_steps() const { return max_steps_; }
499 
500  /// @brief Get the collision data.
501  ///
502  /// @return Returns a reference to the CollisionData.
503  CollisionData& collision_data() { return collision_data_; }
504 
505  /// @brief Sets the callback function for collisions.
506  ///
507  /// @param[in] callback The event callback to call when a collision occurs.
508  /// If a callback is registered, then it is called in addition to evaluating
509  /// the graph.
510  /// @param[in] user_data A void pointer to any data provided to for the
511  /// `callback`.
512  void set_collision_callback(CollisionCallback callback, void* user_data) {
513  collision_callback_ = callback;
514  collision_user_data_ = user_data;
515  }
516 
517  private:
518  void ClearPhysicsData(const corgi::EntityRef& entity);
519  void UpdatePhysicsObjectsTransform(const corgi::EntityRef& entity,
520  bool kinematic_only);
521 
522  // Collision data is cached so that the event graphs can operate on it.
523  CollisionData collision_data_;
524 
525  // An event callback to call when a collision occurs. If a callback is
526  // registered, it is called in addition to evaluating the graph.
527  CollisionCallback collision_callback_;
528  void* collision_user_data_;
529 
530  std::unique_ptr<btDiscreteDynamicsWorld> bullet_world_;
531  std::unique_ptr<btBroadphaseInterface> broadphase_;
532  std::unique_ptr<btDefaultCollisionConfiguration> collision_configuration_;
533  std::unique_ptr<btCollisionDispatcher> collision_dispatcher_;
534  std::unique_ptr<btSequentialImpulseConstraintSolver> constraint_solver_;
535 
536  std::unique_ptr<PhysicsDebugDrawer> debug_drawer_;
537 
538  float gravity_;
539  int max_steps_;
540 };
541 /// @}
542 
543 } // component_library
544 } // corgi
545 
546 CORGI_REGISTER_COMPONENT(corgi::component_library::PhysicsComponent,
547  corgi::component_library::PhysicsData)
548 
549 #endif // CORGI_COMPONENT_LIBRARY_PHYSICS_H_
static const int kDefaultPhysicsMaxSteps
The default number of max steps to advance per frame.
Definition: physics.h:67
std::unique_ptr< uint8_t, std::function< void(uint8_t *)> > RawDataUniquePtr
A pointer type for exported raw data.
Definition: component_interface.h:63
std::unique_ptr< btRigidBody > rigid_body
The btRigidBody of the RigidBodyData.
Definition: physics.h:155
A Component is an object that encapsulates all data and logic for Entities of a particular type...
Definition: component.h:43
void set_collision_callback(CollisionCallback callback, void *user_data)
Sets the callback function for collisions.
Definition: physics.h:512
corgi::EntityRef this_entity
The first Entity involved in the collision.
Definition: physics.h:76
btDiscreteDynamicsWorld * bullet_world()
Get the bullet world.
Definition: physics.h:478
static const int kMaxPhysicsBodies
The maximum number of physics bodies per Entity.
Definition: physics.h:57
static const float kDefaultPhysicsGravity
The constant for gravity.
Definition: physics.h:62
int max_steps() const
Get the max steps.
Definition: physics.h:498
Data describing which Entities were involed in a collision and where.
Definition: physics.h:72
int WorldTime
A typedef that represents time in the game.
Definition: entity_common.h:49
std::unique_ptr< btMotionState > motion_state
The btMotionState of the RigidBodyData.
Definition: physics.h:150
std::string this_tag
A std::string tag to identify the first Entity involved in the collision.
Definition: physics.h:87
mathfu::vec3 offset
The position offset from the origin of the TransformComponent to the center.
Definition: physics.h:125
std::string user_tag
A user-defined C-string tag to identify this rigid body.
Definition: physics.h:140
CollisionData & collision_data()
Get the collision data.
Definition: physics.h:503
int body_count() const
Get the number of physics shapes for this Entity.
Definition: physics.h:247
mathfu::vec3 other_position
The position of the second Entity involved in the collision.
Definition: physics.h:97
Data for scene object Components.
Definition: physics.h:175
float gravity() const
Get the gravity value.
Definition: physics.h:488
bool should_export
Should the shape be included on export.
Definition: physics.h:160
mathfu::vec3 this_position
The position of the first Entity involved in the collision.
Definition: physics.h:81
corgi::EntityRef other_entity
The second Entity involved in the collision.
Definition: physics.h:92
short collides_with
A bit field determining what types of objects it can collide into.
Definition: physics.h:135
A reference object for pointing into the vector pool. It acts as a pointer for vector pool elements a...
Definition: vector_pool.h:72
bool enabled() const
Check if this physics is enabled for this Entity.
Definition: physics.h:242
std::unique_ptr< btCollisionShape > shape
The btCollisionShape of the RigidBodyData.
Definition: physics.h:145
The Component that manages the physics for every Entity that registers with it.
Definition: physics.h:266
void set_max_steps(int max_steps)
Set the max steps.
Definition: physics.h:493
#define CORGI_REGISTER_COMPONENT(ComponentType, DataType)
Definition: component_id_lookup.h:48
void set_gravity(float gravity)
Set the gravity value.
Definition: physics.h:483
std::string other_tag
A std::string tag to identify the second Entity involved in the collision.
Definition: physics.h:103
Data describing a single Bullet rigid body shape.
Definition: physics.h:115
short collision_type
A bit field determining what type of collision object this is.
Definition: physics.h:130
void(* CollisionCallback)(CollisionData *collision_data, void *user_data)
A function pointer for the callback after a collision.
Definition: physics.h:109