diff --git a/dev/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Motion/MotionDataBuilder.cpp b/dev/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Motion/MotionDataBuilder.cpp index a3ff0cd2c4..14afd0e94b 100644 --- a/dev/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Motion/MotionDataBuilder.cpp +++ b/dev/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Motion/MotionDataBuilder.cpp @@ -41,7 +41,7 @@ namespace { - const float kDefaultMaxTranslationError = 0.000025f; + const float kDefaultMaxTranslationError = 0.00025f; const float kDefaultMaxRotationError = 0.000025f; const float kDefaultMaxScaleError = 0.0001f; } diff --git a/dev/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.cpp b/dev/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.cpp index 9599e9b933..79c7dde094 100644 --- a/dev/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.cpp +++ b/dev/Gems/EMotionFX/Code/EMotionFX/Source/Importer/Importer.cpp @@ -634,6 +634,7 @@ namespace EMotionFX // get rid of shared data ResetSharedData(sharedData); sharedData.Clear(); + sharedData.Shrink(); return motion; } diff --git a/dev/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.cpp b/dev/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.cpp index cccc4aabda..66b1be0251 100644 --- a/dev/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.cpp +++ b/dev/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.cpp @@ -220,7 +220,7 @@ namespace EMotionFX //mPool->mFreeList.Reserve( numInstances * 2 ); if (mPool->mFreeList.GetMaxLength() < mPool->mNumInstances) { - mPool->mFreeList.Reserve(mPool->mNumInstances); + mPool->mFreeList.Reserve(mPool->mNumInstances + mPool->mFreeList.GetMaxLength() / 2); } mPool->mFreeList.ResizeFast(startIndex + numInstances); diff --git a/dev/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.cpp b/dev/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.cpp index 96638d636a..7f7d390b0c 100644 --- a/dev/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.cpp +++ b/dev/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.cpp @@ -69,6 +69,7 @@ namespace EMotionFX RenderBackend* renderBackend = AZ::Interface::Get()->GetRenderBackend(); assetData->m_renderActor.reset(renderBackend->CreateActor(assetData)); + assetData->ReleaseEmotionFXData(); return static_cast(assetData->m_emfxActor); } diff --git a/dev/Gems/EMotionFX/Code/Source/Integration/Assets/AnimGraphAsset.cpp b/dev/Gems/EMotionFX/Code/Source/Integration/Assets/AnimGraphAsset.cpp index 2a8ad69db0..5d144943e0 100644 --- a/dev/Gems/EMotionFX/Code/Source/Integration/Assets/AnimGraphAsset.cpp +++ b/dev/Gems/EMotionFX/Code/Source/Integration/Assets/AnimGraphAsset.cpp @@ -90,6 +90,7 @@ namespace EMotionFX } } + assetData->ReleaseEmotionFXData(); AZ_Error("EMotionFX", assetData->m_emfxAnimGraph, "Failed to initialize anim graph asset %s", asset.GetHint().c_str()); return static_cast(assetData->m_emfxAnimGraph); } diff --git a/dev/Gems/EMotionFX/Code/Source/Integration/Assets/AssetCommon.h b/dev/Gems/EMotionFX/Code/Source/Integration/Assets/AssetCommon.h index 865b802f34..c9a57c69c2 100644 --- a/dev/Gems/EMotionFX/Code/Source/Integration/Assets/AssetCommon.h +++ b/dev/Gems/EMotionFX/Code/Source/Integration/Assets/AssetCommon.h @@ -32,6 +32,12 @@ namespace EMotionFX AZ_RTTI(EMotionFXAsset, "{043F606A-A483-4910-8110-D8BC4B78922C}", AZ::Data::AssetData) AZ_CLASS_ALLOCATOR(EMotionFXAsset, EMotionFXAllocator, 0) + void ReleaseEmotionFXData() + { + m_emfxNativeData.clear(); + m_emfxNativeData.shrink_to_fit(); + } + AZStd::vector m_emfxNativeData; }; diff --git a/dev/Gems/EMotionFX/Code/Source/Integration/Assets/MotionAsset.cpp b/dev/Gems/EMotionFX/Code/Source/Integration/Assets/MotionAsset.cpp index ecdeb835a5..95b0e28802 100644 --- a/dev/Gems/EMotionFX/Code/Source/Integration/Assets/MotionAsset.cpp +++ b/dev/Gems/EMotionFX/Code/Source/Integration/Assets/MotionAsset.cpp @@ -48,6 +48,7 @@ namespace EMotionFX assetData->m_emfxMotion->SetIsOwnedByRuntime(true); } + assetData->ReleaseEmotionFXData(); AZ_Error("EMotionFX", assetData->m_emfxMotion, "Failed to initialize motion asset %s", asset.GetHint().c_str()); return (assetData->m_emfxMotion); } diff --git a/dev/Gems/EMotionFX/Code/Source/Integration/Assets/MotionSetAsset.cpp b/dev/Gems/EMotionFX/Code/Source/Integration/Assets/MotionSetAsset.cpp index 1c9d41f102..c523b99ce5 100644 --- a/dev/Gems/EMotionFX/Code/Source/Integration/Assets/MotionSetAsset.cpp +++ b/dev/Gems/EMotionFX/Code/Source/Integration/Assets/MotionSetAsset.cpp @@ -234,6 +234,7 @@ namespace EMotionFX // Set motion set's motion load callback, so if EMotion FX queries back for a motion, // we can pull the one managed through an AZ::Asset. assetData->m_emfxMotionSet->SetCallback(aznew CustomMotionSetCallback(asset)); + assetData->ReleaseEmotionFXData(); return true; } diff --git a/dev/Gems/EMotionFX/Code/Source/Integration/Rendering/Cry/CryRenderActor.cpp b/dev/Gems/EMotionFX/Code/Source/Integration/Rendering/Cry/CryRenderActor.cpp index f76715f562..155d468c85 100644 --- a/dev/Gems/EMotionFX/Code/Source/Integration/Rendering/Cry/CryRenderActor.cpp +++ b/dev/Gems/EMotionFX/Code/Source/Integration/Rendering/Cry/CryRenderActor.cpp @@ -475,6 +475,53 @@ namespace EMotionFX // It's now safe to use this LOD. lod.m_isReady = true; } + + //Cry rendering does skinning on the GPU, the goal is to remove all GPU deformed meshes and unused morph targets. + //We have to do it after the vertex buffers get created for the GPU, for CryRenderActor that is after the Finalize() + const uint32 numNodes = actor->GetNumNodes(); + EMotionFX::Skeleton* skeleton = actor->GetSkeleton(); + if (skeleton == nullptr) + { + AZ_Error("EMotionFX", false, "Skeleton couln't be null here! Will return"); + return; + } + + // iterate through all geometry LOD levels + for (uint32 lodLevel = 0; lodLevel < numLODs; ++lodLevel) + { + // iterate through all nodes + for (uint32 n = 0; n < numNodes; ++n) + { + // get the current node + EMotionFX::Node* node = skeleton->GetNode(n); + if (node == nullptr) + { + continue; + } + + // get the mesh for the node, if there is any + EMotionFX::Mesh* mesh = actor->GetMesh(lodLevel, n); + if (mesh == nullptr) + { + continue; + } + + // skip collision meshes + if (mesh->GetIsCollisionMesh()) + { + continue; + } + + // classify the mesh type + EMotionFX::Mesh::EMeshType meshType = mesh->ClassifyMeshType(lodLevel, actor, node->GetNodeIndex(), false, 4, 200); + + // remove the meshes + if (meshType != EMotionFX::Mesh::MESHTYPE_CPU_DEFORMED) + { + actor->RemoveNodeMeshForLOD(lodLevel, n); + } // if mesh is cpu deformed + } + } } } // namespace Integration } // namespace EMotionFX