Cloth will override all the vertices of the mesh and do CPU skinning on the non-simulated vertices when the optimization 'remove static particles' is enabled
This commit is contained in:
@@ -33,7 +33,6 @@ namespace NvCloth
|
||||
AZ::EntityId entityId,
|
||||
const MeshNodeInfo& meshNodeInfo,
|
||||
const size_t numSimParticles,
|
||||
const AZStd::vector<int>& meshRemappedVertices,
|
||||
AZStd::vector<SkinningInfo>& skinningData)
|
||||
{
|
||||
AZ::Data::Asset<AZ::RPI::ModelAsset> modelAsset;
|
||||
@@ -115,14 +114,7 @@ namespace NvCloth
|
||||
|
||||
for (int vertexIndex = 0; vertexIndex < subMeshInfo.m_numVertices; ++vertexIndex)
|
||||
{
|
||||
const int skinnedDataIndex = meshRemappedVertices[subMeshInfo.m_verticesFirstIndex + vertexIndex];
|
||||
if (skinnedDataIndex < 0)
|
||||
{
|
||||
// Removed particle
|
||||
continue;
|
||||
}
|
||||
|
||||
SkinningInfo& skinningInfo = skinningData[skinnedDataIndex];
|
||||
SkinningInfo& skinningInfo = skinningData[subMeshInfo.m_verticesFirstIndex + vertexIndex];
|
||||
skinningInfo.m_jointIndices.resize(influenceCount);
|
||||
skinningInfo.m_jointWeights.resize(influenceCount);
|
||||
|
||||
@@ -208,19 +200,17 @@ namespace NvCloth
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
// ActorClothSkinning overrides ...
|
||||
void UpdateSkinning() override;
|
||||
void ApplySkinning(
|
||||
const AZStd::vector<AZ::Vector4>& originalPositions,
|
||||
AZStd::vector<AZ::Vector4>& positions) override;
|
||||
bool HasSkinningTransformData() override;
|
||||
void ComputeVertexSkinnningTransform(const SkinningInfo& skinningInfo) override;
|
||||
AZ::Vector3 ComputeSkinningPosition(const AZ::Vector3& originalPosition) override;
|
||||
AZ::Vector3 ComputeSkinningVector(const AZ::Vector3& originalVector) override;
|
||||
|
||||
private:
|
||||
AZ::Vector3 ComputeSkinnedPosition(
|
||||
const AZ::Vector3& originalPosition,
|
||||
const SkinningInfo& skinningInfo,
|
||||
const AZ::Matrix3x4* skinningMatrices);
|
||||
|
||||
const AZ::Matrix3x4* m_skinningMatrices = nullptr;
|
||||
AZ::Matrix3x4 m_vertexSkinningTransform = AZ::Matrix3x4::CreateIdentity();
|
||||
};
|
||||
|
||||
void ActorClothSkinningLinear::UpdateSkinning()
|
||||
@@ -230,35 +220,14 @@ namespace NvCloth
|
||||
m_skinningMatrices = Internal::ObtainSkinningMatrices(m_entityId);
|
||||
}
|
||||
|
||||
void ActorClothSkinningLinear::ApplySkinning(
|
||||
const AZStd::vector<AZ::Vector4>& originalPositions,
|
||||
AZStd::vector<AZ::Vector4>& positions)
|
||||
bool ActorClothSkinningLinear::HasSkinningTransformData()
|
||||
{
|
||||
if (!m_skinningMatrices)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Cloth);
|
||||
|
||||
for (size_t index = 0; index < originalPositions.size(); ++index)
|
||||
{
|
||||
const AZ::Vector3 skinnedPosition = ComputeSkinnedPosition(
|
||||
originalPositions[index].GetAsVector3(),
|
||||
m_skinningData[index],
|
||||
m_skinningMatrices);
|
||||
|
||||
// Avoid overwriting the w component
|
||||
positions[index].Set(skinnedPosition, positions[index].GetW());
|
||||
}
|
||||
return m_skinningMatrices != nullptr;
|
||||
}
|
||||
|
||||
AZ::Vector3 ActorClothSkinningLinear::ComputeSkinnedPosition(
|
||||
const AZ::Vector3& originalPosition,
|
||||
const SkinningInfo& skinningInfo,
|
||||
const AZ::Matrix3x4* skinningMatrices)
|
||||
void ActorClothSkinningLinear::ComputeVertexSkinnningTransform(const SkinningInfo& skinningInfo)
|
||||
{
|
||||
AZ::Matrix3x4 clothSkinningMatrix = AZ::Matrix3x4::CreateZero();
|
||||
m_vertexSkinningTransform = AZ::Matrix3x4::CreateZero();
|
||||
for (size_t weightIndex = 0; weightIndex < skinningInfo.m_jointWeights.size(); ++weightIndex)
|
||||
{
|
||||
const AZ::u16 jointIndex = skinningInfo.m_jointIndices[weightIndex];
|
||||
@@ -273,11 +242,19 @@ namespace NvCloth
|
||||
// This way the skinning results are much similar to the skinning performed in GPU.
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
clothSkinningMatrix.SetRow(i, clothSkinningMatrix.GetRow(i) + skinningMatrices[jointIndex].GetRow(i) * jointWeight);
|
||||
m_vertexSkinningTransform.SetRow(i, m_vertexSkinningTransform.GetRow(i) + m_skinningMatrices[jointIndex].GetRow(i) * jointWeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return clothSkinningMatrix * originalPosition;
|
||||
AZ::Vector3 ActorClothSkinningLinear::ComputeSkinningPosition(const AZ::Vector3& originalPosition)
|
||||
{
|
||||
return m_vertexSkinningTransform * originalPosition;
|
||||
}
|
||||
|
||||
AZ::Vector3 ActorClothSkinningLinear::ComputeSkinningVector(const AZ::Vector3& originalVector)
|
||||
{
|
||||
return (m_vertexSkinningTransform * AZ::Vector4::CreateFromVector3AndFloat(originalVector, 0.0f)).GetAsVector3().GetNormalized();
|
||||
}
|
||||
|
||||
// Specialized class that applies dual quaternion blending skinning
|
||||
@@ -290,22 +267,19 @@ namespace NvCloth
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
// ActorClothSkinning overrides ...
|
||||
void UpdateSkinning() override;
|
||||
void ApplySkinning(
|
||||
const AZStd::vector<AZ::Vector4>& originalPositions,
|
||||
AZStd::vector<AZ::Vector4>& positions) override;
|
||||
bool HasSkinningTransformData() override;
|
||||
void ComputeVertexSkinnningTransform(const SkinningInfo& skinningInfo) override;
|
||||
AZ::Vector3 ComputeSkinningPosition(const AZ::Vector3& originalPosition) override;
|
||||
AZ::Vector3 ComputeSkinningVector(const AZ::Vector3& originalVector) override;
|
||||
|
||||
private:
|
||||
AZ::Vector3 ComputeSkinnedPosition(
|
||||
const AZ::Vector3& originalPosition,
|
||||
const SkinningInfo& skinningInfo,
|
||||
const AZStd::unordered_map<AZ::u16, DualQuat>& skinningDualQuaternions);
|
||||
|
||||
AZStd::unordered_map<AZ::u16, DualQuat> m_skinningDualQuaternions;
|
||||
DualQuat m_vertexSkinningTransform = DualQuat(type_identity::IDENTITY);
|
||||
};
|
||||
|
||||
|
||||
void ActorClothSkinningDualQuaternion::UpdateSkinning()
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Cloth);
|
||||
@@ -313,35 +287,14 @@ namespace NvCloth
|
||||
m_skinningDualQuaternions = Internal::ObtainSkinningDualQuaternions(m_entityId, m_jointIndices);
|
||||
}
|
||||
|
||||
void ActorClothSkinningDualQuaternion::ApplySkinning(
|
||||
const AZStd::vector<AZ::Vector4>& originalPositions,
|
||||
AZStd::vector<AZ::Vector4>& positions)
|
||||
bool ActorClothSkinningDualQuaternion::HasSkinningTransformData()
|
||||
{
|
||||
if (m_skinningDualQuaternions.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Cloth);
|
||||
|
||||
for (size_t index = 0; index < originalPositions.size(); ++index)
|
||||
{
|
||||
const AZ::Vector3 skinnedPosition = ComputeSkinnedPosition(
|
||||
originalPositions[index].GetAsVector3(),
|
||||
m_skinningData[index],
|
||||
m_skinningDualQuaternions);
|
||||
|
||||
// Avoid overwriting the w component
|
||||
positions[index].Set(skinnedPosition, positions[index].GetW());
|
||||
}
|
||||
return !m_skinningDualQuaternions.empty();
|
||||
}
|
||||
|
||||
AZ::Vector3 ActorClothSkinningDualQuaternion::ComputeSkinnedPosition(
|
||||
const AZ::Vector3& originalPosition,
|
||||
const SkinningInfo& skinningInfo,
|
||||
const AZStd::unordered_map<AZ::u16, DualQuat>& skinningDualQuaternions)
|
||||
void ActorClothSkinningDualQuaternion::ComputeVertexSkinnningTransform(const SkinningInfo& skinningInfo)
|
||||
{
|
||||
DualQuat clothSkinningDualQuaternion(type_zero::ZERO);
|
||||
m_vertexSkinningTransform = DualQuat(type_zero::ZERO);
|
||||
for (size_t weightIndex = 0; weightIndex < skinningInfo.m_jointWeights.size(); ++weightIndex)
|
||||
{
|
||||
const AZ::u16 jointIndex = skinningInfo.m_jointIndices[weightIndex];
|
||||
@@ -352,21 +305,28 @@ namespace NvCloth
|
||||
continue;
|
||||
}
|
||||
|
||||
clothSkinningDualQuaternion += skinningDualQuaternions.at(jointIndex) * jointWeight;
|
||||
m_vertexSkinningTransform += m_skinningDualQuaternions.at(jointIndex) * jointWeight;
|
||||
}
|
||||
clothSkinningDualQuaternion.Normalize();
|
||||
m_vertexSkinningTransform.Normalize();
|
||||
}
|
||||
|
||||
return LYVec3ToAZVec3(clothSkinningDualQuaternion * AZVec3ToLYVec3(originalPosition));
|
||||
AZ::Vector3 ActorClothSkinningDualQuaternion::ComputeSkinningPosition(const AZ::Vector3& originalPosition)
|
||||
{
|
||||
return LYVec3ToAZVec3(m_vertexSkinningTransform * AZVec3ToLYVec3(originalPosition));
|
||||
}
|
||||
|
||||
AZ::Vector3 ActorClothSkinningDualQuaternion::ComputeSkinningVector(const AZ::Vector3& originalVector)
|
||||
{
|
||||
return LYVec3ToAZVec3(m_vertexSkinningTransform.nq * AZVec3ToLYVec3(originalVector)).GetNormalized();
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<ActorClothSkinning> ActorClothSkinning::Create(
|
||||
AZ::EntityId entityId,
|
||||
const MeshNodeInfo& meshNodeInfo,
|
||||
const size_t numSimParticles,
|
||||
const AZStd::vector<int>& meshRemappedVertices)
|
||||
const size_t numSimParticles)
|
||||
{
|
||||
AZStd::vector<SkinningInfo> skinningData;
|
||||
if (!Internal::ObtainSkinningData(entityId, meshNodeInfo, numSimParticles, meshRemappedVertices, skinningData))
|
||||
if (!Internal::ObtainSkinningData(entityId, meshNodeInfo, numSimParticles, skinningData))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
@@ -427,6 +387,69 @@ namespace NvCloth
|
||||
{
|
||||
}
|
||||
|
||||
void ActorClothSkinning::ApplySkinning(
|
||||
const AZStd::vector<AZ::Vector4>& originalPositions,
|
||||
AZStd::vector<AZ::Vector4>& positions,
|
||||
const AZStd::vector<int>& meshRemappedVertices)
|
||||
{
|
||||
if (!HasSkinningTransformData() ||
|
||||
originalPositions.empty() ||
|
||||
originalPositions.size() != positions.size() ||
|
||||
m_skinningData.size() != meshRemappedVertices.size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Cloth);
|
||||
|
||||
AZStd::unordered_set<int> skinnedIndices;
|
||||
for (size_t index = 0; index < meshRemappedVertices.size(); ++index)
|
||||
{
|
||||
const int remappedIndex = meshRemappedVertices[index];
|
||||
if (remappedIndex >= 0 && !skinnedIndices.contains(remappedIndex))
|
||||
{
|
||||
ComputeVertexSkinnningTransform(m_skinningData[index]);
|
||||
|
||||
const AZ::Vector3 skinnedPosition = ComputeSkinningPosition(originalPositions[remappedIndex].GetAsVector3());
|
||||
positions[remappedIndex].Set(skinnedPosition, positions[remappedIndex].GetW()); // Avoid overwriting the w component
|
||||
|
||||
skinnedIndices.emplace(remappedIndex); // Avoid computing this index again
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ActorClothSkinning::ApplySkinninOnRemovedVertices(
|
||||
const MeshClothInfo& originalData,
|
||||
ClothComponentMesh::RenderData& renderData,
|
||||
const AZStd::vector<int>& meshRemappedVertices)
|
||||
{
|
||||
if (!HasSkinningTransformData() ||
|
||||
originalData.m_particles.empty() ||
|
||||
originalData.m_particles.size() != renderData.m_particles.size() ||
|
||||
originalData.m_particles.size() != m_skinningData.size() ||
|
||||
m_skinningData.size() != meshRemappedVertices.size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Cloth);
|
||||
|
||||
for (size_t index = 0; index < originalData.m_particles.size(); ++index)
|
||||
{
|
||||
if (meshRemappedVertices[index] < 0)
|
||||
{
|
||||
ComputeVertexSkinnningTransform(m_skinningData[index]);
|
||||
|
||||
const AZ::Vector3 skinnedPosition = ComputeSkinningPosition(originalData.m_particles[index].GetAsVector3());
|
||||
renderData.m_particles[index].Set(skinnedPosition, renderData.m_particles[index].GetW()); // Avoid overwriting the w component
|
||||
|
||||
renderData.m_tangents[index] = ComputeSkinningVector(originalData.m_tangents[index]);
|
||||
renderData.m_bitangents[index] = ComputeSkinningVector(originalData.m_bitangents[index]);
|
||||
renderData.m_normals[index] = ComputeSkinningVector(originalData.m_normals[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ActorClothSkinning::UpdateActorVisibility()
|
||||
{
|
||||
bool isVisible = true;
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
#include <NvCloth/Types.h>
|
||||
|
||||
#include <Components/ClothComponentMesh/ClothComponentMesh.h>
|
||||
|
||||
namespace NvCloth
|
||||
{
|
||||
struct MeshNodeInfo;
|
||||
@@ -42,8 +44,7 @@ namespace NvCloth
|
||||
static AZStd::unique_ptr<ActorClothSkinning> Create(
|
||||
AZ::EntityId entityId,
|
||||
const MeshNodeInfo& meshNodeInfo,
|
||||
const size_t numSimParticles,
|
||||
const AZStd::vector<int>& meshRemappedVertices);
|
||||
const size_t numSimParticles);
|
||||
|
||||
explicit ActorClothSkinning(AZ::EntityId entityId);
|
||||
|
||||
@@ -52,9 +53,17 @@ namespace NvCloth
|
||||
|
||||
//! Applies skinning to a list of positions.
|
||||
//! @note w components are not affected.
|
||||
virtual void ApplySkinning(
|
||||
void ApplySkinning(
|
||||
const AZStd::vector<AZ::Vector4>& originalPositions,
|
||||
AZStd::vector<AZ::Vector4>& positions) = 0;
|
||||
AZStd::vector<AZ::Vector4>& positions,
|
||||
const AZStd::vector<int>& meshRemappedVertices);
|
||||
|
||||
//! Applies skinning to a list of positions and vectors whose vertices
|
||||
//! have not been used for simulation (remapped index is negative).
|
||||
void ApplySkinninOnRemovedVertices(
|
||||
const MeshClothInfo& originalData,
|
||||
ClothComponentMesh::RenderData& renderData,
|
||||
const AZStd::vector<int>& meshRemappedVertices);
|
||||
|
||||
//! Updates visibility variables.
|
||||
void UpdateActorVisibility();
|
||||
@@ -66,6 +75,18 @@ namespace NvCloth
|
||||
bool WasActorVisible() const;
|
||||
|
||||
protected:
|
||||
//! Returns true if it has valid skinning trasform data.
|
||||
virtual bool HasSkinningTransformData() = 0;
|
||||
|
||||
//! Computes the skinnning transformation to apply to a vertex data.
|
||||
virtual void ComputeVertexSkinnningTransform(const SkinningInfo& skinningInfo) = 0;
|
||||
|
||||
//! Computes skinning on a position.
|
||||
virtual AZ::Vector3 ComputeSkinningPosition(const AZ::Vector3& originalPosition) = 0;
|
||||
|
||||
//! Computes skinning on a vector.
|
||||
virtual AZ::Vector3 ComputeSkinningVector(const AZ::Vector3& originalVector) = 0;
|
||||
|
||||
AZ::EntityId m_entityId;
|
||||
|
||||
// Skinning information of all particles
|
||||
|
||||
@@ -166,6 +166,13 @@ namespace NvCloth
|
||||
|
||||
// Initialize render data
|
||||
m_renderDataBufferIndex = 0;
|
||||
{
|
||||
auto& renderData = GetRenderData();
|
||||
renderData.m_particles = m_meshClothInfo.m_particles;
|
||||
renderData.m_tangents = m_meshClothInfo.m_tangents;
|
||||
renderData.m_bitangents = m_meshClothInfo.m_bitangents;
|
||||
renderData.m_normals = m_meshClothInfo.m_normals;
|
||||
}
|
||||
UpdateRenderData(m_cloth->GetParticles());
|
||||
// Copy the first initialized element to the rest of the buffer
|
||||
for (AZ::u32 i = 1; i < RenderDataBufferSize; ++i)
|
||||
@@ -177,7 +184,7 @@ namespace NvCloth
|
||||
m_actorClothColliders = ActorClothColliders::Create(m_entityId);
|
||||
|
||||
// It will return a valid instance if it's an actor with skinning data.
|
||||
m_actorClothSkinning = ActorClothSkinning::Create(m_entityId, m_meshNodeInfo, m_cloth->GetParticles().size(), m_meshRemappedVertices);
|
||||
m_actorClothSkinning = ActorClothSkinning::Create(m_entityId, m_meshNodeInfo, m_meshClothInfo.m_particles.size());
|
||||
m_numberOfClothSkinningUpdates = 0;
|
||||
|
||||
m_clothConstraints = ClothConstraints::Create(
|
||||
@@ -356,7 +363,7 @@ namespace NvCloth
|
||||
{
|
||||
// Update skinning for all particles and apply it to cloth
|
||||
AZStd::vector<SimParticleFormat> particles = m_cloth->GetParticles();
|
||||
m_actorClothSkinning->ApplySkinning(m_cloth->GetInitialParticles(), particles);
|
||||
m_actorClothSkinning->ApplySkinning(m_cloth->GetInitialParticles(), particles, m_meshRemappedVertices);
|
||||
m_cloth->SetParticles(AZStd::move(particles));
|
||||
m_cloth->DiscardParticleDelta();
|
||||
}
|
||||
@@ -372,8 +379,8 @@ namespace NvCloth
|
||||
|
||||
if (m_actorClothSkinning)
|
||||
{
|
||||
m_actorClothSkinning->ApplySkinning(m_clothConstraints->GetMotionConstraints(), m_motionConstraints);
|
||||
m_actorClothSkinning->ApplySkinning(m_clothConstraints->GetSeparationConstraints(), m_separationConstraints);
|
||||
m_actorClothSkinning->ApplySkinning(m_clothConstraints->GetMotionConstraints(), m_motionConstraints, m_meshRemappedVertices);
|
||||
m_actorClothSkinning->ApplySkinning(m_clothConstraints->GetSeparationConstraints(), m_separationConstraints, m_meshRemappedVertices);
|
||||
}
|
||||
|
||||
m_cloth->GetClothConfigurator()->SetMotionConstraints(m_motionConstraints);
|
||||
@@ -392,6 +399,14 @@ namespace NvCloth
|
||||
return;
|
||||
}
|
||||
|
||||
auto& renderData = GetRenderData();
|
||||
|
||||
if (m_config.m_removeStaticTriangles && m_actorClothSkinning)
|
||||
{
|
||||
// Apply skinning to the non-simulated part of the mesh.
|
||||
m_actorClothSkinning->ApplySkinninOnRemovedVertices(m_meshClothInfo, renderData, m_meshRemappedVertices);
|
||||
}
|
||||
|
||||
// Calculate normals of the cloth particles (simplified mesh).
|
||||
AZStd::vector<AZ::Vector3> normals;
|
||||
[[maybe_unused]] bool normalsCalculated =
|
||||
@@ -401,19 +416,10 @@ namespace NvCloth
|
||||
// Copy particles and normals to render data.
|
||||
// Since cloth's vertices were welded together,
|
||||
// the full mesh will result in smooth normals.
|
||||
auto& renderData = GetRenderData();
|
||||
renderData.m_particles.resize_no_construct(m_meshRemappedVertices.size());
|
||||
renderData.m_normals.resize_no_construct(m_meshRemappedVertices.size());
|
||||
for (size_t index = 0; index < m_meshRemappedVertices.size(); ++index)
|
||||
{
|
||||
const int remappedIndex = m_meshRemappedVertices[index];
|
||||
if (remappedIndex < 0)
|
||||
{
|
||||
// Removed particle. Assign initial values to have something valid during tangents and bitangents calculation.
|
||||
renderData.m_particles[index] = m_meshClothInfo.m_particles[index];
|
||||
renderData.m_normals[index] = AZ::Vector3::CreateAxisZ();
|
||||
}
|
||||
else
|
||||
if (remappedIndex >= 0)
|
||||
{
|
||||
renderData.m_particles[index] = particles[remappedIndex];
|
||||
renderData.m_normals[index] = normals[remappedIndex];
|
||||
@@ -505,8 +511,8 @@ namespace NvCloth
|
||||
}
|
||||
const AZ::RPI::ModelLodAsset::Mesh& subMesh = modelLodAsset->GetMeshes()[subMeshInfo.m_primitiveIndex];
|
||||
|
||||
int numVertices = subMeshInfo.m_numVertices;
|
||||
int firstVertex = subMeshInfo.m_verticesFirstIndex;
|
||||
const int numVertices = subMeshInfo.m_numVertices;
|
||||
const int firstVertex = subMeshInfo.m_verticesFirstIndex;
|
||||
if (subMesh.GetVertexCount() != numVertices)
|
||||
{
|
||||
AZ_Error("ClothComponentMesh", false,
|
||||
@@ -540,12 +546,6 @@ namespace NvCloth
|
||||
{
|
||||
const int renderVertexIndex = firstVertex + index;
|
||||
|
||||
if (m_meshRemappedVertices[renderVertexIndex] < 0)
|
||||
{
|
||||
// Removed particle from simulation
|
||||
continue;
|
||||
}
|
||||
|
||||
const SimParticleFormat& renderParticle = renderParticles[renderVertexIndex];
|
||||
destVerticesBuffer[index].Set(
|
||||
renderParticle.GetX(),
|
||||
@@ -604,10 +604,7 @@ namespace NvCloth
|
||||
m_meshClothInfo.m_particles, m_meshClothInfo.m_indices,
|
||||
meshSimplifiedParticles, meshSimplifiedIndices,
|
||||
m_meshRemappedVertices,
|
||||
// [TODO LYN-1890]
|
||||
// Since blend weights cannot be controlled per instance with Atom,
|
||||
// this additional mesh optimization is not possible at the moment.
|
||||
false /*m_config.m_removeStaticTriangles*/);
|
||||
m_config.m_removeStaticTriangles);
|
||||
if (meshSimplifiedParticles.empty() ||
|
||||
meshSimplifiedIndices.empty())
|
||||
{
|
||||
|
||||
@@ -65,6 +65,9 @@ namespace NvCloth
|
||||
AZStd::vector<SimUVType> m_uvs;
|
||||
AZStd::vector<float> m_motionConstraints;
|
||||
AZStd::vector<AZ::Vector2> m_backstopData; //!< X contains offset, Y contains radius.
|
||||
AZStd::vector<AZ::Vector3> m_tangents;
|
||||
AZStd::vector<AZ::Vector3> m_bitangents;
|
||||
AZStd::vector<AZ::Vector3> m_normals;
|
||||
};
|
||||
|
||||
//! Interface to obtain cloth information from inside an Asset.
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
|
||||
#include <AtomLyIntegration/CommonFeatures/Mesh/MeshComponentBus.h>
|
||||
|
||||
#include <NvCloth/ITangentSpaceHelper.h>
|
||||
|
||||
#include <Utils/MeshAssetHelper.h>
|
||||
|
||||
namespace NvCloth
|
||||
@@ -224,6 +226,13 @@ namespace NvCloth
|
||||
meshClothInfo.m_indices.insert(meshClothInfo.m_indices.end(), sourceIndices.begin(), sourceIndices.end());
|
||||
}
|
||||
|
||||
// Calculate tangent space for the mesh.
|
||||
[[maybe_unused]] bool tangentSpaceCalculated =
|
||||
AZ::Interface<ITangentSpaceHelper>::Get()->CalculateTangentSpace(
|
||||
meshClothInfo.m_particles, meshClothInfo.m_indices, meshClothInfo.m_uvs,
|
||||
meshClothInfo.m_tangents, meshClothInfo.m_bitangents, meshClothInfo.m_normals);
|
||||
AZ_Assert(tangentSpaceCalculated, "Failed to calculate tangent space.");
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace NvCloth
|
||||
|
||||
@@ -98,7 +98,7 @@ namespace UnitTest
|
||||
{
|
||||
AZ::EntityId entityId;
|
||||
AZStd::unique_ptr<NvCloth::ActorClothSkinning> actorClothSkinning =
|
||||
NvCloth::ActorClothSkinning::Create(entityId, {}, 0, {});
|
||||
NvCloth::ActorClothSkinning::Create(entityId, {}, 0);
|
||||
|
||||
EXPECT_TRUE(actorClothSkinning.get() == nullptr);
|
||||
}
|
||||
@@ -107,7 +107,7 @@ namespace UnitTest
|
||||
{
|
||||
AZ::EntityId entityId;
|
||||
AZStd::unique_ptr<NvCloth::ActorClothSkinning> actorClothSkinning =
|
||||
NvCloth::ActorClothSkinning::Create(entityId, MeshNodeInfo, MeshRemappedVertices.size(), MeshRemappedVertices);
|
||||
NvCloth::ActorClothSkinning::Create(entityId, MeshNodeInfo, MeshRemappedVertices.size());
|
||||
|
||||
EXPECT_TRUE(actorClothSkinning.get() == nullptr);
|
||||
}
|
||||
@@ -122,7 +122,7 @@ namespace UnitTest
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<NvCloth::ActorClothSkinning> actorClothSkinning =
|
||||
NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), {}, 0, {});
|
||||
NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), {}, 0);
|
||||
|
||||
EXPECT_TRUE(actorClothSkinning.get() == nullptr);
|
||||
}
|
||||
@@ -139,7 +139,7 @@ namespace UnitTest
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<NvCloth::ActorClothSkinning> actorClothSkinning =
|
||||
NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeInfo, MeshVertices.size(), MeshRemappedVertices);
|
||||
NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeInfo, MeshVertices.size());
|
||||
|
||||
EXPECT_TRUE(actorClothSkinning.get() == nullptr);
|
||||
}
|
||||
@@ -156,7 +156,7 @@ namespace UnitTest
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<NvCloth::ActorClothSkinning> actorClothSkinning =
|
||||
NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeInfo, MeshVertices.size(), MeshRemappedVertices);
|
||||
NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeInfo, MeshVertices.size());
|
||||
|
||||
EXPECT_TRUE(actorClothSkinning.get() != nullptr);
|
||||
}
|
||||
@@ -184,7 +184,7 @@ namespace UnitTest
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<NvCloth::ActorClothSkinning> actorClothSkinning =
|
||||
NvCloth::ActorClothSkinning::Create(actorComponent->GetEntityId(), MeshNodeInfo, MeshVertices.size(), MeshRemappedVertices);
|
||||
NvCloth::ActorClothSkinning::Create(actorComponent->GetEntityId(), MeshNodeInfo, MeshVertices.size());
|
||||
ASSERT_TRUE(actorClothSkinning.get() != nullptr);
|
||||
|
||||
const AZStd::vector<NvCloth::SimParticleFormat> clothParticles = {{
|
||||
@@ -195,7 +195,7 @@ namespace UnitTest
|
||||
AZStd::vector<NvCloth::SimParticleFormat> skinnedClothParticles(clothParticles.size(), NvCloth::SimParticleFormat(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
|
||||
actorClothSkinning->UpdateSkinning();
|
||||
actorClothSkinning->ApplySkinning(clothParticles, skinnedClothParticles);
|
||||
actorClothSkinning->ApplySkinning(clothParticles, skinnedClothParticles, MeshRemappedVertices);
|
||||
|
||||
EXPECT_THAT(skinnedClothParticles, ::testing::Pointwise(ContainerIsCloseTolerance(Tolerance), clothParticles));
|
||||
|
||||
@@ -208,7 +208,7 @@ namespace UnitTest
|
||||
AZStd::vector<NvCloth::SimParticleFormat> newSkinnedClothParticles(clothParticles.size(), NvCloth::SimParticleFormat(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
|
||||
actorClothSkinning->UpdateSkinning();
|
||||
actorClothSkinning->ApplySkinning(clothParticles, newSkinnedClothParticles);
|
||||
actorClothSkinning->ApplySkinning(clothParticles, newSkinnedClothParticles, MeshRemappedVertices);
|
||||
|
||||
const AZ::Transform diffTransform = AZ::Transform::CreateRotationY(AZ::DegToRad(90.0f));
|
||||
const AZStd::vector<NvCloth::SimParticleFormat> clothParticlesResult = {{
|
||||
@@ -245,7 +245,7 @@ namespace UnitTest
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<NvCloth::ActorClothSkinning> actorClothSkinning =
|
||||
NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeInfo, MeshVertices.size(), MeshRemappedVertices);
|
||||
NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeInfo, MeshVertices.size());
|
||||
ASSERT_TRUE(actorClothSkinning.get() != nullptr);
|
||||
|
||||
const AZStd::vector<NvCloth::SimParticleFormat> clothParticles = {{
|
||||
@@ -256,7 +256,7 @@ namespace UnitTest
|
||||
AZStd::vector<NvCloth::SimParticleFormat> skinnedClothParticles(clothParticles.size(), NvCloth::SimParticleFormat(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
|
||||
actorClothSkinning->UpdateSkinning();
|
||||
actorClothSkinning->ApplySkinning(clothParticles, skinnedClothParticles);
|
||||
actorClothSkinning->ApplySkinning(clothParticles, skinnedClothParticles, MeshRemappedVertices);
|
||||
|
||||
EXPECT_THAT(skinnedClothParticles, ::testing::Pointwise(ContainerIsCloseTolerance(Tolerance), clothParticles));
|
||||
|
||||
@@ -271,7 +271,7 @@ namespace UnitTest
|
||||
AZStd::vector<NvCloth::SimParticleFormat> newSkinnedClothParticles(clothParticles.size(), NvCloth::SimParticleFormat(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
|
||||
actorClothSkinning->UpdateSkinning();
|
||||
actorClothSkinning->ApplySkinning(clothParticles, newSkinnedClothParticles);
|
||||
actorClothSkinning->ApplySkinning(clothParticles, newSkinnedClothParticles, MeshRemappedVertices);
|
||||
|
||||
const AZStd::vector<NvCloth::SimParticleFormat> clothParticlesResult = {{
|
||||
NvCloth::SimParticleFormat(-48.4177f, -31.9446f, 45.2279f, 1.0f),
|
||||
@@ -294,7 +294,7 @@ namespace UnitTest
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<NvCloth::ActorClothSkinning> actorClothSkinning =
|
||||
NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeInfo, MeshVertices.size(), MeshRemappedVertices);
|
||||
NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeInfo, MeshVertices.size());
|
||||
ASSERT_TRUE(actorClothSkinning.get() != nullptr);
|
||||
|
||||
EXPECT_FALSE(actorClothSkinning->IsActorVisible());
|
||||
|
||||
Reference in New Issue
Block a user