From 875d7eaa7c2ccdc7a72cf572c7bae6af34c41edc Mon Sep 17 00:00:00 2001 From: kaetemi Date: Sat, 19 Sep 2015 19:35:57 +0200 Subject: [PATCH] Flag bones in scene for skel export --HG-- branch : feature-export-assimp --- code/nel/tools/3d/mesh_export/main.cpp | 21 +++- code/nel/tools/3d/mesh_utils/mesh_utils.cpp | 132 +++++++++++++++++++- code/nel/tools/3d/mesh_utils/mesh_utils.h | 12 +- 3 files changed, 156 insertions(+), 9 deletions(-) diff --git a/code/nel/tools/3d/mesh_export/main.cpp b/code/nel/tools/3d/mesh_export/main.cpp index e83727a5c..2e97be830 100644 --- a/code/nel/tools/3d/mesh_export/main.cpp +++ b/code/nel/tools/3d/mesh_export/main.cpp @@ -21,6 +21,9 @@ #include #include +#include +#include + int printHelp(const NLMISC::CCmdArgs &args) { printf("NeL Mesh Export\n"); @@ -29,6 +32,8 @@ int printHelp(const NLMISC::CCmdArgs &args) int main(int argc, char *argv[]) { + NLMISC::CApplicationContext app; + NLMISC::CCmdArgs args; args.setArgs(argc, (const char **)argv); @@ -48,12 +53,16 @@ int main(int argc, char *argv[]) CMeshUtilsSettings settings; settings.SourceFilePath = filePath; - settings.DestinationDirectory = args.getArg('d'); - if (settings.DestinationDirectory.empty()) - settings.DestinationDirectory = args.getLongArg("dst"); - if (settings.DestinationDirectory.empty()) - settings.DestinationDirectory = filePath + "_export"; - settings.DestinationDirectory += "/"; + if (args.haveArg('d')) + settings.DestinationDirectoryPath = args.getArg('d'); + if (settings.DestinationDirectoryPath.empty()) + settings.DestinationDirectoryPath = args.getLongArg("dst"); + if (settings.DestinationDirectoryPath.empty()) + settings.DestinationDirectoryPath = filePath + "_export"; + settings.DestinationDirectoryPath += "/"; + + NL3D::CScene::registerBasics(); + NL3D::registerSerial3d(); return exportScene(settings); } diff --git a/code/nel/tools/3d/mesh_utils/mesh_utils.cpp b/code/nel/tools/3d/mesh_utils/mesh_utils.cpp index 2430b1dc9..60e5c7201 100644 --- a/code/nel/tools/3d/mesh_utils/mesh_utils.cpp +++ b/code/nel/tools/3d/mesh_utils/mesh_utils.cpp @@ -18,8 +18,138 @@ #include #include "mesh_utils.h" -int exportScene(CMeshUtilsSettings &settings) +#include + +#include +#include +#include + +CMeshUtilsSettings::CMeshUtilsSettings() { + ShapeDirectory = "shape"; + IGDirectory = "ig"; + SkelDirectory = "skel"; +} + +struct CNodeContext +{ + CNodeContext() : + AssimpNode(NULL), + IsBone(false) + { + + } + + const aiNode *AssimpNode; + bool IsBone; +}; + +struct CMeshUtilsContext +{ + CMeshUtilsContext(const CMeshUtilsSettings &settings) : Settings(settings), AssimpScene(NULL) + { + + } + + const CMeshUtilsSettings &Settings; + + const aiScene *AssimpScene; + std::map Nodes; +}; + +struct CNodeMeta +{ + // TODO +}; +static const CNodeMeta g_DefaultMeta; + +void importNode(CMeshUtilsContext &context, const aiNode *node, const CNodeMeta *meta) +{ + if (node->mNumMeshes) + { + // TODO + } + + for (unsigned int i = 0; i < node->mNumChildren; ++i) + importNode(context, node->mChildren[i], &g_DefaultMeta); +} + +void validateAssimpNodeNames(CMeshUtilsContext &context, const aiNode *node) +{ + if (!node->mParent || node == context.AssimpScene->mRootNode) + { + // do nothing + } + else if (node->mName.length == 0) + { + nlwarning("CRITICAL: Node has no name"); + } + else + { + CNodeContext &nodeContext = context.Nodes[node->mName.C_Str()]; + + if (nodeContext.AssimpNode && nodeContext.AssimpNode != node) + { + nlwarning("CRITICAL: Node name '%s' appears multiple times", node->mName.C_Str()); + } + else + { + nodeContext.AssimpNode = node; + } + } + + for (unsigned int i = 0; i < node->mNumChildren; ++i) + validateAssimpNodeNames(context, node->mChildren[i]); +} + +void flagAssimpBones(CMeshUtilsContext &context) +{ + // Find out which nodes are bones by checking the mesh meta info + const aiScene *scene = context.AssimpScene; + for (unsigned int i = 0; i < scene->mNumMeshes; ++i) + { + // nldebug("FOUND MESH '%s'\n", scene->mMeshes[i]->mName.C_Str()); + const aiMesh *mesh = scene->mMeshes[i]; + for (unsigned int j = 0; j < mesh->mNumBones; ++j) + { + CNodeContext &nodeContext = context.Nodes[mesh->mBones[i]->mName.C_Str()]; + if (!nodeContext.AssimpNode) + { + nlwarning("CRITICAL: Bone '%s' has no associated node", mesh->mBones[i]->mName.C_Str()); + } + else + { + // Flag as bone + nodeContext.IsBone = true; + + // Flag all parents as bones + const aiNode *parent = nodeContext.AssimpNode; + while (parent = parent->mParent) if (parent->mName.length) + { + context.Nodes[parent->mName.C_Str()].IsBone = true; + } + } + } + } +} + +// TODO: Separate load scene and save scene functions +int exportScene(const CMeshUtilsSettings &settings) +{ + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(settings.SourceFilePath, aiProcess_Triangulate | aiProcess_ValidateDataStructure); // aiProcess_SplitLargeMeshes | aiProcess_LimitBoneWeights + // aiProcess_ValidateDataStructure: TODO: Catch Assimp error output stream + // aiProcess_RemoveRedundantMaterials: Not used because we may override materials with NeL Material from meta + // aiProcess_ImproveCacheLocality: TODO: Verify this does not modify vertex indices + //scene->mRootNode->mMetaData + + CMeshUtilsContext context(settings); + context.AssimpScene = scene; + + flagAssimpBones(context); + + importNode(context, scene->mRootNode, &g_DefaultMeta); + return EXIT_SUCCESS; } diff --git a/code/nel/tools/3d/mesh_utils/mesh_utils.h b/code/nel/tools/3d/mesh_utils/mesh_utils.h index f021f66f8..b7c549689 100644 --- a/code/nel/tools/3d/mesh_utils/mesh_utils.h +++ b/code/nel/tools/3d/mesh_utils/mesh_utils.h @@ -21,10 +21,18 @@ struct CMeshUtilsSettings { + CMeshUtilsSettings(); + + // Absolute Paths std::string SourceFilePath; - std::string DestinationDirectory; + std::string DestinationDirectoryPath; + + // Relative Directories + std::string ShapeDirectory; + std::string IGDirectory; + std::string SkelDirectory; }; -int exportScene(CMeshUtilsSettings &settings); +int exportScene(const CMeshUtilsSettings &settings); /* end of file */