Files
o3de/Gems/PhysX/Code/Source/Utils.h
T
Aaron Ruiz Mora 00e860f326 Physics material system for spectra launch
- Invalidate 'Physics Materials From Mesh' boolean from collider component
- Removed material library from material selector. Default material library will always be used instead.
- Marking failing automated test as xfail
- Added default material to physics configuration.
- Moved material library asset from physx configuration to physics configuration, as it doesn't need to be physx specific.
- Refactor physics material system having into account that there is only one material library in the project.
- Renaming code from DefaultMaterialLibrary to MaterialLibrary.
- All queries about physics materials unified under PhysicsMaterialRequests bus.
- PhysXSystem only manages the material library asset.
- Saving and reloading the same physics material asset with different content didn't trigger a events that the material library has changed.
- Changing Physics Material Request interface to use shared_ptr instead of weak_ptr to be simpler to handle the returned materials and having a more consistent code.
- Refactored Material Manager to improve its implementation. Still following the same approach of "creating materials on the fly as they are requested", but now it's doing it consistently across the interface, with private helpers functions FindOrCreateMaterial that simplify vastly the implementation.
- Material Manager now listens to change event of material library asset and default material configuration so it updates its materials accordingly.
- Complete Material move constructor and operator.
2021-05-28 20:16:25 +01:00

261 lines
13 KiB
C++

