| #pragma once
|
| #include <string>
|
| #include <memory>
|
| #include <vector>
|
| #include <unordered_map>
|
| #include <glm/glm.hpp>
|
| #include "nlohmann/json.hpp"
|
|
|
| #include "CResource.h"
|
| #include "CObjectFactory.h"
|
| #include "CTransform.h"
|
| #include "CScriptObject.h"
|
|
|
| #define LINK_PHYSICS_ENGINE_TO_CLASS(_class, name) std::string _class::GetType() const { return #name; }; CFactoryInitter<_class, CPhysicsEngine> __entity_initter_ ## name = CFactoryInitter<_class, CPhysicsEngine>(#name, std::function<void(CFactoryInitter<_class, CPhysicsEngine>*)>([](CFactoryInitter<_class, CPhysicsEngine>* tter) -> void { tter->m_factory = &CEngine::GetInstance()->PhysicsEnginesFactory; }));
|
| #define DEFINE_PHYSICS_ENGINE() std::string GetType() const override
|
|
|
| class CTriangleMesh : public CResource
|
| {
|
| public:
|
| struct CTriangle
|
| {
|
| std::uint16_t Material;
|
| glm::u64vec3 Index;
|
| };
|
|
|
| void V_SetupLoadPipeline(CLoadPipeline& pipeline) override;
|
|
|
| std::vector<glm::vec3> Vertices;
|
| std::vector<CTriangle> Triangles;
|
|
|
| DEFINE_RESOURCE();
|
| };
|
|
|
| namespace PhysicsShapes
|
| {
|
| class CBasic
|
| {
|
| public:
|
| virtual ~CBasic() = default;
|
|
|
| virtual std::string GetType() const;
|
|
|
| void Load(const nlohmann::json& _json);
|
| virtual void V_Load(const nlohmann::json& _json);
|
|
|
| void Build();
|
| virtual void V_BaseBuild();
|
| virtual void V_Build();
|
|
|
| virtual float GetMargin() const;
|
| virtual void SetMargin(float _margin);
|
| };
|
|
|
| class CTriMesh : public virtual CBasic
|
| {
|
| public:
|
| std::vector<glm::vec3> Vertices;
|
| std::vector<glm::uvec3> Triangles;
|
|
|
| void LoadTrimesh(const std::filesystem::path& path);
|
|
|
| void V_Load(const nlohmann::json& _json) override;
|
| void Merge(float threshold = 0.001f);
|
|
|
| std::string GetType() const override;
|
| };
|
|
|
| class CConvex : public CTriMesh
|
| {
|
| public:
|
| void BuildConvex();
|
| void V_BaseBuild() override;
|
| void V_Load(const nlohmann::json& _json) override;
|
|
|
| std::string GetType() const override;
|
|
|
| bool NeedVHACD = true;
|
| };
|
|
|
| class CCompound : public virtual CBasic
|
| {
|
| public:
|
| struct CChild
|
| {
|
| CTransform Transform;
|
| std::shared_ptr<CBasic> Shape;
|
| };
|
|
|
| std::string GetType() const override;
|
|
|
| void V_Load(const nlohmann::json& _json) override;
|
| void V_BaseBuild() override;
|
| std::vector<CChild> Childs;
|
| };
|
|
|
| class CCapsule : public virtual CBasic
|
| {
|
| public:
|
| void V_Load(const nlohmann::json& _json) override;
|
| std::string GetType() const override;
|
|
|
| float Radius = 2.0f;
|
| float Height = 4.0f;
|
| };
|
|
|
| class CSphere : public virtual CBasic
|
| {
|
| public:
|
| void V_Load(const nlohmann::json& _json) override;
|
| std::string GetType() const override;
|
|
|
| float Radius = 1.0f;
|
| };
|
|
|
| class CBox : public virtual CBasic
|
| {
|
| public:
|
| void V_Load(const nlohmann::json& _json) override;
|
| std::string GetType() const override;
|
|
|
| glm::vec3 HalfExtents = glm::vec3(1.0f, 1.0f, 1.0f);
|
| };
|
| }
|
|
|
| class CCollision : public CResource
|
| {
|
| public:
|
| static std::unique_ptr<PhysicsShapes::CBasic> ParseShape(const nlohmann::json& _json, CTransformBase* _trans = nullptr); //TODO parent transforms
|
| static std::unique_ptr<PhysicsShapes::CBasic> BuildConvexCompound(const nlohmann::json& _json); //TODO parent transforms
|
| static std::unique_ptr<PhysicsShapes::CBasic> LoadNativeConvex(const nlohmann::json& _json); //TODO parent transforms
|
| static void CompileNativeConvex(const std::filesystem::path& _mesh_path, std::vector<std::filesystem::path> _configs_paths = {}, bool vhacd = false);
|
|
|
| void V_SetupLoadPipeline(CLoadPipeline& pipeline) override;
|
| std::unique_ptr<PhysicsShapes::CBasic> Shape;
|
| DEFINE_RESOURCE();
|
| };
|
|
|
| //base for rigid, kinematic, ghost
|
|
|
| enum class EUnitType
|
| {
|
| Rigid,
|
| Kinematic,
|
| Ghost
|
| };
|
|
|
| class CPhysicsWorld;
|
| class CWorldUnit : public CScriptObject
|
| {
|
| public:
|
| virtual ~CWorldUnit() = default;
|
|
|
| void OverridePersistent(CPhysicsWorld* _world);
|
|
|
| void SetCollision(std::shared_ptr<CCollision> _col);
|
| virtual void V_SetCollision(std::shared_ptr<CCollision> _col);
|
|
|
| std::shared_ptr<CCollision> GetCollision() const;
|
| virtual void SetTransform(const CTransform& trans);
|
| virtual void UpdateInternalTransform();
|
|
|
| virtual CTransform GetInternalTransform();
|
| CTransform GetTransform() const;
|
|
|
| CCallbackHandler<void, CTransformBase::CMeasurePack, CTransformBase*>& GetTransformCallback();
|
| CPhysicsWorld* GetWorld() const;
|
|
|
| bool IsUpdatingInternalTransform() const;
|
| void m_setCollisionPtr(std::shared_ptr<CCollision> _col); //TODO HACK
|
|
|
| bool V_BaseScriptInit(std::shared_ptr<sol::state> state, sol::table table) override;
|
| virtual EUnitType GetType() const = 0;
|
| private:
|
| bool m_updatingInternalTransform = false;
|
| CPhysicsWorld* m_World = nullptr;
|
|
|
| CTransform Transform;
|
| std::shared_ptr<CCollision> m_Collision;
|
| };
|
|
|
| //bodies
|
|
|
| class CRigidBody : public virtual CWorldUnit
|
| {
|
| public:
|
| void SetMass(float mass);
|
| virtual void V_SetMass(float mass);
|
|
|
| virtual void SetLinearVelocity(const glm::vec3& vel);
|
| virtual void SetAngularVelocity(const glm::vec3& ang_vel);
|
|
|
| virtual glm::vec3 GetLinearVelocity() const;
|
| virtual glm::vec3 GetAngularVelocity() const;
|
|
|
| virtual void Activate();
|
|
|
| float GetMass() const;
|
| EUnitType GetType() const override;
|
| private:
|
| float m_Mass = 100.0f;
|
| };
|
|
|
| class CKinematicBody : public virtual CWorldUnit
|
| {
|
| public:
|
| EUnitType GetType() const override;
|
| };
|
|
|
| class CGhostBody : public virtual CWorldUnit
|
| {
|
| public:
|
| EUnitType GetType() const override;
|
| };
|
|
|
| //sweep test
|
|
|
| struct CSweepHit
|
| {
|
| CWorldUnit* HitUnit = nullptr;
|
| glm::vec3 HitPointWorld;
|
| glm::vec3 HitNormalWorld;
|
| float HitFraction = 1.0f;
|
| };
|
|
|
| class IConvexSweepResult
|
| {
|
| public:
|
| virtual ~IConvexSweepResult() = default;
|
|
|
| virtual bool HasHit() const = 0;
|
| virtual const CSweepHit& GetHit() const = 0;
|
| };
|
|
|
| class IConvexSweepCallback
|
| {
|
| public:
|
| virtual ~IConvexSweepCallback() = default;
|
| virtual bool OnHit(const CSweepHit& hit) = 0;
|
| };
|
|
|
| //manifolds
|
|
|
| class IContactPoint
|
| {
|
| public:
|
| virtual ~IContactPoint() = default;
|
|
|
| virtual glm::vec3 GetPositionWorldOnA() const = 0;
|
| virtual glm::vec3 GetPositionWorldOnB() const = 0;
|
| virtual glm::vec3 GetNormalWorldOnB() const = 0;
|
| virtual float GetDistance() const = 0;
|
| };
|
|
|
| class IContactManifold
|
| {
|
| public:
|
| virtual ~IContactManifold() = default;
|
|
|
| virtual int GetNumContacts() const = 0;
|
| virtual std::unique_ptr<IContactPoint> GetContact(int index) const = 0;
|
| virtual CWorldUnit* GetUnitA() const = 0;
|
| virtual CWorldUnit* GetUnitB() const = 0;
|
| };
|
|
|
| class IGhostOverlapResult
|
| {
|
| public:
|
| virtual ~IGhostOverlapResult() = default;
|
|
|
| virtual int GetNumOverlappingUnits() const = 0;
|
| virtual CWorldUnit* GetOverlappingUnit(int index) const = 0;
|
|
|
| virtual std::vector<std::unique_ptr<IContactManifold>> GetContactManifolds(CWorldUnit* other) const = 0;
|
| };
|
|
|
| //world
|
|
|
| class CPhysicsEngine;
|
| class CPhysicsWorld : public CScriptObject
|
| {
|
| public:
|
| virtual ~CPhysicsWorld() = default;
|
|
|
| void OverridePersistent(CPhysicsEngine* _engine);
|
| void Step(float deltaTime);
|
|
|
| virtual void V_Step(float deltaTime);
|
|
|
| void SetGravity(const glm::vec3& _gravity);
|
|
|
| virtual glm::vec3 GetGravity() const;
|
| virtual void V_SetGravity(const glm::vec3& _gravity);
|
|
|
| virtual std::unique_ptr<CRigidBody> V_CreateRigidBody(std::shared_ptr<CCollision> _collision, const CTransform& startTransform, float mass);
|
| virtual std::unique_ptr<CKinematicBody> V_CreateKinematicBody(std::shared_ptr<CCollision> _collision, const CTransform& startTransform);
|
| virtual std::unique_ptr<CGhostBody> V_CreateGhostBody(std::shared_ptr<CCollision> _collision, const CTransform& startTransform);
|
|
|
| virtual void V_AddRigidBody(CRigidBody* rgBody);
|
| virtual void V_AddKinematicBody(CKinematicBody* knBody);
|
| virtual void V_AddGhostBody(CGhostBody* ghBody);
|
|
|
| CRigidBody* CreateRigidBody(std::shared_ptr<CCollision> _collision, const CTransform& startTransform, float mass);
|
| CKinematicBody* CreateKinematicBody(std::shared_ptr<CCollision> _collision, const CTransform& startTransform);
|
| CGhostBody* CreateGhostBody(std::shared_ptr<CCollision> _collision, const CTransform& startTransform);
|
|
|
| virtual std::unique_ptr<IConvexSweepResult> V_ConvexSweep
|
| (
|
| std::shared_ptr<CCollision> shape,
|
| const CTransform& from,
|
| const CTransform& to,
|
| IConvexSweepCallback* callback = nullptr,
|
| std::vector<CWorldUnit*> excludeList = {}
|
| ) = 0;
|
| virtual std::unique_ptr<IGhostOverlapResult> V_GetGhostOverlaps(const CGhostBody* ghost) const = 0;
|
| bool V_BaseScriptInit(std::shared_ptr<sol::state> state, sol::table table) override;
|
|
|
| std::vector<std::unique_ptr<CWorldUnit>> Units;
|
| private:
|
| CPhysicsEngine* m_linkedEngine = nullptr;
|
| };
|
|
|
| //engine
|
|
|
| class CPhysicsEngine : public CScriptObject
|
| {
|
| public:
|
| CPhysicsEngine();
|
| virtual ~CPhysicsEngine() = default;
|
| virtual std::string GetType() const;
|
|
|
| CPhysicsWorld* CreateWorld();
|
| virtual std::unique_ptr<CPhysicsWorld> V_CreateWorld();
|
|
|
| CPhysicsWorld* GetWorld(int id);
|
| void Trace(std::function<void(CPhysicsWorld*)> func);
|
|
|
| bool V_BaseScriptInit(std::shared_ptr<sol::state> state, sol::table table) override;
|
|
|
| CObjectFactory<PhysicsShapes::CBasic, std::string> ShapesFactory;
|
| private:
|
| std::vector<std::unique_ptr<CPhysicsWorld>> m_Worlds;
|
| };
|
| |