Terrain Physics Heightfield support
* New Heightfield Components Signed-off-by: John Jones-Steele <jjjoness@amazon.com> * Misc PR fixes * Fixed linux build failure from bad #include * Renamed "Terrain Physics Collider" to "Terrain Physics Heightfield Collider" per physics team feedback * Fixed 1/5 -> 1/4 typo in a comment * Added missing member copies in HeightfieldShapeConfiguration Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Addressed PR feedback Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Changes from review Signed-off-by: John Jones-Steele <jjjoness@amazon.com> * Remove tabs accidently added Signed-off-by: John Jones-Steele <jjjoness@amazon.com> * Fixed overly complicated scaling math. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Added comments to make it more obvious what's happening on CreateEnd / DestroyBegin. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Moved Heightfield CreatePxGeometryFromConfig into its own function Signed-off-by: John Jones-Steele <jjjoness@amazon.com> Co-authored-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
775dda8ed2
commit
3d67be162c
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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/EBus/EBus.h>
|
||||
#include <AzCore/Component/ComponentBus.h>
|
||||
#include <AzCore/Math/Aabb.h>
|
||||
#include <AzFramework/Physics/Material.h>
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
//! The QuadMeshType specifies the property of the heightfield quad.
|
||||
enum class QuadMeshType : uint8_t
|
||||
{
|
||||
SubdivideUpperLeftToBottomRight, //!< Subdivide the quad, from upper left to bottom right |\|, into two triangles.
|
||||
SubdivideBottomLeftToUpperRight, //!< Subdivide the quad, from bottom left to upper right |/|, into two triangles.
|
||||
Hole //!< The quad should be treated as a hole in the heightfield.
|
||||
};
|
||||
|
||||
struct HeightMaterialPoint
|
||||
{
|
||||
float m_height{ 0.0f }; //!< Holds the height of this point in the heightfield relative to the heightfield entity location.
|
||||
QuadMeshType m_quadMeshType{ QuadMeshType::SubdivideUpperLeftToBottomRight }; //!< By default, create two triangles like this |\|, where this point is in the upper left corner.
|
||||
uint8_t m_materialIndex{ 0 }; //!< The surface material index for the upper left corner of this quad.
|
||||
uint16_t m_padding{ 0 }; //!< available for future use.
|
||||
};
|
||||
|
||||
//! An interface to provide heightfield values.
|
||||
class HeightfieldProviderRequests
|
||||
: public AZ::ComponentBus
|
||||
{
|
||||
public:
|
||||
//! Returns the distance between each height in the map.
|
||||
//! @return Vector containing Column Spacing, Rows Spacing.
|
||||
virtual AZ::Vector2 GetHeightfieldGridSpacing() const = 0;
|
||||
|
||||
//! Returns the height field gridsize.
|
||||
//! @param numColumns contains the size of the grid in the x direction.
|
||||
//! @param numRows contains the size of the grid in the y direction.
|
||||
virtual void GetHeightfieldGridSize(int32_t& numColumns, int32_t& numRows) const = 0;
|
||||
|
||||
//! Returns the height field min and max height bounds.
|
||||
//! @param minHeightBounds contains the minimum height that the heightfield can contain.
|
||||
//! @param maxHeightBounds contains the maximum height that the heightfield can contain.
|
||||
virtual void GetHeightfieldHeightBounds(float& minHeightBounds, float& maxHeightBounds) const = 0;
|
||||
|
||||
//! Returns the AABB of the heightfield.
|
||||
//! This is provided separately from the shape AABB because the heightfield might choose to modify the AABB bounds.
|
||||
//! @return AABB of the heightfield.
|
||||
virtual AZ::Aabb GetHeightfieldAabb() const = 0;
|
||||
|
||||
//! Returns the world transform for the heightfield.
|
||||
//! This is provided separately from the entity transform because the heightfield might want to clear out the rotation or scale.
|
||||
//! @return world transform that should be used with the heightfield data.
|
||||
virtual AZ::Transform GetHeightfieldTransform() const = 0;
|
||||
|
||||
//! Returns the list of materials used by the height field.
|
||||
//! @return returns a vector of all materials.
|
||||
virtual AZStd::vector<MaterialId> GetMaterialList() const = 0;
|
||||
|
||||
//! Returns the list of heights used by the height field.
|
||||
//! @return the rows*columns vector of the heights.
|
||||
virtual AZStd::vector<float> GetHeights() const = 0;
|
||||
|
||||
//! Returns the list of heights and materials used by the height field.
|
||||
//! @return the rows*columns vector of the heights and materials.
|
||||
virtual AZStd::vector<Physics::HeightMaterialPoint> GetHeightsAndMaterials() const = 0;
|
||||
};
|
||||
|
||||
using HeightfieldProviderRequestsBus = AZ::EBus<HeightfieldProviderRequests>;
|
||||
|
||||
//! Broadcasts notifications when heightfield data changes - heightfield providers implement HeightfieldRequests bus.
|
||||
class HeightfieldProviderNotifications
|
||||
: public AZ::ComponentBus
|
||||
{
|
||||
public:
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
|
||||
|
||||
//! Called whenever the heightfield data changes.
|
||||
//! @param the AABB of the area of data that changed.
|
||||
virtual void OnHeightfieldDataChanged([[maybe_unused]] const AZ::Aabb& dirtyRegion)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
~HeightfieldProviderNotifications() = default;
|
||||
};
|
||||
|
||||
using HeightfieldProviderNotificationBus = AZ::EBus<HeightfieldProviderNotifications>;
|
||||
} // namespace Physics
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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 <gmock/gmock.h>
|
||||
|
||||
#include <AzFramework/Physics/HeightfieldProviderBus.h>
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
class MockHeightfieldProviderNotificationBusListener
|
||||
: private Physics::HeightfieldProviderNotificationBus::Handler
|
||||
{
|
||||
public:
|
||||
MockHeightfieldProviderNotificationBusListener(AZ::EntityId entityid)
|
||||
{
|
||||
Physics::HeightfieldProviderNotificationBus::Handler::BusConnect(entityid);
|
||||
}
|
||||
|
||||
~MockHeightfieldProviderNotificationBusListener()
|
||||
{
|
||||
Physics::HeightfieldProviderNotificationBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
MOCK_METHOD1(OnHeightfieldDataChanged, void(const AZ::Aabb&));
|
||||
};
|
||||
} // namespace UnitTest
|
||||
@@ -37,6 +37,7 @@ namespace Physics
|
||||
REFLECT_SHAPETYPE_ENUM_VALUE(Sphere);
|
||||
REFLECT_SHAPETYPE_ENUM_VALUE(Cylinder);
|
||||
REFLECT_SHAPETYPE_ENUM_VALUE(PhysicsAsset);
|
||||
REFLECT_SHAPETYPE_ENUM_VALUE(Heightfield);
|
||||
|
||||
#undef REFLECT_SHAPETYPE_ENUM_VALUE
|
||||
}
|
||||
@@ -305,4 +306,125 @@ namespace Physics
|
||||
m_cachedNativeMesh = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void HeightfieldShapeConfiguration::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext
|
||||
->RegisterGenericType<AZStd::shared_ptr<HeightfieldShapeConfiguration>>();
|
||||
|
||||
serializeContext->Class<HeightfieldShapeConfiguration, ShapeConfiguration>()
|
||||
->Version(1);
|
||||
}
|
||||
}
|
||||
|
||||
HeightfieldShapeConfiguration::~HeightfieldShapeConfiguration()
|
||||
{
|
||||
SetCachedNativeHeightfield(nullptr);
|
||||
}
|
||||
|
||||
HeightfieldShapeConfiguration::HeightfieldShapeConfiguration(const HeightfieldShapeConfiguration& other)
|
||||
: ShapeConfiguration(other)
|
||||
, m_gridResolution(other.m_gridResolution)
|
||||
, m_numColumns(other.m_numColumns)
|
||||
, m_numRows(other.m_numRows)
|
||||
, m_samples(other.m_samples)
|
||||
, m_minHeightBounds(other.m_minHeightBounds)
|
||||
, m_maxHeightBounds(other.m_maxHeightBounds)
|
||||
, m_cachedNativeHeightfield(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
HeightfieldShapeConfiguration& HeightfieldShapeConfiguration::operator=(const HeightfieldShapeConfiguration& other)
|
||||
{
|
||||
ShapeConfiguration::operator=(other);
|
||||
|
||||
m_gridResolution = other.m_gridResolution;
|
||||
m_numColumns = other.m_numColumns;
|
||||
m_numRows = other.m_numRows;
|
||||
m_samples = other.m_samples;
|
||||
m_minHeightBounds = other.m_minHeightBounds;
|
||||
m_maxHeightBounds = other.m_maxHeightBounds;
|
||||
|
||||
// Prevent raw pointer from being copied
|
||||
m_cachedNativeHeightfield = nullptr;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void* HeightfieldShapeConfiguration::GetCachedNativeHeightfield() const
|
||||
{
|
||||
return m_cachedNativeHeightfield;
|
||||
}
|
||||
|
||||
void HeightfieldShapeConfiguration::SetCachedNativeHeightfield(void* cachedNativeHeightfield) const
|
||||
{
|
||||
if (m_cachedNativeHeightfield)
|
||||
{
|
||||
Physics::SystemRequestBus::Broadcast(&Physics::SystemRequests::ReleaseNativeHeightfieldObject, m_cachedNativeHeightfield);
|
||||
}
|
||||
|
||||
m_cachedNativeHeightfield = cachedNativeHeightfield;
|
||||
}
|
||||
|
||||
AZ::Vector2 HeightfieldShapeConfiguration::GetGridResolution() const
|
||||
{
|
||||
return m_gridResolution;
|
||||
}
|
||||
|
||||
void HeightfieldShapeConfiguration::SetGridResolution(const AZ::Vector2& gridResolution)
|
||||
{
|
||||
m_gridResolution = gridResolution;
|
||||
}
|
||||
|
||||
int32_t HeightfieldShapeConfiguration::GetNumColumns() const
|
||||
{
|
||||
return m_numColumns;
|
||||
}
|
||||
|
||||
void HeightfieldShapeConfiguration::SetNumColumns(int32_t numColumns)
|
||||
{
|
||||
m_numColumns = numColumns;
|
||||
}
|
||||
|
||||
int32_t HeightfieldShapeConfiguration::GetNumRows() const
|
||||
{
|
||||
return m_numRows;
|
||||
}
|
||||
|
||||
void HeightfieldShapeConfiguration::SetNumRows(int32_t numRows)
|
||||
{
|
||||
m_numRows = numRows;
|
||||
}
|
||||
|
||||
const AZStd::vector<Physics::HeightMaterialPoint>& HeightfieldShapeConfiguration::GetSamples() const
|
||||
{
|
||||
return m_samples;
|
||||
}
|
||||
|
||||
void HeightfieldShapeConfiguration::SetSamples(const AZStd::vector<Physics::HeightMaterialPoint>& samples)
|
||||
{
|
||||
m_samples = samples;
|
||||
}
|
||||
|
||||
float HeightfieldShapeConfiguration::GetMinHeightBounds() const
|
||||
{
|
||||
return m_minHeightBounds;
|
||||
}
|
||||
|
||||
void HeightfieldShapeConfiguration::SetMinHeightBounds(float minBounds)
|
||||
{
|
||||
m_minHeightBounds = minBounds;
|
||||
}
|
||||
|
||||
float HeightfieldShapeConfiguration::GetMaxHeightBounds() const
|
||||
{
|
||||
return m_maxHeightBounds;
|
||||
}
|
||||
|
||||
void HeightfieldShapeConfiguration::SetMaxHeightBounds(float maxBounds)
|
||||
{
|
||||
m_maxHeightBounds = maxBounds;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,10 +9,13 @@
|
||||
#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.
|
||||
@@ -27,6 +30,7 @@ namespace Physics
|
||||
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
|
||||
@@ -196,4 +200,52 @@ namespace Physics
|
||||
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
|
||||
|
||||
@@ -132,6 +132,10 @@ namespace Physics
|
||||
|
||||
virtual AZStd::shared_ptr<Material> CreateMaterial(const Physics::MaterialConfiguration& materialConfiguration) = 0;
|
||||
|
||||
/// Releases the height field object created by the physics backend.
|
||||
/// @param nativeHeightfieldObject Pointer to the height field object.
|
||||
virtual void ReleaseNativeHeightfieldObject(void* nativeHeightfieldObject) = 0;
|
||||
|
||||
/// Releases the mesh object created by the physics backend.
|
||||
/// @param nativeMeshObject Pointer to the mesh object.
|
||||
virtual void ReleaseNativeMeshObject(void* nativeMeshObject) = 0;
|
||||
|
||||
@@ -107,6 +107,7 @@ namespace Physics
|
||||
PhysicsAssetShapeConfiguration::Reflect(context);
|
||||
NativeShapeConfiguration::Reflect(context);
|
||||
CookedMeshShapeConfiguration::Reflect(context);
|
||||
HeightfieldShapeConfiguration::Reflect(context);
|
||||
AzPhysics::SystemInterface::Reflect(context);
|
||||
AzPhysics::Scene::Reflect(context);
|
||||
AzPhysics::CollisionLayer::Reflect(context);
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
#
|
||||
|
||||
set(FILES
|
||||
Mocks/MockHeightfieldProviderBus.h
|
||||
)
|
||||
@@ -228,6 +228,7 @@ set(FILES
|
||||
Physics/Configuration/SimulatedBodyConfiguration.cpp
|
||||
Physics/Configuration/SystemConfiguration.h
|
||||
Physics/Configuration/SystemConfiguration.cpp
|
||||
Physics/HeightfieldProviderBus.h
|
||||
Physics/SimulatedBodies/RigidBody.h
|
||||
Physics/SimulatedBodies/RigidBody.cpp
|
||||
Physics/SimulatedBodies/StaticRigidBody.h
|
||||
@@ -251,6 +252,7 @@ set(FILES
|
||||
Physics/Shape.h
|
||||
Physics/ShapeConfiguration.h
|
||||
Physics/ShapeConfiguration.cpp
|
||||
Physics/HeightfieldProviderBus.h
|
||||
Physics/SystemBus.h
|
||||
Physics/ColliderComponentBus.h
|
||||
Physics/RagdollPhysicsBus.h
|
||||
|
||||
@@ -42,6 +42,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
NAMESPACE AZ
|
||||
FILES_CMAKE
|
||||
Tests/framework_shared_tests_files.cmake
|
||||
AzFramework/Physics/physics_mock_files.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PUBLIC
|
||||
Tests
|
||||
@@ -53,7 +54,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
AZ::AzTest
|
||||
AZ::AzTestShared
|
||||
)
|
||||
|
||||
|
||||
if(PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
|
||||
ly_add_target(
|
||||
|
||||
Reference in New Issue
Block a user