Replace ImportedModelData with ModelData for model importing
This commit is contained in:
@@ -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>
|
||||||
|
|||||||
@@ -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++)
|
||||||
|
|||||||
@@ -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++)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user