Vulkan Schnee 0.0.1 (22840dc8)
High-performance rendering engine
Loading...
Searching...
No Matches
PhysicsBodyComponent.h
1#pragma once
2
3#include "Engine/Component/LogicComponent.h"
4#include "Engine/Physics/CollisionProfile.h"
5#include <glm/glm.hpp>
6#include <glm/gtc/quaternion.hpp>
7#include <entt/entt.hpp>
8#include <functional>
9#include <memory>
10#include <vector>
11#include <set>
12#include <utility>
13
14namespace Engine::Core
15{
16 class PhysicsEngine;
17} // namespace Engine::Core
18
19namespace Engine::Entities
20{
21 class Actor;
22 class SceneNode;
23} // namespace Engine::Entities
24
25class btRigidBody;
26class btCompoundShape;
27class btCollisionShape;
28class btDiscreteDynamicsWorld;
29
30namespace Engine::Components {
31 class Collision;
32
40 class PhysicsBody : public Logic {
41 public:
42 static constexpr bool IsUnique = true;
43 static constexpr const char* ComponentName = "PhysicsBody";
44 using PhysicsBodyCallbackHandle = std::uint64_t;
45
52 PhysicsBody(Entities::Scene* scene, entt::entity entity,
53 std::shared_ptr<Entities::SceneNode> sceneNode);
54
58 ~PhysicsBody() override;
59
60 void beginPlay() override;
61 void endPlay() override;
62 bool drawImGui() override;
63
64 // =========================================================================
65 // Physics Properties
66 // =========================================================================
67
72 void setMass(float mass);
73
78 [[nodiscard]] float getMass() const { return mass_; }
79
84 void setFriction(float friction);
85
90 [[nodiscard]] float getFriction() const { return friction_; }
91
96 void setRestitution(float restitution);
97
102 [[nodiscard]] float getRestitution() const { return restitution_; }
103
109 void setKinematic(bool kinematic);
110
115 [[nodiscard]] bool isKinematic() const { return isKinematic_; }
116
121 void setStatic(bool isStatic);
122
127 [[nodiscard]] bool isStatic() const { return isStatic_; }
128
129 // =========================================================================
130 // Transform Control
131 // =========================================================================
132
137 void teleport(const glm::vec3& position);
138
144 void teleport(const glm::vec3& position, const glm::quat& rotation);
145
150 void setLinearVelocity(const glm::vec3& velocity);
151
156 [[nodiscard]] glm::vec3 getLinearVelocity() const;
157
162 void setAngularVelocity(const glm::vec3& velocity);
163
168 [[nodiscard]] glm::vec3 getAngularVelocity() const;
169
170 // =========================================================================
171 // Collision Management (called by CollisionComponents)
172 // =========================================================================
173
180
187
193
198
203
208 [[nodiscard]] btRigidBody* getRigidBody() const { return rigidBody_; }
209
214 [[nodiscard]] Entities::Actor* getHitActor() const;
215
221
227
232 [[nodiscard]] const std::vector<Components::Collision*> & getCollisions() const { return collisions_; }
233
239 [[nodiscard]] Components::Collision * findCollisionForShape( const btCollisionShape * shape ) const;
240
245 [[nodiscard]] btDiscreteDynamicsWorld* getDynamicsWorld() const;
246
247 // =========================================================================
248 // Collision Callbacks
249 // =========================================================================
250
256
262 template<typename ActorType, typename Callback>
264 {
265 return addBodyCallback(
267 [callback = std::forward<Callback>( callback )]( const Physics::CollisionEvent & event ) mutable
268 {
269 auto * actor = dynamic_cast<ActorType *>( event.otherActor );
270 if ( actor != nullptr )
271 {
272 callback( event, *actor );
273 }
274 }
275 );
276 }
277
283 template<typename ActorType, typename Callback>
285 {
286 return addBodyCallback(
288 [callback = std::forward<Callback>( callback )]( const Physics::CollisionEvent & event ) mutable
289 {
290 auto * actor = dynamic_cast<ActorType *>( event.otherActor );
291 if ( actor != nullptr )
292 {
293 callback( event, *actor );
294 }
295 }
296 );
297 }
298
304 template<typename ActorType, typename Callback>
306 {
307 return addBodyCallback(
309 [callback = std::forward<Callback>( callback )]( const Physics::CollisionEvent & event ) mutable
310 {
311 auto * actor = dynamic_cast<ActorType *>( event.otherActor );
312 if ( actor != nullptr )
313 {
314 callback( event, *actor );
315 }
316 }
317 );
318 }
319
325 template<typename ActorType, typename Callback>
327 {
328 return addBodyCallback(
330 [callback = std::forward<Callback>( callback )]( const Physics::CollisionEvent & event ) mutable
331 {
332 auto * actor = dynamic_cast<ActorType *>( event.otherActor );
333 if ( actor != nullptr )
334 {
335 callback( event, *actor );
336 }
337 }
338 );
339 }
340
346 template<typename ActorType, typename Callback>
348 {
349 return addBodyCallback(
351 [callback = std::forward<Callback>( callback )]( const Physics::CollisionEvent & event ) mutable
352 {
353 auto * actor = dynamic_cast<ActorType *>( event.otherActor );
354 if ( actor != nullptr )
355 {
356 callback( event, *actor );
357 }
358 }
359 );
360 }
361
367 template<typename ActorType, typename Callback>
369 {
370 return addBodyCallback(
372 [callback = std::forward<Callback>( callback )]( const Physics::CollisionEvent & event ) mutable
373 {
374 auto * actor = dynamic_cast<ActorType *>( event.otherActor );
375 if ( actor != nullptr )
376 {
377 callback( event, *actor );
378 }
379 }
380 );
381 }
382
388
394
395 // =========================================================================
396 // Debug Visualization
397 // =========================================================================
398
405 void debugDraw() const;
406
407 private:
414 [[nodiscard]] std::uint16_t getBulletCollisionGroup() const;
415 [[nodiscard]] std::uint16_t getBulletCollisionMask() const;
416 [[nodiscard]] bool shouldUseNoContactResponse() const;
417 [[nodiscard]] Core::PhysicsEngine * getPhysicsEngine() const;
418
424
426 std::vector<BodyCallbackSubscription> & callbacks,
427 std::function<void( const Physics::CollisionEvent & )> callback
428 );
430
431 entt::entity entity_;
432 std::weak_ptr<Entities::SceneNode> sceneNode_;
433
434 std::vector<Components::Collision*> collisions_;
435 btCompoundShape* compoundShape_ = nullptr;
436 btRigidBody* rigidBody_ = nullptr;
437
438 float mass_ = 1.0f;
439 float friction_ = 0.5f;
440 float restitution_ = 0.0f;
441 bool isKinematic_ = false;
442 bool isStatic_ = false;
443 bool shapeDirty_ = true;
444 bool isInitialized_ = false;
448 std::vector<BodyCallbackSubscription> overlapBeginCallbacks_;
449 std::vector<BodyCallbackSubscription> overlapStayCallbacks_;
450 std::vector<BodyCallbackSubscription> overlapEndCallbacks_;
451 std::vector<BodyCallbackSubscription> collisionBeginCallbacks_;
452 std::vector<BodyCallbackSubscription> collisionStayCallbacks_;
453 std::vector<BodyCallbackSubscription> collisionEndCallbacks_;
454
455 // For collision callbacks - track previous frame's collisions
456 std::set<Components::Collision*> previousCollisions_;
457 };
458
459} // namespace EngineCore
Base class for collision shape components.
Logic(Entities::Scene *owningScene)
Constructs a logic component owned by a scene.
float getRestitution() const
Gets the restitution.
std::vector< BodyCallbackSubscription > overlapStayCallbacks_
PhysicsBodyCallbackHandle addBodyCallback(std::vector< BodyCallbackSubscription > &callbacks, std::function< void(const Physics::CollisionEvent &)> callback)
PhysicsBodyCallbackHandle onCollisionBegin(Callback &&callback)
Registers a callback for blocking collision begin events with actors of ActorType.
PhysicsBodyCallbackHandle onOverlapEnd(Callback &&callback)
Registers a callback for overlap end events with actors of ActorType.
float getMass() const
Gets the mass of the rigid body.
void setRestitution(float restitution)
Sets the restitution (bounciness).
void setAngularVelocity(const glm::vec3 &velocity)
Sets the angular velocity.
std::vector< Components::Collision * > collisions_
static constexpr bool IsUnique
Only one physics body may be attached per entity.
float getFriction() const
Gets the friction coefficient.
glm::vec3 getAngularVelocity() const
Gets the angular velocity.
void debugDraw() const
Draws debug visualization of all collision shapes.
std::vector< BodyCallbackSubscription > overlapBeginCallbacks_
void endPlay() override
Called when the component is removed or the game ends.
void beginPlay() override
Called when the component is added to the scene or the game starts.
void setPhysicsBodyHandle(Physics::PhysicsBodyHandle handle)
Sets the physics-engine registration handle for this body.
std::weak_ptr< Entities::SceneNode > sceneNode_
void markCollisionFiltersDirty()
Marks collision filters as needing update on the rigid body.
btDiscreteDynamicsWorld * getDynamicsWorld() const
Gets the Bullet dynamics world.
void setMass(float mass)
Sets the mass of the rigid body.
std::uint64_t PhysicsBodyCallbackHandle
Opaque handle for registered collision callbacks.
std::vector< BodyCallbackSubscription > overlapEndCallbacks_
std::vector< BodyCallbackSubscription > collisionStayCallbacks_
void unregisterCollision(Components::Collision *collision)
Unregisters a collision component from this body. Called by CollisionComponent::endPlay().
void teleport(const glm::vec3 &position, const glm::quat &rotation)
Teleports the body to a new position and rotation.
void markShapeDirty()
Marks the collision shape as needing rebuild. Called when a collision component's shape changes.
void teleport(const glm::vec3 &position)
Teleports the body to a new position.
std::uint16_t getBulletCollisionMask() const
std::vector< BodyCallbackSubscription > collisionEndCallbacks_
Physics::PhysicsBodyHandle getPhysicsBodyHandle() const
Gets the physics-engine registration handle for this body.
glm::vec3 getLinearVelocity() const
Gets the linear velocity.
void rebuildIfDirty()
Rebuilds the collision shape if dirty.
Physics::PhysicsBodyHandle bodyHandle_
void registerCollision(Components::Collision *collision)
Registers a collision component with this body. Called by CollisionComponent::beginPlay().
bool isKinematic() const
Checks if the body is kinematic.
void setLinearVelocity(const glm::vec3 &velocity)
Sets the linear velocity.
PhysicsBody(Entities::Scene *scene, entt::entity entity, std::shared_ptr< Entities::SceneNode > sceneNode)
Constructs a PhysicsBodyComponent.
void removeCollisionCallback(PhysicsBodyCallbackHandle handle)
Removes a previously registered collision callback.
~PhysicsBody() override
Destroys the physics body and releases Bullet resources.
void setFriction(float friction)
Sets the friction coefficient.
void dispatchCollisionEvent(const Physics::CollisionEvent &event)
Dispatches a collision event to callbacks matching its type and response.
Core::PhysicsEngine * getPhysicsEngine() const
PhysicsBodyCallbackHandle onCollisionEnd(Callback &&callback)
Registers a callback for blocking collision end events with actors of ActorType.
PhysicsBodyCallbackHandle onOverlapBegin(Callback &&callback)
Registers a callback for overlap begin events with actors of ActorType.
const std::vector< Components::Collision * > & getCollisions() const
Gets collision components registered with this body.
void processCollisions()
Processes collision events and dispatches callbacks. Called after physics step.
std::vector< BodyCallbackSubscription > collisionBeginCallbacks_
void setStatic(bool isStatic)
Sets whether the body is static (immovable).
static constexpr const char * ComponentName
Component type name.
bool drawImGui() override
Draws component-specific ImGui inspector controls.
Components::Collision * findCollisionForShape(const btCollisionShape *shape) const
Finds the collision component that owns a Bullet collision shape.
void setKinematic(bool kinematic)
Sets whether the body is kinematic. Kinematic bodies are moved by code, not physics.
PhysicsBodyCallbackHandle nextCallbackHandle_
PhysicsBodyCallbackHandle onCollisionStay(Callback &&callback)
Registers a callback for blocking collision stay events with actors of ActorType.
bool isStatic() const
Checks if the body is static.
Entities::Actor * getHitActor() const
Gets the actor owning this physics body when the owning entity is an actor.
std::uint16_t getBulletCollisionGroup() const
btRigidBody * getRigidBody() const
Gets the Bullet rigid body.
std::set< Components::Collision * > previousCollisions_
PhysicsBodyCallbackHandle onOverlapStay(Callback &&callback)
Registers a callback for overlap stay events with actors of ActorType.
Owns the Bullet dynamics world and dispatches engine collision events.
An Actor is similar to an Engine::Entities::Entity. An actor is an Entity with a transform.
Definition Actor.h:71
Represents a node in the scene graph, containing information about its position, rotation,...
Definition SceneGraph.h:27
Owns scene entities, actor lifetime, and the scene graph root.
Definition Scene.h:84
std::function< void(const Physics::CollisionEvent &)> callback
Actor-level collision or overlap event generated by PhysicsEngine.
Runtime handle for a registered physics body component.