Fixing cloth working with Actors by reading directly from ModelAsset instead from EMFX Mesh. (#235)
- Fixing cloth working with Actors by reading directly from ModelAsset instead from EMFX Mesh. - Actor caches map from joint indices in skin metadata to skeleton indices so they can be query later. - Actor cloth skinning reads indices and weights from Model Asset instead from EMFX Mesh. - Actor cloth skinning with unlimited skinning bones. - Sort out cloth unit tests by disabling them until there is a way to create an Atom mesh - Addressing feedback.
This commit is contained in:
@@ -159,7 +159,8 @@ void MainCS(uint3 thread_id: SV_DispatchThreadID)
|
||||
blendWeights.z = InstanceSrg::m_sourceBlendWeights[i * 4 + 2];
|
||||
blendWeights.w = InstanceSrg::m_sourceBlendWeights[i * 4 + 3];
|
||||
|
||||
// When all the blend weights of a vertex are zero it means its data is set by the CPU directly
|
||||
// [TODO ATOM-15288]
|
||||
// Temporary workaround. When all the blend weights of a vertex are zero it means its data is set by the CPU directly
|
||||
// and skinning must be skipped to not overwrite it (e.g. cloth simulation).
|
||||
if(!any(blendWeights))
|
||||
{
|
||||
|
||||
@@ -253,24 +253,10 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
// If there is cloth data, set all the blend weights to zero to indicate
|
||||
// the vertices will be updated by cpu.
|
||||
//
|
||||
// [TODO ATOM-14478]
|
||||
// At the moment blend weights is a shared buffer and therefore all
|
||||
// instances of the actor asset will be affected by it. In the future
|
||||
// this buffer will be unique per instance and modified by cloth component
|
||||
// when necessary.
|
||||
//
|
||||
// [TODO LYN-1890]
|
||||
// At the moment, if there is cloth data it is assumed that every vertex in the
|
||||
// submesh will be simulated by cloth in cpu, so all the weights are set to zero.
|
||||
// But once the blend weights buffer can be modified per instance, it will be set by
|
||||
// the cloth component, which decides whether to control the whole submesh or
|
||||
// to apply an additional simplification pass to remove static triangles from simulation.
|
||||
// Static triangles are the ones that all its vertices won't move during simulation and
|
||||
// therefore its weights won't be altered so they are controlled by GPU.
|
||||
// This additional simplification has been disabled in ClothComponentMesh.cpp for now.
|
||||
// [TODO ATOM-15288]
|
||||
// Temporary workaround. If there is cloth data, set all the blend weights to zero to indicate
|
||||
// the vertices will be updated by cpu. When meshes with cloth data are not dispatched for skinning
|
||||
// this can be hasClothData can be removed.
|
||||
|
||||
// If there is no skinning info, default to 0 weights and display an error
|
||||
if (hasClothData || !sourceSkinningInfo)
|
||||
@@ -370,14 +356,6 @@ namespace AZ
|
||||
AZ_Assert(modelLodAsset->GetMeshes().size() > 0, "ModelLod '%d' for model '%s' has 0 meshes", lodIndex, fullFileName.c_str());
|
||||
const RPI::ModelLodAsset::Mesh& mesh0 = modelLodAsset->GetMeshes()[0];
|
||||
|
||||
// Get the amount of vertices and indices
|
||||
// Get the meshes to process
|
||||
bool hasUVs = false;
|
||||
bool hasUVs2 = false;
|
||||
bool hasTangents = false;
|
||||
bool hasBitangents = false;
|
||||
bool hasClothData = false;
|
||||
|
||||
// Do a pass over the lod to find the number of sub-meshes, the offset and size of each sub-mesh, and total number of vertices in the lod.
|
||||
// These will be combined into one input buffer for the source actor, but these offsets and sizes will be used to create multiple sub-meshes for the target skinned actor
|
||||
uint32_t lodVertexCount = 0;
|
||||
@@ -416,18 +394,18 @@ namespace AZ
|
||||
const AZ::Vector4* sourceTangents = static_cast<const AZ::Vector4*>(mesh->FindOriginalVertexData(EMotionFX::Mesh::ATTRIB_TANGENTS));
|
||||
const AZ::Vector3* sourceBitangents = static_cast<const AZ::Vector3*>(mesh->FindOriginalVertexData(EMotionFX::Mesh::ATTRIB_BITANGENTS));
|
||||
const AZ::Vector2* sourceUVs = static_cast<const AZ::Vector2*>(mesh->FindOriginalVertexData(EMotionFX::Mesh::ATTRIB_UVCOORDS, 0));
|
||||
const AZ::Vector2* sourceUVs2 = static_cast<const AZ::Vector2*>(mesh->FindOriginalVertexData(EMotionFX::Mesh::ATTRIB_UVCOORDS, 1));
|
||||
const uint32_t* sourceClothData = static_cast<uint32_t*>(mesh->FindOriginalVertexData(EMotionFX::Mesh::ATTRIB_CLOTH_DATA));
|
||||
|
||||
hasUVs = (sourceUVs != nullptr);
|
||||
hasUVs2 = (sourceUVs2 != nullptr);
|
||||
hasTangents = (sourceTangents != nullptr);
|
||||
hasBitangents = (sourceBitangents != nullptr);
|
||||
hasClothData = (sourceClothData != nullptr);
|
||||
const bool hasUVs = (sourceUVs != nullptr);
|
||||
const bool hasTangents = (sourceTangents != nullptr);
|
||||
const bool hasBitangents = (sourceBitangents != nullptr);
|
||||
|
||||
// For each sub-mesh within each mesh, we want to create a separate sub-piece.
|
||||
const size_t numSubMeshes = mesh->GetNumSubMeshes();
|
||||
|
||||
AZ_Assert(numSubMeshes == modelLodAsset->GetMeshes().size(),
|
||||
"Number of submeshes (%d) in EMotionFX mesh (lod %d and joint index %d) doesn't match the number of meshes (%d) in model lod asset",
|
||||
numSubMeshes, lodIndex, jointIndex, modelLodAsset->GetMeshes().size());
|
||||
|
||||
for (size_t subMeshIndex = 0; subMeshIndex < numSubMeshes; ++subMeshIndex)
|
||||
{
|
||||
const EMotionFX::SubMesh* subMesh = mesh->GetSubMesh(subMeshIndex);
|
||||
@@ -466,6 +444,9 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the model mesh asset has cloth data. One ModelLodAsset::Mesh corresponds to one EMotionFX::SubMesh.
|
||||
const bool hasClothData = modelLodAsset->GetMeshes()[subMeshIndex].GetSemanticBufferAssetView(AZ::Name("CLOTH_DATA")) != nullptr;
|
||||
|
||||
ProcessSkinInfluences(mesh, subMesh, vertexBufferOffset, blendIndexBufferData, blendWeightBufferData, hasClothData);
|
||||
|
||||
// Increment offsets so that the next sub-mesh can start at the right place
|
||||
|
||||
@@ -512,10 +512,9 @@ namespace AZ
|
||||
MaterialReceiverNotificationBus::Event(m_entityId, &MaterialReceiverNotificationBus::Events::OnMaterialAssignmentsChanged);
|
||||
RegisterActor();
|
||||
|
||||
// [TODO ATOM-14478, LYN-1890]
|
||||
// [TODO ATOM-15288]
|
||||
// Temporary workaround for cloth to make sure the output skinned buffers are filled at least once.
|
||||
// When the blend weights buffer can be unique per instance and updated by cloth component,
|
||||
// FillSkinnedMeshInstanceBuffers can be removed.
|
||||
// When meshes with cloth data are not dispatched for skinning FillSkinnedMeshInstanceBuffers can be removed.
|
||||
FillSkinnedMeshInstanceBuffers();
|
||||
}
|
||||
else
|
||||
|
||||
@@ -156,6 +156,7 @@ namespace EMotionFX
|
||||
result->mRetargetRootNode = mRetargetRootNode;
|
||||
result->mInvBindPoseTransforms = mInvBindPoseTransforms;
|
||||
result->m_optimizeSkeleton = m_optimizeSkeleton;
|
||||
result->m_skinToSkeletonIndexMap = m_skinToSkeletonIndexMap;
|
||||
|
||||
result->RecursiveAddDependencies(this);
|
||||
|
||||
@@ -1490,18 +1491,19 @@ namespace EMotionFX
|
||||
const bool skinMetaAssetExists = DoesSkinMetaAssetExist(meshAssetId);
|
||||
const bool morphTargetMetaAssetExists = DoesMorphTargetMetaAssetExist(m_meshAsset.GetId());
|
||||
|
||||
m_skinToSkeletonIndexMap.clear();
|
||||
|
||||
// Skin and morph target meta assets are ready, fill the runtime mesh data.
|
||||
if ((!skinMetaAssetExists || m_skinMetaAsset.IsReady()) &&
|
||||
(!morphTargetMetaAssetExists || m_morphTargetMetaAsset.IsReady()))
|
||||
{
|
||||
// Optional, not all actors have a skinned meshes.
|
||||
AZStd::unordered_map<AZ::u16, AZ::u16> skinToSkeletonIndexMap;
|
||||
if (skinMetaAssetExists)
|
||||
{
|
||||
skinToSkeletonIndexMap = ConstructSkinToSkeletonIndexMap(m_skinMetaAsset);
|
||||
m_skinToSkeletonIndexMap = ConstructSkinToSkeletonIndexMap(m_skinMetaAsset);
|
||||
}
|
||||
|
||||
ConstructMeshes(skinToSkeletonIndexMap);
|
||||
ConstructMeshes(m_skinToSkeletonIndexMap);
|
||||
|
||||
// Optional, not all actors have morph targets.
|
||||
if (morphTargetMetaAssetExists)
|
||||
|
||||
@@ -893,6 +893,8 @@ namespace EMotionFX
|
||||
const AZ::Data::Asset<AZ::RPI::SkinMetaAsset>& GetSkinMetaAsset() const { return m_skinMetaAsset; }
|
||||
const AZ::Data::Asset<AZ::RPI::MorphTargetMetaAsset>& GetMorphTargetMetaAsset() const { return m_morphTargetMetaAsset; }
|
||||
|
||||
const AZStd::unordered_map<AZ::u16, AZ::u16>& GetSkinToSkeletonIndexMap() const { return m_skinToSkeletonIndexMap; }
|
||||
|
||||
void SetMeshAsset(AZ::Data::Asset<AZ::RPI::ModelAsset> asset) { m_meshAsset = asset; }
|
||||
void SetSkinMetaAsset(AZ::Data::Asset<AZ::RPI::SkinMetaAsset> asset) { m_skinMetaAsset = asset; }
|
||||
void SetMorphTargetMetaAsset(AZ::Data::Asset<AZ::RPI::MorphTargetMetaAsset> asset) { m_morphTargetMetaAsset = asset; }
|
||||
@@ -954,6 +956,7 @@ namespace EMotionFX
|
||||
AZ::Data::Asset<AZ::RPI::SkinMetaAsset> m_skinMetaAsset;
|
||||
AZ::Data::Asset<AZ::RPI::MorphTargetMetaAsset> m_morphTargetMetaAsset;
|
||||
AZStd::recursive_mutex m_mutex;
|
||||
AZStd::unordered_map<AZ::u16, AZ::u16> m_skinToSkeletonIndexMap; //!< Mapping joint indices in skin metadata to skeleton indices.
|
||||
|
||||
static AZ::Data::AssetId ConstructSkinMetaAssetId(const AZ::Data::AssetId& meshAssetId);
|
||||
static bool DoesSkinMetaAssetExist(const AZ::Data::AssetId& meshAssetId);
|
||||
|
||||
@@ -76,7 +76,6 @@ namespace EMotionFX
|
||||
ATTRIB_ORGVTXNUMBERS = 5, /**< Original vertex numbers. Typecast to uint32. Original vertex numbers always exist. */
|
||||
ATTRIB_COLORS128 = 6, /**< Vertex colors in 128-bits. */
|
||||
ATTRIB_BITANGENTS = 7, /**< Vertex bitangents (aka binormal). Typecast to AZ::Vector3. When tangents exists bitangents may still not exist! */
|
||||
ATTRIB_CLOTH_DATA = 8 /**< Vertex cloth data stored as AZ::u32, packed using four 8 bit values, similar to a 32 bit vertex color. */
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
-3
@@ -89,9 +89,6 @@ namespace EMStudio
|
||||
case EMotionFX::Mesh::ATTRIB_BITANGENTS:
|
||||
tmpString = "Vertex bitangents";
|
||||
break;
|
||||
case EMotionFX::Mesh::ATTRIB_CLOTH_DATA:
|
||||
tmpString = "Vertex cloth data in 32-bits";
|
||||
break;
|
||||
default:
|
||||
tmpString = AZStd::string::format("Unknown data (TypeID=%d)", attributeLayerType);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ namespace EMotionFX
|
||||
const AZStd::vector<AZ::Vector3>& vertices,
|
||||
const AZStd::vector<AZ::Vector3>& normals,
|
||||
const AZStd::vector<AZ::Vector2>& uvs,
|
||||
const AZStd::vector<AZ::Color>& clothData,
|
||||
const AZStd::vector<VertexSkinInfluences>& skinningInfo
|
||||
) {
|
||||
const AZ::u32 vertCount = aznumeric_cast<AZ::u32>(vertices.size());
|
||||
@@ -90,16 +89,6 @@ namespace EMotionFX
|
||||
uvsLayer->ResetToOriginalData();
|
||||
}
|
||||
|
||||
// The cloth layer.
|
||||
EMotionFX::VertexAttributeLayerAbstractData* clothLayer = nullptr;
|
||||
if (!clothData.empty() && clothData.size() == vertices.size())
|
||||
{
|
||||
clothLayer = EMotionFX::VertexAttributeLayerAbstractData::Create(vertCount, EMotionFX::Mesh::ATTRIB_CLOTH_DATA, sizeof(AZ::u32), false);
|
||||
mesh->AddVertexAttributeLayer(clothLayer);
|
||||
AZStd::transform(clothData.begin(), clothData.end(), static_cast<AZ::u32*>(clothLayer->GetOriginalData()), [](const AZ::Color& color) { return color.ToU32(); });
|
||||
clothLayer->ResetToOriginalData();
|
||||
}
|
||||
|
||||
auto* subMesh = EMotionFX::SubMesh::Create(
|
||||
/*parentMesh=*/ mesh,
|
||||
/*startVertex=*/ 0,
|
||||
|
||||
@@ -33,7 +33,6 @@ namespace EMotionFX
|
||||
const AZStd::vector<AZ::Vector3>& vertices,
|
||||
const AZStd::vector<AZ::Vector3>& normals,
|
||||
const AZStd::vector<AZ::Vector2>& uvs = {},
|
||||
const AZStd::vector<AZ::Color>& clothData = {},
|
||||
const AZStd::vector<VertexSkinInfluences>& skinningInfo = {}
|
||||
);
|
||||
};
|
||||
|
||||
@@ -13,16 +13,17 @@
|
||||
#include <Cry_Math.h> // Needed for DualQuat
|
||||
#include <MathConversion.h>
|
||||
|
||||
#include <AtomLyIntegration/CommonFeatures/Mesh/MeshComponentBus.h>
|
||||
#include <Integration/ActorComponentBus.h>
|
||||
|
||||
// Needed to access the Mesh information inside Actor.
|
||||
#include <EMotionFX/Source/TransformData.h>
|
||||
#include <EMotionFX/Source/SkinningInfoVertexAttributeLayer.h>
|
||||
#include <EMotionFX/Source/Node.h>
|
||||
#include <EMotionFX/Source/Mesh.h>
|
||||
#include <EMotionFX/Source/ActorInstance.h>
|
||||
|
||||
#include <Components/ClothComponentMesh/ActorClothSkinning.h>
|
||||
#include <Utils/AssetHelper.h>
|
||||
|
||||
#include <AzCore/Math/PackedVector3.h>
|
||||
|
||||
namespace NvCloth
|
||||
{
|
||||
@@ -30,11 +31,30 @@ namespace NvCloth
|
||||
{
|
||||
bool ObtainSkinningData(
|
||||
AZ::EntityId entityId,
|
||||
const AZStd::string& meshNode,
|
||||
const MeshNodeInfo& meshNodeInfo,
|
||||
const size_t numSimParticles,
|
||||
const AZStd::vector<int>& meshRemappedVertices,
|
||||
AZStd::vector<SkinningInfo>& skinningData)
|
||||
{
|
||||
AZ::Data::Asset<AZ::RPI::ModelAsset> modelAsset;
|
||||
AZ::Render::MeshComponentRequestBus::EventResult(
|
||||
modelAsset, entityId, &AZ::Render::MeshComponentRequestBus::Events::GetModelAsset);
|
||||
if (!modelAsset.IsReady())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (modelAsset->GetLodCount() < meshNodeInfo.m_lodLevel)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const AZ::Data::Asset<AZ::RPI::ModelLodAsset>& modelLodAsset = modelAsset->GetLodAssets()[meshNodeInfo.m_lodLevel];
|
||||
if (!modelLodAsset.GetId().IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
EMotionFX::ActorInstance* actorInstance = nullptr;
|
||||
EMotionFX::Integration::ActorComponentRequestBus::EventResult(actorInstance, entityId, &EMotionFX::Integration::ActorComponentRequestBus::Events::GetActorInstance);
|
||||
if (!actorInstance)
|
||||
@@ -48,112 +68,82 @@ namespace NvCloth
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint32 numNodes = actor->GetNumNodes();
|
||||
const uint32 numLODs = actor->GetNumLODLevels();
|
||||
|
||||
const EMotionFX::Mesh* emfxMesh = nullptr;
|
||||
|
||||
// Find the render data of the mesh node
|
||||
for (uint32 lodLevel = 0; lodLevel < numLODs; ++lodLevel)
|
||||
{
|
||||
for (uint32 nodeIndex = 0; nodeIndex < numNodes; ++nodeIndex)
|
||||
{
|
||||
const EMotionFX::Mesh* mesh = actor->GetMesh(lodLevel, nodeIndex);
|
||||
if (!mesh || mesh->GetIsCollisionMesh())
|
||||
{
|
||||
// Skip invalid and collision meshes.
|
||||
continue;
|
||||
}
|
||||
|
||||
const EMotionFX::Node* node = actor->GetSkeleton()->GetNode(nodeIndex);
|
||||
if (meshNode != node->GetNameString())
|
||||
{
|
||||
// Skip nodes other than the one we're looking for.
|
||||
continue;
|
||||
}
|
||||
|
||||
emfxMesh = mesh;
|
||||
break;
|
||||
}
|
||||
|
||||
if (emfxMesh)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!emfxMesh)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const AZ::u32* sourceOriginalVertex = static_cast<AZ::u32*>(emfxMesh->FindOriginalVertexData(EMotionFX::Mesh::ATTRIB_ORGVTXNUMBERS));
|
||||
EMotionFX::SkinningInfoVertexAttributeLayer* sourceSkinningInfo =
|
||||
static_cast<EMotionFX::SkinningInfoVertexAttributeLayer*>(
|
||||
emfxMesh->FindSharedVertexAttributeLayer(EMotionFX::SkinningInfoVertexAttributeLayer::TYPE_ID));
|
||||
|
||||
if (!sourceOriginalVertex || !sourceSkinningInfo)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const int numVertices = emfxMesh->GetNumVertices();
|
||||
if (numVertices == 0)
|
||||
{
|
||||
AZ_Error("ActorClothSkinning", false, "Invalid mesh data");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (meshRemappedVertices.size() != numVertices)
|
||||
{
|
||||
AZ_Error("ActorClothSkinning", false,
|
||||
"Number of vertices (%d) doesn't match the mesh remapping size (%zu)",
|
||||
numVertices, meshRemappedVertices.size());
|
||||
return false;
|
||||
}
|
||||
const auto& skinToSkeletonIndexMap = actor->GetSkinToSkeletonIndexMap();
|
||||
|
||||
skinningData.resize(numSimParticles);
|
||||
for (int index = 0; index < numVertices; ++index)
|
||||
|
||||
// For each submesh...
|
||||
for (const auto& subMeshInfo : meshNodeInfo.m_subMeshes)
|
||||
{
|
||||
const int skinnedDataIndex = meshRemappedVertices[index];
|
||||
if (skinnedDataIndex < 0)
|
||||
if (modelLodAsset->GetMeshes().size() < subMeshInfo.m_primitiveIndex)
|
||||
{
|
||||
AZ_Error("ActorClothSkinning", false,
|
||||
"Unable to access submesh %d from lod asset '%s' as it only has %d submeshes.",
|
||||
subMeshInfo.m_primitiveIndex,
|
||||
modelAsset.GetHint().c_str(),
|
||||
modelLodAsset->GetMeshes().size());
|
||||
return false;
|
||||
}
|
||||
|
||||
const AZ::RPI::ModelLodAsset::Mesh& subMesh = modelLodAsset->GetMeshes()[subMeshInfo.m_primitiveIndex];
|
||||
|
||||
const auto sourcePositions = subMesh.GetSemanticBufferTyped<AZ::PackedVector3f>(AZ::Name("POSITION"));
|
||||
if (sourcePositions.size() != subMeshInfo.m_numVertices)
|
||||
{
|
||||
AZ_Error("ActorClothSkinning", false,
|
||||
"Number of vertices (%zu) in submesh %d doesn't match the cloth's submesh (%d)",
|
||||
sourcePositions.size(), subMeshInfo.m_primitiveIndex, subMeshInfo.m_numVertices);
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto sourceSkinJointIndices = subMesh.GetSemanticBufferTyped<uint16_t>(AZ::Name("SKIN_JOINTINDICES"));
|
||||
const auto sourceSkinWeights = subMesh.GetSemanticBufferTyped<float>(AZ::Name("SKIN_WEIGHTS"));
|
||||
|
||||
if (sourceSkinJointIndices.empty() || sourceSkinWeights.empty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
AZ_Assert(sourceSkinJointIndices.size() == sourceSkinWeights.size(),
|
||||
"Size of skin joint indices buffer (%zu) different from skin weights buffer (%zu)",
|
||||
sourceSkinJointIndices.size(), sourceSkinWeights.size());
|
||||
|
||||
const size_t influenceCount = sourceSkinWeights.size() / sourcePositions.size();
|
||||
if (influenceCount == 0)
|
||||
{
|
||||
// Removed particle
|
||||
continue;
|
||||
}
|
||||
|
||||
SkinningInfo& skinningInfo = skinningData[skinnedDataIndex];
|
||||
|
||||
const AZ::u32 originalVertex = sourceOriginalVertex[index];
|
||||
const AZ::u32 influenceCount = AZ::GetMin<AZ::u32>(MaxSkinningBones, sourceSkinningInfo->GetNumInfluences(originalVertex));
|
||||
AZ::u32 influenceIndex = 0;
|
||||
AZ::u8 weightError = 255;
|
||||
|
||||
for (; influenceIndex < influenceCount; ++influenceIndex)
|
||||
for (int vertexIndex = 0; vertexIndex < subMeshInfo.m_numVertices; ++vertexIndex)
|
||||
{
|
||||
EMotionFX::SkinInfluence* influence = sourceSkinningInfo->GetInfluence(originalVertex, influenceIndex);
|
||||
skinningInfo.m_jointIndices[influenceIndex] = influence->GetNodeNr();
|
||||
skinningInfo.m_jointWeights[influenceIndex] = static_cast<AZ::u8>(AZ::GetClamp<float>(influence->GetWeight() * 255.0f, 0.0f, 255.0f));
|
||||
if (skinningInfo.m_jointWeights[influenceIndex] >= weightError)
|
||||
const int skinnedDataIndex = meshRemappedVertices[subMeshInfo.m_verticesFirstIndex + vertexIndex];
|
||||
if (skinnedDataIndex < 0)
|
||||
{
|
||||
skinningInfo.m_jointWeights[influenceIndex] = weightError;
|
||||
weightError = 0;
|
||||
influenceIndex++;
|
||||
break;
|
||||
// Removed particle
|
||||
continue;
|
||||
}
|
||||
else
|
||||
|
||||
SkinningInfo& skinningInfo = skinningData[skinnedDataIndex];
|
||||
skinningInfo.m_jointIndices.resize(influenceCount);
|
||||
skinningInfo.m_jointWeights.resize(influenceCount);
|
||||
|
||||
for (size_t influenceIndex = 0; influenceIndex < influenceCount; ++influenceIndex)
|
||||
{
|
||||
weightError -= skinningInfo.m_jointWeights[influenceIndex];
|
||||
const AZ::u16 jointIndex = sourceSkinJointIndices[vertexIndex * influenceCount + influenceIndex];
|
||||
const float weight = sourceSkinWeights[vertexIndex * influenceCount + influenceIndex];
|
||||
|
||||
auto skeletonIndexIt = skinToSkeletonIndexMap.find(jointIndex);
|
||||
if (skeletonIndexIt == skinToSkeletonIndexMap.end())
|
||||
{
|
||||
AZ_Error("ActorClothSkinning", false,
|
||||
"Joint index %d from model asset not found in map to skeleton indices",
|
||||
jointIndex);
|
||||
return false;
|
||||
}
|
||||
|
||||
skinningInfo.m_jointIndices[influenceIndex] = skeletonIndexIt->second;
|
||||
skinningInfo.m_jointWeights[influenceIndex] = weight;
|
||||
}
|
||||
}
|
||||
|
||||
skinningInfo.m_jointWeights[0] += weightError;
|
||||
|
||||
for (; influenceIndex < MaxSkinningBones; ++influenceIndex)
|
||||
{
|
||||
skinningInfo.m_jointIndices[influenceIndex] = 0;
|
||||
skinningInfo.m_jointWeights[influenceIndex] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -269,16 +259,16 @@ namespace NvCloth
|
||||
const AZ::Matrix3x4* skinningMatrices)
|
||||
{
|
||||
AZ::Matrix3x4 clothSkinningMatrix = AZ::Matrix3x4::CreateZero();
|
||||
for (int weightIndex = 0; weightIndex < MaxSkinningBones; ++weightIndex)
|
||||
for (size_t weightIndex = 0; weightIndex < skinningInfo.m_jointWeights.size(); ++weightIndex)
|
||||
{
|
||||
if (skinningInfo.m_jointWeights[weightIndex] == 0)
|
||||
const AZ::u16 jointIndex = skinningInfo.m_jointIndices[weightIndex];
|
||||
const float jointWeight = skinningInfo.m_jointWeights[weightIndex];
|
||||
|
||||
if (AZ::IsClose(jointWeight, 0.0f))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const AZ::u16 jointIndex = skinningInfo.m_jointIndices[weightIndex];
|
||||
const float jointWeight = skinningInfo.m_jointWeights[weightIndex] / 255.0f;
|
||||
|
||||
// Blending matrices the same way done in GPU shaders, by adding each weighted matrix element by element.
|
||||
// This way the skinning results are much similar to the skinning performed in GPU.
|
||||
for (int i = 0; i < 3; ++i)
|
||||
@@ -352,16 +342,16 @@ namespace NvCloth
|
||||
const AZStd::unordered_map<AZ::u16, DualQuat>& skinningDualQuaternions)
|
||||
{
|
||||
DualQuat clothSkinningDualQuaternion(type_zero::ZERO);
|
||||
for (int weightIndex = 0; weightIndex < MaxSkinningBones; ++weightIndex)
|
||||
for (size_t weightIndex = 0; weightIndex < skinningInfo.m_jointWeights.size(); ++weightIndex)
|
||||
{
|
||||
if (skinningInfo.m_jointWeights[weightIndex] == 0)
|
||||
const AZ::u16 jointIndex = skinningInfo.m_jointIndices[weightIndex];
|
||||
const float jointWeight = skinningInfo.m_jointWeights[weightIndex];
|
||||
|
||||
if (AZ::IsClose(jointWeight, 0.0f))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const AZ::u16 jointIndex = skinningInfo.m_jointIndices[weightIndex];
|
||||
const float jointWeight = skinningInfo.m_jointWeights[weightIndex] / 255.0f;
|
||||
|
||||
clothSkinningDualQuaternion += skinningDualQuaternions.at(jointIndex) * jointWeight;
|
||||
}
|
||||
clothSkinningDualQuaternion.Normalize();
|
||||
@@ -371,12 +361,12 @@ namespace NvCloth
|
||||
|
||||
AZStd::unique_ptr<ActorClothSkinning> ActorClothSkinning::Create(
|
||||
AZ::EntityId entityId,
|
||||
const AZStd::string& meshNode,
|
||||
const MeshNodeInfo& meshNodeInfo,
|
||||
const size_t numSimParticles,
|
||||
const AZStd::vector<int>& meshRemappedVertices)
|
||||
{
|
||||
AZStd::vector<SkinningInfo> skinningData;
|
||||
if (!Internal::ObtainSkinningData(entityId, meshNode, numSimParticles, meshRemappedVertices, skinningData))
|
||||
if (!Internal::ObtainSkinningData(entityId, meshNodeInfo, numSimParticles, meshRemappedVertices, skinningData))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
@@ -411,14 +401,17 @@ namespace NvCloth
|
||||
AZStd::set<AZ::u16> jointIndices;
|
||||
for (size_t particleIndex = 0; particleIndex < numSimParticles; ++particleIndex)
|
||||
{
|
||||
for (int weightIndex = 0; weightIndex < MaxSkinningBones; ++weightIndex)
|
||||
const SkinningInfo& skinningInfo = skinningData[particleIndex];
|
||||
for (size_t weightIndex = 0; weightIndex < skinningInfo.m_jointWeights.size(); ++weightIndex)
|
||||
{
|
||||
if (skinningData[particleIndex].m_jointWeights[weightIndex] == 0)
|
||||
const AZ::u16 jointIndex = skinningInfo.m_jointIndices[weightIndex];
|
||||
const float jointWeight = skinningInfo.m_jointWeights[weightIndex];
|
||||
|
||||
if (AZ::IsClose(jointWeight, 0.0f))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const AZ::u16 jointIndex = skinningData[particleIndex].m_jointIndices[weightIndex];
|
||||
jointIndices.insert(jointIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,17 +18,16 @@
|
||||
|
||||
namespace NvCloth
|
||||
{
|
||||
//! Maximum number of bones that can influence a particle.
|
||||
static const int MaxSkinningBones = 4;
|
||||
struct MeshNodeInfo;
|
||||
|
||||
//! Skinning information of a particle.
|
||||
struct SkinningInfo
|
||||
{
|
||||
//! Weights of each joint that influence the particle.
|
||||
AZStd::array<AZ::u8, MaxSkinningBones> m_jointWeights;
|
||||
AZStd::vector<float> m_jointWeights;
|
||||
|
||||
//! List of joints that influence the particle.
|
||||
AZStd::array<AZ::u16, MaxSkinningBones> m_jointIndices;
|
||||
AZStd::vector<AZ::u16> m_jointIndices;
|
||||
};
|
||||
|
||||
//! Class to retrieve skinning information from an actor on the same entity
|
||||
@@ -42,7 +41,7 @@ namespace NvCloth
|
||||
|
||||
static AZStd::unique_ptr<ActorClothSkinning> Create(
|
||||
AZ::EntityId entityId,
|
||||
const AZStd::string& meshNode,
|
||||
const MeshNodeInfo& meshNodeInfo,
|
||||
const size_t numSimParticles,
|
||||
const AZStd::vector<int>& meshRemappedVertices);
|
||||
|
||||
|
||||
@@ -177,7 +177,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_config.m_meshNode, m_cloth->GetParticles().size(), m_meshRemappedVertices);
|
||||
m_actorClothSkinning = ActorClothSkinning::Create(m_entityId, m_meshNodeInfo, m_cloth->GetParticles().size(), m_meshRemappedVertices);
|
||||
m_numberOfClothSkinningUpdates = 0;
|
||||
|
||||
m_clothConstraints = ClothConstraints::Create(
|
||||
|
||||
@@ -126,8 +126,7 @@ namespace UnitTest
|
||||
const AZStd::vector<AZ::Vector3>& vertices,
|
||||
const AZStd::vector<AZ::u32>& indices,
|
||||
const AZStd::vector<VertexSkinInfluences>& skinningInfo,
|
||||
const AZStd::vector<AZ::Vector2>& uvs,
|
||||
const AZStd::vector<AZ::Color>& clothData)
|
||||
const AZStd::vector<AZ::Vector2>& uvs)
|
||||
{
|
||||
// Generate the normals for this mesh
|
||||
AZStd::vector<AZ::Vector4> particles(vertices.size());
|
||||
@@ -142,7 +141,6 @@ namespace UnitTest
|
||||
vertices,
|
||||
normals,
|
||||
uvs,
|
||||
clothData,
|
||||
skinningInfo
|
||||
);
|
||||
}
|
||||
|
||||
@@ -62,6 +62,5 @@ namespace UnitTest
|
||||
const AZStd::vector<AZ::Vector3>& vertices,
|
||||
const AZStd::vector<AZ::u32>& indices,
|
||||
const AZStd::vector<VertexSkinInfluences>& skinningInfo = {},
|
||||
const AZStd::vector<AZ::Vector2>& uvs = {},
|
||||
const AZStd::vector<AZ::Color>& clothData = {});
|
||||
const AZStd::vector<AZ::Vector2>& uvs = {});
|
||||
} // namespace UnitTest
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <AzFramework/Components/TransformComponent.h>
|
||||
|
||||
#include <Components/ClothComponentMesh/ActorClothSkinning.h>
|
||||
#include <Utils/AssetHelper.h>
|
||||
|
||||
#include <UnitTestHelper.h>
|
||||
#include <ActorHelper.h>
|
||||
@@ -52,6 +53,20 @@ namespace UnitTest
|
||||
|
||||
const AZ::u32 LodLevel = 0;
|
||||
|
||||
const NvCloth::MeshNodeInfo MeshNodeInfo = {
|
||||
static_cast<int>(LodLevel),
|
||||
{{
|
||||
// One SubMesh
|
||||
{
|
||||
0, // Primitive index
|
||||
0, // First vertex
|
||||
static_cast<int>(MeshVertices.size()), // Vertex count
|
||||
0, // First index
|
||||
static_cast<int>(MeshIndices.size()) // Index count
|
||||
}
|
||||
}}
|
||||
};
|
||||
|
||||
protected:
|
||||
// ::testing::Test overrides ...
|
||||
void SetUp() override;
|
||||
@@ -83,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);
|
||||
}
|
||||
@@ -92,7 +107,7 @@ namespace UnitTest
|
||||
{
|
||||
AZ::EntityId entityId;
|
||||
AZStd::unique_ptr<NvCloth::ActorClothSkinning> actorClothSkinning =
|
||||
NvCloth::ActorClothSkinning::Create(entityId, MeshNodeName, MeshRemappedVertices.size(), MeshRemappedVertices);
|
||||
NvCloth::ActorClothSkinning::Create(entityId, MeshNodeInfo, MeshRemappedVertices.size(), MeshRemappedVertices);
|
||||
|
||||
EXPECT_TRUE(actorClothSkinning.get() == nullptr);
|
||||
}
|
||||
@@ -107,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);
|
||||
}
|
||||
@@ -124,12 +139,12 @@ namespace UnitTest
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<NvCloth::ActorClothSkinning> actorClothSkinning =
|
||||
NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeName, MeshVertices.size(), MeshRemappedVertices);
|
||||
NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeInfo, MeshVertices.size(), MeshRemappedVertices);
|
||||
|
||||
EXPECT_TRUE(actorClothSkinning.get() == nullptr);
|
||||
}
|
||||
|
||||
TEST_F(NvClothActorClothSkinning, ActorClothSkinning_CreateWithActor_ReturnsValidInstance)
|
||||
TEST_F(NvClothActorClothSkinning, DISABLED_ActorClothSkinning_CreateWithActor_ReturnsValidInstance)
|
||||
{
|
||||
{
|
||||
auto actor = AZStd::make_unique<ActorHelper>("actor_test");
|
||||
@@ -141,12 +156,12 @@ namespace UnitTest
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<NvCloth::ActorClothSkinning> actorClothSkinning =
|
||||
NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeName, MeshVertices.size(), MeshRemappedVertices);
|
||||
NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeInfo, MeshVertices.size(), MeshRemappedVertices);
|
||||
|
||||
EXPECT_TRUE(actorClothSkinning.get() != nullptr);
|
||||
}
|
||||
|
||||
TEST_F(NvClothActorClothSkinning, ActorClothSkinning_UpdateAndApplyLinearSkinning_ModifiesVertices)
|
||||
TEST_F(NvClothActorClothSkinning, DISABLED_ActorClothSkinning_UpdateAndApplyLinearSkinning_ModifiesVertices)
|
||||
{
|
||||
const AZ::Transform meshNodeTransform = AZ::Transform::CreateRotationY(AZ::DegToRad(90.0f));
|
||||
|
||||
@@ -169,7 +184,8 @@ namespace UnitTest
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<NvCloth::ActorClothSkinning> actorClothSkinning =
|
||||
NvCloth::ActorClothSkinning::Create(actorComponent->GetEntityId(), MeshNodeName, MeshVertices.size(), MeshRemappedVertices);
|
||||
NvCloth::ActorClothSkinning::Create(actorComponent->GetEntityId(), MeshNodeInfo, MeshVertices.size(), MeshRemappedVertices);
|
||||
ASSERT_TRUE(actorClothSkinning.get() != nullptr);
|
||||
|
||||
const AZStd::vector<NvCloth::SimParticleFormat> clothParticles = {{
|
||||
NvCloth::SimParticleFormat::CreateFromVector3AndFloat(MeshVertices[0], 1.0f),
|
||||
@@ -204,7 +220,7 @@ namespace UnitTest
|
||||
EXPECT_THAT(newSkinnedClothParticles, ::testing::Pointwise(ContainerIsCloseTolerance(Tolerance), clothParticlesResult));
|
||||
}
|
||||
|
||||
TEST_F(NvClothActorClothSkinning, ActorClothSkinning_UpdateAndApplyDualQuatSkinning_ModifiesVertices)
|
||||
TEST_F(NvClothActorClothSkinning, DISABLED_ActorClothSkinning_UpdateAndApplyDualQuatSkinning_ModifiesVertices)
|
||||
{
|
||||
const AZStd::string rootNodeName = "root_node";
|
||||
const AZStd::string meshNodeName = "cloth_mesh_node";
|
||||
@@ -229,7 +245,8 @@ namespace UnitTest
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<NvCloth::ActorClothSkinning> actorClothSkinning =
|
||||
NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), meshNodeName, MeshVertices.size(), MeshRemappedVertices);
|
||||
NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeInfo, MeshVertices.size(), MeshRemappedVertices);
|
||||
ASSERT_TRUE(actorClothSkinning.get() != nullptr);
|
||||
|
||||
const AZStd::vector<NvCloth::SimParticleFormat> clothParticles = {{
|
||||
NvCloth::SimParticleFormat::CreateFromVector3AndFloat(MeshVertices[0], 1.0f),
|
||||
@@ -265,7 +282,7 @@ namespace UnitTest
|
||||
EXPECT_THAT(newSkinnedClothParticles, ::testing::Pointwise(ContainerIsCloseTolerance(Tolerance), clothParticlesResult));
|
||||
}
|
||||
|
||||
TEST_F(NvClothActorClothSkinning, ActorClothSkinning_UpdateActorVisibility_ReturnsExpectedValues)
|
||||
TEST_F(NvClothActorClothSkinning, DISABLED_ActorClothSkinning_UpdateActorVisibility_ReturnsExpectedValues)
|
||||
{
|
||||
{
|
||||
auto actor = AZStd::make_unique<ActorHelper>("actor_test");
|
||||
@@ -277,7 +294,8 @@ namespace UnitTest
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<NvCloth::ActorClothSkinning> actorClothSkinning =
|
||||
NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeName, MeshVertices.size(), MeshRemappedVertices);
|
||||
NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeInfo, MeshVertices.size(), MeshRemappedVertices);
|
||||
ASSERT_TRUE(actorClothSkinning.get() != nullptr);
|
||||
|
||||
EXPECT_FALSE(actorClothSkinning->IsActorVisible());
|
||||
EXPECT_FALSE(actorClothSkinning->WasActorVisible());
|
||||
|
||||
@@ -178,7 +178,7 @@ namespace UnitTest
|
||||
{
|
||||
auto actor = AZStd::make_unique<ActorHelper>("actor_test");
|
||||
auto meshNodeIndex = actor->AddJoint(MeshNodeName);
|
||||
actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, MeshSkinningInfo, MeshUVs, MeshClothData));
|
||||
actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, MeshSkinningInfo, MeshUVs/*, MeshClothData*/));
|
||||
actor->FinishSetup();
|
||||
|
||||
m_actorComponent->SetActorAsset(CreateAssetFromActor(AZStd::move(actor)));
|
||||
@@ -204,7 +204,7 @@ namespace UnitTest
|
||||
EXPECT_THAT(renderData.m_normals, ::testing::Each(IsCloseTolerance(AZ::Vector3::CreateAxisZ(), Tolerance)));
|
||||
}
|
||||
|
||||
TEST_F(NvClothComponentMesh, ClothComponentMesh_TickClothSystem_RunningSimulationVerticesGoDown)
|
||||
TEST_F(NvClothComponentMesh, DISABLED_ClothComponentMesh_TickClothSystem_RunningSimulationVerticesGoDown)
|
||||
{
|
||||
{
|
||||
const float height = 4.7f;
|
||||
@@ -213,7 +213,7 @@ namespace UnitTest
|
||||
|
||||
auto actor = AZStd::make_unique<ActorHelper>("actor_test");
|
||||
auto meshNodeIndex = actor->AddJoint(MeshNodeName);
|
||||
actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, MeshSkinningInfo, MeshUVs, MeshClothData));
|
||||
actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, MeshSkinningInfo, MeshUVs/*, MeshClothData*/));
|
||||
actor->AddClothCollider(collider);
|
||||
actor->FinishSetup();
|
||||
|
||||
@@ -245,12 +245,12 @@ namespace UnitTest
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NvClothComponentMesh, ClothComponentMesh_UpdateConfigurationInvalidEntity_ReturnEmptyRenderData)
|
||||
TEST_F(NvClothComponentMesh, DISABLED_ClothComponentMesh_UpdateConfigurationInvalidEntity_ReturnEmptyRenderData)
|
||||
{
|
||||
{
|
||||
auto actor = AZStd::make_unique<ActorHelper>("actor_test");
|
||||
auto meshNodeIndex = actor->AddJoint(MeshNodeName);
|
||||
actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, MeshSkinningInfo, MeshUVs, MeshClothData));
|
||||
actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, MeshSkinningInfo, MeshUVs/*, MeshClothData*/));
|
||||
actor->FinishSetup();
|
||||
|
||||
m_actorComponent->SetActorAsset(CreateAssetFromActor(AZStd::move(actor)));
|
||||
@@ -281,7 +281,7 @@ namespace UnitTest
|
||||
{
|
||||
auto actor = AZStd::make_unique<ActorHelper>("actor_test");
|
||||
auto meshNodeIndex = actor->AddJoint(MeshNodeName);
|
||||
actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, MeshSkinningInfo, MeshUVs, MeshClothData));
|
||||
actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, MeshSkinningInfo, MeshUVs/*, MeshClothData*/));
|
||||
actor->FinishSetup();
|
||||
|
||||
m_actorComponent->SetActorAsset(CreateAssetFromActor(AZStd::move(actor)));
|
||||
@@ -306,7 +306,7 @@ namespace UnitTest
|
||||
{
|
||||
auto actor = AZStd::make_unique<ActorHelper>("actor_test2");
|
||||
auto meshNodeIndex = actor->AddJoint(MeshNodeName);
|
||||
actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(newMeshVertices, MeshIndices, MeshSkinningInfo, MeshUVs, MeshClothData));
|
||||
actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(newMeshVertices, MeshIndices, MeshSkinningInfo, MeshUVs/*, MeshClothData*/));
|
||||
actor->FinishSetup();
|
||||
|
||||
newActorComponent->SetActorAsset(CreateAssetFromActor(AZStd::move(actor)));
|
||||
@@ -325,12 +325,12 @@ namespace UnitTest
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NvClothComponentMesh, ClothComponentMesh_UpdateConfigurationInvalidMeshNode_ReturnEmptyRenderData)
|
||||
TEST_F(NvClothComponentMesh, DISABLED_ClothComponentMesh_UpdateConfigurationInvalidMeshNode_ReturnEmptyRenderData)
|
||||
{
|
||||
{
|
||||
auto actor = AZStd::make_unique<ActorHelper>("actor_test");
|
||||
auto meshNodeIndex = actor->AddJoint(MeshNodeName);
|
||||
actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, MeshSkinningInfo, MeshUVs, MeshClothData));
|
||||
actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, MeshSkinningInfo, MeshUVs/*, MeshClothData*/));
|
||||
actor->FinishSetup();
|
||||
|
||||
m_actorComponent->SetActorAsset(CreateAssetFromActor(AZStd::move(actor)));
|
||||
@@ -370,8 +370,8 @@ namespace UnitTest
|
||||
auto actor = AZStd::make_unique<ActorHelper>("actor_test");
|
||||
auto meshNodeIndex = actor->AddJoint(MeshNodeName);
|
||||
auto meshNode2Index = actor->AddJoint(meshNode2Name);
|
||||
actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, MeshSkinningInfo, MeshUVs, MeshClothData));
|
||||
actor->SetMesh(LodLevel, meshNode2Index, CreateEMotionFXMesh(mesh2Vertices, MeshIndices, MeshSkinningInfo, MeshUVs, MeshClothData));
|
||||
actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, MeshSkinningInfo, MeshUVs/*, MeshClothData*/));
|
||||
actor->SetMesh(LodLevel, meshNode2Index, CreateEMotionFXMesh(mesh2Vertices, MeshIndices, MeshSkinningInfo, MeshUVs/*, MeshClothData*/));
|
||||
actor->FinishSetup();
|
||||
|
||||
m_actorComponent->SetActorAsset(CreateAssetFromActor(AZStd::move(actor)));
|
||||
@@ -396,12 +396,12 @@ namespace UnitTest
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NvClothComponentMesh, ClothComponentMesh_UpdateConfigurationInvertingGravity_RunningSimulationVerticesGoUp)
|
||||
TEST_F(NvClothComponentMesh, DISABLED_ClothComponentMesh_UpdateConfigurationInvertingGravity_RunningSimulationVerticesGoUp)
|
||||
{
|
||||
{
|
||||
auto actor = AZStd::make_unique<ActorHelper>("actor_test");
|
||||
auto meshNodeIndex = actor->AddJoint(MeshNodeName);
|
||||
actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, MeshSkinningInfo, MeshUVs, MeshClothData));
|
||||
actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, MeshSkinningInfo, MeshUVs/*, MeshClothData*/));
|
||||
actor->FinishSetup();
|
||||
|
||||
m_actorComponent->SetActorAsset(CreateAssetFromActor(AZStd::move(actor)));
|
||||
@@ -444,7 +444,7 @@ namespace UnitTest
|
||||
{
|
||||
auto actor = AZStd::make_unique<ActorHelper>("actor_test");
|
||||
auto meshNodeIndex = actor->AddJoint(MeshNodeName);
|
||||
actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, MeshSkinningInfo, MeshUVs, MeshClothData));
|
||||
actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, MeshSkinningInfo, MeshUVs/*, MeshClothData*/));
|
||||
actor->FinishSetup();
|
||||
|
||||
m_actorComponent->SetActorAsset(CreateAssetFromActor(AZStd::move(actor)));
|
||||
|
||||
@@ -196,7 +196,7 @@ namespace UnitTest
|
||||
{
|
||||
auto actor = AZStd::make_unique<ActorHelper>("actor_test");
|
||||
auto meshNodeIndex = actor->AddJoint(meshNodeName);
|
||||
actor->SetMesh(lodLevel, meshNodeIndex, CreateEMotionFXMesh(meshVertices, meshIndices, meshSkinningInfo, meshUVs, meshClothData));
|
||||
actor->SetMesh(lodLevel, meshNodeIndex, CreateEMotionFXMesh(meshVertices, meshIndices, meshSkinningInfo, meshUVs/*, meshClothData*/));
|
||||
actor->FinishSetup();
|
||||
|
||||
actorComponent->SetActorAsset(CreateAssetFromActor(AZStd::move(actor)));
|
||||
|
||||
@@ -253,7 +253,7 @@ namespace UnitTest
|
||||
auto actor = AZStd::make_unique<ActorHelper>("actor_test");
|
||||
actor->AddJoint(JointRootName);
|
||||
auto meshNodeIndex = actor->AddJoint(MeshNodeName, AZ::Transform::CreateIdentity(), JointRootName);
|
||||
actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, {}, MeshUVs, MeshClothData));
|
||||
actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, {}, MeshUVs/*, MeshClothData*/));
|
||||
actor->FinishSetup();
|
||||
|
||||
editorActorComponent->SetActorAsset(CreateAssetFromActor(AZStd::move(actor)));
|
||||
@@ -284,7 +284,7 @@ namespace UnitTest
|
||||
auto actor = AZStd::make_unique<ActorHelper>("actor_test");
|
||||
actor->AddJoint(JointRootName);
|
||||
auto meshNodeIndex = actor->AddJoint(MeshNodeName, AZ::Transform::CreateIdentity(), JointRootName);
|
||||
actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, {}, MeshUVs, meshClothDataNoBackstop));
|
||||
actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, {}, MeshUVs/*, meshClothDataNoBackstop*/));
|
||||
actor->FinishSetup();
|
||||
|
||||
editorActorComponent->SetActorAsset(CreateAssetFromActor(AZStd::move(actor)));
|
||||
@@ -310,7 +310,7 @@ namespace UnitTest
|
||||
auto actor = AZStd::make_unique<ActorHelper>("actor_test");
|
||||
actor->AddJoint(JointRootName);
|
||||
auto meshNodeIndex = actor->AddJoint(MeshNodeName, AZ::Transform::CreateIdentity(), JointRootName);
|
||||
actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, {}, MeshUVs, MeshClothData));
|
||||
actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, {}, MeshUVs/*, MeshClothData*/));
|
||||
actor->FinishSetup();
|
||||
|
||||
editorActorComponent->SetActorAsset(CreateAssetFromActor(AZStd::move(actor)));
|
||||
@@ -337,7 +337,7 @@ namespace UnitTest
|
||||
auto actor = AZStd::make_unique<ActorHelper>("actor_test");
|
||||
actor->AddJoint(JointRootName);
|
||||
auto meshNodeIndex = actor->AddJoint(MeshNodeName, AZ::Transform::CreateIdentity(), JointRootName);
|
||||
actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, {}, MeshUVs, MeshClothData));
|
||||
actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, {}, MeshUVs/*, MeshClothData*/));
|
||||
actor->FinishSetup();
|
||||
|
||||
editorActorComponent->SetActorAsset(CreateAssetFromActor(AZStd::move(actor)));
|
||||
|
||||
@@ -172,9 +172,9 @@ namespace UnitTest
|
||||
auto meshNode1Index = actor->AddJoint(MeshNode1Name, AZ::Transform::CreateTranslation(AZ::Vector3(3.0f, -2.0f, 0.0f)), RootNodeName);
|
||||
auto otherNodeIndex = actor->AddJoint(OtherNodeName, AZ::Transform::CreateTranslation(AZ::Vector3(0.5f, 0.0f, 0.0f)), RootNodeName);
|
||||
auto meshNode2Index = actor->AddJoint(MeshNode2Name, AZ::Transform::CreateTranslation(AZ::Vector3(0.2f, 0.6f, 1.0f)), OtherNodeName);
|
||||
actor->SetMesh(LodLevel, meshNode1Index, CreateEMotionFXMesh(MeshVertices, MeshIndices, MeshSkinningInfo, MeshUVs, MeshClothData));
|
||||
actor->SetMesh(LodLevel, meshNode1Index, CreateEMotionFXMesh(MeshVertices, MeshIndices, MeshSkinningInfo, MeshUVs/*, MeshClothData*/));
|
||||
actor->SetMesh(LodLevel, otherNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices));
|
||||
actor->SetMesh(LodLevel, meshNode2Index, CreateEMotionFXMesh(MeshVertices, MeshIndices, MeshSkinningInfo, MeshUVs, MeshClothData));
|
||||
actor->SetMesh(LodLevel, meshNode2Index, CreateEMotionFXMesh(MeshVertices, MeshIndices, MeshSkinningInfo, MeshUVs/*, MeshClothData*/));
|
||||
actor->FinishSetup();
|
||||
|
||||
m_actorComponent->SetActorAsset(CreateAssetFromActor(AZStd::move(actor)));
|
||||
@@ -202,9 +202,9 @@ namespace UnitTest
|
||||
auto meshNode1Index = actor->AddJoint(MeshNode1Name, AZ::Transform::CreateTranslation(AZ::Vector3(3.0f, -2.0f, 0.0f)), RootNodeName);
|
||||
auto otherNodeIndex = actor->AddJoint(OtherNodeName, AZ::Transform::CreateTranslation(AZ::Vector3(0.5f, 0.0f, 0.0f)), RootNodeName);
|
||||
auto meshNode2Index = actor->AddJoint(MeshNode2Name, AZ::Transform::CreateTranslation(AZ::Vector3(0.2f, 0.6f, 1.0f)), OtherNodeName);
|
||||
actor->SetMesh(LodLevel, meshNode1Index, CreateEMotionFXMesh(MeshVertices, MeshIndices, MeshSkinningInfo, MeshUVs, MeshClothData));
|
||||
actor->SetMesh(LodLevel, meshNode1Index, CreateEMotionFXMesh(MeshVertices, MeshIndices, MeshSkinningInfo, MeshUVs/*, MeshClothData*/));
|
||||
actor->SetMesh(LodLevel, otherNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices));
|
||||
actor->SetMesh(LodLevel, meshNode2Index, CreateEMotionFXMesh(MeshVertices, MeshIndices, MeshSkinningInfo, MeshUVs, MeshClothData));
|
||||
actor->SetMesh(LodLevel, meshNode2Index, CreateEMotionFXMesh(MeshVertices, MeshIndices, MeshSkinningInfo, MeshUVs/*, MeshClothData*/));
|
||||
actor->FinishSetup();
|
||||
|
||||
m_actorComponent->SetActorAsset(CreateAssetFromActor(AZStd::move(actor)));
|
||||
|
||||
Reference in New Issue
Block a user