/
redgpu
/
ezEngine
Обзор
Документация
Войти
/
redgpu
/
ezEngine
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
dev
Code/Engine/Core/Interfaces/PhysicsWorldModule.h
267 строк
11 KB
Jan Krassnigg
Added Jolt heightmap resource, some code cleanup (#1953)
03 июн 2026, 08:10
Не верифицирован
03 июн 2026, 08:10
259ea00
Код
Авторство
О чём код?
#pragma once #include <Core/Interfaces/PhysicsQuery.h> #include <Core/ResourceManager/ResourceHandle.h> #include <Core/World/WorldModule.h> #include <Foundation/Communication/Message.h> #include <Foundation/Containers/DynamicArray.h> #include <Foundation/Math/BoundingBoxSphere.h> #include <Foundation/Math/Vec2.h> #include <Foundation/Strings/String.h> struct ezGameObjectHandle; struct ezSkeletonResourceDescriptor; /// Interface for physics world modules that provide physics simulation and queries. /// /// Physics world modules implement physics functionality for a world, including /// collision detection, raycasting, and shape queries. Different physics engines /// can provide their own implementations of this interface. class EZ_CORE_DLL ezPhysicsWorldModuleInterface : public ezWorldModule { EZ_ADD_DYNAMIC_REFLECTION(ezPhysicsWorldModuleInterface, ezWorldModule); protected: ezPhysicsWorldModuleInterface(ezWorld* pWorld) : ezWorldModule(pWorld) { } public: /// \brief Searches for a collision layer with the given name and returns its index. /// /// Returns ezInvalidIndex if no such collision layer exists. virtual ezUInt32 GetCollisionLayerByName(ezStringView sName) const = 0; /// \brief Searches for a weight category with the given name and returns its key. /// /// Returns ezWeightCategoryConfig::InvalidKey if no such category exists. virtual ezUInt8 GetWeightCategoryByName(ezStringView sName) const = 0; /// \brief Searches for an impulse type with the given name and returns its key. /// /// Returns ezImpulseTypeConfig::InvalidKey if no such category exists. virtual ezUInt8 GetImpulseTypeByName(ezStringView sName) const = 0; virtual bool Raycast(ezPhysicsCastResult& out_result, const ezVec3& vStart, const ezVec3& vDir, float fDistance, const ezPhysicsQueryParameters& params, ezPhysicsHitCollection collection = ezPhysicsHitCollection::Closest) const = 0; virtual bool RaycastAll(ezPhysicsCastResultArray& out_results, const ezVec3& vStart, const ezVec3& vDir, float fDistance, const ezPhysicsQueryParameters& params) const = 0; virtual bool SweepTestSphere(ezPhysicsCastResult& out_result, float fSphereRadius, const ezVec3& vStart, const ezVec3& vDir, float fDistance, const ezPhysicsQueryParameters& params, ezPhysicsHitCollection collection = ezPhysicsHitCollection::Closest) const = 0; virtual bool SweepTestBox(ezPhysicsCastResult& out_result, const ezVec3& vBoxExtents, const ezTransform& transform, const ezVec3& vDir, float fDistance, const ezPhysicsQueryParameters& params, ezPhysicsHitCollection collection = ezPhysicsHitCollection::Closest) const = 0; virtual bool SweepTestCapsule(ezPhysicsCastResult& out_result, float fCapsuleRadius, float fCapsuleHeight, const ezTransform& transform, const ezVec3& vDir, float fDistance, const ezPhysicsQueryParameters& params, ezPhysicsHitCollection collection = ezPhysicsHitCollection::Closest) const = 0; virtual bool SweepTestCylinder(ezPhysicsCastResult& out_result, float fCylinderRadius, float fCylinderHeight, const ezTransform& transform, const ezVec3& vDir, float fDistance, const ezPhysicsQueryParameters& params, ezPhysicsHitCollection collection = ezPhysicsHitCollection::Closest) const = 0; virtual bool OverlapTestSphere(float fSphereRadius, const ezVec3& vPosition, const ezPhysicsQueryParameters& params) const = 0; virtual bool OverlapTestBox(const ezVec3& vBoxExtents, const ezVec3& vPosition, const ezTransform& transform, const ezPhysicsQueryParameters& params) const = 0; virtual bool OverlapTestCapsule(float fCapsuleRadius, float fCapsuleHeight, const ezTransform& transform, const ezPhysicsQueryParameters& params) const = 0; virtual bool OverlapTestCylinder(float fCylinderRadius, float fCylinderHeight, const ezTransform& transform, const ezPhysicsQueryParameters& params) const = 0; virtual void QueryShapesInSphere(ezPhysicsOverlapResultArray& out_results, float fSphereRadius, const ezVec3& vPosition, const ezPhysicsQueryParameters& params) const = 0; virtual void QueryShapesInBox(ezPhysicsOverlapResultArray& out_results, const ezVec3& vBoxExtents, const ezTransform& transform, const ezPhysicsQueryParameters& params) const = 0; virtual void QueryShapesInCapsule(ezPhysicsOverlapResultArray& out_results, float fCapsuleRadius, float fCapsuleHeight, const ezTransform& transform, const ezPhysicsQueryParameters& params) const = 0; virtual void QueryShapesInCylinder(ezPhysicsOverlapResultArray& out_results, float fCylinderRadius, float fCylinderHeight, const ezTransform& transform, const ezPhysicsQueryParameters& params) const = 0; virtual ezVec3 GetGravity() const = 0; ////////////////////////////////////////////////////////////////////////// // ABSTRACTION HELPERS // // These functions are used to be able to use certain physics functionality, without having a direct dependency on the exact implementation (Jolt / PhysX). // If no physics module is available, they simply do nothing. // Add functions on demand. /// \brief Adds a static actor with a box shape to pOwner. virtual void AddStaticCollisionBox(ezGameObject* pOwner, ezVec3 vBoxSize) { EZ_IGNORE_UNUSED(pOwner); EZ_IGNORE_UNUSED(vBoxSize); } /// Data for creating a heightfield collider. struct HeightfieldColliderData { ezVec2 m_vHalfExtents; ezUInt32 m_uiResolution = 64; /// Height samples in row-major order, m_uiResolution * m_uiResolution entries. ezDynamicArray<float> m_Heights; /// Per-cell material indices (one per quad, (m_uiResolution-1)^2 entries). Indexes into m_Surfaces. ezDynamicArray<ezUInt8> m_MaterialIndices; ezDynamicArray<ezSurfaceResourceHandle> m_Surfaces; ezUInt8 m_uiCollisionLayer = 0; }; /// Tries to create a heightfield collider on pOwner by reusing a shape previously cached under sIdentifier. /// /// Removes any existing heightfield collider component from pOwner first. /// Returns EZ_FAILURE if no shape with that identifier is cached; the caller should then /// call CreateHeightfieldCollider() with the full data. virtual ezResult TrySetHeightfieldCollider(ezGameObject* pOwner, ezStringView sIdentifier) { EZ_IGNORE_UNUSED(pOwner); EZ_IGNORE_UNUSED(sIdentifier); return EZ_FAILURE; } /// Creates a heightfield collider on pOwner from the given height data and caches the resulting shape under sIdentifier. /// /// Removes any existing heightfield collider component from pOwner first. /// If a non-empty sIdentifier is supplied, the shape is stored so that future calls to /// TrySetHeightfieldCollider() with the same identifier can skip the data rebuild. virtual void CreateHeightfieldCollider(ezGameObject* pOwner, ezStringView sIdentifier, const HeightfieldColliderData& data) { EZ_IGNORE_UNUSED(pOwner); EZ_IGNORE_UNUSED(sIdentifier); EZ_IGNORE_UNUSED(data); } /// Removes the heightfield collider component from pOwner, if present. /// /// Decrements the reference count of the cached shape. If the count reaches zero, the cached shape is evicted. virtual void RemoveHeightfieldCollider(ezGameObject* pOwner) { EZ_IGNORE_UNUSED(pOwner); } struct JointConfig { ezGameObjectHandle m_hActorA; ezGameObjectHandle m_hActorB; ezTransform m_LocalFrameA = ezTransform::MakeIdentity(); ezTransform m_LocalFrameB = ezTransform::MakeIdentity(); }; struct FixedJointConfig : JointConfig { }; /// \brief Adds a fixed joint to pOwner. virtual void AddFixedJointComponent(ezGameObject* pOwner, const ezPhysicsWorldModuleInterface::FixedJointConfig& cfg) { EZ_IGNORE_UNUSED(pOwner); EZ_IGNORE_UNUSED(cfg); } /// \brief Gets world space bounds of a physics object if its shape type is included in shapeTypes and its collision layer interacts with uiCollisionLayer. virtual ezBoundingBoxSphere GetWorldSpaceBounds(ezGameObject* pOwner, ezUInt32 uiCollisionLayer, ezBitflags<ezPhysicsShapeType> shapeTypes, bool bIncludeChildObjects) const { EZ_IGNORE_UNUSED(pOwner); EZ_IGNORE_UNUSED(uiCollisionLayer); EZ_IGNORE_UNUSED(shapeTypes); EZ_IGNORE_UNUSED(bIncludeChildObjects); return ezBoundingBoxSphere::MakeInvalid(); } }; /// \brief Used to apply a physical impulse on the object struct EZ_CORE_DLL ezMsgPhysicsAddImpulse : public ezMessage { EZ_DECLARE_MESSAGE_TYPE(ezMsgPhysicsAddImpulse, ezMessage); ezVec3 m_vGlobalPosition; ezVec3 m_vImpulse; ezUInt8 m_uiImpulseType = 0; ezUInt32 m_uiObjectFilterID = ezInvalidIndex; // Physics-engine specific information, may be available or not. void* m_pInternalPhysicsShape = nullptr; void* m_pInternalPhysicsActor = nullptr; }; struct EZ_CORE_DLL ezMsgPhysicsJointBroke : public ezMessage { EZ_DECLARE_MESSAGE_TYPE(ezMsgPhysicsJointBroke, ezMessage); ezGameObjectHandle m_hJointObject; }; /// \brief Sent by components such as ezJoltGrabObjectComponent to indicate that the object has been grabbed or released. struct EZ_CORE_DLL ezMsgObjectGrabbed : public ezMessage { EZ_DECLARE_MESSAGE_TYPE(ezMsgObjectGrabbed, ezMessage); ezGameObjectHandle m_hGrabbedBy; bool m_bGotGrabbed = true; }; /// \brief Send this to components such as ezJoltGrabObjectComponent to demand that m_hGrabbedObjectToRelease should no longer be grabbed. struct EZ_CORE_DLL ezMsgReleaseObjectGrab : public ezMessage { EZ_DECLARE_MESSAGE_TYPE(ezMsgReleaseObjectGrab, ezMessage); ezGameObjectHandle m_hGrabbedObjectToRelease; }; /// \brief Can be sent by character controllers to inform objects when a CC pushes into them. /// /// Whether this message is sent, depends on the character controller implementation. /// This is mainly meant for less important interactions, like breaking decorative things. struct EZ_CORE_DLL ezMsgPhysicCharacterContact : public ezMessage { EZ_DECLARE_MESSAGE_TYPE(ezMsgPhysicCharacterContact, ezMessage); ezComponentHandle m_hCharacter; ezVec3 m_vGlobalPosition; ezVec3 m_vNormal; ezVec3 m_vCharacterVelocity; float m_fImpact; }; /// \brief Sent to physics components that have contact reporting enabled (see ezOnJoltContact::SendContactMsg). /// /// Only sent for certain physics object combinations, e.g. debris doesn't trigger this. /// The reported contact position and normal is an average of the contact manifold. /// This is mainly meant for less important interactions, like breaking decorative things. struct EZ_CORE_DLL ezMsgPhysicContact : public ezMessage { EZ_DECLARE_MESSAGE_TYPE(ezMsgPhysicContact, ezMessage); ezGameObjectHandle m_hOtherObject; ezVec3 m_vGlobalPosition; ezVec3 m_vNormal; float m_fImpactSqr; }; ////////////////////////////////////////////////////////////////////////// struct EZ_CORE_DLL ezSmcTriangle { EZ_DECLARE_POD_TYPE(); ezUInt32 m_uiVertexIndices[3]; }; struct EZ_CORE_DLL ezSmcSubMesh { EZ_DECLARE_POD_TYPE(); ezUInt32 m_uiFirstTriangle = 0; ezUInt32 m_uiNumTriangles = 0; ezUInt16 m_uiSurfaceIndex = 0; }; struct EZ_CORE_DLL ezSmcDescription { ezDeque<ezVec3> m_Vertices; ezDeque<ezSmcTriangle> m_Triangles; ezDeque<ezSmcSubMesh> m_SubMeshes; ezDeque<ezString> m_Surfaces; }; struct EZ_CORE_DLL ezMsgBuildStaticMesh : public ezMessage { EZ_DECLARE_MESSAGE_TYPE(ezMsgBuildStaticMesh, ezMessage); /// \brief Append data to this description to add meshes to the automatic static mesh generation ezSmcDescription* m_pStaticMeshDescription = nullptr; };