diff --git a/Source/Engine/ContentImporters/ImportModel.cpp b/Source/Engine/ContentImporters/ImportModel.cpp index 5448fe8fb..b2a9434c9 100644 --- a/Source/Engine/ContentImporters/ImportModel.cpp +++ b/Source/Engine/ContentImporters/ImportModel.cpp @@ -83,10 +83,14 @@ bool ImportModel::TryGetImportOptions(const StringView& path, Options& options) struct PrefabObject { + enum + { + Model, + SkinnedModel, + } Type; int32 NodeIndex; String Name; String AssetPath; - bool IsSkinned = false; }; void RepackMeshLightmapUVs(ModelData& data) @@ -282,7 +286,7 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context) options.SplitObjects = false; options.ObjectIndex = -1; - // Import all of the objects recursive but use current model data to skip loading file again + // Import all the objects recursive but use current model data to skip loading file again options.Cached = &cached; HashSet objectNames; Function splitImport = [&context, &autoImportOutput, &objectNames](Options& splitOptions, const StringView& objectName, String& outputPath, MeshData* meshData) @@ -329,32 +333,32 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context) return AssetsImportingManager::Import(context.InputPath, outputPath, &splitOptions); }; - auto splitOptions = options; LOG(Info, "Splitting imported {0} meshes", meshesByName.Count()); - PrefabObject prefabObject; for (int32 groupIndex = 0; groupIndex < meshesByName.Count(); groupIndex++) { auto& group = meshesByName[groupIndex]; // Cache object options (nested sub-object import removes the meshes) - prefabObject.NodeIndex = group.First()->NodeIndex; - prefabObject.Name = group.First()->Name; + MeshData* firstMesh = group.First(); + prefabObject.NodeIndex = firstMesh->NodeIndex; + prefabObject.Name = firstMesh->Name; - // Defaul value for ModelType - splitOptions.Type = ModelTool::ModelType::Model; - - // Search for Skinned Model - if (group.First()->BlendWeights.HasItems() || group.First()->BlendShapes.HasItems() ) + // Detect model type + if ((firstMesh->BlendIndices.HasItems() && firstMesh->BlendWeights.HasItems()) || firstMesh->BlendShapes.HasItems()) { - LOG(Info, "Mesh {0} is Skinned", prefabObject.Name); splitOptions.Type = ModelTool::ModelType::SkinnedModel; - prefabObject.IsSkinned = true; + prefabObject.Type = PrefabObject::SkinnedModel; + } + else + { + splitOptions.Type = ModelTool::ModelType::Model; + prefabObject.Type = PrefabObject::Model; } splitOptions.ObjectIndex = groupIndex; - if (!splitImport(splitOptions, group.GetKey(), prefabObject.AssetPath, group.First())) + if (!splitImport(splitOptions, group.GetKey(), prefabObject.AssetPath, firstMesh)) { prefabObjects.Add(prefabObject); } @@ -748,26 +752,32 @@ CreateAssetResult ImportModel::CreatePrefab(CreateAssetContext& context, const M nodeActors.Clear(); for (const PrefabObject& e : prefabObjects) { - if (e.NodeIndex == nodeIndex) + if (e.NodeIndex != nodeIndex) + continue; + Actor* a = nullptr; + switch (e.Type) { - if(e.IsSkinned) - { - LOG(Info,"Creating animated model prefab {0}.", e.Name); - auto* actor = New(); - actor->SetName(e.Name); - if (auto* skinnedModel = Content::LoadAsync(e.AssetPath)) - actor->SkinnedModel = skinnedModel; - nodeActors.Add(actor); - } - else - { - auto* actor = New(); - actor->SetName(e.Name); - if (auto* model = Content::LoadAsync(e.AssetPath)) - actor->Model = model; - nodeActors.Add(actor); - } + case PrefabObject::Model: + { + auto* actor = New(); + if (auto* model = Content::LoadAsync(e.AssetPath)) + actor->Model = model; + a = actor; + break; } + case PrefabObject::SkinnedModel: + { + auto* actor = New(); + if (auto* skinnedModel = Content::LoadAsync(e.AssetPath)) + actor->SkinnedModel = skinnedModel; + a = actor; + break; + } + default: + continue; + } + a->SetName(e.Name); + nodeActors.Add(a); } Actor* nodeActor = nodeActors.Count() == 1 ? nodeActors[0] : New(); if (nodeActors.Count() > 1) diff --git a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp index b93220de4..b1340bfa7 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp @@ -786,7 +786,7 @@ bool ModelTool::ImportDataAssimp(const String& path, ModelData& data, Options& o } // Import skeleton - if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Skeleton) && context.Bones.HasItems()) + if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Skeleton)) { data.Skeleton.Nodes.Resize(context.Nodes.Count(), false); for (int32 i = 0; i < context.Nodes.Count(); i++) diff --git a/Source/Engine/Tools/ModelTool/ModelTool.OpenFBX.cpp b/Source/Engine/Tools/ModelTool/ModelTool.OpenFBX.cpp index e530e7b7c..81ce46d6c 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.OpenFBX.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.OpenFBX.cpp @@ -1404,7 +1404,7 @@ bool ModelTool::ImportDataOpenFBX(const String& path, ModelData& data, Options& } // Import skeleton - if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Skeleton) && context.Bones.HasItems()) + if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Skeleton)) { data.Skeleton.Nodes.Resize(context.Nodes.Count(), false); for (int32 i = 0; i < context.Nodes.Count(); i++) diff --git a/Source/Engine/Tools/ModelTool/ModelTool.cpp b/Source/Engine/Tools/ModelTool/ModelTool.cpp index e15c45c5e..48322687c 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.cpp @@ -1012,12 +1012,6 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option options.ImportTypes |= ImportDataTypes::Textures; break; case ModelType::SkinnedModel: - if (!data.Skeleton.Bones.HasItems()) - { - LOG(Warning, "Model is not Skinned, it will be imported as Static"); - options.ImportTypes = ImportDataTypes::Geometry | ImportDataTypes::Nodes; - options.Type = ModelType::Model; - } options.ImportTypes = ImportDataTypes::Geometry | ImportDataTypes::Nodes | ImportDataTypes::Skeleton; if (options.ImportMaterials) options.ImportTypes |= ImportDataTypes::Materials; @@ -1058,7 +1052,6 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option { if (mesh->BlendShapes.IsEmpty()) continue; - for (int32 blendShapeIndex = mesh->BlendShapes.Count() - 1; blendShapeIndex >= 0; blendShapeIndex--) { auto& blendShape = mesh->BlendShapes[blendShapeIndex]; @@ -1083,8 +1076,7 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option } } } - if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Skeleton) - && (data.Skeleton.Bones.HasItems() || data.LODs[0].Meshes[0]->BlendShapes.HasItems())) + if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Skeleton)) { LOG(Info, "Imported skeleton has {0} bones and {1} nodes", data.Skeleton.Bones.Count(), data.Nodes.Count()); @@ -1224,7 +1216,9 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option for (int32 i = 0; i < meshesCount; i++) { const auto mesh = data.LODs[0].Meshes[i]; - if ((mesh->BlendIndices.IsEmpty() || mesh->BlendWeights.IsEmpty()) && data.Skeleton.Bones.HasItems()) + + // If imported mesh has skeleton but no indices or weights then need to setup those (except in Prefab mode when we conditionally import meshes based on type) + if ((mesh->BlendIndices.IsEmpty() || mesh->BlendWeights.IsEmpty()) && data.Skeleton.Bones.HasItems() && (options.Type != ModelType::Prefab)) { auto indices = Int4::Zero; auto weights = Float4::UnitX; @@ -2101,7 +2095,6 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option { if (mesh->BlendShapes.IsEmpty()) continue; - for (auto& blendShape : mesh->BlendShapes) { // Compute min/max for used vertex indices