Replace ImportedModelData with ModelData for model importing

This commit is contained in:
Wojtek Figat
2023-11-30 11:46:07 +01:00
parent c5df7ad689
commit 6e92d3103c
5 changed files with 87 additions and 174 deletions

View File

@@ -366,12 +366,32 @@ struct FLAXENGINE_API MaterialSlotEntry
bool UsesProperties() const; bool UsesProperties() const;
}; };
/// <summary>
/// Data container for model hierarchy node.
/// </summary>
struct FLAXENGINE_API ModelDataNode
{
/// <summary>
/// The parent node index. The root node uses value -1.
/// </summary>
int32 ParentIndex;
/// <summary>
/// The local transformation of the node, relative to the parent node.
/// </summary>
Transform LocalTransform;
/// <summary>
/// The name of this node.
/// </summary>
String Name;
};
/// <summary> /// <summary>
/// Data container for LOD metadata and sub meshes. /// Data container for LOD metadata and sub meshes.
/// </summary> /// </summary>
class FLAXENGINE_API ModelLodData struct FLAXENGINE_API ModelLodData
{ {
public:
/// <summary> /// <summary>
/// The screen size to switch LODs. Bottom limit of the model screen size to render this LOD. /// The screen size to switch LODs. Bottom limit of the model screen size to render this LOD.
/// </summary> /// </summary>
@@ -382,14 +402,6 @@ public:
/// </summary> /// </summary>
Array<MeshData*> Meshes; Array<MeshData*> Meshes;
public:
/// <summary>
/// Initializes a new instance of the <see cref="ModelLodData"/> class.
/// </summary>
ModelLodData()
{
}
/// <summary> /// <summary>
/// Finalizes an instance of the <see cref="ModelLodData"/> class. /// Finalizes an instance of the <see cref="ModelLodData"/> class.
/// </summary> /// </summary>
@@ -426,7 +438,7 @@ public:
Array<MaterialSlotEntry> Materials; Array<MaterialSlotEntry> Materials;
/// <summary> /// <summary>
/// Array with all LODs. The first element is the top most LOD0 followed by the LOD1, LOD2, etc. /// Array with all Level Of Details that contain meshes. The first element is the top most LOD0 followed by the LOD1, LOD2, etc.
/// </summary> /// </summary>
Array<ModelLodData> LODs; Array<ModelLodData> LODs;
@@ -435,6 +447,11 @@ public:
/// </summary> /// </summary>
SkeletonData Skeleton; SkeletonData Skeleton;
/// <summary>
/// The scene nodes (in hierarchy).
/// </summary>
Array<ModelDataNode> Nodes;
/// <summary> /// <summary>
/// The node animations. /// The node animations.
/// </summary> /// </summary>

View File

@@ -238,7 +238,7 @@ void ProcessNodes(AssimpImporterData& data, aiNode* aNode, int32 parentIndex)
} }
} }
bool ProcessMesh(ImportedModelData& result, AssimpImporterData& data, const aiMesh* aMesh, MeshData& mesh, String& errorMsg) bool ProcessMesh(ModelData& result, AssimpImporterData& data, const aiMesh* aMesh, MeshData& mesh, String& errorMsg)
{ {
// Properties // Properties
mesh.Name = aMesh->mName.C_Str(); mesh.Name = aMesh->mName.C_Str();
@@ -363,7 +363,7 @@ bool ProcessMesh(ImportedModelData& result, AssimpImporterData& data, const aiMe
} }
// Blend Indices and Blend Weights // Blend Indices and Blend Weights
if (aMesh->mNumBones > 0 && aMesh->mBones && EnumHasAnyFlags(result.Types, ImportDataTypes::Skeleton)) if (aMesh->mNumBones > 0 && aMesh->mBones && EnumHasAnyFlags(data.Options.ImportTypes, ImportDataTypes::Skeleton))
{ {
const int32 vertexCount = mesh.Positions.Count(); const int32 vertexCount = mesh.Positions.Count();
mesh.BlendIndices.Resize(vertexCount); mesh.BlendIndices.Resize(vertexCount);
@@ -444,7 +444,7 @@ bool ProcessMesh(ImportedModelData& result, AssimpImporterData& data, const aiMe
} }
// Blend Shapes // Blend Shapes
if (aMesh->mNumAnimMeshes > 0 && EnumHasAnyFlags(result.Types, ImportDataTypes::Skeleton) && data.Options.ImportBlendShapes) if (aMesh->mNumAnimMeshes > 0 && EnumHasAnyFlags(data.Options.ImportTypes, ImportDataTypes::Skeleton) && data.Options.ImportBlendShapes)
{ {
mesh.BlendShapes.EnsureCapacity(aMesh->mNumAnimMeshes); mesh.BlendShapes.EnsureCapacity(aMesh->mNumAnimMeshes);
for (unsigned int animMeshIndex = 0; animMeshIndex < aMesh->mNumAnimMeshes; animMeshIndex++) for (unsigned int animMeshIndex = 0; animMeshIndex < aMesh->mNumAnimMeshes; animMeshIndex++)
@@ -489,7 +489,7 @@ bool ProcessMesh(ImportedModelData& result, AssimpImporterData& data, const aiMe
return false; return false;
} }
bool ImportTexture(ImportedModelData& result, AssimpImporterData& data, aiString& aFilename, int32& textureIndex, TextureEntry::TypeHint type) bool ImportTexture(ModelData& result, AssimpImporterData& data, aiString& aFilename, int32& textureIndex, TextureEntry::TypeHint type)
{ {
// Find texture file path // Find texture file path
const String filename = String(aFilename.C_Str()).TrimTrailing(); const String filename = String(aFilename.C_Str()).TrimTrailing();
@@ -514,7 +514,7 @@ bool ImportTexture(ImportedModelData& result, AssimpImporterData& data, aiString
return true; return true;
} }
bool ImportMaterialTexture(ImportedModelData& result, AssimpImporterData& data, const aiMaterial* aMaterial, aiTextureType aTextureType, int32& textureIndex, TextureEntry::TypeHint type) bool ImportMaterialTexture(ModelData& result, AssimpImporterData& data, const aiMaterial* aMaterial, aiTextureType aTextureType, int32& textureIndex, TextureEntry::TypeHint type)
{ {
aiString aFilename; aiString aFilename;
if (aMaterial->GetTexture(aTextureType, 0, &aFilename, nullptr, nullptr, nullptr, nullptr) == AI_SUCCESS) if (aMaterial->GetTexture(aTextureType, 0, &aFilename, nullptr, nullptr, nullptr, nullptr) == AI_SUCCESS)
@@ -560,7 +560,7 @@ bool ImportMaterialTexture(ImportedModelData& result, AssimpImporterData& data,
return false; return false;
} }
bool ImportMaterials(ImportedModelData& result, AssimpImporterData& data, String& errorMsg) bool ImportMaterials(ModelData& result, AssimpImporterData& data, String& errorMsg)
{ {
const uint32 materialsCount = data.Scene->mNumMaterials; const uint32 materialsCount = data.Scene->mNumMaterials;
result.Materials.Resize(materialsCount, false); result.Materials.Resize(materialsCount, false);
@@ -574,7 +574,7 @@ bool ImportMaterials(ImportedModelData& result, AssimpImporterData& data, String
materialSlot.Name = String(aName.C_Str()).TrimTrailing(); materialSlot.Name = String(aName.C_Str()).TrimTrailing();
materialSlot.AssetID = Guid::Empty; materialSlot.AssetID = Guid::Empty;
if (EnumHasAnyFlags(result.Types, ImportDataTypes::Materials)) if (EnumHasAnyFlags(data.Options.ImportTypes, ImportDataTypes::Materials))
{ {
aiColor3D aColor; aiColor3D aColor;
if (aMaterial->Get(AI_MATKEY_COLOR_DIFFUSE, aColor) == AI_SUCCESS) if (aMaterial->Get(AI_MATKEY_COLOR_DIFFUSE, aColor) == AI_SUCCESS)
@@ -586,7 +586,7 @@ bool ImportMaterials(ImportedModelData& result, AssimpImporterData& data, String
if (aMaterial->Get(AI_MATKEY_OPACITY, aFloat) == AI_SUCCESS) if (aMaterial->Get(AI_MATKEY_OPACITY, aFloat) == AI_SUCCESS)
materialSlot.Opacity.Value = aFloat; materialSlot.Opacity.Value = aFloat;
if (EnumHasAnyFlags(result.Types, ImportDataTypes::Textures)) if (EnumHasAnyFlags(data.Options.ImportTypes, ImportDataTypes::Textures))
{ {
ImportMaterialTexture(result, data, aMaterial, aiTextureType_DIFFUSE, materialSlot.Diffuse.TextureIndex, TextureEntry::TypeHint::ColorRGB); ImportMaterialTexture(result, data, aMaterial, aiTextureType_DIFFUSE, materialSlot.Diffuse.TextureIndex, TextureEntry::TypeHint::ColorRGB);
ImportMaterialTexture(result, data, aMaterial, aiTextureType_EMISSIVE, materialSlot.Emissive.TextureIndex, TextureEntry::TypeHint::ColorRGB); ImportMaterialTexture(result, data, aMaterial, aiTextureType_EMISSIVE, materialSlot.Emissive.TextureIndex, TextureEntry::TypeHint::ColorRGB);
@@ -612,7 +612,7 @@ bool IsMeshInvalid(const aiMesh* aMesh)
return aMesh->mPrimitiveTypes != aiPrimitiveType_TRIANGLE || aMesh->mNumVertices == 0 || aMesh->mNumFaces == 0 || aMesh->mFaces[0].mNumIndices != 3; return aMesh->mPrimitiveTypes != aiPrimitiveType_TRIANGLE || aMesh->mNumVertices == 0 || aMesh->mNumFaces == 0 || aMesh->mFaces[0].mNumIndices != 3;
} }
bool ImportMesh(int32 i, ImportedModelData& result, AssimpImporterData& data, String& errorMsg) bool ImportMesh(int32 i, ModelData& result, AssimpImporterData& data, String& errorMsg)
{ {
const auto aMesh = data.Scene->mMeshes[i]; const auto aMesh = data.Scene->mMeshes[i];
@@ -739,7 +739,7 @@ void ImportCurve(aiQuatKey* keys, uint32 keysCount, LinearCurve<Quaternion>& cur
} }
} }
bool ModelTool::ImportDataAssimp(const char* path, ImportedModelData& data, Options& options, String& errorMsg) bool ModelTool::ImportDataAssimp(const char* path, ModelData& data, Options& options, String& errorMsg)
{ {
auto context = (AssimpImporterData*)options.SplitContext; auto context = (AssimpImporterData*)options.SplitContext;
if (!context) if (!context)
@@ -750,8 +750,8 @@ bool ModelTool::ImportDataAssimp(const char* path, ImportedModelData& data, Opti
AssimpInited = true; AssimpInited = true;
LOG(Info, "Assimp {0}.{1}.{2}", aiGetVersionMajor(), aiGetVersionMinor(), aiGetVersionRevision()); LOG(Info, "Assimp {0}.{1}.{2}", aiGetVersionMajor(), aiGetVersionMinor(), aiGetVersionRevision());
} }
bool importMeshes = EnumHasAnyFlags(data.Types, ImportDataTypes::Geometry); bool importMeshes = EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Geometry);
bool importAnimations = EnumHasAnyFlags(data.Types, ImportDataTypes::Animations); bool importAnimations = EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Animations);
context = New<AssimpImporterData>(path, options); context = New<AssimpImporterData>(path, options);
// Setup import flags // Setup import flags
@@ -820,7 +820,7 @@ bool ModelTool::ImportDataAssimp(const char* path, ImportedModelData& data, Opti
} }
// Import geometry // Import geometry
if (EnumHasAnyFlags(data.Types, ImportDataTypes::Geometry) && context->Scene->HasMeshes()) if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Geometry) && context->Scene->HasMeshes())
{ {
const int meshCount = context->Scene->mNumMeshes; const int meshCount = context->Scene->mNumMeshes;
if (options.SplitObjects && options.ObjectIndex == -1 && meshCount > 1) if (options.SplitObjects && options.ObjectIndex == -1 && meshCount > 1)
@@ -863,7 +863,7 @@ bool ModelTool::ImportDataAssimp(const char* path, ImportedModelData& data, Opti
} }
// Import skeleton // Import skeleton
if (EnumHasAnyFlags(data.Types, ImportDataTypes::Skeleton)) if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Skeleton))
{ {
data.Skeleton.Nodes.Resize(context->Nodes.Count(), false); data.Skeleton.Nodes.Resize(context->Nodes.Count(), false);
for (int32 i = 0; i < context->Nodes.Count(); i++) for (int32 i = 0; i < context->Nodes.Count(); i++)
@@ -893,7 +893,7 @@ bool ModelTool::ImportDataAssimp(const char* path, ImportedModelData& data, Opti
} }
// Import animations // Import animations
if (EnumHasAnyFlags(data.Types, ImportDataTypes::Animations) && context->Scene->HasAnimations()) if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Animations) && context->Scene->HasAnimations())
{ {
const int32 animCount = (int32)context->Scene->mNumAnimations; const int32 animCount = (int32)context->Scene->mNumAnimations;
if (options.SplitObjects && options.ObjectIndex == -1 && animCount > 1) if (options.SplitObjects && options.ObjectIndex == -1 && animCount > 1)
@@ -948,7 +948,7 @@ bool ModelTool::ImportDataAssimp(const char* path, ImportedModelData& data, Opti
} }
// Import nodes // Import nodes
if (EnumHasAnyFlags(data.Types, ImportDataTypes::Nodes)) if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Nodes))
{ {
data.Nodes.Resize(context->Nodes.Count()); data.Nodes.Resize(context->Nodes.Count());
for (int32 i = 0; i < context->Nodes.Count(); i++) for (int32 i = 0; i < context->Nodes.Count(); i++)

View File

@@ -182,7 +182,7 @@ struct OpenFbxImporterData
#endif #endif
} }
bool ImportMaterialTexture(ImportedModelData& result, const ofbx::Material* mat, ofbx::Texture::TextureType textureType, int32& textureIndex, TextureEntry::TypeHint type) const bool ImportMaterialTexture(ModelData& result, const ofbx::Material* mat, ofbx::Texture::TextureType textureType, int32& textureIndex, TextureEntry::TypeHint type) const
{ {
const ofbx::Texture* tex = mat->getTexture(textureType); const ofbx::Texture* tex = mat->getTexture(textureType);
if (tex) if (tex)
@@ -217,7 +217,7 @@ struct OpenFbxImporterData
return false; return false;
} }
int32 AddMaterial(ImportedModelData& result, const ofbx::Material* mat) int32 AddMaterial(ModelData& result, const ofbx::Material* mat)
{ {
int32 index = Materials.Find(mat); int32 index = Materials.Find(mat);
if (index == -1) if (index == -1)
@@ -229,11 +229,11 @@ struct OpenFbxImporterData
if (mat) if (mat)
material.Name = String(mat->name).TrimTrailing(); material.Name = String(mat->name).TrimTrailing();
if (mat && EnumHasAnyFlags(result.Types, ImportDataTypes::Materials)) if (mat && EnumHasAnyFlags(Options.ImportTypes, ImportDataTypes::Materials))
{ {
material.Diffuse.Color = ToColor(mat->getDiffuseColor()); material.Diffuse.Color = ToColor(mat->getDiffuseColor());
if (EnumHasAnyFlags(result.Types, ImportDataTypes::Textures)) if (EnumHasAnyFlags(Options.ImportTypes, ImportDataTypes::Textures))
{ {
ImportMaterialTexture(result, mat, ofbx::Texture::DIFFUSE, material.Diffuse.TextureIndex, TextureEntry::TypeHint::ColorRGB); ImportMaterialTexture(result, mat, ofbx::Texture::DIFFUSE, material.Diffuse.TextureIndex, TextureEntry::TypeHint::ColorRGB);
ImportMaterialTexture(result, mat, ofbx::Texture::EMISSIVE, material.Emissive.TextureIndex, TextureEntry::TypeHint::ColorRGB); ImportMaterialTexture(result, mat, ofbx::Texture::EMISSIVE, material.Emissive.TextureIndex, TextureEntry::TypeHint::ColorRGB);
@@ -522,7 +522,7 @@ bool ImportBones(OpenFbxImporterData& data, String& errorMsg)
return false; return false;
} }
bool ProcessMesh(ImportedModelData& result, OpenFbxImporterData& data, const ofbx::Mesh* aMesh, MeshData& mesh, String& errorMsg, int32 triangleStart, int32 triangleEnd) bool ProcessMesh(ModelData& result, OpenFbxImporterData& data, const ofbx::Mesh* aMesh, MeshData& mesh, String& errorMsg, int32 triangleStart, int32 triangleEnd)
{ {
// Prepare // Prepare
const int32 firstVertexOffset = triangleStart * 3; const int32 firstVertexOffset = triangleStart * 3;
@@ -682,7 +682,7 @@ bool ProcessMesh(ImportedModelData& result, OpenFbxImporterData& data, const ofb
} }
// Blend Indices and Blend Weights // Blend Indices and Blend Weights
if (skin && skin->getClusterCount() > 0 && EnumHasAnyFlags(result.Types, ImportDataTypes::Skeleton)) if (skin && skin->getClusterCount() > 0 && EnumHasAnyFlags(data.Options.ImportTypes, ImportDataTypes::Skeleton))
{ {
mesh.BlendIndices.Resize(vertexCount); mesh.BlendIndices.Resize(vertexCount);
mesh.BlendWeights.Resize(vertexCount); mesh.BlendWeights.Resize(vertexCount);
@@ -746,7 +746,7 @@ bool ProcessMesh(ImportedModelData& result, OpenFbxImporterData& data, const ofb
} }
// Blend Shapes // Blend Shapes
if (blendShape && blendShape->getBlendShapeChannelCount() > 0 && EnumHasAnyFlags(result.Types, ImportDataTypes::Skeleton) && data.Options.ImportBlendShapes) if (blendShape && blendShape->getBlendShapeChannelCount() > 0 && EnumHasAnyFlags(data.Options.ImportTypes, ImportDataTypes::Skeleton) && data.Options.ImportBlendShapes)
{ {
mesh.BlendShapes.EnsureCapacity(blendShape->getBlendShapeChannelCount()); mesh.BlendShapes.EnsureCapacity(blendShape->getBlendShapeChannelCount());
for (int32 channelIndex = 0; channelIndex < blendShape->getBlendShapeChannelCount(); channelIndex++) for (int32 channelIndex = 0; channelIndex < blendShape->getBlendShapeChannelCount(); channelIndex++)
@@ -853,7 +853,7 @@ bool ProcessMesh(ImportedModelData& result, OpenFbxImporterData& data, const ofb
return false; return false;
} }
bool ImportMesh(ImportedModelData& result, OpenFbxImporterData& data, const ofbx::Mesh* aMesh, String& errorMsg, int32 triangleStart, int32 triangleEnd) bool ImportMesh(ModelData& result, OpenFbxImporterData& data, const ofbx::Mesh* aMesh, String& errorMsg, int32 triangleStart, int32 triangleEnd)
{ {
// Find the parent node // Find the parent node
int32 nodeIndex = data.FindNode(aMesh); int32 nodeIndex = data.FindNode(aMesh);
@@ -906,7 +906,7 @@ bool ImportMesh(ImportedModelData& result, OpenFbxImporterData& data, const ofbx
return false; return false;
} }
bool ImportMesh(int32 index, ImportedModelData& result, OpenFbxImporterData& data, String& errorMsg) bool ImportMesh(int32 index, ModelData& result, OpenFbxImporterData& data, String& errorMsg)
{ {
const auto aMesh = data.Scene->getMesh(index); const auto aMesh = data.Scene->getMesh(index);
const auto aGeometry = aMesh->getGeometry(); const auto aGeometry = aMesh->getGeometry();
@@ -1006,7 +1006,7 @@ void ImportCurve(const ofbx::AnimationCurveNode* curveNode, LinearCurve<T>& curv
} }
} }
bool ImportAnimation(int32 index, ImportedModelData& data, OpenFbxImporterData& importerData) bool ImportAnimation(int32 index, ModelData& data, OpenFbxImporterData& importerData)
{ {
const ofbx::AnimationStack* stack = importerData.Scene->getAnimationStack(index); const ofbx::AnimationStack* stack = importerData.Scene->getAnimationStack(index);
const ofbx::AnimationLayer* layer = stack->getLayer(0); const ofbx::AnimationLayer* layer = stack->getLayer(0);
@@ -1103,7 +1103,7 @@ static Float3 FbxVectorFromAxisAndSign(int axis, int sign)
return { 0.f, 0.f, 0.f }; return { 0.f, 0.f, 0.f };
} }
bool ModelTool::ImportDataOpenFBX(const char* path, ImportedModelData& data, Options& options, String& errorMsg) bool ModelTool::ImportDataOpenFBX(const char* path, ModelData& data, Options& options, String& errorMsg)
{ {
auto context = (OpenFbxImporterData*)options.SplitContext; auto context = (OpenFbxImporterData*)options.SplitContext;
if (!context) if (!context)
@@ -1116,7 +1116,7 @@ bool ModelTool::ImportDataOpenFBX(const char* path, ImportedModelData& data, Opt
return true; return true;
} }
ofbx::u64 loadFlags = 0; ofbx::u64 loadFlags = 0;
if (EnumHasAnyFlags(data.Types, ImportDataTypes::Geometry)) if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Geometry))
{ {
loadFlags |= (ofbx::u64)ofbx::LoadFlags::TRIANGULATE; loadFlags |= (ofbx::u64)ofbx::LoadFlags::TRIANGULATE;
if (!options.ImportBlendShapes) if (!options.ImportBlendShapes)
@@ -1161,7 +1161,7 @@ bool ModelTool::ImportDataOpenFBX(const char* path, ImportedModelData& data, Opt
#endif #endif
// Extract embedded textures // Extract embedded textures
if (EnumHasAnyFlags(data.Types, ImportDataTypes::Textures)) if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Textures))
{ {
String outputPath; String outputPath;
for (int i = 0, c = scene->getEmbeddedDataCount(); i < c; i++) for (int i = 0, c = scene->getEmbeddedDataCount(); i < c; i++)
@@ -1232,7 +1232,7 @@ bool ModelTool::ImportDataOpenFBX(const char* path, ImportedModelData& data, Opt
DeleteMe<OpenFbxImporterData> contextCleanup(options.SplitContext ? nullptr : context); DeleteMe<OpenFbxImporterData> contextCleanup(options.SplitContext ? nullptr : context);
// Build final skeleton bones hierarchy before importing meshes // Build final skeleton bones hierarchy before importing meshes
if (EnumHasAnyFlags(data.Types, ImportDataTypes::Skeleton)) if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Skeleton))
{ {
if (ImportBones(*context, errorMsg)) if (ImportBones(*context, errorMsg))
{ {
@@ -1244,7 +1244,7 @@ bool ModelTool::ImportDataOpenFBX(const char* path, ImportedModelData& data, Opt
} }
// Import geometry (meshes and materials) // Import geometry (meshes and materials)
if (EnumHasAnyFlags(data.Types, ImportDataTypes::Geometry) && context->Scene->getMeshCount() > 0) if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Geometry) && context->Scene->getMeshCount() > 0)
{ {
const int meshCount = context->Scene->getMeshCount(); const int meshCount = context->Scene->getMeshCount();
if (options.SplitObjects && options.ObjectIndex == -1 && meshCount > 1) if (options.SplitObjects && options.ObjectIndex == -1 && meshCount > 1)
@@ -1303,7 +1303,7 @@ bool ModelTool::ImportDataOpenFBX(const char* path, ImportedModelData& data, Opt
} }
// Import skeleton // Import skeleton
if (EnumHasAnyFlags(data.Types, ImportDataTypes::Skeleton)) if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Skeleton))
{ {
data.Skeleton.Nodes.Resize(context->Nodes.Count(), false); data.Skeleton.Nodes.Resize(context->Nodes.Count(), false);
for (int32 i = 0; i < context->Nodes.Count(); i++) for (int32 i = 0; i < context->Nodes.Count(); i++)
@@ -1343,7 +1343,7 @@ bool ModelTool::ImportDataOpenFBX(const char* path, ImportedModelData& data, Opt
} }
// Import animations // Import animations
if (EnumHasAnyFlags(data.Types, ImportDataTypes::Animations)) if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Animations))
{ {
const int animCount = context->Scene->getAnimationStackCount(); const int animCount = context->Scene->getAnimationStackCount();
if (options.SplitObjects && options.ObjectIndex == -1 && animCount > 1) if (options.SplitObjects && options.ObjectIndex == -1 && animCount > 1)
@@ -1386,7 +1386,7 @@ bool ModelTool::ImportDataOpenFBX(const char* path, ImportedModelData& data, Opt
} }
// Import nodes // Import nodes
if (EnumHasAnyFlags(data.Types, ImportDataTypes::Nodes)) if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Nodes))
{ {
data.Nodes.Resize(context->Nodes.Count()); data.Nodes.Resize(context->Nodes.Count());
for (int32 i = 0; i < context->Nodes.Count(); i++) for (int32 i = 0; i < context->Nodes.Count(); i++)

View File

@@ -332,26 +332,6 @@ bool ModelTool::GenerateModelSDF(Model* inputModel, ModelData* modelData, float
#if USE_EDITOR #if USE_EDITOR
BoundingBox ImportedModelData::LOD::GetBox() const
{
if (Meshes.IsEmpty())
return BoundingBox::Empty;
BoundingBox box;
Meshes[0]->CalculateBox(box);
for (int32 i = 1; i < Meshes.Count(); i++)
{
if (Meshes[i]->Positions.HasItems())
{
BoundingBox t;
Meshes[i]->CalculateBox(t);
BoundingBox::Merge(box, t, box);
}
}
return box;
}
void ModelTool::Options::Serialize(SerializeStream& stream, const void* otherObj) void ModelTool::Options::Serialize(SerializeStream& stream, const void* otherObj)
{ {
SERIALIZE_GET_OTHER_OBJ(ModelTool::Options); SERIALIZE_GET_OTHER_OBJ(ModelTool::Options);
@@ -463,7 +443,7 @@ void RemoveNamespace(String& name)
name = name.Substring(namespaceStart + 1); name = name.Substring(namespaceStart + 1);
} }
bool ModelTool::ImportData(const String& path, ImportedModelData& data, Options& options, String& errorMsg) bool ModelTool::ImportData(const String& path, ModelData& data, Options& options, String& errorMsg)
{ {
// Validate options // Validate options
options.Scale = Math::Clamp(options.Scale, 0.0001f, 100000.0f); options.Scale = Math::Clamp(options.Scale, 0.0001f, 100000.0f);
@@ -610,7 +590,7 @@ bool ModelTool::ImportData(const String& path, ImportedModelData& data, Options&
} }
// Flip normals of the imported geometry // Flip normals of the imported geometry
if (options.FlipNormals && EnumHasAnyFlags(data.Types, ImportDataTypes::Geometry)) if (options.FlipNormals && EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Geometry))
{ {
for (auto& lod : data.LODs) for (auto& lod : data.LODs)
{ {
@@ -783,30 +763,29 @@ bool ModelTool::ImportModel(const String& path, ModelData& meshData, Options& op
const auto startTime = DateTime::NowUTC(); const auto startTime = DateTime::NowUTC();
// Import data // Import data
ImportDataTypes importDataTypes;
switch (options.Type) switch (options.Type)
{ {
case ModelType::Model: case ModelType::Model:
importDataTypes = ImportDataTypes::Geometry | ImportDataTypes::Nodes; options.ImportTypes = ImportDataTypes::Geometry | ImportDataTypes::Nodes;
if (options.ImportMaterials) if (options.ImportMaterials)
importDataTypes |= ImportDataTypes::Materials; options.ImportTypes |= ImportDataTypes::Materials;
if (options.ImportTextures) if (options.ImportTextures)
importDataTypes |= ImportDataTypes::Textures; options.ImportTypes |= ImportDataTypes::Textures;
break; break;
case ModelType::SkinnedModel: case ModelType::SkinnedModel:
importDataTypes = ImportDataTypes::Geometry | ImportDataTypes::Nodes | ImportDataTypes::Skeleton; options.ImportTypes = ImportDataTypes::Geometry | ImportDataTypes::Nodes | ImportDataTypes::Skeleton;
if (options.ImportMaterials) if (options.ImportMaterials)
importDataTypes |= ImportDataTypes::Materials; options.ImportTypes |= ImportDataTypes::Materials;
if (options.ImportTextures) if (options.ImportTextures)
importDataTypes |= ImportDataTypes::Textures; options.ImportTypes |= ImportDataTypes::Textures;
break; break;
case ModelType::Animation: case ModelType::Animation:
importDataTypes = ImportDataTypes::Animations; options.ImportTypes = ImportDataTypes::Animations;
break; break;
default: default:
return true; return true;
} }
ImportedModelData data(importDataTypes); ModelData data;
if (ImportData(path, data, options, errorMsg)) if (ImportData(path, data, options, errorMsg))
return true; return true;
@@ -965,7 +944,7 @@ bool ModelTool::ImportModel(const String& path, ModelData& meshData, Options& op
auto& texture = data.Textures[i]; auto& texture = data.Textures[i];
// Auto-import textures // Auto-import textures
if (autoImportOutput.IsEmpty() || (data.Types & ImportDataTypes::Textures) == ImportDataTypes::None || texture.FilePath.IsEmpty()) if (autoImportOutput.IsEmpty() || (options.ImportTypes & ImportDataTypes::Textures) == ImportDataTypes::None || texture.FilePath.IsEmpty())
continue; continue;
String filename = StringUtils::GetFileNameWithoutExtension(texture.FilePath); String filename = StringUtils::GetFileNameWithoutExtension(texture.FilePath);
for (int32 j = filename.Length() - 1; j >= 0; j--) for (int32 j = filename.Length() - 1; j >= 0; j--)
@@ -1012,7 +991,7 @@ bool ModelTool::ImportModel(const String& path, ModelData& meshData, Options& op
material.Name = TEXT("Material ") + StringUtils::ToString(i); material.Name = TEXT("Material ") + StringUtils::ToString(i);
// Auto-import materials // Auto-import materials
if (autoImportOutput.IsEmpty() || (data.Types & ImportDataTypes::Materials) == ImportDataTypes::None || !material.UsesProperties()) if (autoImportOutput.IsEmpty() || (options.ImportTypes & ImportDataTypes::Materials) == ImportDataTypes::None || !material.UsesProperties())
continue; continue;
auto filename = material.Name; auto filename = material.Name;
for (int32 j = filename.Length() - 1; j >= 0; j--) for (int32 j = filename.Length() - 1; j >= 0; j--)
@@ -1124,10 +1103,10 @@ bool ModelTool::ImportModel(const String& path, ModelData& meshData, Options& op
} }
// Perform simple nodes mapping to single node (will transform meshes to model local space) // Perform simple nodes mapping to single node (will transform meshes to model local space)
SkeletonMapping<ImportedModelData::Node> skeletonMapping(data.Nodes, nullptr); SkeletonMapping<ModelDataNode> skeletonMapping(data.Nodes, nullptr);
// Refresh skeleton updater with model skeleton // Refresh skeleton updater with model skeleton
SkeletonUpdater<ImportedModelData::Node> hierarchyUpdater(data.Nodes); SkeletonUpdater<ModelDataNode> hierarchyUpdater(data.Nodes);
hierarchyUpdater.UpdateMatrices(); hierarchyUpdater.UpdateMatrices();
// Move meshes in the new nodes // Move meshes in the new nodes
@@ -1421,10 +1400,10 @@ bool ModelTool::ImportModel(const String& path, ModelData& meshData, Options& op
} }
// Perform simple nodes mapping to single node (will transform meshes to model local space) // Perform simple nodes mapping to single node (will transform meshes to model local space)
SkeletonMapping<ImportedModelData::Node> skeletonMapping(data.Nodes, nullptr); SkeletonMapping<ModelDataNode> skeletonMapping(data.Nodes, nullptr);
// Refresh skeleton updater with model skeleton // Refresh skeleton updater with model skeleton
SkeletonUpdater<ImportedModelData::Node> hierarchyUpdater(data.Nodes); SkeletonUpdater<ModelDataNode> hierarchyUpdater(data.Nodes);
hierarchyUpdater.UpdateMatrices(); hierarchyUpdater.UpdateMatrices();
if (options.CalculateBoneOffsetMatrices) if (options.CalculateBoneOffsetMatrices)

View File

@@ -56,94 +56,6 @@ enum class ImportDataTypes : int32
DECLARE_ENUM_OPERATORS(ImportDataTypes); DECLARE_ENUM_OPERATORS(ImportDataTypes);
/// <summary>
/// Imported model data container. Represents unified model source file data (meshes, animations, skeleton, materials).
/// </summary>
class ImportedModelData
{
public:
struct LOD
{
Array<MeshData*> Meshes;
BoundingBox GetBox() const;
};
struct Node
{
/// <summary>
/// The parent node index. The root node uses value -1.
/// </summary>
int32 ParentIndex;
/// <summary>
/// The local transformation of the node, relative to the parent node.
/// </summary>
Transform LocalTransform;
/// <summary>
/// The name of this node.
/// </summary>
String Name;
};
public:
/// <summary>
/// The import data types types.
/// </summary>
ImportDataTypes Types;
/// <summary>
/// The textures slots.
/// </summary>
Array<TextureEntry> Textures;
/// <summary>
/// The material slots.
/// </summary>
Array<MaterialSlotEntry> Materials;
/// <summary>
/// The level of details data with meshes.
/// </summary>
Array<LOD> LODs;
/// <summary>
/// The skeleton data.
/// </summary>
SkeletonData Skeleton;
/// <summary>
/// The scene nodes.
/// </summary>
Array<Node> Nodes;
/// <summary>
/// The node animations.
/// </summary>
AnimationData Animation;
public:
/// <summary>
/// Initializes a new instance of the <see cref="ImportedModelData"/> class.
/// </summary>
/// <param name="types">The types.</param>
ImportedModelData(ImportDataTypes types)
{
Types = types;
}
/// <summary>
/// Finalizes an instance of the <see cref="ImportedModelData"/> class.
/// </summary>
~ImportedModelData()
{
// Ensure to cleanup data
for (int32 i = 0; i < LODs.Count(); i++)
LODs[i].Meshes.ClearDelete();
}
};
#endif #endif
struct ModelSDFHeader struct ModelSDFHeader
@@ -382,10 +294,15 @@ public:
API_FIELD(Attributes="EditorOrder(3030), EditorDisplay(\"Other\")") API_FIELD(Attributes="EditorOrder(3030), EditorDisplay(\"Other\")")
String SubAssetFolder = TEXT(""); String SubAssetFolder = TEXT("");
public: // Internals
// Runtime data for objects splitting during import (used internally) // Runtime data for objects splitting during import (used internally)
void* SplitContext = nullptr; void* SplitContext = nullptr;
Function<bool(Options& splitOptions, const String& objectName)> OnSplitImport; Function<bool(Options& splitOptions, const String& objectName)> OnSplitImport;
// Internal flags for objects to import.
ImportDataTypes ImportTypes = ImportDataTypes::None;
public: public:
// [ISerializable] // [ISerializable]
void Serialize(SerializeStream& stream, const void* otherObj) override; void Serialize(SerializeStream& stream, const void* otherObj) override;
@@ -401,7 +318,7 @@ public:
/// <param name="options">The import options.</param> /// <param name="options">The import options.</param>
/// <param name="errorMsg">The error message container.</param> /// <param name="errorMsg">The error message container.</param>
/// <returns>True if fails, otherwise false.</returns> /// <returns>True if fails, otherwise false.</returns>
static bool ImportData(const String& path, ImportedModelData& data, Options& options, String& errorMsg); static bool ImportData(const String& path, ModelData& data, Options& options, String& errorMsg);
/// <summary> /// <summary>
/// Imports the model. /// Imports the model.
@@ -444,13 +361,13 @@ public:
private: private:
static void CalculateBoneOffsetMatrix(const Array<SkeletonNode>& nodes, Matrix& offsetMatrix, int32 nodeIndex); static void CalculateBoneOffsetMatrix(const Array<SkeletonNode>& nodes, Matrix& offsetMatrix, int32 nodeIndex);
#if USE_ASSIMP #if USE_ASSIMP
static bool ImportDataAssimp(const char* path, ImportedModelData& data, Options& options, String& errorMsg); static bool ImportDataAssimp(const char* path, ModelData& data, Options& options, String& errorMsg);
#endif #endif
#if USE_AUTODESK_FBX_SDK #if USE_AUTODESK_FBX_SDK
static bool ImportDataAutodeskFbxSdk(const char* path, ImportedModelData& data, Options& options, String& errorMsg); static bool ImportDataAutodeskFbxSdk(const char* path, ModelData& data, Options& options, String& errorMsg);
#endif #endif
#if USE_OPEN_FBX #if USE_OPEN_FBX
static bool ImportDataOpenFBX(const char* path, ImportedModelData& data, Options& options, String& errorMsg); static bool ImportDataOpenFBX(const char* path, ModelData& data, Options& options, String& errorMsg);
#endif #endif
#endif #endif
}; };