Flag bones in scene for skel export
This commit is contained in:
parent
d08d09b341
commit
607ecda469
3 changed files with 156 additions and 9 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in a new issue