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 {
32
33
50 class PhysicsSystem: public System<PhysicsSystem, std::tuple<PhysicsState, ObjectBounds>, std::tuple<>>, public SignalTracker {
51 public:
58 using ConstraintID = std::size_t;
59
64 using SignalCollidedData = std::pair<CollisionPair, Collision>;
65
71
76 using SignalCollided = std::shared_ptr<Signal<SignalCollidedData>>;
77
82 using SignalSeparated = std::shared_ptr<Signal<SignalSeparatedData>>;
83
84
89 static const std::string SignalCollidedPrefix;
90
95 static const std::string SignalSeparatedPrefix;
96
97 explicit PhysicsSystem(std::weak_ptr<ECSWorld> world):
98 System<PhysicsSystem, std::tuple<PhysicsState, ObjectBounds>, std::tuple<>>{ world }
99 {}
100
107 inline static std::string getSystemTypeName() { return "PhysicsSystem"; }
108
115 inline void setSubsteps(uint8_t newSubsteps) {
116 assert(newSubsteps > 0 && "Substeps must be 1 or greater");
117 mSubsteps = newSubsteps;
118 }
119
124 inline uint8_t getSubsteps() const {
125 return mSubsteps;
126 }
127
132 template<typename TConstraint, typename TConstraintData>
133 ConstraintID registerConstraint(const std::vector<std::pair<EntityID, TConstraintData>>& constraintData, float compliance);
134
139 void unregisterConstraint(ConstraintID constraint);
140
141 private:
142
143 // storage for intermediate physics state
145 ObjectBounds mBounds;
146 PhysicsState mPhysics;
147 };
148
149 // storage for intermediate collision events
151 SignalCollidedData mCollided;
152 SignalSeparatedData mSeparated;
153 };
154
160 bool mCollided { false };
161 CollisionEvent mEvent;
162 };
163
168 void onSimulationActivated() override;
169
176 void onSimulationStep(uint32_t timestepMillis) override;
177
184 void onEntityEnabled(EntityID entityID) override;
185
193 void onEntityUpdated(EntityID entityID, ComponentType updatedComponent) override;
194
199 void onEntityDisabled(EntityID entityID) override;
200
205 bool isConstraintActive(ConstraintID constraint) const;
206
212 void updateProperties(EntityID entityID);
213
220
229 void integrateForces(float substepSeconds, std::unordered_map<EntityID, PhysicsStateFull>& previousState, std::unordered_map<EntityID, PhysicsStateFull>& currentState);
230
235 void deriveVelocities(float substepSeconds, const std::unordered_map<EntityID, PhysicsStateFull>& previousState, std::unordered_map<EntityID, PhysicsStateFull>& currentState);
236
241 void applyPositionCollisionConstraints(std::map<CollisionPair, CollisionConstraint>& potentialCollisions, float substepSeconds, std::unordered_map<EntityID, PhysicsStateFull>& currentState);
242
247 void applyVelocityCollisionConstraints(std::map<CollisionPair, CollisionConstraint>& constraints, float substepSeconds, std::unordered_map<EntityID, PhysicsStateFull>& currentState);
248
253 void applyPositionConstraints(std::map<CollisionPair, CollisionConstraint>& constraints, float substepSeconds, std::unordered_map<EntityID, PhysicsStateFull>& currentState);
254
259 void applyVelocityConstraints(std::map<CollisionPair, CollisionConstraint>& constraints, float substepSeconds, std::unordered_map<EntityID, PhysicsStateFull>& currentState);
260
269 std::map<CollisionPair, CollisionConstraint>& potentialCollisions,
270 std::queue<CollisionReport>& queuedReports,
271 std::unordered_map<EntityID, PhysicsStateFull>& previousStates,
272 std::unordered_map<EntityID, PhysicsStateFull>& currentStates,
273 uint8_t nthSubstep
274 );
275
280 void onCollided(const CollisionPair& pair, const Collision& collision, std::queue<CollisionReport>& queuedReports);
281
286 void onSeparated(const CollisionPair& pair, std::queue<CollisionReport>& queuedReports);
287
293
299
305 void reportCollisions(
306 std::queue<CollisionReport>& reports,
307 std::unordered_map<EntityID, std::pair<SignalCollided, SignalSeparated>> signallers
308 ) const;
309
315 bool wasColliding(const CollisionPair& pair) const;
316
321 void collectPotentialCollisions(float substepSeconds, std::queue<CollisionReport>& queuedReports);
322
328 std::set<EntityID> mEntitiesUninitialized {};
329
334 std::unordered_map<EntityID, PhysicsStateFull> mEntityStatePrevious {};
335
340 std::unordered_map<EntityID, PhysicsStateFull> mEntityStateCurrent {};
341
347 std::unordered_map<EntityID, std::set<ConstraintID>> mEntityConstraintMap {};
348
356
361 std::unordered_map<EntityID, std::unordered_set<EntityID>> mEntityCollision {};
362
367 std::unordered_set<EntityID> mPotentialColliders {};
368
373 std::queue<CollisionReport> mCollisionReports {};
374
379 std::unordered_map<EntityID, std::pair<SignalCollided, SignalSeparated>> mCollisionSignallers {};
380
385 std::map<CollisionPair, CollisionConstraint> mCollisionConstraints {};
386
393 std::vector<std::pair<std::unique_ptr<BaseConstraint>, std::vector<EntityID>>> mConstraints {};
394
399 std::unordered_set<ConstraintID> mConstraintsDeleted {};
400
410 uint8_t mSubsteps { 3 };
411
417
423 };
424
425 inline const std::string PhysicsSystem::SignalCollidedPrefix { "collided_" };
426 inline const std::string PhysicsSystem::SignalSeparatedPrefix { "separated_" };
427
428 template<typename TConstraint, typename TConstraintData>
429 PhysicsSystem::ConstraintID PhysicsSystem::registerConstraint(const std::vector<std::pair<EntityID, TConstraintData>>& participants, float compliance) {
430 // reclaim a deleted constraint id if possible
431 ConstraintID newConstraint { mConstraints.size() };
432 if(!mConstraintsDeleted.empty()) {
433 newConstraint = *mConstraintsDeleted.begin();
434 mConstraintsDeleted.erase(newConstraint);
435 }
436
437 // get separate constraint parameter and participating entity lists
438 std::vector<EntityID> entities {};
439 std::vector<TConstraintData> constraintData {};
440 for(const std::pair<EntityID, TConstraintData>& participant: participants) {
441 constraintData.push_back(participant.second);
442 entities.push_back(participant.first);
443 }
444
445 // create constraint
446 if(newConstraint == mConstraints.size()) {
447 mConstraints.push_back({
448 std::make_unique<TConstraint>(constraintData, compliance),
449 entities
450 });
451 } else {
452 mConstraints[newConstraint] = {
453 std::make_unique<TConstraint>(constraintData, compliance),
454 entities
455 };
456 }
457
458 for(const auto& entity: entities) {
459 mEntityConstraintMap[entity].insert(newConstraint);
460 }
461
462 return newConstraint;
463 }
464}
465
466#endif
467
Names two distinct entities participating in a collision, with their entity IDs sorted in ascending o...
Definition sweep_prune.hpp:29
void updateCollisionEventQueue(std::map< CollisionPair, CollisionConstraint > &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:369
std::queue< CollisionReport > mCollisionReports
Storage for collision reports that should be signalled this simulation frame.
Definition system.hpp:373
void onEntityEnabled(EntityID entityID) override
Updates this entity's physics properties.
Definition system.cpp:416
void onEntityUpdated(EntityID entityID, ComponentType updatedComponent) override
Updates this entity's physics properties.
Definition system.cpp:448
ConstraintID registerConstraint(const std::vector< std::pair< EntityID, TConstraintData > > &constraintData, float compliance)
Registers a constraint for the physics system to evaluate every substep.
Definition system.hpp:429
uint8_t getSubsteps() const
Gets the number of substeps used in the physics solver's XPBD implementation.
Definition system.hpp:124
void unregisterCollisionSignal(EntityID entity)
Unregisters collision signals for this entity.
Definition system.cpp:540
std::size_t ConstraintID
ID naming a unique constraint registered with the physics system.
Definition system.hpp:58
std::pair< CollisionPair, Collision > SignalCollidedData
Struct containing data about a collision event.
Definition system.hpp:64
static std::string getSystemTypeName()
The system type string for this class.
Definition system.hpp:107
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:74
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:600
bool mRequiresInitialization
Whether physics properties for all eligible entities should be recomputed.
Definition system.hpp:416
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:560
uint8_t mSubsteps
The number of substeps used in the physics system's XPBD implementation.
Definition system.hpp:410
std::unordered_map< EntityID, PhysicsStateFull > mEntityStatePrevious
Storage for local entity states prior to the integration step each substep.
Definition system.hpp:334
void applyPositionConstraints(std::map< CollisionPair, CollisionConstraint > &constraints, float substepSeconds, std::unordered_map< EntityID, PhysicsStateFull > &currentState)
Applies all active position constraints.
Definition system.cpp:281
void updateProperties(EntityID entityID)
Computes rotational inertia from mass and object bounds.
Definition system.cpp:474
std::shared_ptr< Signal< SignalCollidedData > > SignalCollided
Signal for reporting collision start events.
Definition system.hpp:76
void onSimulationActivated() override
Marks this system as requiring initialization on the nearest update.
Definition system.cpp:16
void setSubsteps(uint8_t newSubsteps)
Sets the number of substeps used for physics integration using XPBD.
Definition system.hpp:115
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:347
std::unordered_set< EntityID > mPotentialColliders
A list of entities that may collide this frame.
Definition system.hpp:367
bool mConstraintsInitialized
Whether we have yet to determine which constraints are active and which are not.
Definition system.hpp:422
std::map< CollisionPair, CollisionConstraint > mCollisionConstraints
Storage for pairs of entities that are likely to collide (or are colliding) this simulation frame.
Definition system.hpp:385
SweepPrune mBroadPhase
Representation of the structure/technique being used to detect likely collisions.
Definition system.hpp:355
static const std::string SignalSeparatedPrefix
Prefix for the name under which separated Signals are advertised.
Definition system.hpp:95
void collectPotentialCollisions(float substepSeconds, std::queue< CollisionReport > &queuedReports)
Collects potential collisions and builds constraints from them.
Definition system.cpp:147
std::unordered_map< EntityID, PhysicsStateFull > mEntityStateCurrent
Storage for current local entity states, eventually pushed to ECS component tables.
Definition system.hpp:340
void applyVelocityCollisionConstraints(std::map< CollisionPair, CollisionConstraint > &constraints, float substepSeconds, std::unordered_map< EntityID, PhysicsStateFull > &currentState)
Correctly applies collision velocity constraint for each potential collision detected.
Definition system.cpp:316
void applyPositionCollisionConstraints(std::map< CollisionPair, CollisionConstraint > &potentialCollisions, float substepSeconds, std::unordered_map< EntityID, PhysicsStateFull > &currentState)
Correctly applies collision position constraint for each potential collision detected.
Definition system.cpp:259
void applyVelocityConstraints(std::map< CollisionPair, CollisionConstraint > &constraints, float substepSeconds, std::unordered_map< EntityID, PhysicsStateFull > &currentState)
Applies all active velocity constraints.
Definition system.cpp:310
bool isConstraintActive(ConstraintID constraint) const
Whether or not a particular constraint is active.
Definition system.cpp:460
std::shared_ptr< Signal< SignalSeparatedData > > SignalSeparated
Signal for reporting the separation of two colliding bodies.
Definition system.hpp:82
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:333
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:631
void unregisterConstraint(ConstraintID constraint)
Removes a constraint.
Definition system.cpp:452
static const std::string SignalCollidedPrefix
Prefix for the name under which collided Signals are advertised.
Definition system.hpp:89
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:328
void onEntityDisabled(EntityID entityID) override
Removes entity from to-initialize list.
Definition system.cpp:420
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:574
CollisionPair SignalSeparatedData
Struct containing data about a separation event.
Definition system.hpp:70
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:393
void onSimulationStep(uint32_t timestepMillis) override
Updates physics simulation.
Definition system.cpp:20
std::unordered_map< EntityID, std::pair< SignalCollided, SignalSeparated > > mCollisionSignallers
Entities whose collision events are signalled by this system.
Definition system.hpp:379
void registerCollisionSignal(EntityID entity)
Registers collision signals for this entity.
Definition system.cpp:544
std::unordered_map< EntityID, std::unordered_set< EntityID > > mEntityCollision
All currently intersecting entities.
Definition system.hpp:361
std::unordered_set< ConstraintID > mConstraintsDeleted
IDs of constraints that were deleted and which may be reused to define a new constraint.
Definition system.hpp:399
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:1087
ToyMaker Engine's implementation of an ECS system.
ECSType ComponentType
An unsigned integer representing the type of a component.
Definition ecs_world.hpp:103
std::uint64_t EntityID
A single unsigned integer used as a name for an entity managed by an ECS system.
Definition ecs_world.hpp:68
Namespace containing all class definitions and functions related to the ToyMaker engine.
Definition application.hpp:25
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:897
A component defining the true bounds of a spatially queryable object situated somewhere in the world.
Definition types.hpp:926
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:160
Acceleration structure for finding pairs of objects whose AABBs are intersecting.