feat(physics): add runtime physics scaffolding
This commit is contained in:
23
engine/include/XCEngine/Components/BoxColliderComponent.h
Normal file
23
engine/include/XCEngine/Components/BoxColliderComponent.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <XCEngine/Components/ColliderComponent.h>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Components {
|
||||
|
||||
class BoxColliderComponent : public ColliderComponent {
|
||||
public:
|
||||
std::string GetName() const override { return "BoxCollider"; }
|
||||
|
||||
const Math::Vector3& GetSize() const { return m_size; }
|
||||
void SetSize(const Math::Vector3& value);
|
||||
|
||||
void Serialize(std::ostream& os) const override;
|
||||
void Deserialize(std::istream& is) override;
|
||||
|
||||
private:
|
||||
Math::Vector3 m_size = Math::Vector3::One();
|
||||
};
|
||||
|
||||
} // namespace Components
|
||||
} // namespace XCEngine
|
||||
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <XCEngine/Components/ColliderComponent.h>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Components {
|
||||
|
||||
class CapsuleColliderComponent : public ColliderComponent {
|
||||
public:
|
||||
std::string GetName() const override { return "CapsuleCollider"; }
|
||||
|
||||
float GetRadius() const { return m_radius; }
|
||||
void SetRadius(float value);
|
||||
|
||||
float GetHeight() const { return m_height; }
|
||||
void SetHeight(float value);
|
||||
|
||||
ColliderAxis GetAxis() const { return m_axis; }
|
||||
void SetAxis(ColliderAxis value);
|
||||
|
||||
void Serialize(std::ostream& os) const override;
|
||||
void Deserialize(std::istream& is) override;
|
||||
|
||||
private:
|
||||
float m_radius = 0.5f;
|
||||
float m_height = 2.0f;
|
||||
ColliderAxis m_axis = ColliderAxis::Y;
|
||||
};
|
||||
|
||||
} // namespace Components
|
||||
} // namespace XCEngine
|
||||
46
engine/include/XCEngine/Components/ColliderComponent.h
Normal file
46
engine/include/XCEngine/Components/ColliderComponent.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <XCEngine/Components/Component.h>
|
||||
#include <XCEngine/Core/Math/Vector3.h>
|
||||
#include <cstdint>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Components {
|
||||
|
||||
enum class ColliderAxis : uint8_t {
|
||||
X = 0,
|
||||
Y = 1,
|
||||
Z = 2
|
||||
};
|
||||
|
||||
class ColliderComponent : public Component {
|
||||
public:
|
||||
bool IsTrigger() const { return m_isTrigger; }
|
||||
void SetTrigger(bool value) { m_isTrigger = value; }
|
||||
|
||||
const Math::Vector3& GetCenter() const { return m_center; }
|
||||
void SetCenter(const Math::Vector3& value);
|
||||
|
||||
float GetStaticFriction() const { return m_staticFriction; }
|
||||
void SetStaticFriction(float value);
|
||||
|
||||
float GetDynamicFriction() const { return m_dynamicFriction; }
|
||||
void SetDynamicFriction(float value);
|
||||
|
||||
float GetRestitution() const { return m_restitution; }
|
||||
void SetRestitution(float value);
|
||||
|
||||
protected:
|
||||
void SerializeBase(std::ostream& os) const;
|
||||
bool DeserializeBaseField(const std::string& key, const std::string& value);
|
||||
|
||||
private:
|
||||
bool m_isTrigger = false;
|
||||
Math::Vector3 m_center = Math::Vector3::Zero();
|
||||
float m_staticFriction = 0.6f;
|
||||
float m_dynamicFriction = 0.6f;
|
||||
float m_restitution = 0.0f;
|
||||
};
|
||||
|
||||
} // namespace Components
|
||||
} // namespace XCEngine
|
||||
@@ -53,6 +53,7 @@ public:
|
||||
component->m_gameObject = this;
|
||||
T* ptr = component.get();
|
||||
m_components.emplace_back(std::move(component));
|
||||
NotifyComponentAdded(ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
@@ -120,6 +121,7 @@ public:
|
||||
|
||||
for (auto it = m_components.begin(); it != m_components.end(); ++it) {
|
||||
if (T* casted = dynamic_cast<T*>(it->get())) {
|
||||
NotifyComponentRemoving(casted);
|
||||
m_components.erase(it);
|
||||
return;
|
||||
}
|
||||
@@ -139,6 +141,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
NotifyComponentRemoving(component);
|
||||
m_components.erase(it);
|
||||
return true;
|
||||
}
|
||||
@@ -213,6 +216,8 @@ public:
|
||||
void Deserialize(std::istream& is);
|
||||
|
||||
private:
|
||||
void NotifyComponentAdded(Component* component);
|
||||
void NotifyComponentRemoving(Component* component);
|
||||
void NotifyComponentsBecameActive();
|
||||
void NotifyComponentsBecameInactive();
|
||||
void PropagateActiveInHierarchyChange(bool oldParentActiveInHierarchy, bool newParentActiveInHierarchy);
|
||||
|
||||
44
engine/include/XCEngine/Components/RigidbodyComponent.h
Normal file
44
engine/include/XCEngine/Components/RigidbodyComponent.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include <XCEngine/Components/Component.h>
|
||||
#include <XCEngine/Physics/PhysicsTypes.h>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Components {
|
||||
|
||||
class RigidbodyComponent : public Component {
|
||||
public:
|
||||
std::string GetName() const override { return "Rigidbody"; }
|
||||
|
||||
Physics::PhysicsBodyType GetBodyType() const { return m_bodyType; }
|
||||
void SetBodyType(Physics::PhysicsBodyType value) { m_bodyType = value; }
|
||||
|
||||
float GetMass() const { return m_mass; }
|
||||
void SetMass(float value);
|
||||
|
||||
float GetLinearDamping() const { return m_linearDamping; }
|
||||
void SetLinearDamping(float value);
|
||||
|
||||
float GetAngularDamping() const { return m_angularDamping; }
|
||||
void SetAngularDamping(float value);
|
||||
|
||||
bool GetUseGravity() const { return m_useGravity; }
|
||||
void SetUseGravity(bool value) { m_useGravity = value; }
|
||||
|
||||
bool GetEnableCCD() const { return m_enableCCD; }
|
||||
void SetEnableCCD(bool value) { m_enableCCD = value; }
|
||||
|
||||
void Serialize(std::ostream& os) const override;
|
||||
void Deserialize(std::istream& is) override;
|
||||
|
||||
private:
|
||||
Physics::PhysicsBodyType m_bodyType = Physics::PhysicsBodyType::Dynamic;
|
||||
float m_mass = 1.0f;
|
||||
float m_linearDamping = 0.0f;
|
||||
float m_angularDamping = 0.05f;
|
||||
bool m_useGravity = true;
|
||||
bool m_enableCCD = false;
|
||||
};
|
||||
|
||||
} // namespace Components
|
||||
} // namespace XCEngine
|
||||
23
engine/include/XCEngine/Components/SphereColliderComponent.h
Normal file
23
engine/include/XCEngine/Components/SphereColliderComponent.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <XCEngine/Components/ColliderComponent.h>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Components {
|
||||
|
||||
class SphereColliderComponent : public ColliderComponent {
|
||||
public:
|
||||
std::string GetName() const override { return "SphereCollider"; }
|
||||
|
||||
float GetRadius() const { return m_radius; }
|
||||
void SetRadius(float value);
|
||||
|
||||
void Serialize(std::ostream& os) const override;
|
||||
void Deserialize(std::istream& is) override;
|
||||
|
||||
private:
|
||||
float m_radius = 0.5f;
|
||||
};
|
||||
|
||||
} // namespace Components
|
||||
} // namespace XCEngine
|
||||
28
engine/include/XCEngine/Physics/PhysicsTypes.h
Normal file
28
engine/include/XCEngine/Physics/PhysicsTypes.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include <XCEngine/Core/Math/Vector3.h>
|
||||
#include <cstdint>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Components {
|
||||
|
||||
class GameObject;
|
||||
class Scene;
|
||||
|
||||
} // namespace Components
|
||||
|
||||
namespace Physics {
|
||||
|
||||
enum class PhysicsBodyType : uint8_t {
|
||||
Static = 0,
|
||||
Dynamic,
|
||||
Kinematic
|
||||
};
|
||||
|
||||
struct PhysicsWorldCreateInfo {
|
||||
Components::Scene* scene = nullptr;
|
||||
Math::Vector3 gravity = Math::Vector3(0.0f, -9.81f, 0.0f);
|
||||
};
|
||||
|
||||
} // namespace Physics
|
||||
} // namespace XCEngine
|
||||
56
engine/include/XCEngine/Physics/PhysicsWorld.h
Normal file
56
engine/include/XCEngine/Physics/PhysicsWorld.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include <XCEngine/Physics/PhysicsTypes.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Components {
|
||||
|
||||
class Component;
|
||||
|
||||
} // namespace Components
|
||||
} // namespace XCEngine
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Physics {
|
||||
|
||||
class PhysXWorldBackend;
|
||||
|
||||
class PhysicsWorld {
|
||||
public:
|
||||
PhysicsWorld();
|
||||
~PhysicsWorld();
|
||||
|
||||
static bool IsPhysXAvailable();
|
||||
|
||||
bool Initialize(const PhysicsWorldCreateInfo& createInfo);
|
||||
void Shutdown();
|
||||
void Step(float fixedDeltaTime);
|
||||
|
||||
bool IsInitialized() const { return m_initialized; }
|
||||
const PhysicsWorldCreateInfo& GetCreateInfo() const { return m_createInfo; }
|
||||
size_t GetTrackedRigidbodyCount() const { return m_trackedRigidbodyCount; }
|
||||
size_t GetTrackedColliderCount() const { return m_trackedColliderCount; }
|
||||
|
||||
private:
|
||||
void AttachSceneEventHandlers(Components::Scene* scene);
|
||||
void DetachSceneEventHandlers();
|
||||
void RebuildTrackedSceneState();
|
||||
void TrackGameObjectComponents(Components::GameObject* gameObject, int delta);
|
||||
void TrackComponent(Components::Component* component, int delta);
|
||||
|
||||
PhysicsWorldCreateInfo m_createInfo;
|
||||
bool m_initialized = false;
|
||||
uint64_t m_componentAddedSubscriptionId = 0;
|
||||
uint64_t m_componentRemovedSubscriptionId = 0;
|
||||
uint64_t m_gameObjectDestroyedSubscriptionId = 0;
|
||||
size_t m_trackedRigidbodyCount = 0;
|
||||
size_t m_trackedColliderCount = 0;
|
||||
std::unique_ptr<PhysXWorldBackend> m_backend;
|
||||
};
|
||||
|
||||
} // namespace Physics
|
||||
} // namespace XCEngine
|
||||
17
engine/include/XCEngine/Physics/RaycastHit.h
Normal file
17
engine/include/XCEngine/Physics/RaycastHit.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <XCEngine/Physics/PhysicsTypes.h>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Physics {
|
||||
|
||||
struct RaycastHit {
|
||||
Components::GameObject* gameObject = nullptr;
|
||||
Math::Vector3 point = Math::Vector3::Zero();
|
||||
Math::Vector3 normal = Math::Vector3::Zero();
|
||||
float distance = 0.0f;
|
||||
bool isTrigger = false;
|
||||
};
|
||||
|
||||
} // namespace Physics
|
||||
} // namespace XCEngine
|
||||
@@ -71,6 +71,8 @@ public:
|
||||
|
||||
Core::Event<GameObject*>& OnGameObjectCreated() { return m_onGameObjectCreated; }
|
||||
Core::Event<GameObject*>& OnGameObjectDestroyed() { return m_onGameObjectDestroyed; }
|
||||
Core::Event<GameObject*, Component*>& OnComponentAdded() { return m_onComponentAdded; }
|
||||
Core::Event<GameObject*, Component*>& OnComponentRemoved() { return m_onComponentRemoved; }
|
||||
|
||||
private:
|
||||
GameObject* FindInChildren(GameObject* parent, const std::string& name) const;
|
||||
@@ -108,6 +110,8 @@ private:
|
||||
|
||||
Core::Event<GameObject*> m_onGameObjectCreated;
|
||||
Core::Event<GameObject*> m_onGameObjectDestroyed;
|
||||
Core::Event<GameObject*, Component*> m_onComponentAdded;
|
||||
Core::Event<GameObject*, Component*> m_onComponentRemoved;
|
||||
|
||||
friend class GameObject;
|
||||
friend class SceneManager;
|
||||
|
||||
@@ -16,6 +16,12 @@ struct UISystemFrameResult;
|
||||
|
||||
} // namespace Runtime
|
||||
} // namespace UI
|
||||
|
||||
namespace Physics {
|
||||
|
||||
class PhysicsWorld;
|
||||
|
||||
} // namespace Physics
|
||||
} // namespace XCEngine
|
||||
|
||||
namespace XCEngine {
|
||||
@@ -50,9 +56,14 @@ public:
|
||||
|
||||
bool IsRunning() const { return m_running; }
|
||||
Scene* GetScene() const { return m_scene; }
|
||||
Physics::PhysicsWorld* GetPhysicsWorld() const { return m_physicsWorld.get(); }
|
||||
|
||||
private:
|
||||
void CreatePhysicsWorldForScene(Scene* scene);
|
||||
void DestroyPhysicsWorld();
|
||||
|
||||
std::unique_ptr<UI::Runtime::UISceneRuntimeContext> m_uiRuntime;
|
||||
std::unique_ptr<Physics::PhysicsWorld> m_physicsWorld;
|
||||
Scene* m_scene = nullptr;
|
||||
bool m_running = false;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user