Flag bones in scene for skel export

This commit is contained in:
kaetemi 2015-09-19 19:35:57 +02:00
parent d08d09b341
commit 607ecda469
3 changed files with 156 additions and 9 deletions

View file

@ -21,6 +21,9 @@
#include <nel/misc/cmd_args.h> #include <nel/misc/cmd_args.h>
#include <nel/misc/path.h> #include <nel/misc/path.h>
#include <nel/3d/register_3d.h>
#include <nel/3d/scene.h>
int printHelp(const NLMISC::CCmdArgs &args) int printHelp(const NLMISC::CCmdArgs &args)
{ {
printf("NeL Mesh Export\n"); printf("NeL Mesh Export\n");
@ -29,6 +32,8 @@ int printHelp(const NLMISC::CCmdArgs &args)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
NLMISC::CApplicationContext app;
NLMISC::CCmdArgs args; NLMISC::CCmdArgs args;
args.setArgs(argc, (const char **)argv); args.setArgs(argc, (const char **)argv);
@ -48,12 +53,16 @@ int main(int argc, char *argv[])
CMeshUtilsSettings settings; CMeshUtilsSettings settings;
settings.SourceFilePath = filePath; settings.SourceFilePath = filePath;
settings.DestinationDirectory = args.getArg('d'); if (args.haveArg('d'))
if (settings.DestinationDirectory.empty()) settings.DestinationDirectoryPath = args.getArg('d');
settings.DestinationDirectory = args.getLongArg("dst"); if (settings.DestinationDirectoryPath.empty())
if (settings.DestinationDirectory.empty()) settings.DestinationDirectoryPath = args.getLongArg("dst");
settings.DestinationDirectory = filePath + "_export"; if (settings.DestinationDirectoryPath.empty())
settings.DestinationDirectory += "/"; settings.DestinationDirectoryPath = filePath + "_export";
settings.DestinationDirectoryPath += "/";
NL3D::CScene::registerBasics();
NL3D::registerSerial3d();
return exportScene(settings); return exportScene(settings);
} }

View file

@ -18,8 +18,138 @@
#include <nel/misc/types_nl.h> #include <nel/misc/types_nl.h>
#include "mesh_utils.h" #include "mesh_utils.h"
int exportScene(CMeshUtilsSettings &settings) #include <nel/misc/debug.h>
#include <assimp/postprocess.h>
#include <assimp/scene.h>
#include <assimp/Importer.hpp>
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<std::string, CNodeContext> 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; return EXIT_SUCCESS;
} }

View file

@ -21,10 +21,18 @@
struct CMeshUtilsSettings struct CMeshUtilsSettings
{ {
CMeshUtilsSettings();
// Absolute Paths
std::string SourceFilePath; 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 */ /* end of file */