/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include namespace AZ { namespace SceneAPI { namespace FbxSceneBuilder { const AZStd::string AssImpSkinWeightsImporter::s_skinWeightName = "SkinWeight_"; AssImpSkinWeightsImporter::AssImpSkinWeightsImporter() { BindToCall(&AssImpSkinWeightsImporter::ImportSkinWeights); BindToCall(&AssImpSkinWeightsImporter::SetupNamedBoneLinks); } void AssImpSkinWeightsImporter::Reflect(ReflectContext* context) { SerializeContext* serializeContext = azrtti_cast(context); if (serializeContext) { serializeContext->Class()->Version(3); // LYN-2576 } } Events::ProcessingResult AssImpSkinWeightsImporter::ImportSkinWeights(AssImpSceneNodeAppendedContext& context) { AZ_TraceContext("Importer", "Skin Weights"); aiNode* currentNode = context.m_sourceNode.GetAssImpNode(); const aiScene* scene = context.m_sourceScene.GetAssImpScene(); if(currentNode->mNumMeshes <= 0) { return Events::ProcessingResult::Ignored; } GetMeshDataFromParentResult meshDataResult(GetMeshDataFromParent(context)); if (!meshDataResult.IsSuccess()) { return meshDataResult.GetError(); } const SceneData::GraphData::MeshData* const parentMeshData(meshDataResult.GetValue()); int parentMeshIndex = parentMeshData->GetSdkMeshIndex(); Events::ProcessingResultCombiner combinedSkinWeightsResult; for(unsigned nodeMeshIndex = 0; nodeMeshIndex < currentNode->mNumMeshes; ++nodeMeshIndex) { if (nodeMeshIndex != parentMeshIndex) { // Only generate skinning data for the parent mesh. // Each AssImp mesh is assigned to a unique node, // so the skinning data should be generated as a child node // for the associated parent mesh. continue; } int sceneMeshIndex = currentNode->mMeshes[nodeMeshIndex]; const aiMesh* mesh = scene->mMeshes[sceneMeshIndex]; // Don't create this until a bone with weights is encountered Containers::SceneGraph::NodeIndex weightsIndexForMesh; AZStd::string skinWeightName; AZStd::shared_ptr skinWeightData; for(unsigned b = 0; b < mesh->mNumBones; ++b) { const aiBone* bone = mesh->mBones[b]; if(bone->mNumWeights <= 0) { continue; } if (!weightsIndexForMesh.IsValid()) { skinWeightName = s_skinWeightName; skinWeightName += AZStd::to_string(nodeMeshIndex); RenamedNodesMap::SanitizeNodeName(skinWeightName, context.m_scene.GetGraph(), context.m_currentGraphPosition); weightsIndexForMesh = context.m_scene.GetGraph().AddChild(context.m_currentGraphPosition, skinWeightName.c_str()); AZ_Error("SkinWeightsImporter", weightsIndexForMesh.IsValid(), "Failed to create SceneGraph node for attribute."); if (!weightsIndexForMesh.IsValid()) { combinedSkinWeightsResult += Events::ProcessingResult::Failure; continue; } skinWeightData = AZStd::make_shared(); } Pending pending; pending.m_bone = bone; pending.m_numVertices = mesh->mNumVertices; pending.m_skinWeightData = skinWeightData; m_pendingSkinWeights.push_back(pending); } Events::ProcessingResult skinWeightsResult; AssImpSceneAttributeDataPopulatedContext dataPopulated(context, skinWeightData, weightsIndexForMesh, skinWeightName); skinWeightsResult = Events::Process(dataPopulated); if (skinWeightsResult != Events::ProcessingResult::Failure) { skinWeightsResult = AddAttributeDataNodeWithContexts(dataPopulated); } combinedSkinWeightsResult += skinWeightsResult; } return combinedSkinWeightsResult.GetResult(); } Events::ProcessingResult AssImpSkinWeightsImporter::SetupNamedBoneLinks(AssImpFinalizeSceneContext& /*context*/) { AZ_TraceContext("Importer", "Skin Weights"); for (auto& it : m_pendingSkinWeights) { it.m_skinWeightData->ResizeContainerSpace(it.m_numVertices); AZStd::string boneName = it.m_bone->mName.C_Str(); int boneId = it.m_skinWeightData->GetBoneId(boneName); for(unsigned weight = 0; weight < it.m_bone->mNumWeights; ++weight) { DataTypes::ISkinWeightData::Link link; link.boneId = boneId; link.weight = it.m_bone->mWeights[weight].mWeight; it.m_skinWeightData->AddAndSortLink(it.m_bone->mWeights[weight].mVertexId, link); } } const auto result = m_pendingSkinWeights.empty() ? Events::ProcessingResult::Ignored : Events::ProcessingResult::Success; m_pendingSkinWeights.clear(); return result; } } // namespace FbxSceneBuilder } // namespace SceneAPI } // namespace AZ