diff --git a/code/nel/tools/3d/mesh_utils/assimp_material.cpp b/code/nel/tools/3d/mesh_utils/assimp_material.cpp index 6a786d63b..b542ada14 100644 --- a/code/nel/tools/3d/mesh_utils/assimp_material.cpp +++ b/code/nel/tools/3d/mesh_utils/assimp_material.cpp @@ -48,10 +48,8 @@ inline CRGBA convColor(const aiColor4D &ac) return CRGBA(ac.r * 255.99f, ac.g * 255.99f, ac.b * 255.99f, ac.a * 255.99f); } -CSmartPtr assimpMaterial(CMeshUtilsContext &context, const aiMaterial *am) +void assimpMaterial(NL3D::CMaterial &mat, CMeshUtilsContext &context, const aiMaterial *am) { - CSmartPtr matp = new CMaterial(); - CMaterial &mat = *matp; mat.initLighted(); mat.setShader(CMaterial::Normal); @@ -107,12 +105,20 @@ CSmartPtr assimpMaterial(CMeshUtilsContext &context, const aiMaterial if (am->Get(AI_MATKEY_COLOR_EMISSIVE, c3) == aiReturn_SUCCESS) mat.setEmissive(convColor(c3)); +} +CSmartPtr assimpMaterial(CMeshUtilsContext &context, const aiMaterial *am) +{ + CSmartPtr matp = new CMaterial(); + CMaterial &mat = *matp; + assimpMaterial(mat, context, am); return matp; } void assimpMaterials(CMeshUtilsContext &context) { + set materialNames; + const aiScene *scene = context.InternalScene; for (unsigned int mi = 0; mi < scene->mNumMaterials; ++mi) { @@ -131,10 +137,18 @@ void assimpMaterials(CMeshUtilsContext &context) "Material has no name"); continue; } + + if (materialNames.find(amname.C_Str()) != materialNames.end()) + { + tlerror(context.ToolLogger, context.Settings.SourceFilePath.c_str(), + "Material name '%s' used more than once", amname.C_Str()); + continue; + } if (context.SceneMeta.Materials.find(amname.C_Str()) == context.SceneMeta.Materials.end()) { + materialNames.insert(amname.C_Str()); context.SceneMeta.Materials[amname.C_Str()] = assimpMaterial(context, am); } } diff --git a/code/nel/tools/3d/mesh_utils/assimp_material.h b/code/nel/tools/3d/mesh_utils/assimp_material.h index eac083573..062ca95bb 100644 --- a/code/nel/tools/3d/mesh_utils/assimp_material.h +++ b/code/nel/tools/3d/mesh_utils/assimp_material.h @@ -17,8 +17,12 @@ #include -struct CMeshUtilsContext; +namespace NL3D { + class CMaterial; +} +struct CMeshUtilsContext; +void assimpMaterial(NL3D::CMaterial &mat, CMeshUtilsContext &context, const aiMaterial *am); void assimpMaterials(CMeshUtilsContext &context); /* end of file */ diff --git a/code/nel/tools/3d/mesh_utils/assimp_shape.cpp b/code/nel/tools/3d/mesh_utils/assimp_shape.cpp index c369b358b..a329f30ab 100644 --- a/code/nel/tools/3d/mesh_utils/assimp_shape.cpp +++ b/code/nel/tools/3d/mesh_utils/assimp_shape.cpp @@ -32,6 +32,8 @@ #include +#include "assimp_material.h" + using namespace std; using namespace NLMISC; using namespace NL3D; @@ -50,10 +52,31 @@ using namespace NL3D; // TODO: Skinned - reverse transform by skeleton root bone to align? -void assimpBuildBaseMesh(CMeshBase::CMeshBaseBuild &buildBaseMesh, CNodeContext &nodeContext) +void assimpBuildBaseMesh(CMeshBase::CMeshBaseBuild &buildBaseMesh, CMeshUtilsContext &context, CNodeContext &nodeContext) { const aiNode *node = nodeContext.InternalNode; - // TODO: Reference CExportNel::buildBaseMeshInterface + // Reference CExportNel::buildBaseMeshInterface + + // Load materials + buildBaseMesh.Materials.resize(node->mNumMeshes); + + for (unsigned int mi = 0; mi < node->mNumMeshes; ++mi) + { + const aiMesh *mesh = context.InternalScene->mMeshes[node->mMeshes[mi]]; + const aiMaterial *am = context.InternalScene->mMaterials[mesh->mMaterialIndex]; + + aiString amname; + if (am->Get(AI_MATKEY_NAME, amname) != aiReturn_SUCCESS) + { + tlerror(context.ToolLogger, context.Settings.SourceFilePath.c_str(), + "Material used by node '%s' has no name", node->mName.C_Str()); // TODO: Maybe autogen names by index in mesh or node if this is actually a thing + assimpMaterial(buildBaseMesh.Materials[mi], context, am); + } + else + { + buildBaseMesh.Materials[mi] = *context.SceneMeta.Materials[amname.C_Str()]; + } + } } inline CVector convVector(const aiVector3D &av) @@ -101,6 +124,9 @@ bool assimpBuildMesh(CMesh::CMeshBuild &buildMesh, CMeshBase::CMeshBaseBuild &bu } } + // Default vertex flags + buildMesh.VertexFlags = CVertexBuffer::PositionFlag | CVertexBuffer::NormalFlag; + // TODO: UV Channels for (uint i = 0; i < CVertexBuffer::MaxStage; ++i) buildMesh.UVRouting[i] = i; @@ -208,7 +234,7 @@ bool assimpShape(CMeshUtilsContext &context, CNodeContext &nodeContext) // Fill the build interface of CMesh CMeshBase::CMeshBaseBuild buildBaseMesh; - assimpBuildBaseMesh(buildBaseMesh, nodeContext); + assimpBuildBaseMesh(buildBaseMesh, context, nodeContext); CMesh::CMeshBuild buildMesh; if (!assimpBuildMesh(buildMesh, buildBaseMesh, context, nodeContext)) diff --git a/code/nel/tools/3d/mesh_utils/mesh_utils.cpp b/code/nel/tools/3d/mesh_utils/mesh_utils.cpp index 66454c984..3d9b6c42a 100644 --- a/code/nel/tools/3d/mesh_utils/mesh_utils.cpp +++ b/code/nel/tools/3d/mesh_utils/mesh_utils.cpp @@ -21,6 +21,9 @@ #include #include #include +#include + +#include #include "database_config.h" #include "scene_meta.h" @@ -217,6 +220,34 @@ void flagExpandedBones(CMeshUtilsContext &context) } } +void exportShapes(CMeshUtilsContext &context) +{ + for (TNodeContextMap::iterator it(context.Nodes.begin()), end(context.Nodes.end()); it != end; ++it) + { + CNodeContext &nodeContext = it->second; + if (nodeContext.Shape) + { + std::string shapePath = context.Settings.DestinationDirectoryPath + "/" + it->first + ".shape"; + context.ToolLogger.writeDepend(NLMISC::BUILD, shapePath.c_str(), "*"); + NLMISC::COFile f; + if (f.open(shapePath, false, false, true)) + { + try + { + NL3D::CShapeStream shapeStream(nodeContext.Shape); + shapeStream.serial(f); + f.close(); + } + catch (...) + { + tlerror(context.ToolLogger, context.Settings.SourceFilePath.c_str(), + "Shape '%s' serialization failed!", it->first.c_str()); + } + } + } + } +} + // TODO: Separate load scene and save scene functions int exportScene(const CMeshUtilsSettings &settings) { @@ -277,6 +308,9 @@ int exportScene(const CMeshUtilsSettings &settings) // Import shapes importShapes(context, context.InternalScene->mRootNode); + // Export shapes + exportShapes(context); + return EXIT_SUCCESS; }