You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
252 lines
10 KiB
C++
252 lines
10 KiB
C++
/*
|
|
* 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 <AzCore/Math/Vector3.h>
|
|
#include <AzCore/Math/Vector2.h>
|
|
#include <AzCore/Math/Quaternion.h>
|
|
#include <AzCore/Asset/AssetCommon.h>
|
|
#include <AzCore/Serialization/SerializeContext.h>
|
|
|
|
#include <AzFramework/Physics/HeightfieldProviderBus.h>
|
|
|
|
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<AZ::Data::AssetData> 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<AZ::u8>& GetCookedMeshData() const;
|
|
|
|
MeshType GetMeshType() const;
|
|
|
|
void* GetCachedNativeMesh() const;
|
|
void SetCachedNativeMesh(void* cachedNativeMesh) const;
|
|
|
|
private:
|
|
void ReleaseCachedNativeMesh();
|
|
|
|
AZStd::vector<AZ::u8> 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<Physics::HeightMaterialPoint>& GetSamples() const;
|
|
void SetSamples(const AZStd::vector<Physics::HeightMaterialPoint>& 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<float>::lowest()};
|
|
float m_maxHeightBounds{AZStd::numeric_limits<float>::max()};
|
|
//! The grid of sample points for the heightfield.
|
|
AZStd::vector<Physics::HeightMaterialPoint> m_samples;
|
|
//! An optional storage pointer for the physics system to cache its native heightfield representation.
|
|
mutable void* m_cachedNativeHeightfield{ nullptr };
|
|
};
|
|
} // namespace Physics
|