+ add Exporter::RegisterExporter and Exporter::UnregisterExporter pair of methods. Make parts of the internal export interface public to allow custom exporters to be added on the fly. This is a non-breaking API change.
git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@1084 67173fc5-114c-0410-ac8e-9d2fd5bffc1fpull/2/head
parent
c807fd65f3
commit
255ed412d5
|
@ -75,47 +75,20 @@ void ExportSceneObj(const char*,IOSystem*, const aiScene*);
|
||||||
void ExportSceneSTL(const char*,IOSystem*, const aiScene*);
|
void ExportSceneSTL(const char*,IOSystem*, const aiScene*);
|
||||||
void ExportScene3DS(const char*, IOSystem*, const aiScene*) {}
|
void ExportScene3DS(const char*, IOSystem*, const aiScene*) {}
|
||||||
|
|
||||||
/// Function pointer type of a Export worker function
|
|
||||||
typedef void (*fpExportFunc)(const char*,IOSystem*,const aiScene*);
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
/// Internal description of an Assimp export format option
|
|
||||||
struct ExportFormatEntry
|
|
||||||
{
|
|
||||||
/// Public description structure to be returned by aiGetExportFormatDescription()
|
|
||||||
aiExportFormatDesc mDescription;
|
|
||||||
|
|
||||||
// Worker function to do the actual exporting
|
|
||||||
fpExportFunc mExportFunction;
|
|
||||||
|
|
||||||
// Postprocessing steps to be executed PRIOR to calling mExportFunction
|
|
||||||
unsigned int mEnforcePP;
|
|
||||||
|
|
||||||
// Constructor to fill all entries
|
|
||||||
ExportFormatEntry( const char* pId, const char* pDesc, const char* pExtension, fpExportFunc pFunction, unsigned int pEnforcePP = 0u)
|
|
||||||
{
|
|
||||||
mDescription.id = pId;
|
|
||||||
mDescription.description = pDesc;
|
|
||||||
mDescription.fileExtension = pExtension;
|
|
||||||
mExportFunction = pFunction;
|
|
||||||
mEnforcePP = pEnforcePP;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// global array of all export formats which Assimp supports in its current build
|
// global array of all export formats which Assimp supports in its current build
|
||||||
ExportFormatEntry gExporters[] =
|
Exporter::ExportFormatEntry gExporters[] =
|
||||||
{
|
{
|
||||||
#ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER
|
#ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER
|
||||||
ExportFormatEntry( "collada", "COLLADA - Digital Asset Exchange Schema", "dae", &ExportSceneCollada),
|
Exporter::ExportFormatEntry( "collada", "COLLADA - Digital Asset Exchange Schema", "dae", &ExportSceneCollada),
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER
|
#ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER
|
||||||
ExportFormatEntry( "obj", "Wavefront OBJ format", "obj", &ExportSceneObj),
|
Exporter::ExportFormatEntry( "obj", "Wavefront OBJ format", "obj", &ExportSceneObj),
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef ASSIMP_BUILD_NO_STL_EXPORTER
|
#ifndef ASSIMP_BUILD_NO_STL_EXPORTER
|
||||||
ExportFormatEntry( "stl", "Stereolithography", "stl" , &ExportSceneSTL,
|
Exporter::ExportFormatEntry( "stl", "Stereolithography", "stl" , &ExportSceneSTL,
|
||||||
aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_PreTransformVertices
|
aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_PreTransformVertices
|
||||||
),
|
),
|
||||||
#endif
|
#endif
|
||||||
|
@ -125,6 +98,8 @@ ExportFormatEntry gExporters[] =
|
||||||
//#endif
|
//#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define ASSIMP_NUM_EXPORTERS (sizeof(gExporters)/sizeof(gExporters[0]))
|
||||||
|
|
||||||
|
|
||||||
class ExporterPimpl {
|
class ExporterPimpl {
|
||||||
public:
|
public:
|
||||||
|
@ -135,6 +110,10 @@ public:
|
||||||
, mIsDefaultIOHandler(true)
|
, mIsDefaultIOHandler(true)
|
||||||
{
|
{
|
||||||
GetPostProcessingStepInstanceList(mPostProcessingSteps);
|
GetPostProcessingStepInstanceList(mPostProcessingSteps);
|
||||||
|
|
||||||
|
// grab all builtin exporters
|
||||||
|
mExporters.resize(ASSIMP_NUM_EXPORTERS);
|
||||||
|
std::copy(gExporters,gExporters+ASSIMP_NUM_EXPORTERS,mExporters.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
~ExporterPimpl()
|
~ExporterPimpl()
|
||||||
|
@ -158,9 +137,11 @@ public:
|
||||||
|
|
||||||
/** Last fatal export error */
|
/** Last fatal export error */
|
||||||
std::string mError;
|
std::string mError;
|
||||||
|
|
||||||
|
/** Exporters, this includes those registered using #Assimp::Exporter::RegisterExporter */
|
||||||
|
std::vector<Exporter::ExportFormatEntry> mExporters;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ASSIMP_NUM_EXPORTERS (sizeof(gExporters)/sizeof(gExporters[0]))
|
|
||||||
|
|
||||||
} // end of namespace Assimp
|
} // end of namespace Assimp
|
||||||
|
|
||||||
|
@ -239,8 +220,9 @@ aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const
|
||||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||||
|
|
||||||
pimpl->mError = "";
|
pimpl->mError = "";
|
||||||
for (size_t i = 0; i < ASSIMP_NUM_EXPORTERS; ++i) {
|
for (size_t i = 0; i < pimpl->mExporters.size(); ++i) {
|
||||||
if (!strcmp(gExporters[i].mDescription.id,pFormatId)) {
|
const Exporter::ExportFormatEntry& exp = pimpl->mExporters[i];
|
||||||
|
if (!strcmp(exp.mDescription.id,pFormatId)) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
@ -258,7 +240,7 @@ aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const
|
||||||
const unsigned int nonIdempotentSteps = aiProcess_FlipWindingOrder | aiProcess_FlipUVs | aiProcess_MakeLeftHanded;
|
const unsigned int nonIdempotentSteps = aiProcess_FlipWindingOrder | aiProcess_FlipUVs | aiProcess_MakeLeftHanded;
|
||||||
|
|
||||||
// Erase all pp steps that were already applied to this scene
|
// Erase all pp steps that were already applied to this scene
|
||||||
unsigned int pp = (gExporters[i].mEnforcePP | pPreprocessing) & ~(priv
|
unsigned int pp = (exp.mEnforcePP | pPreprocessing) & ~(priv
|
||||||
? (priv->mPPStepsApplied & ~nonIdempotentSteps)
|
? (priv->mPPStepsApplied & ~nonIdempotentSteps)
|
||||||
: 0u);
|
: 0u);
|
||||||
|
|
||||||
|
@ -282,7 +264,7 @@ aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbosify || (gExporters[i].mEnforcePP & aiProcess_JoinIdenticalVertices)) {
|
if (verbosify || (exp.mEnforcePP & aiProcess_JoinIdenticalVertices)) {
|
||||||
DefaultLogger::get()->debug("export: Scene data not in verbose format, applying MakeVerboseFormat step first");
|
DefaultLogger::get()->debug("export: Scene data not in verbose format, applying MakeVerboseFormat step first");
|
||||||
|
|
||||||
MakeVerboseFormatProcess proc;
|
MakeVerboseFormatProcess proc;
|
||||||
|
@ -331,7 +313,7 @@ aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const
|
||||||
privOut->mPPStepsApplied |= pp;
|
privOut->mPPStepsApplied |= pp;
|
||||||
}
|
}
|
||||||
|
|
||||||
gExporters[i].mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get());
|
exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get());
|
||||||
}
|
}
|
||||||
catch (DeadlyExportError& err) {
|
catch (DeadlyExportError& err) {
|
||||||
pimpl->mError = err.what();
|
pimpl->mError = err.what();
|
||||||
|
@ -383,18 +365,42 @@ const aiExportDataBlob* Exporter :: GetOrphanedBlob() const
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
size_t Exporter :: GetExportFormatCount() const
|
size_t Exporter :: GetExportFormatCount() const
|
||||||
{
|
{
|
||||||
return ASSIMP_NUM_EXPORTERS;
|
return pimpl->mExporters.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
const aiExportFormatDesc* Exporter :: GetExportFormatDescription( size_t pIndex ) const
|
const aiExportFormatDesc* Exporter :: GetExportFormatDescription( size_t pIndex ) const
|
||||||
{
|
{
|
||||||
if (pIndex >= ASSIMP_NUM_EXPORTERS) {
|
if (pIndex >= GetExportFormatCount()) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return &gExporters[pIndex].mDescription;
|
return &pimpl->mExporters[pIndex].mDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
aiReturn Exporter :: RegisterExporter(const ExportFormatEntry& desc)
|
||||||
|
{
|
||||||
|
BOOST_FOREACH(const ExportFormatEntry& e, pimpl->mExporters) {
|
||||||
|
if (!strcmp(e.mDescription.id,desc.mDescription.id)) {
|
||||||
|
return aiReturn_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pimpl->mExporters.push_back(desc);
|
||||||
|
return aiReturn_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void Exporter :: UnregisterExporter(const char* id)
|
||||||
|
{
|
||||||
|
for(std::vector<ExportFormatEntry>::iterator it = pimpl->mExporters.begin(); it != pimpl->mExporters.end(); ++it) {
|
||||||
|
if (!strcmp((*it).mDescription.id,id)) {
|
||||||
|
pimpl->mExporters.erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif // !ASSIMP_BUILD_NO_EXPORT
|
#endif // !ASSIMP_BUILD_NO_EXPORT
|
||||||
|
|
|
@ -52,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
class ExporterPimpl;
|
class ExporterPimpl;
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------
|
||||||
/** CPP-API: The Exporter class forms an C++ interface to the export functionality
|
/** CPP-API: The Exporter class forms an C++ interface to the export functionality
|
||||||
* of the Open Asset Import Library. Note that the export interface is available
|
* of the Open Asset Import Library. Note that the export interface is available
|
||||||
|
@ -76,6 +77,37 @@ class ASSIMP_API Exporter
|
||||||
// : public boost::noncopyable
|
// : public boost::noncopyable
|
||||||
//#endif // __cplusplus
|
//#endif // __cplusplus
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** Function pointer type of a Export worker function */
|
||||||
|
typedef void (*fpExportFunc)(const char*,IOSystem*,const aiScene*);
|
||||||
|
|
||||||
|
/** Internal description of an Assimp export format option */
|
||||||
|
struct ExportFormatEntry
|
||||||
|
{
|
||||||
|
/// Public description structure to be returned by aiGetExportFormatDescription()
|
||||||
|
aiExportFormatDesc mDescription;
|
||||||
|
|
||||||
|
// Worker function to do the actual exporting
|
||||||
|
fpExportFunc mExportFunction;
|
||||||
|
|
||||||
|
// Postprocessing steps to be executed PRIOR to invoking mExportFunction
|
||||||
|
unsigned int mEnforcePP;
|
||||||
|
|
||||||
|
// Constructor to fill all entries
|
||||||
|
ExportFormatEntry( const char* pId, const char* pDesc, const char* pExtension, fpExportFunc pFunction, unsigned int pEnforcePP = 0u)
|
||||||
|
{
|
||||||
|
mDescription.id = pId;
|
||||||
|
mDescription.description = pDesc;
|
||||||
|
mDescription.fileExtension = pExtension;
|
||||||
|
mExportFunction = pFunction;
|
||||||
|
mEnforcePP = pEnforcePP;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExportFormatEntry() : mExportFunction(), mEnforcePP() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
@ -223,6 +255,30 @@ public:
|
||||||
const aiExportFormatDesc* GetExportFormatDescription( size_t pIndex ) const;
|
const aiExportFormatDesc* GetExportFormatDescription( size_t pIndex ) const;
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
/** Register a custom exporter. Custom export formats are limited to
|
||||||
|
* to the current #Exporter instance and do not affect the
|
||||||
|
* library globally.
|
||||||
|
* @param desc Exporter description.
|
||||||
|
* @return aiReturn_SUCCESS if the export format was successfully
|
||||||
|
* registered. A common cause that would prevent an exporter
|
||||||
|
* from being registered is that its format id is already
|
||||||
|
* occupied by another format. */
|
||||||
|
aiReturn RegisterExporter(const ExportFormatEntry& desc);
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
/** Remove an export format previously registered with #RegisterExporter
|
||||||
|
* from the #Exporter instance (this can also be used to drop
|
||||||
|
* builtin exporters because those are implicitly registered
|
||||||
|
* using #RegisterExporter).
|
||||||
|
* @param id Format id to be unregistered, this refers to the
|
||||||
|
* 'id' field of #aiExportFormatDesc.
|
||||||
|
* @note Calling this method on a format description not yet registered
|
||||||
|
* has no effect.*/
|
||||||
|
void UnregisterExporter(const char* id);
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Just because we don't want you to know how we're hacking around.
|
// Just because we don't want you to know how we're hacking around.
|
||||||
|
|
Loading…
Reference in New Issue