diff --git a/Source/Engine/ContentImporters/ImportModel.cpp b/Source/Engine/ContentImporters/ImportModel.cpp index be71236ab..a007a740d 100644 --- a/Source/Engine/ContentImporters/ImportModel.cpp +++ b/Source/Engine/ContentImporters/ImportModel.cpp @@ -19,6 +19,7 @@ #include "Engine/Animations/AnimEvent.h" #include "Engine/Level/Actors/EmptyActor.h" #include "Engine/Level/Actors/StaticModel.h" +#include "Engine/Level/Actors/AnimatedModel.h" #include "Engine/Level/Prefabs/Prefab.h" #include "Engine/Level/Prefabs/PrefabManager.h" #include "Engine/Level/Scripts/ModelPrefab.h" @@ -84,6 +85,7 @@ struct PrefabObject int32 NodeIndex; String Name; String AssetPath; + bool IsSkinned = false; }; void RepackMeshLightmapUVs(ModelData& data) @@ -320,8 +322,10 @@ 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++) { @@ -331,7 +335,17 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context) prefabObject.NodeIndex = group.First()->NodeIndex; prefabObject.Name = group.First()->Name; + // Defaul value for ModelType splitOptions.Type = ModelTool::ModelType::Model; + + // Search for Skinned Model + if (group.First()->BlendShapes.HasItems()) + { + LOG(Info, "Mesh {0} is Skinned", prefabObject.Name); + splitOptions.Type = ModelTool::ModelType::SkinnedModel; + prefabObject.IsSkinned = true; + } + splitOptions.ObjectIndex = groupIndex; if (!splitImport(splitOptions, group.GetKey(), prefabObject.AssetPath, group.First())) { @@ -594,8 +608,8 @@ CreateAssetResult ImportModel::Create(CreateAssetContext& context) CreateAssetResult ImportModel::CreateModel(CreateAssetContext& context, const ModelData& modelData, const Options* options) { PROFILE_CPU(); - IMPORT_SETUP(Model, Model::SerializedVersion); - static_assert(Model::SerializedVersion == 30, "Update code."); + IMPORT_SETUP(Model, Model::SerializedVersion); + static_assert(Model::SerializedVersion == 30, "Update code."); // Save model header MemoryWriteStream stream(4096); @@ -722,22 +736,30 @@ CreateAssetResult ImportModel::CreatePrefab(CreateAssetContext& context, const M { if (e.NodeIndex == nodeIndex) { - auto* actor = New(); - actor->SetName(e.Name); - if (auto* model = Content::LoadAsync(e.AssetPath)) + if(e.IsSkinned) { - actor->Model = model; + LOG(Info,"Model {0} is Animated", 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); } - nodeActors.Add(actor); } } Actor* nodeActor = nodeActors.Count() == 1 ? nodeActors[0] : New(); if (nodeActors.Count() > 1) { for (Actor* e : nodeActors) - { e->SetParent(nodeActor); - } } if (nodeActors.Count() != 1) { diff --git a/Source/Engine/Tools/ModelTool/ModelTool.cpp b/Source/Engine/Tools/ModelTool/ModelTool.cpp index fe268c350..cc483f333 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.cpp @@ -1131,7 +1131,7 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option options.ImportTypes |= ImportDataTypes::Skeleton; break; case ModelType::Prefab: - options.ImportTypes = ImportDataTypes::Geometry | ImportDataTypes::Nodes | ImportDataTypes::Animations; + options.ImportTypes = ImportDataTypes::Geometry | ImportDataTypes::Nodes | ImportDataTypes::Skeleton | ImportDataTypes::Animations; if (options.ImportMaterials) options.ImportTypes |= ImportDataTypes::Materials; if (options.ImportTextures) @@ -1157,6 +1157,9 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option { for (auto& mesh : lod.Meshes) { + if (mesh->BlendShapes.IsEmpty()) + continue; + for (int32 blendShapeIndex = mesh->BlendShapes.Count() - 1; blendShapeIndex >= 0; blendShapeIndex--) { auto& blendShape = mesh->BlendShapes[blendShapeIndex]; @@ -2111,12 +2114,13 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option #undef REMAP_VERTEX_BUFFER // Remap blend shapes - dstMesh->BlendShapes.Resize(srcMesh->BlendShapes.Count()); + dstMesh->BlendShapes.Clear(); + dstMesh->BlendShapes.EnsureCapacity(srcMesh->BlendShapes.Count(), false); for (int32 blendShapeIndex = 0; blendShapeIndex < srcMesh->BlendShapes.Count(); blendShapeIndex++) { const auto& srcBlendShape = srcMesh->BlendShapes[blendShapeIndex]; - auto& dstBlendShape = dstMesh->BlendShapes[blendShapeIndex]; - + //auto& dstBlendShape = dstMesh->BlendShapes[blendShapeIndex]; + BlendShape dstBlendShape; dstBlendShape.Name = srcBlendShape.Name; dstBlendShape.Weight = srcBlendShape.Weight; dstBlendShape.Vertices.EnsureCapacity(srcBlendShape.Vertices.Count()); @@ -2125,19 +2129,21 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option auto v = srcBlendShape.Vertices[i]; v.VertexIndex = remap[v.VertexIndex]; if (v.VertexIndex != ~0u) - { dstBlendShape.Vertices.Add(v); - } } + + if (dstBlendShape.Vertices.HasItems()) + dstMesh->BlendShapes.Add(dstBlendShape); } + /* // Remove empty blend shapes for (int32 blendShapeIndex = dstMesh->BlendShapes.Count() - 1; blendShapeIndex >= 0; blendShapeIndex--) { if (dstMesh->BlendShapes[blendShapeIndex].Vertices.IsEmpty()) dstMesh->BlendShapes.RemoveAt(blendShapeIndex); } - + */ // Optimize generated LOD meshopt_optimizeVertexCache(dstMesh->Indices.Get(), dstMesh->Indices.Get(), dstMeshIndexCount, dstMeshVertexCount); meshopt_optimizeOverdraw(dstMesh->Indices.Get(), dstMesh->Indices.Get(), dstMeshIndexCount, (const float*)dstMesh->Positions.Get(), dstMeshVertexCount, sizeof(Float3), 1.05f); @@ -2182,6 +2188,9 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option { for (auto& mesh : lod.Meshes) { + if (mesh->BlendShapes.IsEmpty()) + continue; + for (auto& blendShape : mesh->BlendShapes) { // Compute min/max for used vertex indices