Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp
// make the geometry LOD levels compatible with the skeletal LOD levels
// it remaps skinning influences of vertices that are linked to disabled bones, to other enabled bones
make the geometry LOD levels compatible with the skeletal LOD levels
it remaps skinning influences of vertices that are linked to disabled bones, to other enabled bones
make the geometry LOD levels compatible with the skeletal LOD levels it remaps skinning influences of vertices that are linked to disabled bones to other enabled bones
void Actor::MakeGeomLODsCompatibleWithSkeletalLODs()
    {
        const AZStd::vector<LODLevel>& lodLevels = m_meshLodData.m_lodLevels;
        const size_t numGeomLODs = lodLevels.size();
        for (size_t geomLod = 0; geomLod < numGeomLODs; ++geomLod)
        {
            const size_t numNodes = m_skeleton->GetNumNodes();
            for (size_t n = 0; n < numNodes; ++n)
            {
                Node* node = m_skeleton->GetNode(n);
                Mesh* mesh = GetMesh(static_cast<uint32>(geomLod), n);
                if (mesh == nullptr)
                {
                    continue;
                }
                SkinningInfoVertexAttributeLayer* layer = (SkinningInfoVertexAttributeLayer*)mesh->FindSharedVertexAttributeLayer(SkinningInfoVertexAttributeLayer::TYPE_ID);
                if (layer == nullptr)
                {
                    continue;
                }
                const uint32* orgVertices = (uint32*)mesh->FindOriginalVertexData(Mesh::ATTRIB_ORGVTXNUMBERS);
                const size_t numSubMeshes = mesh->GetNumSubMeshes();
                for (size_t s = 0; s < numSubMeshes; ++s)
                {
                    SubMesh* subMesh = mesh->GetSubMesh(s);
                    const uint32 startVertex = subMesh->GetStartVertex();
                    const uint32 numVertices = subMesh->GetNumVertices();
                    for (uint32 v = 0; v < numVertices; ++v)
                    {
                        const uint32 vertexIndex    = startVertex + v;
                        const uint32 orgVertex      = orgVertices[vertexIndex];
                        const size_t numInfluences = layer->GetNumInfluences(orgVertex);
                        for (size_t i = 0; i < numInfluences; ++i)
                        {
                            SkinInfluence* influence = layer->GetInfluence(orgVertex, i);
                            if (m_skeleton->GetNode(influence->GetNodeNr())->GetSkeletalLODStatus(static_cast<uint32>(geomLod)) == false)
                            {
                                const size_t newNodeIndex = FindFirstActiveParentBone(geomLod, influence->GetNodeNr());
                                if (newNodeIndex == InvalidIndex)
                                {
                                    MCore::LogWarning("EMotionFX::Actor::MakeGeomLODsCompatibleWithSkeletalLODs() - Failed to find an enabled parent for node '%s' in skeletal LOD %d of actor '%s' (0x%x)", node->GetName(), geomLod, GetFileName(), this);
                                    continue;
                                }
                                influence->SetNodeNr(static_cast<uint16>(newNodeIndex));
                            }
                        } 
                        for (uint32 x = 0; x < numVertices; ++x)
                        {
                            layer->CollapseInfluences(orgVertices[startVertex + x]);
                        }
                    } 
                    subMesh->ReinitBonesArray(layer);
                } 
                MeshDeformerStack* stack = GetMeshDeformerStack(static_cast<uint32>(geomLod), node->GetNodeIndex());
                if (stack)
                {
                    stack->ReinitializeDeformers(this, node, static_cast<uint32>(geomLod));
                }
            } 
        }
    }
void Actor :: MakeGeomLODsCompatibleWithSkeletalLODs ( ) { const AZStd :: vector < LODLevel > & lodLevels = m_meshLodData . m_lodLevels ; const size_t numGeomLODs = lodLevels . size ( ) ; for ( size_t geomLod = 0 ; geomLod < numGeomLODs ; ++ geomLod ) { const size_t numNodes = m_skeleton -> GetNumNodes ( ) ; for ( size_t n = 0 ; n < numNodes ; ++ n ) { Node * node = m_skeleton -> GetNode ( n ) ; Mesh * mesh = GetMesh ( static_cast < uint32 > ( geomLod ) , n ) ; if ( mesh == nullptr ) { continue ; } SkinningInfoVertexAttributeLayer * layer = ( SkinningInfoVertexAttributeLayer * ) mesh -> FindSharedVertexAttributeLayer ( SkinningInfoVertexAttributeLayer :: TYPE_ID ) ; if ( layer == nullptr ) { continue ; } const uint32 * orgVertices = ( uint32 * ) mesh -> FindOriginalVertexData ( Mesh :: ATTRIB_ORGVTXNUMBERS ) ; const size_t numSubMeshes = mesh -> GetNumSubMeshes ( ) ; for ( size_t s = 0 ; s < numSubMeshes ; ++ s ) { SubMesh * subMesh = mesh -> GetSubMesh ( s ) ; const uint32 startVertex = subMesh -> GetStartVertex ( ) ; const uint32 numVertices = subMesh -> GetNumVertices ( ) ; for ( uint32 v = 0 ; v < numVertices ; ++ v ) { const uint32 vertexIndex = startVertex + v ; const uint32 orgVertex = orgVertices [ vertexIndex ] ; const size_t numInfluences = layer -> GetNumInfluences ( orgVertex ) ; for ( size_t i = 0 ; i < numInfluences ; ++ i ) { SkinInfluence * influence = layer -> GetInfluence ( orgVertex , i ) ; if ( m_skeleton -> GetNode ( influence -> GetNodeNr ( ) ) -> GetSkeletalLODStatus ( static_cast < uint32 > ( geomLod ) ) == false ) { const size_t newNodeIndex = FindFirstActiveParentBone ( geomLod , influence -> GetNodeNr ( ) ) ; if ( newNodeIndex == InvalidIndex ) { MCore :: LogWarning ( " " , node -> GetName ( ) , geomLod , GetFileName ( ) , this ) ; continue ; } influence -> SetNodeNr ( static_cast < uint16 > ( newNodeIndex ) ) ; } } for ( uint32 x = 0 ; x < numVertices ; ++ x ) { layer -> CollapseInfluences ( orgVertices [ startVertex + x ] ) ; } } subMesh -> ReinitBonesArray ( layer ) ; } MeshDeformerStack * stack = GetMeshDeformerStack ( static_cast < uint32 > ( geomLod ) , node -> GetNodeIndex ( ) ) ; if ( stack ) { stack -> ReinitializeDeformers ( this , node , static_cast < uint32 > ( geomLod ) ) ; } } } }
make the geometry LOD levels compatible with the skeletal LOD levels
it remaps skinning influences of vertices that are linked to disabled bones, to other enabled bones
make the geometry LOD levels compatible with the skeletal LOD levels it remaps skinning influences of vertices that are linked to disabled bones to other enabled bones
// for all geometry lod levels // for all nodes // check if this node has a mesh, if not we can skip it // check if the mesh is skinned, if not, we don't need to do anything // get shortcuts to the original vertex numbers // for all submeshes // for all vertices in the submesh // for all skinning influences of the vertex // if the bone is disabled // find the first parent bone that is enabled in this LOD // set the new node index // for all influences // optimize the influences // if they all use the same bone, just make one influence of it with weight 1.0 // for all verts // clear the bones array // for all submeshes // reinit the mesh deformer stacks // for all nodes