Merge pull request #69 from aws-lumberyard-dev/non-uniform-scale-mesh
support for non-uniform scale component with atom mesh component
This commit is contained in:
@@ -146,8 +146,8 @@ namespace AZ
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
|
||||
->Method("GetTranslated", &Aabb::GetTranslated)
|
||||
->Method("GetSurfaceArea", &Aabb::GetSurfaceArea)
|
||||
->Method("GetTransformedObb", &Aabb::GetTransformedObb)
|
||||
->Method("GetTransformedAabb", &Aabb::GetTransformedAabb)
|
||||
->Method("GetTransformedObb", static_cast<Obb(Aabb::*)(const Transform&) const>(&Aabb::GetTransformedObb))
|
||||
->Method("GetTransformedAabb", static_cast<Aabb(Aabb::*)(const Transform&) const>(&Aabb::GetTransformedAabb))
|
||||
->Method("ApplyTransform", &Aabb::ApplyTransform)
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
|
||||
->Method("Clone", [](const Aabb& rhs) -> Aabb { return rhs; })
|
||||
@@ -195,6 +195,20 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
Obb Aabb::GetTransformedObb(const Matrix3x4& matrix3x4) const
|
||||
{
|
||||
Matrix3x4 matrixNoScale = matrix3x4;
|
||||
const AZ::Vector3 scale = matrixNoScale.ExtractScale();
|
||||
const AZ::Quaternion rotation = AZ::Quaternion::CreateFromMatrix3x4(matrixNoScale);
|
||||
|
||||
return Obb::CreateFromPositionRotationAndHalfLengths(
|
||||
matrix3x4 * GetCenter(),
|
||||
rotation,
|
||||
0.5f * scale * GetExtents()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
void Aabb::ApplyTransform(const Transform& transform)
|
||||
{
|
||||
Vector3 a, b, axisCoeffs;
|
||||
@@ -224,4 +238,17 @@ namespace AZ
|
||||
m_min = newMin;
|
||||
m_max = newMax;
|
||||
}
|
||||
|
||||
|
||||
void Aabb::ApplyMatrix3x4(const Matrix3x4& matrix3x4)
|
||||
{
|
||||
const AZ::Vector3 extents = GetExtents();
|
||||
const AZ::Vector3 center = matrix3x4 * GetCenter();
|
||||
AZ::Vector3 newHalfExtents(
|
||||
0.5f * matrix3x4.GetRowAsVector3(0).GetAbs().Dot(extents),
|
||||
0.5f * matrix3x4.GetRowAsVector3(1).GetAbs().Dot(extents),
|
||||
0.5f * matrix3x4.GetRowAsVector3(2).GetAbs().Dot(extents));
|
||||
m_min = center - newHalfExtents;
|
||||
m_max = center + newHalfExtents;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,11 +129,21 @@ namespace AZ
|
||||
|
||||
void ApplyTransform(const Transform& transform);
|
||||
|
||||
void ApplyMatrix3x4(const Matrix3x4& matrix3x4);
|
||||
|
||||
void MultiplyByScale(const Vector3& scale);
|
||||
|
||||
//! Transforms an Aabb and returns the resulting Obb.
|
||||
class Obb GetTransformedObb(const Transform& transform) const;
|
||||
[[nodiscard]] Obb GetTransformedObb(const Transform& transform) const;
|
||||
|
||||
//! Transforms an Aabb and returns the resulting Obb.
|
||||
[[nodiscard]] Obb GetTransformedObb(const Matrix3x4& matrix3x4) const;
|
||||
|
||||
//! Returns a new AABB containing the transformed AABB.
|
||||
Aabb GetTransformedAabb(const Transform& transform) const;
|
||||
[[nodiscard]] Aabb GetTransformedAabb(const Transform& transform) const;
|
||||
|
||||
//! Returns a new AABB containing the transformed AABB.
|
||||
[[nodiscard]] Aabb GetTransformedAabb(const Matrix3x4& matrix3x4) const;
|
||||
|
||||
//! Checks if this aabb is equal to another within a floating point tolerance.
|
||||
bool IsClose(const Aabb& rhs, float tolerance = Constants::Tolerance) const;
|
||||
|
||||
@@ -292,6 +292,14 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE void Aabb::MultiplyByScale(const Vector3& scale)
|
||||
{
|
||||
m_min *= scale;
|
||||
m_max *= scale;
|
||||
AZ_MATH_ASSERT(IsValid(), "Min must be less than Max");
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Aabb Aabb::GetTransformedAabb(const Transform& transform) const
|
||||
{
|
||||
Aabb aabb = Aabb::CreateFromMinMax(m_min, m_max);
|
||||
@@ -300,6 +308,14 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Aabb Aabb::GetTransformedAabb(const Matrix3x4& matrix3x4) const
|
||||
{
|
||||
Aabb aabb = Aabb::CreateFromMinMax(m_min, m_max);
|
||||
aabb.ApplyMatrix3x4(matrix3x4);
|
||||
return aabb;
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE bool Aabb::IsClose(const Aabb& rhs, float tolerance) const
|
||||
{
|
||||
return m_min.IsClose(rhs.m_min, tolerance) && m_max.IsClose(rhs.m_max, tolerance);
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzCore/Math/Transform.h>
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
#include <AZTestShared/Math/MathTestHelpers.h>
|
||||
|
||||
using namespace AZ;
|
||||
|
||||
@@ -385,4 +386,77 @@ namespace UnitTest
|
||||
EXPECT_TRUE(aabb.GetMin().IsClose(transAabb.GetMin()));
|
||||
EXPECT_TRUE(aabb.GetMax().IsClose(transAabb.GetMax()));
|
||||
}
|
||||
|
||||
TEST(MATH_AabbTransform, GetTransformedObbMatrix3x4)
|
||||
{
|
||||
Vector3 min(-1.0f, -2.0f, -3.0f);
|
||||
Vector3 max(4.0f, 3.0f, 2.0f);
|
||||
Aabb aabb = Aabb::CreateFromMinMax(min, max);
|
||||
|
||||
Quaternion rotation(0.46f, 0.26f, 0.58f, 0.62f);
|
||||
Vector3 translation(5.0f, 7.0f, 9.0f);
|
||||
|
||||
Matrix3x4 matrix3x4 = Matrix3x4::CreateFromQuaternionAndTranslation(rotation, translation);
|
||||
|
||||
matrix3x4.MultiplyByScale(Vector3(0.5f, 1.5f, 2.0f));
|
||||
|
||||
Obb obb = aabb.GetTransformedObb(matrix3x4);
|
||||
|
||||
EXPECT_THAT(obb.GetRotation(), IsClose(rotation));
|
||||
EXPECT_THAT(obb.GetHalfLengths(), IsClose(Vector3(1.25f, 3.75f, 5.0f)));
|
||||
EXPECT_THAT(obb.GetPosition(), IsClose(Vector3(3.928f, 7.9156f, 9.3708f)));
|
||||
}
|
||||
|
||||
TEST(MATH_AabbTransform, GetTransformedAabbMatrix3x4)
|
||||
{
|
||||
Vector3 min(2.0f, 3.0f, 5.0f);
|
||||
Vector3 max(6.0f, 5.0f, 11.0f);
|
||||
Aabb aabb = Aabb::CreateFromMinMax(min, max);
|
||||
|
||||
Quaternion rotation(0.34f, 0.46f, 0.58f, 0.58f);
|
||||
Vector3 translation(-3.0f, -4.0f, -5.0f);
|
||||
|
||||
Matrix3x4 matrix3x4 = Matrix3x4::CreateFromQuaternionAndTranslation(rotation, translation);
|
||||
|
||||
matrix3x4.MultiplyByScale(Vector3(1.2f, 0.8f, 2.0f));
|
||||
|
||||
Aabb transformedAabb = aabb.GetTransformedAabb(matrix3x4);
|
||||
|
||||
EXPECT_THAT(transformedAabb.GetMin(), IsClose(Vector3(4.1488f, -0.01216f, -0.31904f)));
|
||||
EXPECT_THAT(transformedAabb.GetMax(), IsClose(Vector3(16.3216f, 6.54272f, 5.98112f)));
|
||||
}
|
||||
|
||||
TEST(MATH_AabbTransform, GetTransformedObbFitsInsideTransformedAabb)
|
||||
{
|
||||
Vector3 min(4.0f, 3.0f, 1.0f);
|
||||
Vector3 max(7.0f, 6.0f, 8.0f);
|
||||
Aabb aabb = Aabb::CreateFromMinMax(min, max);
|
||||
|
||||
Quaternion rotation(0.40f, 0.40f, 0.64f, 0.52f);
|
||||
Vector3 translation(-2.0f, 4.0f, -3.0f);
|
||||
|
||||
Matrix3x4 matrix3x4 = Matrix3x4::CreateFromQuaternionAndTranslation(rotation, translation);
|
||||
|
||||
matrix3x4.MultiplyByScale(Vector3(2.2f, 0.6f, 1.4f));
|
||||
|
||||
Aabb transformedAabb = aabb.GetTransformedAabb(matrix3x4);
|
||||
Obb transformedObb = aabb.GetTransformedObb(matrix3x4);
|
||||
Aabb aabbContainingTransformedObb = Aabb::CreateFromObb(transformedObb);
|
||||
|
||||
EXPECT_THAT(transformedAabb.GetMin(), IsClose(aabbContainingTransformedObb.GetMin()));
|
||||
EXPECT_THAT(transformedAabb.GetMax(), IsClose(aabbContainingTransformedObb.GetMax()));
|
||||
}
|
||||
|
||||
TEST(MATH_AabbTransform, MultiplyByScale)
|
||||
{
|
||||
Vector3 min(2.0f, 6.0f, 8.0f);
|
||||
Vector3 max(6.0f, 9.0f, 10.0f);
|
||||
Aabb aabb = Aabb::CreateFromMinMax(min, max);
|
||||
|
||||
Vector3 scale(0.5f, 2.0f, 1.5f);
|
||||
aabb.MultiplyByScale(scale);
|
||||
|
||||
EXPECT_THAT(aabb.GetMin(), IsClose(Vector3(1.0f, 12.0f, 12.0f)));
|
||||
EXPECT_THAT(aabb.GetMax(), IsClose(Vector3(3.0f, 18.0f, 15.0f)));
|
||||
}
|
||||
}
|
||||
|
||||
BIN
Binary file not shown.
@@ -145,8 +145,10 @@ namespace AZ
|
||||
const MaterialAssignmentMap& GetMaterialAssignmentMap(const MeshHandle& meshHandle) const override;
|
||||
void ConnectModelChangeEventHandler(const MeshHandle& meshHandle, ModelChangedEvent::Handler& handler) override;
|
||||
|
||||
void SetTransform(const MeshHandle& meshHandle, const AZ::Transform& transform) override;
|
||||
void SetTransform(const MeshHandle& meshHandle, const AZ::Transform& transform,
|
||||
const AZ::Vector3& nonUniformScale = AZ::Vector3::CreateOne()) override;
|
||||
Transform GetTransform(const MeshHandle& meshHandle) override;
|
||||
Vector3 GetNonUniformScale(const MeshHandle& meshHandle) override;
|
||||
|
||||
void SetSortKey(const MeshHandle& meshHandle, RHI::DrawItemSortKey sortKey) override;
|
||||
RHI::DrawItemSortKey GetSortKey(const MeshHandle& meshHandle) override;
|
||||
|
||||
+4
-1
@@ -62,9 +62,12 @@ namespace AZ
|
||||
//! Connects a handler to any changes to an RPI::Model. Changes include loading and reloading.
|
||||
virtual void ConnectModelChangeEventHandler(const MeshHandle& meshHandle, ModelChangedEvent::Handler& handler) = 0;
|
||||
//! Sets the transform for a given mesh handle.
|
||||
virtual void SetTransform(const MeshHandle& meshHandle, const AZ::Transform& transform) = 0;
|
||||
virtual void SetTransform(const MeshHandle& meshHandle, const Transform& transform,
|
||||
const Vector3& nonUniformScale = Vector3::CreateOne()) = 0;
|
||||
//! Gets the transform for a given mesh handle.
|
||||
virtual Transform GetTransform(const MeshHandle& meshHandle) = 0;
|
||||
//! Gets the non-uniform scale for a given mesh handle.
|
||||
virtual Vector3 GetNonUniformScale(const MeshHandle& meshHandle) = 0;
|
||||
//! Sets the sort key for a given mesh handle.
|
||||
virtual void SetSortKey(const MeshHandle& meshHandle, RHI::DrawItemSortKey sortKey) = 0;
|
||||
//! Gets the sort key for a given mesh handle.
|
||||
|
||||
+3
-1
@@ -50,8 +50,10 @@ namespace AZ
|
||||
// TransformServiceFeatureProcessorInterface overrides ...
|
||||
ObjectId ReserveObjectId() override;
|
||||
void ReleaseObjectId(ObjectId& id) override;
|
||||
void SetTransformForId(ObjectId id, const AZ::Transform& transform) override;
|
||||
void SetTransformForId(ObjectId id, const AZ::Transform& transform,
|
||||
const AZ::Vector3& nonUniformScale = AZ::Vector3::CreateOne()) override;
|
||||
AZ::Transform GetTransformForId(ObjectId id) const override;
|
||||
AZ::Vector3 GetNonUniformScaleForId(ObjectId id) const override;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
+6
-3
@@ -13,6 +13,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Math/Transform.h>
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <Atom/RPI.Public/FeatureProcessor.h>
|
||||
|
||||
namespace AZ
|
||||
@@ -34,11 +35,13 @@ namespace AZ
|
||||
//! Releases an object ID to be used by others. The passed in handle is invalidated.
|
||||
virtual void ReleaseObjectId(ObjectId& id) = 0;
|
||||
|
||||
//! Sets the transform for a given id. Id must be one reserved earlier.
|
||||
virtual void SetTransformForId(ObjectId id, const AZ::Transform& transform) = 0;
|
||||
//! Sets the transform (and optionally non-uniform scale) for a given id. Id must be one reserved earlier.
|
||||
virtual void SetTransformForId(ObjectId id, const AZ::Transform& transform,
|
||||
const AZ::Vector3& nonUniformScale = AZ::Vector3::CreateOne()) = 0;
|
||||
//! Gets the transform for a given id. Id must be one reserved earlier.
|
||||
virtual AZ::Transform GetTransformForId(ObjectId) const = 0;
|
||||
|
||||
//! Gets the non-uniform scale for a given id. Id must be one reserved earlier.
|
||||
virtual AZ::Vector3 GetNonUniformScaleForId(ObjectId id) const = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,11 +31,12 @@ namespace UnitTest
|
||||
MOCK_CONST_METHOD1(GetModel, AZStd::intrusive_ptr<AZ::RPI::Model>(const MeshHandle&));
|
||||
MOCK_CONST_METHOD1(GetMaterialAssignmentMap, const AZ::Render::MaterialAssignmentMap&(const MeshHandle&));
|
||||
MOCK_METHOD2(ConnectModelChangeEventHandler, void(const MeshHandle&, ModelChangedEvent::Handler&));
|
||||
MOCK_METHOD2(SetTransform, void(const MeshHandle&, const AZ::Transform&));
|
||||
MOCK_METHOD3(SetTransform, void(const MeshHandle&, const AZ::Transform&, const AZ::Vector3&));
|
||||
MOCK_METHOD2(SetExcludeFromReflectionCubeMaps, void(const MeshHandle&, bool));
|
||||
MOCK_METHOD2(SetMaterialAssignmentMap, void(const MeshHandle&, const AZ::Data::Instance<AZ::RPI::Material>&));
|
||||
MOCK_METHOD2(SetMaterialAssignmentMap, void(const MeshHandle&, const AZ::Render::MaterialAssignmentMap&));
|
||||
MOCK_METHOD1(GetTransform, AZ::Transform (const MeshHandle&));
|
||||
MOCK_METHOD1(GetTransform, AZ::Transform(const MeshHandle&));
|
||||
MOCK_METHOD1(GetNonUniformScale, AZ::Vector3(const MeshHandle&));
|
||||
MOCK_METHOD2(SetSortKey, void (const MeshHandle&, AZ::RHI::DrawItemSortKey));
|
||||
MOCK_METHOD1(GetSortKey, AZ::RHI::DrawItemSortKey(const MeshHandle&));
|
||||
MOCK_METHOD2(SetLodOverride, void(const MeshHandle&, AZ::RPI::Cullable::LodOverride));
|
||||
|
||||
@@ -504,7 +504,7 @@ namespace AZ
|
||||
box.m_faceCullMode = ConvertRPIFaceCullFlag(faceCull);
|
||||
box.m_color = color;
|
||||
box.m_scale = localMatrix3x4.ExtractScale() * extents;
|
||||
box.m_position = localMatrix3x4.GetTranslation() + center;
|
||||
box.m_position = matrix3x4 * center;
|
||||
box.m_rotationMatrix = Matrix3x3::CreateFromMatrix3x4(localMatrix3x4);
|
||||
box.m_pointSize = m_pointSize;
|
||||
box.m_viewProjOverrideIndex = viewProjOverrideIndex;
|
||||
|
||||
@@ -256,7 +256,7 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
void MeshFeatureProcessor::SetTransform(const MeshHandle& meshHandle, const AZ::Transform& transform)
|
||||
void MeshFeatureProcessor::SetTransform(const MeshHandle& meshHandle, const AZ::Transform& transform, const AZ::Vector3& nonUniformScale)
|
||||
{
|
||||
if (meshHandle.IsValid())
|
||||
{
|
||||
@@ -264,12 +264,12 @@ namespace AZ
|
||||
meshData.m_cullBoundsNeedsUpdate = true;
|
||||
meshData.m_objectSrgNeedsUpdate = true;
|
||||
|
||||
m_transformService->SetTransformForId(meshHandle->m_objectId, transform);
|
||||
m_transformService->SetTransformForId(meshHandle->m_objectId, transform, nonUniformScale);
|
||||
|
||||
// ray tracing data needs to be updated with the new transform
|
||||
if (m_rayTracingFeatureProcessor)
|
||||
{
|
||||
m_rayTracingFeatureProcessor->SetMeshTransform(meshHandle->m_objectId, transform);
|
||||
m_rayTracingFeatureProcessor->SetMeshTransform(meshHandle->m_objectId, transform, nonUniformScale);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -287,6 +287,19 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 MeshFeatureProcessor::GetNonUniformScale(const MeshHandle& meshHandle)
|
||||
{
|
||||
if (meshHandle.IsValid())
|
||||
{
|
||||
return m_transformService->GetNonUniformScaleForId(meshHandle->m_objectId);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Assert(false, "Invalid mesh handle");
|
||||
return Vector3::CreateOne();
|
||||
}
|
||||
}
|
||||
|
||||
void MeshFeatureProcessor::SetSortKey(const MeshHandle& meshHandle, RHI::DrawItemSortKey sortKey)
|
||||
{
|
||||
if (meshHandle.IsValid())
|
||||
@@ -845,10 +858,13 @@ namespace AZ
|
||||
AZ_Assert(m_model, "The model has not finished loading yet");
|
||||
|
||||
Transform localToWorld = transformService->GetTransformForId(m_objectId);
|
||||
Vector3 nonUniformScale = transformService->GetNonUniformScaleForId(m_objectId);
|
||||
|
||||
Vector3 center;
|
||||
float radius;
|
||||
Aabb localAabb = m_model->GetAabb();
|
||||
localAabb.MultiplyByScale(nonUniformScale);
|
||||
|
||||
localAabb.GetTransformedAabb(localToWorld).GetAsSphere(center, radius);
|
||||
|
||||
m_cullable.m_cullData.m_boundingSphere = Sphere(center, radius);
|
||||
|
||||
+1
@@ -81,6 +81,7 @@ namespace AZ
|
||||
->HitGroupIndex(blasIndex)
|
||||
->Blas(rayTracingSubMesh.m_blas)
|
||||
->Transform(rayTracingMesh.second.m_transform)
|
||||
->NonUniformScale(rayTracingMesh.second.m_nonUniformScale)
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@ namespace AZ
|
||||
m_meshInfoBufferNeedsUpdate = true;
|
||||
}
|
||||
|
||||
void RayTracingFeatureProcessor::SetMeshTransform(const ObjectId objectId, AZ::Transform transform)
|
||||
void RayTracingFeatureProcessor::SetMeshTransform(const ObjectId objectId, const AZ::Transform transform, const AZ::Vector3 nonUniformScale)
|
||||
{
|
||||
if (!m_rayTracingEnabled)
|
||||
{
|
||||
@@ -154,6 +154,7 @@ namespace AZ
|
||||
if (itMesh != m_meshes.end())
|
||||
{
|
||||
itMesh->second.m_transform = transform;
|
||||
itMesh->second.m_nonUniformScale = nonUniformScale;
|
||||
m_revision++;
|
||||
}
|
||||
|
||||
|
||||
@@ -68,6 +68,9 @@ namespace AZ
|
||||
// mesh transform
|
||||
AZ::Transform m_transform = AZ::Transform::CreateIdentity();
|
||||
|
||||
// mesh non-uniform scale
|
||||
AZ::Vector3 m_nonUniformScale = AZ::Vector3::CreateOne();
|
||||
|
||||
// flag indicating if the Blas objects in the sub-meshes are built
|
||||
bool m_blasBuilt = false;
|
||||
};
|
||||
@@ -85,7 +88,8 @@ namespace AZ
|
||||
|
||||
//! Sets the ray tracing mesh transform
|
||||
//! This will cause an update to the RayTracing acceleration structure on the next frame
|
||||
void SetMeshTransform(const ObjectId objectId, const AZ::Transform transform);
|
||||
void SetMeshTransform(const ObjectId objectId, const AZ::Transform transform,
|
||||
const AZ::Vector3 nonUniformScale = AZ::Vector3::CreateOne());
|
||||
|
||||
//! Retrieves ray tracing data for all meshes in the scene
|
||||
const MeshMap& GetMeshes() const { return m_meshes; }
|
||||
|
||||
+14
-4
@@ -210,14 +210,14 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
void TransformServiceFeatureProcessor::SetTransformForId(ObjectId id, const AZ::Transform& transform)
|
||||
void TransformServiceFeatureProcessor::SetTransformForId(ObjectId id, const AZ::Transform& transform, const AZ::Vector3& nonUniformScale)
|
||||
{
|
||||
AZ_Error("TransformServiceFeatureProcessor", m_isWriteable, "Transform data cannot be written to during this phase");
|
||||
AZ_Error("TransformServiceFeatureProcessor", id.IsValid(), "Attempting to set the transform for an invalid handle.");
|
||||
if (id.IsValid())
|
||||
{
|
||||
AZ::Matrix3x4 matrix3x4 = AZ::Matrix3x4::CreateFromTransform(transform);
|
||||
|
||||
matrix3x4.MultiplyByScale(nonUniformScale);
|
||||
matrix3x4.StoreToRowMajorFloat12(m_objectToWorldTransforms.at(id.GetIndex()).m_transform);
|
||||
|
||||
// Inverse transpose to take the non-uniform scale out of the transform for usage with normals.
|
||||
@@ -228,8 +228,18 @@ namespace AZ
|
||||
|
||||
AZ::Transform TransformServiceFeatureProcessor::GetTransformForId(ObjectId id) const
|
||||
{
|
||||
AZ_Error("TransformServiceFeatureProcessor", id.IsValid(), "Attempting to set the transform for an invalid handle.");
|
||||
return AZ::Transform::CreateFromMatrix3x4( Matrix3x4::CreateFromRowMajorFloat12(m_objectToWorldTransforms.at(id.GetIndex()).m_transform) );
|
||||
AZ_Error("TransformServiceFeatureProcessor", id.IsValid(), "Attempting to get the transform for an invalid handle.");
|
||||
AZ::Matrix3x4 matrix3x4 = AZ::Matrix3x4::CreateFromRowMajorFloat12(m_objectToWorldTransforms.at(id.GetIndex()).m_transform);
|
||||
AZ::Transform transform = AZ::Transform::CreateFromMatrix3x4(matrix3x4);
|
||||
transform.ExtractScale();
|
||||
return transform;
|
||||
}
|
||||
|
||||
AZ::Vector3 TransformServiceFeatureProcessor::GetNonUniformScaleForId(ObjectId id) const
|
||||
{
|
||||
AZ_Error("TransformServiceFeatureProcessor", id.IsValid(), "Attempting to get the non-uniform scale for an invalid handle.");
|
||||
AZ::Matrix3x4 matrix3x4 = AZ::Matrix3x4::CreateFromRowMajorFloat12(m_objectToWorldTransforms.at(id.GetIndex()).m_transform);
|
||||
return matrix3x4.RetrieveScale();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,6 +111,7 @@ namespace AZ
|
||||
uint32_t m_instanceID = 0;
|
||||
uint32_t m_hitGroupIndex = 0;
|
||||
AZ::Transform m_transform = AZ::Transform::CreateIdentity();
|
||||
AZ::Vector3 m_nonUniformScale = AZ::Vector3::CreateOne();
|
||||
RHI::Ptr<RHI::RayTracingBlas> m_blas;
|
||||
};
|
||||
using RayTracingTlasInstanceVector = AZStd::vector<RayTracingTlasInstance>;
|
||||
@@ -154,6 +155,7 @@ namespace AZ
|
||||
RayTracingTlasDescriptor* InstanceID(uint32_t instanceID);
|
||||
RayTracingTlasDescriptor* HitGroupIndex(uint32_t hitGroupIndex);
|
||||
RayTracingTlasDescriptor* Transform(const AZ::Transform& transform);
|
||||
RayTracingTlasDescriptor* NonUniformScale(const AZ::Vector3& nonUniformScale);
|
||||
RayTracingTlasDescriptor* Blas(RHI::Ptr<RHI::RayTracingBlas>& blas);
|
||||
RayTracingTlasDescriptor* InstancesBuffer(RHI::Ptr<RHI::Buffer>& tlasInstances);
|
||||
RayTracingTlasDescriptor* NumInstances(uint32_t numInstancesInBuffer);
|
||||
|
||||
@@ -85,6 +85,13 @@ namespace AZ
|
||||
return this;
|
||||
}
|
||||
|
||||
RayTracingTlasDescriptor* RayTracingTlasDescriptor::NonUniformScale(const AZ::Vector3& nonUniformScale)
|
||||
{
|
||||
AZ_Assert(m_buildContext, "NonUniformSCale property can only be added to an Instance entry");
|
||||
m_buildContext->m_nonUniformScale = nonUniformScale;
|
||||
return this;
|
||||
}
|
||||
|
||||
RayTracingTlasDescriptor* RayTracingTlasDescriptor::Blas(RHI::Ptr<RHI::RayTracingBlas>& blas)
|
||||
{
|
||||
AZ_Assert(m_buildContext, "Blas property can only be added to an Instance entry");
|
||||
|
||||
@@ -89,8 +89,9 @@ namespace AZ
|
||||
mappedData[i].InstanceID = instance.m_instanceID;
|
||||
mappedData[i].InstanceContributionToHitGroupIndex = instance.m_hitGroupIndex;
|
||||
// convert transform to row-major 3x4
|
||||
AZ::Matrix3x4 matrix34 = AZ::Matrix3x4::CreateFromTransform(instance.m_transform);
|
||||
matrix34.StoreToRowMajorFloat12(&mappedData[i].Transform[0][0]);
|
||||
AZ::Matrix3x4 matrix3x4 = AZ::Matrix3x4::CreateFromTransform(instance.m_transform);
|
||||
matrix3x4.MultiplyByScale(instance.m_nonUniformScale);
|
||||
matrix3x4.StoreToRowMajorFloat12(&mappedData[i].Transform[0][0]);
|
||||
mappedData[i].AccelerationStructure = static_cast<DX12::Buffer*>(blas->GetBuffers().m_blasBuffer.get())->GetMemoryView().GetGpuAddress();
|
||||
// [GFX TODO][ATOM-5270] Add ray tracing TLAS instance mask support
|
||||
mappedData[i].InstanceMask = 0x1;
|
||||
|
||||
@@ -92,9 +92,9 @@ namespace AZ
|
||||
|
||||
mappedData[i].instanceCustomIndex = instance.m_instanceID;
|
||||
mappedData[i].instanceShaderBindingTableRecordOffset = instance.m_hitGroupIndex;
|
||||
// convert transform to row-major 3x4
|
||||
AZ::Matrix3x4 matrix34 = AZ::Matrix3x4::CreateFromTransform(instance.m_transform);
|
||||
matrix34.StoreToRowMajorFloat12(&mappedData[i].transform.matrix[0][0]);
|
||||
AZ::Matrix3x4 matrix3x4 = AZ::Matrix3x4::CreateFromTransform(instance.m_transform);
|
||||
matrix3x4.MultiplyByScale(instance.m_nonUniformScale);
|
||||
matrix3x4.StoreToRowMajorFloat12(&mappedData[i].transform.matrix[0][0]);
|
||||
|
||||
RayTracingBlas* blas = static_cast<RayTracingBlas*>(instance.m_blas.get());
|
||||
VkAccelerationStructureDeviceAddressInfoKHR addressInfo = {};
|
||||
|
||||
@@ -73,12 +73,14 @@ namespace AZ
|
||||
//! [GFX TODO][ATOM-4343 Bake mesh spatial during AP processing]
|
||||
//!
|
||||
//! @param modelTransform a transform that puts the model into the ray's coordinate space
|
||||
//! @param nonUniformScale Non-uniform scale applied in the model's local frame.
|
||||
//! @param rayStart position where the ray starts
|
||||
//! @param dir direction where the ray ends (does not have to be unit length)
|
||||
//! @param distanceFactor if an intersection is detected, this will be set such that distanceFactor * dir.length == distance to intersection
|
||||
//! @param normal if an intersection is detected, this will be set to the normal at the point of intersection
|
||||
//! @return true if the ray intersects the mesh
|
||||
bool RayIntersection(const AZ::Transform& modelTransform, const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distanceFactor, AZ::Vector3& normal) const;
|
||||
bool RayIntersection(const AZ::Transform& modelTransform, const AZ::Vector3& nonUniformScale, const AZ::Vector3& rayStart,
|
||||
const AZ::Vector3& dir, float& distanceFactor, AZ::Vector3& normal) const;
|
||||
|
||||
//! Get available UV names from the model and its lods.
|
||||
const AZStd::unordered_set<AZ::Name>& GetUvNames() const;
|
||||
|
||||
@@ -164,18 +164,22 @@ namespace AZ
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Model::RayIntersection(const AZ::Transform& modelTransform, const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distanceFactor, AZ::Vector3& normal) const
|
||||
bool Model::RayIntersection(const AZ::Transform& modelTransform, const AZ::Vector3& nonUniformScale, const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distanceFactor, AZ::Vector3& normal) const
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(Debug::ProfileCategory::AzRender);
|
||||
const AZ::Vector3 clampedScale = nonUniformScale.GetMax(AZ::Vector3(AZ::MinTransformScale));
|
||||
|
||||
const AZ::Transform inverseTM = modelTransform.GetInverse();
|
||||
const AZ::Vector3 raySrcLocal = inverseTM.TransformPoint(rayStart);
|
||||
const AZ::Vector3 raySrcLocal = inverseTM.TransformPoint(rayStart) / clampedScale;
|
||||
|
||||
// Instead of just rotating 'dir' we need it to be scaled too, so that 'distanceFactor' will be in the target units rather than object local units.
|
||||
const AZ::Vector3 rayDest = rayStart + dir;
|
||||
const AZ::Vector3 rayDestLocal = inverseTM.TransformPoint(rayDest);
|
||||
const AZ::Vector3 rayDestLocal = inverseTM.TransformPoint(rayDest) / clampedScale;
|
||||
const AZ::Vector3 rayDirLocal = rayDestLocal - raySrcLocal;
|
||||
|
||||
return LocalRayIntersection(raySrcLocal, rayDirLocal, distanceFactor, normal);
|
||||
bool result = LocalRayIntersection(raySrcLocal, rayDirLocal, distanceFactor, normal);
|
||||
normal = (normal * clampedScale).GetNormalized();
|
||||
return result;
|
||||
}
|
||||
|
||||
const AZStd::unordered_set<AZ::Name>& Model::GetUvNames() const
|
||||
|
||||
@@ -137,9 +137,12 @@ namespace AZ
|
||||
AZ::Transform transform = AZ::Transform::CreateIdentity();
|
||||
AZ::TransformBus::EventResult(transform, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM);
|
||||
|
||||
AZ::Vector3 nonUniformScale = AZ::Vector3::CreateOne();
|
||||
AZ::NonUniformScaleRequestBus::EventResult(nonUniformScale, GetEntityId(), &AZ::NonUniformScaleRequests::GetScale);
|
||||
|
||||
AZ::Vector3 ignoreNormal;
|
||||
|
||||
return m_controller.GetModel()->RayIntersection(transform, src, dir, distance, ignoreNormal);
|
||||
return m_controller.GetModel()->RayIntersection(transform, nonUniformScale, src, dir, distance, ignoreNormal);
|
||||
}
|
||||
|
||||
bool EditorMeshComponent::SupportsEditorRayIntersect()
|
||||
|
||||
@@ -188,6 +188,11 @@ namespace AZ
|
||||
m_meshFeatureProcessor = RPI::Scene::GetFeatureProcessorForEntity<MeshFeatureProcessorInterface>(m_entityId);
|
||||
AZ_Error("MeshComponentController", m_meshFeatureProcessor, "Unable to find a MeshFeatureProcessorInterface on the entityId.");
|
||||
|
||||
m_cachedNonUniformScale = AZ::Vector3::CreateOne();
|
||||
AZ::NonUniformScaleRequestBus::EventResult(m_cachedNonUniformScale, m_entityId, &AZ::NonUniformScaleRequests::GetScale);
|
||||
AZ::NonUniformScaleRequestBus::Event(m_entityId, &AZ::NonUniformScaleRequests::RegisterScaleChangedEvent,
|
||||
m_nonUniformScaleChangedHandler);
|
||||
|
||||
MeshComponentRequestBus::Handler::BusConnect(m_entityId);
|
||||
TransformNotificationBus::Handler::BusConnect(m_entityId);
|
||||
MaterialReceiverRequestBus::Handler::BusConnect(m_entityId);
|
||||
@@ -209,6 +214,8 @@ namespace AZ
|
||||
MaterialReceiverRequestBus::Handler::BusDisconnect();
|
||||
MaterialComponentNotificationBus::Handler::BusDisconnect();
|
||||
|
||||
m_nonUniformScaleChangedHandler.Disconnect();
|
||||
|
||||
m_meshFeatureProcessor = nullptr;
|
||||
m_transformInterface = nullptr;
|
||||
m_entityId = AZ::EntityId(AZ::EntityId::InvalidEntityId);
|
||||
@@ -229,7 +236,16 @@ namespace AZ
|
||||
{
|
||||
if (m_meshFeatureProcessor)
|
||||
{
|
||||
m_meshFeatureProcessor->SetTransform(m_meshHandle, world);
|
||||
m_meshFeatureProcessor->SetTransform(m_meshHandle, world, m_cachedNonUniformScale);
|
||||
}
|
||||
}
|
||||
|
||||
void MeshComponentController::HandleNonUniformScaleChange(const AZ::Vector3& nonUniformScale)
|
||||
{
|
||||
m_cachedNonUniformScale = nonUniformScale;
|
||||
if (m_meshFeatureProcessor)
|
||||
{
|
||||
m_meshFeatureProcessor->SetTransform(m_meshHandle, m_transformInterface->GetWorldTM(), m_cachedNonUniformScale);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,8 +291,9 @@ namespace AZ
|
||||
m_meshHandle = m_meshFeatureProcessor->AcquireMesh(m_configuration.m_modelAsset, materials);
|
||||
m_meshFeatureProcessor->ConnectModelChangeEventHandler(m_meshHandle, m_changeEventHandler);
|
||||
|
||||
const AZ::Transform& transform = m_transformInterface ? m_transformInterface->GetWorldTM() : Transform::Identity();
|
||||
m_meshFeatureProcessor->SetTransform(m_meshHandle, transform);
|
||||
const AZ::Transform& transform = m_transformInterface ? m_transformInterface->GetWorldTM() : AZ::Transform::CreateIdentity();
|
||||
|
||||
m_meshFeatureProcessor->SetTransform(m_meshHandle, transform, m_cachedNonUniformScale);
|
||||
m_meshFeatureProcessor->SetSortKey(m_meshHandle, m_configuration.m_sortKey);
|
||||
m_meshFeatureProcessor->SetLodOverride(m_meshHandle, m_configuration.m_lodOverride);
|
||||
m_meshFeatureProcessor->SetExcludeFromReflectionCubeMaps(m_meshHandle, m_configuration.m_excludeFromReflectionCubeMaps);
|
||||
@@ -413,7 +430,16 @@ namespace AZ
|
||||
Aabb MeshComponentController::GetLocalBounds()
|
||||
{
|
||||
const Data::Instance<RPI::Model> model = GetModel();
|
||||
return model ? model->GetAabb() : Aabb::CreateNull();
|
||||
if (model)
|
||||
{
|
||||
Aabb aabb = model->GetAabb();
|
||||
aabb.MultiplyByScale(m_cachedNonUniformScale);
|
||||
return aabb;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Aabb::CreateNull();
|
||||
}
|
||||
}
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzCore/Component/NonUniformScaleBus.h>
|
||||
|
||||
#include <AtomCore/Instance/InstanceDatabase.h>
|
||||
|
||||
@@ -122,17 +123,25 @@ namespace AZ
|
||||
void UnregisterModel();
|
||||
void RefreshModelRegistration();
|
||||
|
||||
void HandleNonUniformScaleChange(const AZ::Vector3& nonUniformScale);
|
||||
|
||||
Render::MeshFeatureProcessorInterface* m_meshFeatureProcessor = nullptr;
|
||||
Render::MeshFeatureProcessorInterface::MeshHandle m_meshHandle;
|
||||
TransformInterface* m_transformInterface = nullptr;
|
||||
AZ::EntityId m_entityId;
|
||||
bool m_isVisible = true;
|
||||
MeshComponentConfig m_configuration;
|
||||
AZ::Vector3 m_cachedNonUniformScale = AZ::Vector3::CreateOne();
|
||||
|
||||
MeshFeatureProcessorInterface::ModelChangedEvent::Handler m_changeEventHandler
|
||||
{
|
||||
[&](Data::Instance<RPI::Model> model) { HandleModelChange(model); }
|
||||
};
|
||||
|
||||
AZ::NonUniformScaleChangedEvent::Handler m_nonUniformScaleChangedHandler
|
||||
{
|
||||
[&](const AZ::Vector3& nonUniformScale) { HandleNonUniformScaleChange(nonUniformScale); }
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace Render
|
||||
|
||||
@@ -74,10 +74,7 @@ namespace Blast
|
||||
{
|
||||
if (m_chunkActors[chunkId])
|
||||
{
|
||||
auto transform = m_chunkActors[chunkId]->GetWorldBody()->GetTransform();
|
||||
// Multiply by scale because the transform on the world body does not store scale
|
||||
transform.MultiplyByScale(m_scale);
|
||||
m_meshFeatureProcessor->SetTransform(m_chunkMeshHandles[chunkId], transform);
|
||||
m_meshFeatureProcessor->SetTransform(m_chunkMeshHandles[chunkId], m_chunkActors[chunkId]->GetWorldBody()->GetTransform(), m_scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ namespace Blast
|
||||
|
||||
// ActorRenderManager::SyncMeshes
|
||||
{
|
||||
EXPECT_CALL(*m_mockMeshFeatureProcessor, SetTransform(_, _))
|
||||
EXPECT_CALL(*m_mockMeshFeatureProcessor, SetTransform(_, _, _))
|
||||
.Times(aznumeric_cast<int>(m_actorFactory->m_mockActors[0]->GetChunkIndices().size()));
|
||||
actorRenderManager->SyncMeshes();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user