/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <PhysX/ForceRegionComponentBus.h>
#include <AzCore/Math/Quaternion.h>
#include <AzCore/Math/Transform.h>
#include <AzCore/Math/Vector3.h>
#include <AzFramework/Physics/Material.h>
#include <AzFramework/Physics/Shape.h>
#include <AzFramework/Physics/ShapeConfiguration.h>
#include <AzCore/std/optional.h>
#include <PxPhysicsAPI.h>
namespace AzPhysics
{
class CollisionGroup;
struct RigidBodyConfiguration;
struct StaticRigidBodyConfiguration;
struct StaticRigidBody;
class Scene;
}
namespace Physics
{
class RigidBodyConfiguration;
class ColliderConfiguration;
class ShapeConfiguration;
}
namespace PhysX
{
class Shape;
class ActorData;
class Material;
struct TerrainConfiguration;
namespace Pipeline
{
class MeshAssetData;
} // namespace Pipeline
namespace Utils
{
bool CreatePxGeometryFromConfig(const Physics::ShapeConfiguration& shapeConfiguration, physx::PxGeometryHolder& pxGeometry);
physx::PxShape* CreatePxShapeFromConfig(
const Physics::ColliderConfiguration& colliderConfiguration,
const Physics::ShapeConfiguration& shapeConfiguration,
AzPhysics::CollisionGroup& assignedCollisionGroup
);
AzPhysics::Scene* GetDefaultScene();
//! Creates a PhysX cooked mesh config from the given points.
//!
//! @param pointList Vector of points to build the mesh from.
//! @param scale Scale to be assigned to the cooked mesh.
//! @return Either a valid cooked mesh or none if the cooking failed.
//!
AZStd::optional<Physics::CookedMeshShapeConfiguration> CreatePxCookedMeshConfiguration(const AZStd::vector<AZ::Vector3>& pointList, const AZ::Vector3& scale);
//! Returns whether a shape configuration describes a primitive shape such as a box or sphere, as opposed to mesh geometry.
bool IsPrimitiveShape(const Physics::ShapeConfiguration& shapeConfig);
//! Minimum and maximum values for the level of subdivision used when approximating capsules and spheres with convex meshes.
//! The maximum value is chosen so that the number of faces and vertices generated by CreateConvexFromPrimitive will be within
//! the limit imposed by PhysX (255).
//! @{
constexpr AZ::u8 MinCapsuleSubdivisionLevel = 1;
constexpr AZ::u8 MaxCapsuleSubdivisionLevel = 5;
//! @}
AZStd::optional<Physics::CookedMeshShapeConfiguration> CreateConvexFromPrimitive(
const Physics::ColliderConfiguration& colliderConfig,
const Physics::ShapeConfiguration& primitiveShapeConfig, AZ::u8 subdivisionLevel, const AZ::Vector3& scale);
// 255 is the hard limit for PhysX number of vertices/faces. Upper bound is set to something sensible and less than this hard limit.
constexpr AZ::u8 MinFrustumSubdivisions = 3;
constexpr AZ::u8 MaxFrustumSubdivisions = 125;
//! Creates the points for a given frustum along the z axis as specified by the supplied arguements.
//!
//! @param height Height of the frustum. Must be greater than 0.
//! @param bottomRadius Radius of bottom cace of frustum. Must be greater than 0 if topRadius is 0, otherwise can be 0.
//! @param topRadius Radius of top face of frustum. Must be greater than 0 if bottompRadius is 0, otherwise can be 0.
//! @param subdivisionsNumber of angular subdivisions. Must be between 3 and 125 inclusive.
//! @return Either a valid point list or none if any of the arguements are invalid.
//!
AZStd::optional<AZStd::vector<AZ::Vector3>> CreatePointsAtFrustumExtents(float height, float bottomRadius, float topRadius, AZ::u8 subdivisions);
AZStd::string ConvexCookingResultToString(physx::PxConvexMeshCookingResult::Enum convexCookingResultCode);
AZStd::string TriMeshCookingResultToString(physx::PxTriangleMeshCookingResult::Enum triangleCookingResultCode);
bool WriteCookedMeshToFile(const AZStd::string& filePath, const Pipeline::MeshAssetData& assetData);
bool WriteCookedMeshToFile(const AZStd::string& filePath, const AZStd::vector<AZ::u8>& physxData,
Physics::CookedMeshShapeConfiguration::MeshType meshType);
bool CookConvexToPxOutputStream(const AZ::Vector3* vertices, AZ::u32 vertexCount, physx::PxOutputStream& stream);
bool CookTriangleMeshToToPxOutputStream(const AZ::Vector3* vertices, AZ::u32 vertexCount,
const AZ::u32* indices, AZ::u32 indexCount, physx::PxOutputStream& stream);
bool MeshDataToPxGeometry(physx::PxBase* meshData, physx::PxGeometryHolder &pxGeometry, const AZ::Vector3& scale);
//! Returns all connected busIds of the specified type.
template<typename BusT>
AZStd::vector<typename BusT::BusIdType> FindConnectedBusIds()
{
AZStd::vector<typename BusT::BusIdType> busIds;
BusT::EnumerateHandlers([&busIds](typename BusT::Events* /*handler*/)
{
busIds.emplace_back(*BusT::GetCurrentBusId());
return true;
});
return busIds;
}
//! Logs a warning message using the names of the entities provided.
void WarnEntityNames(const AZStd::vector<AZ::EntityId>& entityIds, const char* category, const char* message);
//! Logs a warning if there is more than one connected bus of the particular type.
template<typename BusT>
void LogWarningIfMultipleComponents(const char* messageCategroy, const char* messageFormat)
{
const auto entityIds = FindConnectedBusIds<BusT>();
if (entityIds.size() > 1)
{
WarnEntityNames(entityIds, messageCategroy, messageFormat);
}
}
//! Converts collider position and orientation offsets to a transform.
AZ::Transform GetColliderLocalTransform(const AZ::Vector3& colliderRelativePosition
, const AZ::Quaternion& colliderRelativeRotation);
//! Combines collider position and orientation offsets and world transform to a transform.
AZ::Transform GetColliderWorldTransform(const AZ::Transform& worldTransform
, const AZ::Vector3& colliderRelativePosition
, const AZ::Quaternion& colliderRelativeRotation);
//! Converts points in a collider's local space to world space positions
//! accounting for collider position and orientation offsets.
void ColliderPointsLocalToWorld(AZStd::vector<AZ::Vector3>& pointsInOut
, const AZ::Transform& worldTransform
, const AZ::Vector3& colliderRelativePosition
, const AZ::Quaternion& colliderRelativeRotation
, const AZ::Vector3& nonUniformScale);
//! Returns AABB of collider by constructing PxGeometry from collider and shape configuration,
//! and invoking physx::PxGeometryQuery::getWorldBounds.
//! This function is used only by editor components.
AZ::Aabb GetColliderAabb(const AZ::Transform& worldTransform
, bool hasNonUniformScale
, AZ::u8 subdivisionLevel
, const ::Physics::ShapeConfiguration& shapeConfiguration
, const ::Physics::ColliderConfiguration& colliderConfiguration);
bool TriggerColliderExists(AZ::EntityId entityId);
void GetShapesFromAsset(const Physics::PhysicsAssetShapeConfiguration& assetConfiguration,
const Physics::ColliderConfiguration& originalColliderConfiguration, bool hasNonUniformScale,
AZ::u8 subdivisionLevel, AZStd::vector<AZStd::shared_ptr<Physics::Shape>>& resultingShapes);
void GetColliderShapeConfigsFromAsset(const Physics::PhysicsAssetShapeConfiguration& assetConfiguration,
const Physics::ColliderConfiguration& originalColliderConfiguration,
bool hasNonUniformScale, AZ::u8 subdivisionLevel, AzPhysics::ShapeColliderPairList& resultingColliderShapes);
//! Gets the scale from the entity's Transform component.
AZ::Vector3 GetTransformScale(AZ::EntityId entityId);
//! Returns a vector scale with each element equal to the max element from the entity's Transform component.
AZ::Vector3 GetUniformScale(AZ::EntityId entityId);
//! Gets the scale from the entity's Non-Uniform Scale component, if it is present.
//! Otherwise (1, 1, 1) is returned.
AZ::Vector3 GetNonUniformScale(AZ::EntityId entityId);
//! Gets the overall scale, taking into account the scale from both the entity's Transform component and the
//! Non-Uniform Scale component, if it is present.
AZ::Vector3 GetOverallScale(AZ::EntityId entityId);
//! Returns defaultValue if the input is infinite or NaN, otherwise returns the input unchanged.
const AZ::Vector3& Sanitize(const AZ::Vector3& input, const AZ::Vector3& defaultValue = AZ::Vector3::CreateZero());
namespace Geometry
{
using PointList = AZStd::vector<AZ::Vector3>;
//! Generates a list of points on a box.
PointList GenerateBoxPoints(const AZ::Vector3& min, const AZ::Vector3& max);
//! Generates a list of points on the surface of a sphere.
PointList GenerateSpherePoints(float radius);
//! Generates a list of points on the surface of a cylinder.
PointList GenerateCylinderPoints(float height, float radius);
//! Generates vertices and indices representing the provided box geometry
void GetBoxGeometry(const physx::PxBoxGeometry& geometry, AZStd::vector<AZ::Vector3>& vertices, AZStd::vector<AZ::u32>& indices);
//! Generates vertices and indices representing the provided capsule geometry
void GetCapsuleGeometry(const physx::PxCapsuleGeometry& geometry, AZStd::vector<AZ::Vector3>& vertices, AZStd::vector<AZ::u32>& indices, const AZ::u32 stacks, const AZ::u32 slices);
//! Generates vertices and indices representing the provided convex mesh geometry
void GetConvexMeshGeometry(const physx::PxConvexMeshGeometry& geometry, AZStd::vector<AZ::Vector3>& vertices, AZStd::vector<AZ::u32>& indices);
//! Generates vertices and indices representing the provided heightfield geometry, optionally limited to a bounding box
void GetHeightFieldGeometry(const physx::PxHeightFieldGeometry& geometry, AZStd::vector<AZ::Vector3>& vertices, AZStd::vector<AZ::u32>& indices, AZ::Aabb* optionalBounds);
//! Generates vertices and indices representing the provided sphere geometry and optional stacks and slices
void GetSphereGeometry(const physx::PxSphereGeometry& geometry, AZStd::vector<AZ::Vector3>& vertices, AZStd::vector<AZ::u32>& indices, const AZ::u32 stacks, const AZ::u32 slices);
//! Generates vertices and indices representing the provided triangle mesh geometry
void GetTriangleMeshGeometry(const physx::PxTriangleMeshGeometry& geometry, AZStd::vector<AZ::Vector3>& vertices, AZStd::vector<AZ::u32>& indices);
} // namespace Geometry
//! Returns the World transform of an entity with scale.
//! This can be used if ComputeJointLocalTransform will be invoked with the result as an argument since ComputeJointLocalTransform will remove scale.
AZ::Transform GetEntityWorldTransformWithScale(AZ::EntityId entityId);
//! Returns the World transform of an entity without scale.
AZ::Transform GetEntityWorldTransformWithoutScale(AZ::EntityId entityId);
//! Computes the local transform of joint from an entity given the joint's world transform and the entity's world transform.
AZ::Transform ComputeJointLocalTransform(const AZ::Transform& jointWorldTransform,
const AZ::Transform& entityWorldTransform);
//! Computes the world transform of joint given the joint's local transform from an entity and the entity's world transform.
AZ::Transform ComputeJointWorldTransform(const AZ::Transform& jointLocalTransform,
const AZ::Transform& entityWorldTransform);
} // namespace Utils
namespace ReflectionUtils
{
//! Reflect API specific to PhysX physics. Generic physics API should be reflected in Physics::ReflectionUtils::ReflectPhysicsApi.
void ReflectPhysXOnlyApi(AZ::ReflectContext* context);
} // namespace ReflectionUtils
namespace PxActorFactories
{
AZStd::shared_ptr<physx::PxRigidDynamic> CreatePxRigidBody(const AzPhysics::RigidBodyConfiguration& configuration);
AZStd::shared_ptr<physx::PxRigidStatic> CreatePxStaticRigidBody(const AzPhysics::StaticRigidBodyConfiguration& configuration);
} // namespace PxActorFactories
namespace StaticRigidBodyUtils
{
bool CanCreateRuntimeComponent(const AZ::Entity& editorEntity);
bool TryCreateRuntimeComponent(const AZ::Entity& editorEntity, AZ::Entity& gameEntity);
} // namespace StaticRigidBodyComponent
} // namespace PhysX