ToyMaker Game Engine 0.0.2
ToyMaker is a game engine developed and maintained by Zoheb Shujauddin.
Loading...
Searching...
No Matches
system.hpp
Go to the documentation of this file.
1
10
16
17#ifndef TOYMAKERENGINE_PHYSICSSYSTEM_H
18#define TOYMAKERENGINE_PHYSICSSYSTEM_H
19
20#include <unordered_set>
21
22#include <nlohmann/json.hpp>
23
24#include "../core/ecs_world.hpp"
25#include "../signals.hpp"
28
29#include "types.hpp"
30
31namespace ToyMaker {
48 class PhysicsSystem: public System<PhysicsSystem, std::tuple<PhysicsState, ObjectBounds>, std::tuple<>>, public SignalTracker {
49 public:
56 using ConstraintID = std::size_t;
57
62 using SignalCollidedData = std::pair<CollisionPair, Collision>;
63
69
74 using SignalCollided = std::shared_ptr<Signal<SignalCollidedData>>;
75
80 using SignalSeparated = std::shared_ptr<Signal<SignalSeparatedData>>;
81
82
87 static const std::string SignalCollidedPrefix;
88
93 static const std::string SignalSeparatedPrefix;
94
95 explicit PhysicsSystem(std::weak_ptr<ECSWorld> world):
96 System<PhysicsSystem, std::tuple<PhysicsState, ObjectBounds>, std::tuple<>>{ world }
97 {}
98
105 inline static std::string getSystemTypeName() { return "PhysicsSystem"; }
106
113 inline void setSubsteps(uint8_t newSubsteps) {
114 assert(newSubsteps > 0 && "Substeps must be 1 or greater");
115 mSubsteps = newSubsteps;
116 }
117
122 inline uint8_t getSubsteps() const {
123 return mSubsteps;
124 }
125
132 template<typename TConstraint,
133 std::enable_if_t<
134 std::is_base_of<
136 TConstraint
137 >::value, bool
138 > = true
139 >
141 const typename TConstraint::Config& config,
142 const std::vector<std::pair<EntityID, typename TConstraint::Parameter>>& parameters,
143 float compliance
144 );
145
152 template<typename TConstraint>
153 TConstraint& getConstraint(ConstraintID constraint);
154
160 template<typename TConstraint>
161 const TConstraint& getConstraint(ConstraintID constraint) const;
162
167 void unregisterConstraint(ConstraintID constraint);
168
169 private:
170
171 // storage for intermediate physics state
173 ObjectBounds mBounds;
174 PhysicsState mPhysics;
175 };
176
177 // storage for intermediate collision events
179 SignalCollidedData mCollided;
180 SignalSeparatedData mSeparated;
181 };
182
188 bool mCollided { false };
189 CollisionEvent mEvent;
190 };
191
196 void onSimulationActivated() override;
197
204 void onSimulationStep(uint32_t timestepMillis) override;
205
212 void onEntityEnabled(EntityID entityID) override;
213
221 void onEntityUpdated(EntityID entityID, ComponentType updatedComponent) override;
222
227 void onEntityDisabled(EntityID entityID) override;
228
233 bool isConstraintActive(ConstraintID constraint) const;
234
240 void updateProperties(EntityID entityID);
241
248
257 void integrateForces(float substepSeconds, std::unordered_map<EntityID, PhysicsStateFull>& previousState, std::unordered_map<EntityID, PhysicsStateFull>& currentState);
258
263 void deriveVelocities(float substepSeconds, const std::unordered_map<EntityID, PhysicsStateFull>& previousState, std::unordered_map<EntityID, PhysicsStateFull>& currentState);
264
269 void applyPositionCollisionConstraints(std::map<CollisionPair, ConstraintContactManifold>& potentialCollisions, float substepSeconds, std::unordered_map<EntityID, PhysicsStateFull>& currentState);
270
275 void applyVelocityCollisionConstraints(std::map<CollisionPair, ConstraintContactManifold>& constraints, float substepSeconds, std::unordered_map<EntityID, PhysicsStateFull>& currentState);
276
281 void applyPositionConstraints(std::map<CollisionPair, ConstraintContactManifold>& constraints, float substepSeconds, std::unordered_map<EntityID, PhysicsStateFull>& currentState);
282
287 void applyVelocityConstraints(std::map<CollisionPair, ConstraintContactManifold>& constraints, float substepSeconds, std::unordered_map<EntityID, PhysicsStateFull>& currentState);
288
297 std::map<CollisionPair, ConstraintContactManifold>& potentialCollisions,
298 std::queue<CollisionReport>& queuedReports,
299 std::unordered_map<EntityID, PhysicsStateFull>& previousStates,
300 std::unordered_map<EntityID, PhysicsStateFull>& currentStates,
301 uint8_t nthSubstep
302 );
303
308 void onCollided(const CollisionPair& pair, const Collision& collision, std::queue<CollisionReport>& queuedReports);
309
314 void onSeparated(const CollisionPair& pair, std::queue<CollisionReport>& queuedReports);
315
321
327
333 void reportCollisions(
334 std::queue<CollisionReport>& reports,
335 std::unordered_map<EntityID, std::pair<SignalCollided, SignalSeparated>> signallers
336 ) const;
337
343 bool wasColliding(const CollisionPair& pair) const;
344
349 void collectPotentialCollisions(float substepSeconds, std::queue<CollisionReport>& queuedReports);
350
356 std::set<EntityID> mEntitiesUninitialized {};
357
362 std::unordered_map<EntityID, PhysicsStateFull> mEntityStatePrevious {};
363
368 std::unordered_map<EntityID, PhysicsStateFull> mEntityStateCurrent {};
369
375 std::unordered_map<EntityID, std::set<ConstraintID>> mEntityConstraintMap {};
376
383 std::vector<std::pair<std::unique_ptr<BaseConstraint>, std::vector<EntityID>>> mConstraints {};
384
389 std::unordered_set<ConstraintID> mConstraintsDeleted {};
390
395 std::unordered_map<EntityID, ConstraintDampingRigidbody> mEntityDamping {};
396
404
409 std::unordered_map<EntityID, std::unordered_set<EntityID>> mEntityCollision {};
410
415 std::unordered_set<EntityID> mPotentialColliders {};
416
421 std::queue<CollisionReport> mCollisionReports {};
422
427 std::unordered_map<EntityID, std::pair<SignalCollided, SignalSeparated>> mCollisionSignallers {};
428
433 std::map<CollisionPair, ConstraintContactManifold> mCollisionConstraints {};
434
444 uint8_t mSubsteps { 3 };
445
451
457 };
458
459 inline const std::string PhysicsSystem::SignalCollidedPrefix { "collided_" };
460 inline const std::string PhysicsSystem::SignalSeparatedPrefix { "separated_" };
461
462 template<typename TConstraint,
463 std::enable_if_t<
464 std::is_base_of<
466 TConstraint
467 >::value, bool
468 >
469 >
471 const typename TConstraint::Config& config,
472 const std::vector<std::pair<EntityID, typename TConstraint::Parameter>>& participants,
473 float compliance
474 ) {
475 // reclaim a deleted constraint id if possible
476 ConstraintID newConstraint { mConstraints.size() };
477 if(!mConstraintsDeleted.empty()) {
478 newConstraint = *mConstraintsDeleted.begin();
479 mConstraintsDeleted.erase(newConstraint);
480 }
481
482 // get separate constraint parameter and participating entity lists
483 std::unordered_set<EntityID> registeredEntities {};
484 std::vector<EntityID> entities {};
485 std::vector<typename TConstraint::Parameter> constraintData {};
486 for(const std::pair<EntityID, typename TConstraint::Parameter>& participant: participants) {
487 const bool alreadyRegistered {
488 registeredEntities.find(participant.first) != registeredEntities.end()
489 };
490 assert(!alreadyRegistered && "An entity has appeared twice in the constraint registration list, which is invalid.");
491 constraintData.push_back(participant.second);
492 entities.push_back(participant.first);
493 registeredEntities.insert(participant.first);
494 }
495
496 // create constraint
497 if(newConstraint == mConstraints.size()) {
498 mConstraints.push_back({
499 std::make_unique<TConstraint>(config, constraintData, compliance),
500 entities
501 });
502 } else {
503 mConstraints[newConstraint] = {
504 std::make_unique<TConstraint>(config, constraintData, compliance),
505 entities
506 };
507 }
508
509 for(const auto& entity: entities) {
510 mEntityConstraintMap[entity].insert(newConstraint);
511 }
512
513 return newConstraint;
514 }
515
516 template<typename TConstraint>
518 return static_cast<TConstraint>(*mConstraints.at(constraint).first);
519 }
520
521 template<typename TConstraint>
522 const TConstraint& PhysicsSystem::getConstraint(ConstraintID constraint) const {
523 return static_cast<TConstraint>(*mConstraints.at(constraint).first);
524 }
525}
526
527#endif
528
Names two distinct entities participating in a collision, with their entity IDs sorted in ascending o...
Definition sweep_prune.hpp:29
Subclass implementation for any constraint which takes data of type TParameter.
Definition types.hpp:716
void applyVelocityConstraints(std::map< CollisionPair, ConstraintContactManifold > &constraints, float substepSeconds, std::unordered_map< EntityID, PhysicsStateFull > &currentState)
Applies all active velocity constraints.
Definition system.cpp:327
std::queue< CollisionReport > mCollisionReports
Storage for collision reports that should be signalled this simulation frame.
Definition system.hpp:421
void onEntityEnabled(EntityID entityID) override
Updates this entity's physics properties.
Definition system.cpp:476
TConstraint & getConstraint(ConstraintID constraint)
Returns a mutable reference to a constraint for viewing and modification.
Definition system.hpp:517
void onEntityUpdated(EntityID entityID, ComponentType updatedComponent) override
Updates this entity's physics properties.
Definition system.cpp:510
uint8_t getSubsteps() const
Gets the number of substeps used in the physics solver's XPBD implementation.
Definition system.hpp:122
void unregisterCollisionSignal(EntityID entity)
Unregisters collision signals for this entity.
Definition system.cpp:602
std::size_t ConstraintID
ID naming a unique constraint registered with the physics system.
Definition system.hpp:56
std::pair< CollisionPair, Collision > SignalCollidedData
Struct containing data about a collision event.
Definition system.hpp:62
static std::string getSystemTypeName()
The system type string for this class.
Definition system.hpp:105
void integrateForces(float substepSeconds, std::unordered_map< EntityID, PhysicsStateFull > &previousState, std::unordered_map< EntityID, PhysicsStateFull > &currentState)
Derives position and rotation updates for physics objects based on their current state and forces act...
Definition system.cpp:68
void onSeparated(const CollisionPair &pair, std::queue< CollisionReport > &queuedReports)
Removes pair of entities from collision list, appending collision event to queue if required.
Definition system.cpp:662
bool mRequiresInitialization
Whether physics properties for all eligible entities should be recomputed.
Definition system.hpp:450
bool wasColliding(const CollisionPair &pair) const
Whether or not a particular pair of entities have their collision tracked by the physics system.
Definition system.cpp:622
uint8_t mSubsteps
The number of substeps used in the physics system's XPBD implementation.
Definition system.hpp:444
std::unordered_map< EntityID, PhysicsStateFull > mEntityStatePrevious
Storage for local entity states prior to the integration step each substep.
Definition system.hpp:362
void updateProperties(EntityID entityID)
Computes rotational inertia from mass and object bounds.
Definition system.cpp:536
std::shared_ptr< Signal< SignalCollidedData > > SignalCollided
Signal for reporting collision start events.
Definition system.hpp:74
void onSimulationActivated() override
Marks this system as requiring initialization on the nearest update.
Definition system.cpp:18
void setSubsteps(uint8_t newSubsteps)
Sets the number of substeps used for physics integration using XPBD.
Definition system.hpp:113
std::unordered_map< EntityID, std::set< ConstraintID > > mEntityConstraintMap
Associates each entity with its set of constraints, used to determine whether the constraint can be e...
Definition system.hpp:375
std::unordered_set< EntityID > mPotentialColliders
A list of entities that may collide this frame.
Definition system.hpp:415
void applyPositionConstraints(std::map< CollisionPair, ConstraintContactManifold > &constraints, float substepSeconds, std::unordered_map< EntityID, PhysicsStateFull > &currentState)
Applies all active position constraints.
Definition system.cpp:281
bool mConstraintsInitialized
Whether we have yet to determine which constraints are active and which are not.
Definition system.hpp:456
SweepPrune mBroadPhase
Representation of the structure/technique being used to detect likely collisions.
Definition system.hpp:403
ConstraintID registerConstraint(const typename TConstraint::Config &config, const std::vector< std::pair< EntityID, typename TConstraint::Parameter > > &parameters, float compliance)
Registers a constraint for the physics system to evaluate every substep.
Definition system.hpp:470
static const std::string SignalSeparatedPrefix
Prefix for the name under which separated Signals are advertised.
Definition system.hpp:93
void collectPotentialCollisions(float substepSeconds, std::queue< CollisionReport > &queuedReports)
Collects potential collisions and builds constraints from them.
Definition system.cpp:142
std::unordered_map< EntityID, ConstraintDampingRigidbody > mEntityDamping
Mapping of entities to their velocity damping constraints.
Definition system.hpp:395
std::unordered_map< EntityID, PhysicsStateFull > mEntityStateCurrent
Storage for current local entity states, eventually pushed to ECS component tables.
Definition system.hpp:368
bool isConstraintActive(ConstraintID constraint) const
Whether or not a particular constraint is active.
Definition system.cpp:522
std::shared_ptr< Signal< SignalSeparatedData > > SignalSeparated
Signal for reporting the separation of two colliding bodies.
Definition system.hpp:80
std::map< CollisionPair, ConstraintContactManifold > mCollisionConstraints
Storage for pairs of entities that are likely to collide (or are colliding) this simulation frame.
Definition system.hpp:433
void updateCollisionEventQueue(std::map< CollisionPair, ConstraintContactManifold > &potentialCollisions, std::queue< CollisionReport > &queuedReports, std::unordered_map< EntityID, PhysicsStateFull > &previousStates, std::unordered_map< EntityID, PhysicsStateFull > &currentStates, uint8_t nthSubstep)
Tests each pair of potential colliders for intersection, adds collision report to the queue if config...
Definition system.cpp:429
void deriveVelocities(float substepSeconds, const std::unordered_map< EntityID, PhysicsStateFull > &previousState, std::unordered_map< EntityID, PhysicsStateFull > &currentState)
Derives actual object velocities after integration and constraint solve.
Definition system.cpp:387
void reportCollisions(std::queue< CollisionReport > &reports, std::unordered_map< EntityID, std::pair< SignalCollided, SignalSeparated > > signallers) const
Signals all collisions and separations collected over the course of the simulation step,...
Definition system.cpp:693
void unregisterConstraint(ConstraintID constraint)
Removes a constraint.
Definition system.cpp:514
static const std::string SignalCollidedPrefix
Prefix for the name under which collided Signals are advertised.
Definition system.hpp:87
void refreshActiveConstraints()
Determines which constraints are inactive (by virtue of all of their entities being enabled) and whic...
std::set< EntityID > mEntitiesUninitialized
Holds entities that haven't undergone proper initialization, and therefore aren't eligible for proper...
Definition system.hpp:356
void onEntityDisabled(EntityID entityID) override
Removes entity from to-initialize list.
Definition system.cpp:481
void onCollided(const CollisionPair &pair, const Collision &collision, std::queue< CollisionReport > &queuedReports)
Registers a pair of entities as intersecting, signalling to collision signal observers if required.
Definition system.cpp:636
CollisionPair SignalSeparatedData
Struct containing data about a separation event.
Definition system.hpp:68
void applyVelocityCollisionConstraints(std::map< CollisionPair, ConstraintContactManifold > &constraints, float substepSeconds, std::unordered_map< EntityID, PhysicsStateFull > &currentState)
Correctly applies collision velocity constraint for each potential collision detected.
Definition system.cpp:370
std::vector< std::pair< std::unique_ptr< BaseConstraint >, std::vector< EntityID > > > mConstraints
A list of all constraints known to the physics system, evaluated every frame.
Definition system.hpp:383
void onSimulationStep(uint32_t timestepMillis) override
Updates physics simulation.
Definition system.cpp:22
std::unordered_map< EntityID, std::pair< SignalCollided, SignalSeparated > > mCollisionSignallers
Entities whose collision events are signalled by this system.
Definition system.hpp:427
void applyPositionCollisionConstraints(std::map< CollisionPair, ConstraintContactManifold > &potentialCollisions, float substepSeconds, std::unordered_map< EntityID, PhysicsStateFull > &currentState)
Correctly applies collision position constraint for each potential collision detected.
Definition system.cpp:259
void registerCollisionSignal(EntityID entity)
Registers collision signals for this entity.
Definition system.cpp:606
std::unordered_map< EntityID, std::unordered_set< EntityID > > mEntityCollision
All currently intersecting entities.
Definition system.hpp:409
std::unordered_set< ConstraintID > mConstraintsDeleted
IDs of constraints that were deleted and which may be reused to define a new constraint.
Definition system.hpp:389
SignalTracker()
Constructs a new SignalTracker object.
A class designed around finding which pairs of AABBs may be intersecting (so as to limit the number o...
Definition sweep_prune.hpp:85
A system template that disables systems with this form of declaration.
Definition ecs_world.hpp:1085
ToyMaker Engine's implementation of an ECS system.
ECSType ComponentType
An unsigned integer representing the type of a component.
Definition ecs_world.hpp:101
std::uint64_t EntityID
A single unsigned integer used as a name for an entity managed by an ECS system.
Definition ecs_world.hpp:66
Namespace containing all class definitions and functions related to the ToyMaker engine.
Definition application.hpp:26
STL namespace.
Classes relating to this engine's implementation of signals. Contains template classes used to define...
Classes and structs representing data related to the engine's spatial query system (the precursor to ...
Data representing everything about a collision.
Definition types.hpp:816
A component defining the true bounds of a spatially queryable object situated somewhere in the world.
Definition types.hpp:845
Component representing the physics state of the body it's attached to at some particular point in tim...
Definition types.hpp:142
bool mCollided
Whether this report corresponds to a collided or separated event.
Definition system.hpp:188
Acceleration structure for finding pairs of objects whose AABBs are intersecting.