updating atom mesh component to support non-uniform scale component

This commit is contained in:
greerdv
2021-04-14 14:05:59 +01:00
parent 5de3ff4c61
commit 2fb2813b48
35 changed files with 166 additions and 84 deletions
+29 -2
View File
@@ -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 = 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;
}
}
+9 -1
View File
@@ -129,12 +129,20 @@ namespace AZ
void ApplyTransform(const Transform& transform);
void ApplyMatrix3x4(const Matrix3x4& matrix3x4);
//! Transforms an Aabb and returns the resulting Obb.
class Obb GetTransformedObb(const Transform& transform) const;
Obb GetTransformedObb(const Transform& transform) const;
//! Transforms an Aabb and returns the resulting Obb.
Obb GetTransformedObb(const Matrix3x4& matrix3x4) const;
//! Returns a new AABB containing the transformed AABB.
Aabb GetTransformedAabb(const Transform& transform) const;
//! Returns a new AABB containing the transformed AABB.
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;
@@ -300,6 +300,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);
@@ -144,8 +144,8 @@ 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;
Transform GetTransform(const MeshHandle& meshHandle) override;
void SetMatrix3x4(const MeshHandle& meshHandle, const AZ::Matrix3x4& matrix3x4) override;
Matrix3x4 GetMatrix3x4(const MeshHandle& meshHandle) override;
void SetSortKey(const MeshHandle& meshHandle, RHI::DrawItemSortKey sortKey) override;
RHI::DrawItemSortKey GetSortKey(const MeshHandle& meshHandle) override;
@@ -61,10 +61,10 @@ namespace AZ
virtual const MaterialAssignmentMap& GetMaterialAssignmentMap(const MeshHandle& meshHandle) const = 0;
//! 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;
//! Gets the transform for a given mesh handle.
virtual Transform GetTransform(const MeshHandle& meshHandle) = 0;
//! Sets the Matrix3x4 for a given mesh handle.
virtual void SetMatrix3x4(const MeshHandle& meshHandle, const AZ::Matrix3x4& matrix3x4) = 0;
//! Gets the Matrix3x4 for a given mesh handle.
virtual Matrix3x4 GetMatrix3x4(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.
@@ -37,7 +37,7 @@ namespace AZ
void SetProbeOuterExtents(const ReflectionProbeHandle& probe, const AZ::Vector3& outerExtents) override;
void SetProbeInnerExtents(const ReflectionProbeHandle& probe, const AZ::Vector3& innerExtents) override;
void SetProbeCubeMap(const ReflectionProbeHandle& probe, Data::Instance<RPI::Image>& cubeMapImage) override;
void SetProbeTransform(const ReflectionProbeHandle& probe, const AZ::Transform& transform) override;
void SetProbeMatrix3x4(const ReflectionProbeHandle& probe, const AZ::Matrix3x4& matrix3x4) override;
void BakeProbe(const ReflectionProbeHandle& probe, BuildCubeMapCallback callback) override;
void NotifyCubeMapAssetReady(const AZStd::string relativePath, NotifyCubeMapAssetReadyCallback callback) override;
bool IsValidProbeHandle(const ReflectionProbeHandle& probe) const override { return (probe.get() != nullptr); }
@@ -48,7 +48,7 @@ namespace AZ
virtual void SetProbeOuterExtents(const ReflectionProbeHandle& handle, const AZ::Vector3& outerExtents) = 0;
virtual void SetProbeInnerExtents(const ReflectionProbeHandle& handle, const AZ::Vector3& innerExtents) = 0;
virtual void SetProbeCubeMap(const ReflectionProbeHandle& handle, Data::Instance<RPI::Image>& cubeMapImage) = 0;
virtual void SetProbeTransform(const ReflectionProbeHandle& handle, const AZ::Transform& transform) = 0;
virtual void SetProbeMatrix3x4(const ReflectionProbeHandle& handle, const AZ::Matrix3x4& matrix3x4) = 0;
virtual void BakeProbe(const ReflectionProbeHandle& handle, BuildCubeMapCallback callback) = 0;
virtual void NotifyCubeMapAssetReady(const AZStd::string relativePath, NotifyCubeMapAssetReadyCallback callback) = 0;
virtual bool IsValidProbeHandle(const ReflectionProbeHandle& probe) const = 0;
@@ -50,8 +50,8 @@ namespace AZ
// TransformServiceFeatureProcessorInterface overrides ...
ObjectId ReserveObjectId() override;
void ReleaseObjectId(ObjectId& id) override;
void SetTransformForId(ObjectId id, const AZ::Transform& transform) override;
AZ::Transform GetTransformForId(ObjectId id) const override;
void SetMatrix3x4ForId(ObjectId id, const AZ::Matrix3x4& matrix3x4) override;
AZ::Matrix3x4 GetMatrix3x4ForId(ObjectId id) const override;
private:
@@ -34,10 +34,10 @@ 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;
//! Gets the transform for a given id. Id must be one reserved earlier.
virtual AZ::Transform GetTransformForId(ObjectId) const = 0;
//! Sets the Matrix3x4 for a given id. Id must be one reserved earlier.
virtual void SetMatrix3x4ForId(ObjectId id, const AZ::Matrix3x4& transform) = 0;
//! Gets the Matrix3x4 for a given id. Id must be one reserved earlier.
virtual AZ::Matrix3x4 GetMatrix3x4ForId(ObjectId) const = 0;
};
}
@@ -31,11 +31,11 @@ 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_METHOD2(SetMatrix3x4, void(const MeshHandle&, const AZ::Matrix3x4&));
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(GetMatrix3x4, AZ::Matrix3x4 (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;
@@ -186,10 +186,10 @@ namespace AZ
// set irradiance color and worldInverseTranspose constants
Vector4 color(subMesh.m_irradianceColor.GetR(), subMesh.m_irradianceColor.GetG(), subMesh.m_irradianceColor.GetB(), 1.0f);
AZ::Transform meshTransform = transformFeatureProcessor->GetTransformForId(TransformServiceFeatureProcessorInterface::ObjectId(mesh.first));
AZ::Transform noScaleTransform = meshTransform;
noScaleTransform.ExtractScale();
AZ::Matrix3x3 rotationMatrix = Matrix3x3::CreateFromTransform(noScaleTransform);
AZ::Matrix3x4 meshMatrix3x4 = transformFeatureProcessor->GetMatrix3x4ForId(TransformServiceFeatureProcessorInterface::ObjectId(mesh.first));
AZ::Matrix3x4 noScaleMatrix3x4 = meshMatrix3x4;
noScaleMatrix3x4.ExtractScale();
AZ::Matrix3x3 rotationMatrix = Matrix3x3::CreateFromMatrix3x4(noScaleMatrix3x4);
rotationMatrix = rotationMatrix.GetInverseFull().GetTranspose();
m_closestHitData[m_meshCount].m_materialColor = color;
@@ -256,7 +256,7 @@ namespace AZ
}
}
void MeshFeatureProcessor::SetTransform(const MeshHandle& meshHandle, const AZ::Transform& transform)
void MeshFeatureProcessor::SetMatrix3x4(const MeshHandle& meshHandle, const AZ::Matrix3x4& matrix3x4)
{
if (meshHandle.IsValid())
{
@@ -264,26 +264,26 @@ namespace AZ
meshData.m_cullBoundsNeedsUpdate = true;
meshData.m_objectSrgNeedsUpdate = true;
m_transformService->SetTransformForId(meshHandle->m_objectId, transform);
m_transformService->SetMatrix3x4ForId(meshHandle->m_objectId, matrix3x4);
// ray tracing data needs to be updated with the new transform
if (m_rayTracingFeatureProcessor)
{
m_rayTracingFeatureProcessor->SetMeshTransform(meshHandle->m_objectId, transform);
m_rayTracingFeatureProcessor->SetMeshMatrix3x4(meshHandle->m_objectId, matrix3x4);
}
}
}
Transform MeshFeatureProcessor::GetTransform(const MeshHandle& meshHandle)
Matrix3x4 MeshFeatureProcessor::GetMatrix3x4(const MeshHandle& meshHandle)
{
if (meshHandle.IsValid())
{
return m_transformService->GetTransformForId(meshHandle->m_objectId);
return m_transformService->GetMatrix3x4ForId(meshHandle->m_objectId);
}
else
{
AZ_Assert(false, "Invalid mesh handle");
return Transform::CreateIdentity();
return Matrix3x4::CreateIdentity();
}
}
@@ -841,7 +841,7 @@ namespace AZ
AZ_Assert(m_cullBoundsNeedsUpdate, "This function only needs to be called if the culling bounds need to be rebuilt");
AZ_Assert(m_model, "The model has not finished loading yet");
Transform localToWorld = transformService->GetTransformForId(m_objectId);
Matrix3x4 localToWorld = transformService->GetMatrix3x4ForId(m_objectId);
Vector3 center;
float radius;
@@ -919,11 +919,11 @@ namespace AZ
// retrieve the list of probes that contain the centerpoint of the mesh
TransformServiceFeatureProcessor* transformServiceFeatureProcessor = m_scene->GetFeatureProcessor<TransformServiceFeatureProcessor>();
Transform transform = transformServiceFeatureProcessor->GetTransformForId(m_objectId);
Matrix3x4 matrix3x4 = transformServiceFeatureProcessor->GetMatrix3x4ForId(m_objectId);
ReflectionProbeFeatureProcessor* reflectionProbeFeatureProcessor = m_scene->GetFeatureProcessor<ReflectionProbeFeatureProcessor>();
ReflectionProbeFeatureProcessor::ReflectionProbeVector reflectionProbes;
reflectionProbeFeatureProcessor->FindReflectionProbes(transform.GetTranslation(), reflectionProbes);
reflectionProbeFeatureProcessor->FindReflectionProbes(matrix3x4.GetTranslation(), reflectionProbes);
if (!reflectionProbes.empty() && reflectionProbes[0])
{
@@ -83,7 +83,7 @@ namespace AZ
->InstanceID(blasIndex)
->HitGroupIndex(blasIndex)
->Blas(rayTracingSubMesh.m_blas)
->Transform(rayTracingMesh.second.m_transform)
->Matrix3x4(rayTracingMesh.second.m_matrix3x4)
;
}
@@ -97,7 +97,7 @@ namespace AZ
}
// set initial transform
mesh.m_transform = m_transformServiceFeatureProcessor->GetTransformForId(objectId);
mesh.m_matrix3x4 = m_transformServiceFeatureProcessor->GetMatrix3x4ForId(objectId);
m_revision++;
m_subMeshCount += aznumeric_cast<uint32_t>(subMeshes.size());
@@ -119,7 +119,7 @@ namespace AZ
}
}
void RayTracingFeatureProcessor::SetMeshTransform(const ObjectId objectId, AZ::Transform transform)
void RayTracingFeatureProcessor::SetMeshMatrix3x4(const ObjectId objectId, const AZ::Matrix3x4 matrix3x4)
{
if (!m_rayTracingEnabled)
{
@@ -129,7 +129,7 @@ namespace AZ
MeshMap::iterator itMesh = m_meshes.find(objectId.GetIndex());
if (itMesh != m_meshes.end())
{
itMesh->second.m_transform = transform;
itMesh->second.m_matrix3x4 = matrix3x4;
m_revision++;
}
}
@@ -66,7 +66,7 @@ namespace AZ
SubMeshVector m_subMeshes;
// mesh transform
AZ::Transform m_transform = AZ::Transform::CreateIdentity();
AZ::Matrix3x4 m_matrix3x4 = AZ::Matrix3x4::CreateIdentity();
// flag indicating if the Blas objects in the sub-meshes are built
bool m_blasBuilt = false;
@@ -85,7 +85,7 @@ 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 SetMeshMatrix3x4(const ObjectId objectId, const AZ::Matrix3x4 matrix3x4);
//! Retrieves ray tracing data for all meshes in the scene
const MeshMap& GetMeshes() const { return m_meshes; }
@@ -70,7 +70,7 @@ namespace AZ
m_visualizationMeshHandle = m_meshFeatureProcessor->AcquireMesh(m_visualizationModelAsset);
m_meshFeatureProcessor->SetExcludeFromReflectionCubeMaps(m_visualizationMeshHandle, true);
m_meshFeatureProcessor->SetRayTracingEnabled(m_visualizationMeshHandle, false);
m_meshFeatureProcessor->SetTransform(m_visualizationMeshHandle, AZ::Transform::CreateIdentity());
m_meshFeatureProcessor->SetMatrix3x4(m_visualizationMeshHandle, AZ::Matrix3x4::CreateIdentity());
// We have to pre-load this asset before creating a Material instance because the InstanceDatabase will attempt a blocking load which could deadlock,
// particularly when slices are involved.
@@ -206,10 +206,10 @@ namespace AZ
}
void ReflectionProbe::SetTransform(const AZ::Transform& transform)
void ReflectionProbe::SetMatrix3x4(const AZ::Matrix3x4& matrix3x4)
{
m_position = transform.GetTranslation();
m_meshFeatureProcessor->SetTransform(m_visualizationMeshHandle, transform);
m_position = matrix3x4.GetTranslation();
m_meshFeatureProcessor->SetMatrix3x4(m_visualizationMeshHandle, matrix3x4);
m_outerAabbWs = Aabb::CreateCenterHalfExtents(m_position, m_outerExtents / 2.0f);
m_innerAabbWs = Aabb::CreateCenterHalfExtents(m_position, m_innerExtents / 2.0f);
m_updateSrg = true;
@@ -76,7 +76,7 @@ namespace AZ
void Simulate(uint32_t probeIndex);
const Vector3& GetPosition() const { return m_position; }
void SetTransform(const AZ::Transform& transform);
void SetMatrix3x4(const AZ::Matrix3x4& matrix3x4);
const AZ::Vector3& GetOuterExtents() const { return m_outerExtents; }
void SetOuterExtents(const AZ::Vector3& outerExtents);
@@ -223,7 +223,7 @@ namespace AZ
{
AZStd::shared_ptr<ReflectionProbe> reflectionProbe = AZStd::make_shared<ReflectionProbe>();
reflectionProbe->Init(GetParentScene(), &m_reflectionRenderData);
reflectionProbe->SetTransform(transform);
reflectionProbe->SetMatrix3x4(AZ::Matrix3x4::CreateFromTransform(transform));
reflectionProbe->SetUseParallaxCorrection(useParallaxCorrection);
m_reflectionProbes.push_back(reflectionProbe);
m_probeSortRequired = true;
@@ -264,10 +264,10 @@ namespace AZ
probe->SetCubeMapImage(cubeMapImage);
}
void ReflectionProbeFeatureProcessor::SetProbeTransform(const ReflectionProbeHandle& probe, const AZ::Transform& transform)
void ReflectionProbeFeatureProcessor::SetProbeMatrix3x4(const ReflectionProbeHandle& probe, const AZ::Matrix3x4& matrix3x4)
{
AZ_Assert(probe.get(), "SetProbeTransform called with an invalid handle");
probe->SetTransform(transform);
AZ_Assert(probe.get(), "SetProbeMatrix3x4 called with an invalid handle");
probe->SetMatrix3x4(matrix3x4);
m_probeSortRequired = true;
}
@@ -210,14 +210,12 @@ namespace AZ
}
}
void TransformServiceFeatureProcessor::SetTransformForId(ObjectId id, const AZ::Transform& transform)
void TransformServiceFeatureProcessor::SetMatrix3x4ForId(ObjectId id, const AZ::Matrix3x4& matrix3x4)
{
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.StoreToRowMajorFloat12(m_objectToWorldTransforms.at(id.GetIndex()).m_transform);
// Inverse transpose to take the non-uniform scale out of the transform for usage with normals.
@@ -226,10 +224,10 @@ namespace AZ
}
}
AZ::Transform TransformServiceFeatureProcessor::GetTransformForId(ObjectId id) const
AZ::Matrix3x4 TransformServiceFeatureProcessor::GetMatrix3x4ForId(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) );
return AZ::Matrix3x4::CreateFromRowMajorFloat12(m_objectToWorldTransforms.at(id.GetIndex()).m_transform);
}
}
}
@@ -12,7 +12,7 @@
#pragma once
#include <AzCore/std/containers/vector.h>
#include <AzCore/Math/Transform.h>
#include <AzCore/Math/Matrix3x4.h>
#include <Atom/RHI/IndexBufferView.h>
#include <Atom/RHI/StreamBufferView.h>
#include <Atom/RHI.Reflect/Format.h>
@@ -110,7 +110,7 @@ namespace AZ
{
uint32_t m_instanceID = 0;
uint32_t m_hitGroupIndex = 0;
AZ::Transform m_transform = AZ::Transform::CreateIdentity();
AZ::Matrix3x4 m_matrix3x4 = AZ::Matrix3x4::CreateIdentity();
RHI::Ptr<RHI::RayTracingBlas> m_blas;
};
using RayTracingTlasInstanceVector = AZStd::vector<RayTracingTlasInstance>;
@@ -153,7 +153,7 @@ namespace AZ
RayTracingTlasDescriptor* Instance();
RayTracingTlasDescriptor* InstanceID(uint32_t instanceID);
RayTracingTlasDescriptor* HitGroupIndex(uint32_t hitGroupIndex);
RayTracingTlasDescriptor* Transform(const AZ::Transform& transform);
RayTracingTlasDescriptor* Matrix3x4(const AZ::Matrix3x4& matrix3x4);
RayTracingTlasDescriptor* Blas(RHI::Ptr<RHI::RayTracingBlas>& blas);
RayTracingTlasDescriptor* InstancesBuffer(RHI::Ptr<RHI::Buffer>& tlasInstances);
RayTracingTlasDescriptor* NumInstances(uint32_t numInstancesInBuffer);
@@ -78,10 +78,10 @@ namespace AZ
return this;
}
RayTracingTlasDescriptor* RayTracingTlasDescriptor::Transform(const AZ::Transform& transform)
RayTracingTlasDescriptor* RayTracingTlasDescriptor::Matrix3x4(const AZ::Matrix3x4& matrix3x4)
{
AZ_Assert(m_buildContext, "Transform property can only be added to an Instance entry");
m_buildContext->m_transform = transform;
AZ_Assert(m_buildContext, "Matrix3x4 property can only be added to an Instance entry");
m_buildContext->m_matrix3x4 = matrix3x4;
return this;
}
@@ -89,8 +89,7 @@ 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]);
instance.m_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,7 @@ 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]);
instance.m_matrix3x4.StoreToRowMajorFloat12(&mappedData[i].transform.matrix[0][0]);
RayTracingBlas* blas = static_cast<RayTracingBlas*>(instance.m_blas.get());
VkAccelerationStructureDeviceAddressInfoKHR addressInfo = {};
@@ -72,11 +72,13 @@ 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
//! @return true if the ray intersects the mesh
bool RayIntersection(const AZ::Transform& modelTransform, const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distanceFactor) const;
bool RayIntersection(const AZ::Transform& modelTransform, const AZ::Vector3& nonUniformScale, const AZ::Vector3& rayStart,
const AZ::Vector3& dir, float& distanceFactor) const;
//! Get available UV names from the model and its lods.
const AZStd::unordered_set<AZ::Name>& GetUvNames() const;
@@ -164,15 +164,15 @@ namespace AZ
return false;
}
bool Model::RayIntersection(const AZ::Transform& modelTransform, const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distanceFactor) const
bool Model::RayIntersection(const AZ::Transform& modelTransform, const AZ::Vector3& nonUniformScale, const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distanceFactor) const
{
AZ_PROFILE_FUNCTION(Debug::ProfileCategory::AzRender);
const AZ::Transform inverseTM = modelTransform.GetInverse();
const AZ::Vector3 raySrcLocal = inverseTM.TransformPoint(rayStart);
const AZ::Vector3 raySrcLocal = inverseTM.TransformPoint(rayStart) / nonUniformScale;
// 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) / nonUniformScale;
const AZ::Vector3 rayDirLocal = rayDestLocal - raySrcLocal;
return LocalRayIntersection(raySrcLocal, rayDirLocal, distanceFactor);
@@ -137,7 +137,10 @@ namespace AZ
AZ::Transform transform = AZ::Transform::CreateIdentity();
AZ::TransformBus::EventResult(transform, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM);
return m_controller.GetModel()->RayIntersection(transform, src, dir, distance);
AZ::Vector3 nonUniformScale = AZ::Vector3::CreateOne();
AZ::NonUniformScaleRequestBus::EventResult(nonUniformScale, GetEntityId(), &AZ::NonUniformScaleRequests::GetScale);
return m_controller.GetModel()->RayIntersection(transform, nonUniformScale, src, dir, distance);
}
bool EditorMeshComponent::SupportsEditorRayIntersect()
@@ -180,6 +180,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);
@@ -216,11 +221,24 @@ namespace AZ
return m_configuration;
}
void MeshComponentController::OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& world)
void MeshComponentController::OnTransformChanged([[maybe_unused]] const AZ::Transform& local, [[maybe_unused]] const AZ::Transform& world)
{
UpdateOverallMatrix();
}
void MeshComponentController::HandleNonUniformScaleChange(const AZ::Vector3 & nonUniformScale)
{
m_cachedNonUniformScale = nonUniformScale;
UpdateOverallMatrix();
}
void MeshComponentController::UpdateOverallMatrix()
{
if (m_meshFeatureProcessor)
{
m_meshFeatureProcessor->SetTransform(m_meshHandle, world);
Matrix3x4 world = Matrix3x4::CreateFromTransform(m_transformInterface->GetWorldTM());
world.MultiplyByScale(m_cachedNonUniformScale);
m_meshFeatureProcessor->SetMatrix3x4(m_meshHandle, world);
}
}
@@ -266,8 +284,8 @@ 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::Matrix3x4& matrix3x4 = m_transformInterface ? Matrix3x4::CreateFromTransform(m_transformInterface->GetWorldTM()) : Matrix3x4::Identity();
m_meshFeatureProcessor->SetMatrix3x4(m_meshHandle, matrix3x4);
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);
@@ -403,7 +421,17 @@ 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.SetMin(aabb.GetMin() * m_cachedNonUniformScale);
aabb.SetMax(aabb.GetMax() * 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>
@@ -120,17 +121,26 @@ namespace AZ
void UnregisterModel();
void RefreshModelRegistration();
void HandleNonUniformScaleChange(const AZ::Vector3& nonUniformScale);
void UpdateOverallMatrix();
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
@@ -199,7 +199,7 @@ namespace AZ
return;
}
m_featureProcessor->SetProbeTransform(m_handle, world);
m_featureProcessor->SetProbeMatrix3x4(m_handle, Matrix3x4::CreateFromTransform(world));
}
void ReflectionProbeComponentController::OnShapeChanged(ShapeChangeReasons changeReason)
@@ -187,8 +187,9 @@ namespace AZ
void AtomActorInstance::OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& world)
{
// The mesh transform is used to determine where the actor instance is actually rendered
m_meshFeatureProcessor->SetTransform(*m_meshHandle, world); // handle validity is checked internally.
// The mesh Matrix3x4 is used to determine where the actor instance is actually rendered
AZ::Matrix3x4 matrix3x4 = AZ::Matrix3x4::CreateFromTransform(world);
m_meshFeatureProcessor->SetMatrix3x4(*m_meshHandle, matrix3x4); // handle validity is checked internally.
if (m_skinnedMeshRenderProxy.IsValid())
{
@@ -193,7 +193,7 @@ namespace Blast
AZ::Transform transform = AZ::Transform::Identity();
AZ::TransformBus::EventResult(transform, GetEntityId(), &AZ::TransformInterface::GetWorldTM);
m_meshFeatureProcessor->SetTransform(m_meshHandle, transform);
m_meshFeatureProcessor->SetMatrix3x4(m_meshHandle, AZ::Matrix3x4::CreateFromTransform(transform));
}
}
@@ -232,7 +232,7 @@ namespace Blast
{
if (m_meshFeatureProcessor)
{
m_meshFeatureProcessor->SetTransform(m_meshHandle, world);
m_meshFeatureProcessor->SetMatrix3x4(m_meshHandle, AZ::Matrix3x4::CreateFromTransform(world));
}
}
} // namespace Blast
@@ -74,10 +74,10 @@ namespace Blast
{
if (m_chunkActors[chunkId])
{
auto transform = m_chunkActors[chunkId]->GetWorldBody()->GetTransform();
auto matrix3x4 = AZ::Matrix3x4::CreateFromTransform(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);
matrix3x4.MultiplyByScale(m_scale);
m_meshFeatureProcessor->SetMatrix3x4(m_chunkMeshHandles[chunkId], matrix3x4);
}
}
}
@@ -114,7 +114,7 @@ namespace Blast
// ActorRenderManager::SyncMeshes
{
EXPECT_CALL(*m_mockMeshFeatureProcessor, SetTransform(_, _))
EXPECT_CALL(*m_mockMeshFeatureProcessor, SetMatrix3x4(_, _))
.Times(aznumeric_cast<int>(m_actorFactory->m_mockActors[0]->GetChunkIndices().size()));
actorRenderManager->SyncMeshes();
}
@@ -248,7 +248,7 @@ namespace WhiteBox
void AtomRenderMesh::UpdateTransform(const AZ::Transform& worldFromLocal)
{
m_meshFeatureProcessor->SetTransform(m_meshHandle, worldFromLocal);
m_meshFeatureProcessor->SetMatrix3x4(m_meshHandle, AZ::Matrix3x4::CreateFromTransform(worldFromLocal));
}
void AtomRenderMesh::UpdateMaterial([[maybe_unused]] const WhiteBoxMaterial& material)