/* * Copyright (c) Contributors to the Open 3D Engine Project. * For complete copyright and license terms please see the LICENSE at the root of this distribution. * * SPDX-License-Identifier: Apache-2.0 OR MIT * */ #pragma once #include #include #include #include #include #include namespace Physics { /// Used to identify shape configuration type from base class. enum class ShapeType : AZ::u8 { Sphere, Box, Capsule, Cylinder, ConvexHull, ///< Not Supported in physx TriangleMesh, ///< Not Supported in physx Native, ///< Native shape configuration if user wishes to bypass generic shape configurations. PhysicsAsset, ///< Shapes configured in the asset. CookedMesh, ///< Stores a blob of mesh data cooked for the specific engine. Heightfield ///< Interacts with the physics system heightfield }; class ShapeConfiguration { public: AZ_CLASS_ALLOCATOR(ShapeConfiguration, AZ::SystemAllocator, 0); AZ_RTTI(ShapeConfiguration, "{1FD56C72-6055-4B35-9253-07D432B94E91}"); static void Reflect(AZ::ReflectContext* context); virtual ~ShapeConfiguration() = default; virtual ShapeType GetShapeType() const = 0; AZ::Vector3 m_scale = AZ::Vector3::CreateOne(); }; class SphereShapeConfiguration : public ShapeConfiguration { public: AZ_CLASS_ALLOCATOR(SphereShapeConfiguration, AZ::SystemAllocator, 0); AZ_RTTI(SphereShapeConfiguration, "{0B9F3D2E-0780-4B0B-BFEE-B41C5FDE774A}", ShapeConfiguration); static void Reflect(AZ::ReflectContext* context); explicit SphereShapeConfiguration(float radius = 0.5f); ShapeType GetShapeType() const override { return ShapeType::Sphere; } float m_radius = 0.5f; }; class BoxShapeConfiguration : public ShapeConfiguration { public: AZ_CLASS_ALLOCATOR(BoxShapeConfiguration, AZ::SystemAllocator, 0); AZ_RTTI(BoxShapeConfiguration, "{E58040ED-3E50-4882-B0E9-525E7A548F8D}", ShapeConfiguration); static void Reflect(AZ::ReflectContext* context); explicit BoxShapeConfiguration(const AZ::Vector3& boxDimensions = AZ::Vector3::CreateOne()); ShapeType GetShapeType() const override { return ShapeType::Box; } AZ::Vector3 m_dimensions = AZ::Vector3::CreateOne(); }; class CapsuleShapeConfiguration : public ShapeConfiguration { public: AZ_CLASS_ALLOCATOR(CapsuleShapeConfiguration, AZ::SystemAllocator, 0); AZ_RTTI(CapsuleShapeConfiguration, "{19C6A07E-5644-46B7-A49E-48703B56ED32}", ShapeConfiguration); static void Reflect(AZ::ReflectContext* context); explicit CapsuleShapeConfiguration(float height = 1.0f, float radius = 0.25f); ShapeType GetShapeType() const override { return ShapeType::Capsule; } float m_height = 1.0f; float m_radius = 0.25f; private: void OnHeightChanged(); void OnRadiusChanged(); }; class ConvexHullShapeConfiguration : public ShapeConfiguration { public: AZ_CLASS_ALLOCATOR(ConvexHullShapeConfiguration, AZ::SystemAllocator, 0); ShapeType GetShapeType() const override { return ShapeType::ConvexHull; } const void* m_vertexData = nullptr; AZ::u32 m_vertexCount = 0; AZ::u32 m_vertexStride = 4; const void* m_planeData = nullptr; AZ::u32 m_planeCount = 0; AZ::u32 m_planeStride = 4; const void* m_adjacencyData = nullptr; AZ::u32 m_adjacencyCount = 0; AZ::u32 m_adjacencyStride = 4; bool m_copyData = true; ///< If set, vertex buffer will be copied in the native physics implementation, }; class TriangleMeshShapeConfiguration : public ShapeConfiguration { public: AZ_CLASS_ALLOCATOR(TriangleMeshShapeConfiguration, AZ::SystemAllocator, 0); ShapeType GetShapeType() const override { return ShapeType::TriangleMesh; } const void* m_vertexData = nullptr; AZ::u32 m_vertexCount = 0; AZ::u32 m_vertexStride = 4; ///< Data size of a given vertex, e.g. float * 3 = 12. const void* m_indexData = nullptr; AZ::u32 m_indexCount = 0; AZ::u32 m_indexStride = 12; ///< Data size of indices for a given triangle, e.g. AZ::u32 * 3 = 12. bool m_copyData = true; ///< If set, vertex/index buffers will be copied in the native physics implementation, ///< and don't need to be kept alive by the caller; }; class PhysicsAssetShapeConfiguration : public ShapeConfiguration { public: AZ_CLASS_ALLOCATOR(PhysicsAssetShapeConfiguration, AZ::SystemAllocator, 0); AZ_RTTI(PhysicsAssetShapeConfiguration, "{1C0046D9-BC9E-4F93-9F0E-D62654FB18EA}", ShapeConfiguration); static void Reflect(AZ::ReflectContext* context); ShapeType GetShapeType() const override; AZ::Data::Asset m_asset{ AZ::Data::AssetLoadBehavior::PreLoad }; AZ::Vector3 m_assetScale = AZ::Vector3::CreateOne(); bool m_useMaterialsFromAsset = true; AZ::u8 m_subdivisionLevel = 4; ///< The level of subdivision if a primitive shape is replaced with a convex mesh due to scaling. }; class NativeShapeConfiguration : public ShapeConfiguration { public: AZ_CLASS_ALLOCATOR(NativeShapeConfiguration, AZ::SystemAllocator, 0); AZ_RTTI(NativeShapeConfiguration, "{6CB8FE4A-A577-49AF-81F4-4F1AD245859A}", ShapeConfiguration); static void Reflect(AZ::ReflectContext* context); ShapeType GetShapeType() const override { return ShapeType::Native; } void* m_nativeShapePtr = nullptr; ///< Native shape ptr. This will not be serialised AZ::Vector3 m_nativeShapeScale = AZ::Vector3::CreateOne(); ///< Native shape scale. This will be serialised }; class CookedMeshShapeConfiguration : public ShapeConfiguration { public: AZ_CLASS_ALLOCATOR(CookedMeshShapeConfiguration, AZ::SystemAllocator, 0); AZ_RTTI(CookedMeshShapeConfiguration, "{D9E58241-36BB-4A4F-B50C-1736EB7E841F}", ShapeConfiguration); static void Reflect(AZ::ReflectContext* context); enum class MeshType : AZ::u8 { TriangleMesh = 0, Convex }; CookedMeshShapeConfiguration() = default; CookedMeshShapeConfiguration(const CookedMeshShapeConfiguration&); CookedMeshShapeConfiguration& operator=(const CookedMeshShapeConfiguration&); ~CookedMeshShapeConfiguration(); ShapeType GetShapeType() const override; //! Sets the cooked data. This will release the cached mesh. //! Input data has to be in the physics engine specific format. //! (e.g. in PhysX: result of cookTriangleMesh or cookConvexMesh). void SetCookedMeshData(const AZ::u8* cookedData, size_t cookedDataSize, MeshType type); const AZStd::vector& GetCookedMeshData() const; MeshType GetMeshType() const; void* GetCachedNativeMesh() const; void SetCachedNativeMesh(void* cachedNativeMesh) const; private: void ReleaseCachedNativeMesh(); AZStd::vector m_cookedData; MeshType m_type = MeshType::TriangleMesh; //! Cached native mesh object (e.g. PxConvexMesh or PxTriangleMesh). This data is not serialized. mutable void* m_cachedNativeMesh = nullptr; }; class HeightfieldShapeConfiguration : public ShapeConfiguration { public: AZ_CLASS_ALLOCATOR(HeightfieldShapeConfiguration, AZ::SystemAllocator, 0); AZ_RTTI(HeightfieldShapeConfiguration, "{8DF47C83-D2A9-4E7C-8620-5E173E43C0B3}", ShapeConfiguration); static void Reflect(AZ::ReflectContext* context); HeightfieldShapeConfiguration() = default; HeightfieldShapeConfiguration(const HeightfieldShapeConfiguration&); HeightfieldShapeConfiguration& operator=(const HeightfieldShapeConfiguration&); ~HeightfieldShapeConfiguration(); ShapeType GetShapeType() const override { return ShapeType::Heightfield; } void* GetCachedNativeHeightfield() const; void SetCachedNativeHeightfield(void* cachedNativeHeightfield) const; AZ::Vector2 GetGridResolution() const; void SetGridResolution(const AZ::Vector2& gridSpacing); int32_t GetNumColumns() const; void SetNumColumns(int32_t numColumns); int32_t GetNumRows() const; void SetNumRows(int32_t numRows); const AZStd::vector& GetSamples() const; void SetSamples(const AZStd::vector& samples); float GetMinHeightBounds() const; void SetMinHeightBounds(float minBounds); float GetMaxHeightBounds() const; void SetMaxHeightBounds(float maxBounds); private: //! The number of meters between each heightfield sample. AZ::Vector2 m_gridResolution{ 1.0f }; //! The number of columns in the heightfield sample grid. int32_t m_numColumns{ 0 }; //! The number of rows in the heightfield sample grid. int32_t m_numRows{ 0 }; //! The minimum and maximum heights that can be used by this heightfield. //! This can be used by the physics system to choose a more optimal heightfield data type internally (ex: int16, uint8) float m_minHeightBounds{AZStd::numeric_limits::lowest()}; float m_maxHeightBounds{AZStd::numeric_limits::max()}; //! The grid of sample points for the heightfield. AZStd::vector m_samples; //! An optional storage pointer for the physics system to cache its native heightfield representation. mutable void* m_cachedNativeHeightfield{ nullptr }; }; } // namespace Physics