Updated assimp to commit 1d565b0 with iFire
Signed-off-by: RevoluPowered <gordon@gordonite.tech> Signed-off-by: K. S. Ernest (iFIre) Lee <ernest.lee@chibifire.com>
This commit is contained in:
parent
73d2a99761
commit
243f400ee2
|
@ -9,6 +9,7 @@ env_assimp.Prepend(CPPPATH=['#thirdparty/assimp/include'])
|
|||
env_assimp.Prepend(CPPPATH=['#thirdparty/assimp/code/Importer/IFC'])
|
||||
env_assimp.Prepend(CPPPATH=['#thirdparty/misc'])
|
||||
env_assimp.Prepend(CPPPATH=['#thirdparty/assimp/code'])
|
||||
env_assimp.Prepend(CPPPATH=['#thirdparty/assimp/common'])
|
||||
env_assimp.Prepend(CPPPATH=['#thirdparty/assimp/contrib/irrXML/'])
|
||||
env_assimp.Prepend(CPPPATH=['#thirdparty/assimp/contrib/unzip/'])
|
||||
env_assimp.Prepend(CPPPATH=['#thirdparty/assimp/code/Importer/STEPParser'])
|
||||
|
@ -65,11 +66,11 @@ env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_STEP_IMPORTER'])
|
|||
env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_IFC_IMPORTER'])
|
||||
env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_XGL_IMPORTER'])
|
||||
env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_ASSBIN_IMPORTER'])
|
||||
env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_GLTF_IMPORTER'])
|
||||
env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_C4D_IMPORTER'])
|
||||
env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_3MF_IMPORTER'])
|
||||
env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_X3D_IMPORTER'])
|
||||
|
||||
env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_GLTF_IMPORTER'])
|
||||
env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_GLTF2_IMPORTER'])
|
||||
env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_SINGLETHREADED'])
|
||||
|
||||
if(env['platform'] == 'windows'):
|
||||
|
@ -84,7 +85,13 @@ elif(env['platform'] == 'osx'):
|
|||
|
||||
env_thirdparty = env_assimp.Clone()
|
||||
env_thirdparty.disable_warnings()
|
||||
env_thirdparty.add_source_files(env.modules_sources, Glob('#thirdparty/assimp/code/*.cpp'))
|
||||
env_thirdparty.add_source_files(env.modules_sources, Glob('#thirdparty/assimp/code/Common/*.cpp'))
|
||||
env_thirdparty.add_source_files(env.modules_sources, Glob('#thirdparty/assimp/code/PostProcessing/*.cpp'))
|
||||
env_thirdparty.add_source_files(env.modules_sources, Glob('#thirdparty/assimp/code/Material/*.cpp'))
|
||||
env_thirdparty.add_source_files(env.modules_sources, Glob('#thirdparty/assimp/code/FBX/*.cpp'))
|
||||
env_thirdparty.add_source_files(env.modules_sources, Glob('#thirdparty/assimp/code/MMD/*.cpp'))
|
||||
env_thirdparty.add_source_files(env.modules_sources, Glob('#thirdparty/assimp/code/glTF/*.cpp'))
|
||||
env_thirdparty.add_source_files(env.modules_sources, Glob('#thirdparty/assimp/code/glTF2/*.cpp'))
|
||||
|
||||
# Godot's own source files
|
||||
env_assimp.add_source_files(env.modules_sources, "*.cpp")
|
||||
|
|
|
@ -254,8 +254,9 @@ rm -rf contrib/irrXML
|
|||
rm -rf contrib/Open3DGC
|
||||
rm -rf contrib/openddlparser
|
||||
rm -rf contrib/poly2tri
|
||||
rm -rf contrib/rapidjson
|
||||
#rm -rf contrib/rapidjson
|
||||
rm -rf contrib/unzip
|
||||
rm -rf contrib/zip
|
||||
rm -rf contrib/stb_image
|
||||
rm .travis*
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
## assimp
|
||||
|
||||
- Upstream: http://github.com/assimp/assimp
|
||||
- Version: git (d3d98a7ec0c8d38e1952b46dfe53f7e9233dc92d)
|
||||
- Version: git (1d565b0aab5a2ee00462f18c5b8a81f6a5454a48)
|
||||
- License: BSD-3-Clause
|
||||
|
||||
|
||||
|
|
|
@ -646,6 +646,21 @@ enum aiComponent {
|
|||
#define AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING \
|
||||
"AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** @brief Set wether the FBX importer shall not remove empty bones.
|
||||
*
|
||||
*
|
||||
* Empty bone are often used to define connections for other models.
|
||||
*/
|
||||
#define AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES \
|
||||
"AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** @brief Set wether the FBX importer shall convert the unit from cm to m.
|
||||
*/
|
||||
#define AI_CONFIG_FBX_CONVERT_TO_M \
|
||||
"AI_CONFIG_FBX_CONVERT_TO_M"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** @brief Set the vertex animation keyframe to be imported
|
||||
*
|
||||
|
@ -978,3 +993,4 @@ enum aiComponent {
|
|||
/* #cmakedefine ASSIMP_DOUBLE_PRECISION 1 */
|
||||
|
||||
#endif // !! AI_CONFIG_H_INC
|
||||
|
||||
|
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the following
|
||||
conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file AssimpCExport.cpp
|
||||
Assimp C export interface. See Exporter.cpp for some notes.
|
||||
*/
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_EXPORT
|
||||
|
||||
#include "CInterfaceIOWrapper.h"
|
||||
#include <assimp/SceneCombiner.h>
|
||||
#include "Common/ScenePrivate.h"
|
||||
#include <assimp/Exporter.hpp>
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API size_t aiGetExportFormatCount(void)
|
||||
{
|
||||
return Exporter().GetExportFormatCount();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API const aiExportFormatDesc* aiGetExportFormatDescription( size_t index)
|
||||
{
|
||||
// Note: this is valid as the index always pertains to a built-in exporter,
|
||||
// for which the returned structure is guaranteed to be of static storage duration.
|
||||
Exporter exporter;
|
||||
const aiExportFormatDesc* orig( exporter.GetExportFormatDescription( index ) );
|
||||
if (NULL == orig) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
aiExportFormatDesc *desc = new aiExportFormatDesc;
|
||||
desc->description = new char[ strlen( orig->description ) + 1 ]();
|
||||
::strncpy( (char*) desc->description, orig->description, strlen( orig->description ) );
|
||||
desc->fileExtension = new char[ strlen( orig->fileExtension ) + 1 ]();
|
||||
::strncpy( ( char* ) desc->fileExtension, orig->fileExtension, strlen( orig->fileExtension ) );
|
||||
desc->id = new char[ strlen( orig->id ) + 1 ]();
|
||||
::strncpy( ( char* ) desc->id, orig->id, strlen( orig->id ) );
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API void aiReleaseExportFormatDescription( const aiExportFormatDesc *desc ) {
|
||||
if (NULL == desc) {
|
||||
return;
|
||||
}
|
||||
|
||||
delete [] desc->description;
|
||||
delete [] desc->fileExtension;
|
||||
delete [] desc->id;
|
||||
delete desc;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API void aiCopyScene(const aiScene* pIn, aiScene** pOut)
|
||||
{
|
||||
if (!pOut || !pIn) {
|
||||
return;
|
||||
}
|
||||
|
||||
SceneCombiner::CopyScene(pOut,pIn,true);
|
||||
ScenePriv(*pOut)->mIsCopy = true;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API void aiFreeScene(const C_STRUCT aiScene* pIn)
|
||||
{
|
||||
// note: aiReleaseImport() is also able to delete scene copies, but in addition
|
||||
// it also handles scenes with import metadata.
|
||||
delete pIn;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API aiReturn aiExportScene( const aiScene* pScene, const char* pFormatId, const char* pFileName, unsigned int pPreprocessing )
|
||||
{
|
||||
return ::aiExportSceneEx(pScene,pFormatId,pFileName,NULL,pPreprocessing);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API aiReturn aiExportSceneEx( const aiScene* pScene, const char* pFormatId, const char* pFileName, aiFileIO* pIO, unsigned int pPreprocessing )
|
||||
{
|
||||
Exporter exp;
|
||||
|
||||
if (pIO) {
|
||||
exp.SetIOHandler(new CIOSystemWrapper(pIO));
|
||||
}
|
||||
return exp.Export(pScene,pFormatId,pFileName,pPreprocessing);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API const C_STRUCT aiExportDataBlob* aiExportSceneToBlob( const aiScene* pScene, const char* pFormatId, unsigned int pPreprocessing )
|
||||
{
|
||||
Exporter exp;
|
||||
if (!exp.ExportToBlob(pScene,pFormatId,pPreprocessing)) {
|
||||
return NULL;
|
||||
}
|
||||
const aiExportDataBlob* blob = exp.GetOrphanedBlob();
|
||||
ai_assert(blob);
|
||||
|
||||
return blob;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API C_STRUCT void aiReleaseExportBlob( const aiExportDataBlob* pData )
|
||||
{
|
||||
delete pData;
|
||||
}
|
||||
|
||||
#endif // !ASSIMP_BUILD_NO_EXPORT
|
|
@ -0,0 +1,695 @@
|
|||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the following
|
||||
conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
---------------------------------------------------------------------------
|
||||
*/
|
||||
/** @file Assimp.cpp
|
||||
* @brief Implementation of the Plain-C API
|
||||
*/
|
||||
|
||||
#include <assimp/cimport.h>
|
||||
#include <assimp/LogStream.hpp>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
#include <assimp/Importer.hpp>
|
||||
#include <assimp/importerdesc.h>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/GenericProperty.h>
|
||||
#include <assimp/Exceptional.h>
|
||||
#include <assimp/BaseImporter.h>
|
||||
|
||||
#include "CApi/CInterfaceIOWrapper.h"
|
||||
#include "Importer.h"
|
||||
#include "ScenePrivate.h"
|
||||
|
||||
#include <list>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#ifndef ASSIMP_BUILD_SINGLETHREADED
|
||||
# include <thread>
|
||||
# include <mutex>
|
||||
#endif
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
using namespace Assimp;
|
||||
|
||||
namespace Assimp {
|
||||
// underlying structure for aiPropertyStore
|
||||
typedef BatchLoader::PropertyMap PropertyMap;
|
||||
|
||||
/** Stores the LogStream objects for all active C log streams */
|
||||
struct mpred {
|
||||
bool operator () (const aiLogStream& s0, const aiLogStream& s1) const {
|
||||
return s0.callback<s1.callback&&s0.user<s1.user;
|
||||
}
|
||||
};
|
||||
typedef std::map<aiLogStream, Assimp::LogStream*, mpred> LogStreamMap;
|
||||
|
||||
/** Stores the LogStream objects allocated by #aiGetPredefinedLogStream */
|
||||
typedef std::list<Assimp::LogStream*> PredefLogStreamMap;
|
||||
|
||||
/** Local storage of all active log streams */
|
||||
static LogStreamMap gActiveLogStreams;
|
||||
|
||||
/** Local storage of LogStreams allocated by #aiGetPredefinedLogStream */
|
||||
static PredefLogStreamMap gPredefinedStreams;
|
||||
|
||||
/** Error message of the last failed import process */
|
||||
static std::string gLastErrorString;
|
||||
|
||||
/** Verbose logging active or not? */
|
||||
static aiBool gVerboseLogging = false;
|
||||
|
||||
/** will return all registered importers. */
|
||||
void GetImporterInstanceList(std::vector< BaseImporter* >& out);
|
||||
|
||||
/** will delete all registered importers. */
|
||||
void DeleteImporterInstanceList(std::vector< BaseImporter* >& out);
|
||||
} // namespace assimp
|
||||
|
||||
|
||||
#ifndef ASSIMP_BUILD_SINGLETHREADED
|
||||
/** Global mutex to manage the access to the log-stream map */
|
||||
static std::mutex gLogStreamMutex;
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Custom LogStream implementation for the C-API
|
||||
class LogToCallbackRedirector : public LogStream {
|
||||
public:
|
||||
explicit LogToCallbackRedirector(const aiLogStream& s)
|
||||
: stream (s) {
|
||||
ai_assert(NULL != s.callback);
|
||||
}
|
||||
|
||||
~LogToCallbackRedirector() {
|
||||
#ifndef ASSIMP_BUILD_SINGLETHREADED
|
||||
std::lock_guard<std::mutex> lock(gLogStreamMutex);
|
||||
#endif
|
||||
// (HACK) Check whether the 'stream.user' pointer points to a
|
||||
// custom LogStream allocated by #aiGetPredefinedLogStream.
|
||||
// In this case, we need to delete it, too. Of course, this
|
||||
// might cause strange problems, but the chance is quite low.
|
||||
|
||||
PredefLogStreamMap::iterator it = std::find(gPredefinedStreams.begin(),
|
||||
gPredefinedStreams.end(), (Assimp::LogStream*)stream.user);
|
||||
|
||||
if (it != gPredefinedStreams.end()) {
|
||||
delete *it;
|
||||
gPredefinedStreams.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
/** @copydoc LogStream::write */
|
||||
void write(const char* message) {
|
||||
stream.callback(message,stream.user);
|
||||
}
|
||||
|
||||
private:
|
||||
aiLogStream stream;
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ReportSceneNotFoundError() {
|
||||
ASSIMP_LOG_ERROR("Unable to find the Assimp::Importer for this aiScene. "
|
||||
"The C-API does not accept scenes produced by the C++ API and vice versa");
|
||||
|
||||
ai_assert(false);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Reads the given file and returns its content.
|
||||
const aiScene* aiImportFile( const char* pFile, unsigned int pFlags) {
|
||||
return aiImportFileEx(pFile,pFlags,NULL);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const aiScene* aiImportFileEx( const char* pFile, unsigned int pFlags, aiFileIO* pFS) {
|
||||
return aiImportFileExWithProperties(pFile, pFlags, pFS, NULL);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFlags,
|
||||
aiFileIO* pFS, const aiPropertyStore* props) {
|
||||
ai_assert(NULL != pFile);
|
||||
|
||||
const aiScene* scene = NULL;
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
|
||||
// create an Importer for this file
|
||||
Assimp::Importer* imp = new Assimp::Importer();
|
||||
|
||||
// copy properties
|
||||
if(props) {
|
||||
const PropertyMap* pp = reinterpret_cast<const PropertyMap*>(props);
|
||||
ImporterPimpl* pimpl = imp->Pimpl();
|
||||
pimpl->mIntProperties = pp->ints;
|
||||
pimpl->mFloatProperties = pp->floats;
|
||||
pimpl->mStringProperties = pp->strings;
|
||||
pimpl->mMatrixProperties = pp->matrices;
|
||||
}
|
||||
// setup a custom IO system if necessary
|
||||
if (pFS) {
|
||||
imp->SetIOHandler( new CIOSystemWrapper (pFS) );
|
||||
}
|
||||
|
||||
// and have it read the file
|
||||
scene = imp->ReadFile( pFile, pFlags);
|
||||
|
||||
// if succeeded, store the importer in the scene and keep it alive
|
||||
if( scene) {
|
||||
ScenePrivateData* priv = const_cast<ScenePrivateData*>( ScenePriv(scene) );
|
||||
priv->mOrigImporter = imp;
|
||||
} else {
|
||||
// if failed, extract error code and destroy the import
|
||||
gLastErrorString = imp->GetErrorString();
|
||||
delete imp;
|
||||
}
|
||||
|
||||
// return imported data. If the import failed the pointer is NULL anyways
|
||||
ASSIMP_END_EXCEPTION_REGION(const aiScene*);
|
||||
|
||||
return scene;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const aiScene* aiImportFileFromMemory(
|
||||
const char* pBuffer,
|
||||
unsigned int pLength,
|
||||
unsigned int pFlags,
|
||||
const char* pHint)
|
||||
{
|
||||
return aiImportFileFromMemoryWithProperties(pBuffer, pLength, pFlags, pHint, NULL);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const aiScene* aiImportFileFromMemoryWithProperties(
|
||||
const char* pBuffer,
|
||||
unsigned int pLength,
|
||||
unsigned int pFlags,
|
||||
const char* pHint,
|
||||
const aiPropertyStore* props)
|
||||
{
|
||||
ai_assert( NULL != pBuffer );
|
||||
ai_assert( 0 != pLength );
|
||||
|
||||
const aiScene* scene = NULL;
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
|
||||
// create an Importer for this file
|
||||
Assimp::Importer* imp = new Assimp::Importer();
|
||||
|
||||
// copy properties
|
||||
if(props) {
|
||||
const PropertyMap* pp = reinterpret_cast<const PropertyMap*>(props);
|
||||
ImporterPimpl* pimpl = imp->Pimpl();
|
||||
pimpl->mIntProperties = pp->ints;
|
||||
pimpl->mFloatProperties = pp->floats;
|
||||
pimpl->mStringProperties = pp->strings;
|
||||
pimpl->mMatrixProperties = pp->matrices;
|
||||
}
|
||||
|
||||
// and have it read the file from the memory buffer
|
||||
scene = imp->ReadFileFromMemory( pBuffer, pLength, pFlags,pHint);
|
||||
|
||||
// if succeeded, store the importer in the scene and keep it alive
|
||||
if( scene) {
|
||||
ScenePrivateData* priv = const_cast<ScenePrivateData*>( ScenePriv(scene) );
|
||||
priv->mOrigImporter = imp;
|
||||
}
|
||||
else {
|
||||
// if failed, extract error code and destroy the import
|
||||
gLastErrorString = imp->GetErrorString();
|
||||
delete imp;
|
||||
}
|
||||
// return imported data. If the import failed the pointer is NULL anyways
|
||||
ASSIMP_END_EXCEPTION_REGION(const aiScene*);
|
||||
return scene;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Releases all resources associated with the given import process.
|
||||
void aiReleaseImport( const aiScene* pScene)
|
||||
{
|
||||
if (!pScene) {
|
||||
return;
|
||||
}
|
||||
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
|
||||
// find the importer associated with this data
|
||||
const ScenePrivateData* priv = ScenePriv(pScene);
|
||||
if( !priv || !priv->mOrigImporter) {
|
||||
delete pScene;
|
||||
}
|
||||
else {
|
||||
// deleting the Importer also deletes the scene
|
||||
// Note: the reason that this is not written as 'delete priv->mOrigImporter'
|
||||
// is a suspected bug in gcc 4.4+ (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52339)
|
||||
Importer* importer = priv->mOrigImporter;
|
||||
delete importer;
|
||||
}
|
||||
|
||||
ASSIMP_END_EXCEPTION_REGION(void);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API const aiScene* aiApplyPostProcessing(const aiScene* pScene,
|
||||
unsigned int pFlags)
|
||||
{
|
||||
const aiScene* sc = NULL;
|
||||
|
||||
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
|
||||
// find the importer associated with this data
|
||||
const ScenePrivateData* priv = ScenePriv(pScene);
|
||||
if( !priv || !priv->mOrigImporter) {
|
||||
ReportSceneNotFoundError();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sc = priv->mOrigImporter->ApplyPostProcessing(pFlags);
|
||||
|
||||
if (!sc) {
|
||||
aiReleaseImport(pScene);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ASSIMP_END_EXCEPTION_REGION(const aiScene*);
|
||||
return sc;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API const aiScene *aiApplyCustomizedPostProcessing( const aiScene *scene,
|
||||
BaseProcess* process,
|
||||
bool requestValidation ) {
|
||||
const aiScene* sc( NULL );
|
||||
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
|
||||
// find the importer associated with this data
|
||||
const ScenePrivateData* priv = ScenePriv( scene );
|
||||
if ( NULL == priv || NULL == priv->mOrigImporter ) {
|
||||
ReportSceneNotFoundError();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sc = priv->mOrigImporter->ApplyCustomizedPostProcessing( process, requestValidation );
|
||||
|
||||
if ( !sc ) {
|
||||
aiReleaseImport( scene );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ASSIMP_END_EXCEPTION_REGION( const aiScene* );
|
||||
|
||||
return sc;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void CallbackToLogRedirector (const char* msg, char* dt)
|
||||
{
|
||||
ai_assert( NULL != msg );
|
||||
ai_assert( NULL != dt );
|
||||
LogStream* s = (LogStream*)dt;
|
||||
|
||||
s->write(msg);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API aiLogStream aiGetPredefinedLogStream(aiDefaultLogStream pStream,const char* file)
|
||||
{
|
||||
aiLogStream sout;
|
||||
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
LogStream* stream = LogStream::createDefaultStream(pStream,file);
|
||||
if (!stream) {
|
||||
sout.callback = NULL;
|
||||
sout.user = NULL;
|
||||
}
|
||||
else {
|
||||
sout.callback = &CallbackToLogRedirector;
|
||||
sout.user = (char*)stream;
|
||||
}
|
||||
gPredefinedStreams.push_back(stream);
|
||||
ASSIMP_END_EXCEPTION_REGION(aiLogStream);
|
||||
return sout;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API void aiAttachLogStream( const aiLogStream* stream )
|
||||
{
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
|
||||
#ifndef ASSIMP_BUILD_SINGLETHREADED
|
||||
std::lock_guard<std::mutex> lock(gLogStreamMutex);
|
||||
#endif
|
||||
|
||||
LogStream* lg = new LogToCallbackRedirector(*stream);
|
||||
gActiveLogStreams[*stream] = lg;
|
||||
|
||||
if (DefaultLogger::isNullLogger()) {
|
||||
DefaultLogger::create(NULL,(gVerboseLogging == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL));
|
||||
}
|
||||
DefaultLogger::get()->attachStream(lg);
|
||||
ASSIMP_END_EXCEPTION_REGION(void);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API aiReturn aiDetachLogStream( const aiLogStream* stream)
|
||||
{
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
|
||||
#ifndef ASSIMP_BUILD_SINGLETHREADED
|
||||
std::lock_guard<std::mutex> lock(gLogStreamMutex);
|
||||
#endif
|
||||
// find the log-stream associated with this data
|
||||
LogStreamMap::iterator it = gActiveLogStreams.find( *stream);
|
||||
// it should be there... else the user is playing fools with us
|
||||
if( it == gActiveLogStreams.end()) {
|
||||
return AI_FAILURE;
|
||||
}
|
||||
DefaultLogger::get()->detatchStream( it->second );
|
||||
delete it->second;
|
||||
|
||||
gActiveLogStreams.erase( it);
|
||||
|
||||
if (gActiveLogStreams.empty()) {
|
||||
DefaultLogger::kill();
|
||||
}
|
||||
ASSIMP_END_EXCEPTION_REGION(aiReturn);
|
||||
return AI_SUCCESS;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API void aiDetachAllLogStreams(void)
|
||||
{
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
#ifndef ASSIMP_BUILD_SINGLETHREADED
|
||||
std::lock_guard<std::mutex> lock(gLogStreamMutex);
|
||||
#endif
|
||||
Logger *logger( DefaultLogger::get() );
|
||||
if ( NULL == logger ) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (LogStreamMap::iterator it = gActiveLogStreams.begin(); it != gActiveLogStreams.end(); ++it) {
|
||||
logger->detatchStream( it->second );
|
||||
delete it->second;
|
||||
}
|
||||
gActiveLogStreams.clear();
|
||||
DefaultLogger::kill();
|
||||
|
||||
ASSIMP_END_EXCEPTION_REGION(void);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API void aiEnableVerboseLogging(aiBool d)
|
||||
{
|
||||
if (!DefaultLogger::isNullLogger()) {
|
||||
DefaultLogger::get()->setLogSeverity((d == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL));
|
||||
}
|
||||
gVerboseLogging = d;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns the error text of the last failed import process.
|
||||
const char* aiGetErrorString()
|
||||
{
|
||||
return gLastErrorString.c_str();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
// Return the description of a importer given its index
|
||||
const aiImporterDesc* aiGetImportFormatDescription( size_t pIndex)
|
||||
{
|
||||
return Importer().GetImporterInfo(pIndex);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
// Return the number of importers
|
||||
size_t aiGetImportFormatCount(void)
|
||||
{
|
||||
return Importer().GetImporterCount();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns the error text of the last failed import process.
|
||||
aiBool aiIsExtensionSupported(const char* szExtension)
|
||||
{
|
||||
ai_assert(NULL != szExtension);
|
||||
aiBool candoit=AI_FALSE;
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
|
||||
// FIXME: no need to create a temporary Importer instance just for that ..
|
||||
Assimp::Importer tmp;
|
||||
candoit = tmp.IsExtensionSupported(std::string(szExtension)) ? AI_TRUE : AI_FALSE;
|
||||
|
||||
ASSIMP_END_EXCEPTION_REGION(aiBool);
|
||||
return candoit;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Get a list of all file extensions supported by ASSIMP
|
||||
void aiGetExtensionList(aiString* szOut)
|
||||
{
|
||||
ai_assert(NULL != szOut);
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
|
||||
// FIXME: no need to create a temporary Importer instance just for that ..
|
||||
Assimp::Importer tmp;
|
||||
tmp.GetExtensionList(*szOut);
|
||||
|
||||
ASSIMP_END_EXCEPTION_REGION(void);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Get the memory requirements for a particular import.
|
||||
void aiGetMemoryRequirements(const C_STRUCT aiScene* pIn,
|
||||
C_STRUCT aiMemoryInfo* in)
|
||||
{
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
|
||||
// find the importer associated with this data
|
||||
const ScenePrivateData* priv = ScenePriv(pIn);
|
||||
if( !priv || !priv->mOrigImporter) {
|
||||
ReportSceneNotFoundError();
|
||||
return;
|
||||
}
|
||||
|
||||
return priv->mOrigImporter->GetMemoryRequirements(*in);
|
||||
ASSIMP_END_EXCEPTION_REGION(void);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API aiPropertyStore* aiCreatePropertyStore(void)
|
||||
{
|
||||
return reinterpret_cast<aiPropertyStore*>( new PropertyMap() );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API void aiReleasePropertyStore(aiPropertyStore* p)
|
||||
{
|
||||
delete reinterpret_cast<PropertyMap*>(p);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Importer::SetPropertyInteger
|
||||
ASSIMP_API void aiSetImportPropertyInteger(aiPropertyStore* p, const char* szName, int value)
|
||||
{
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
|
||||
SetGenericProperty<int>(pp->ints,szName,value);
|
||||
ASSIMP_END_EXCEPTION_REGION(void);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Importer::SetPropertyFloat
|
||||
ASSIMP_API void aiSetImportPropertyFloat(aiPropertyStore* p, const char* szName, ai_real value)
|
||||
{
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
|
||||
SetGenericProperty<ai_real>(pp->floats,szName,value);
|
||||
ASSIMP_END_EXCEPTION_REGION(void);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Importer::SetPropertyString
|
||||
ASSIMP_API void aiSetImportPropertyString(aiPropertyStore* p, const char* szName,
|
||||
const C_STRUCT aiString* st)
|
||||
{
|
||||
if (!st) {
|
||||
return;
|
||||
}
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
|
||||
SetGenericProperty<std::string>(pp->strings,szName,std::string(st->C_Str()));
|
||||
ASSIMP_END_EXCEPTION_REGION(void);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Importer::SetPropertyMatrix
|
||||
ASSIMP_API void aiSetImportPropertyMatrix(aiPropertyStore* p, const char* szName,
|
||||
const C_STRUCT aiMatrix4x4* mat)
|
||||
{
|
||||
if (!mat) {
|
||||
return;
|
||||
}
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
|
||||
SetGenericProperty<aiMatrix4x4>(pp->matrices,szName,*mat);
|
||||
ASSIMP_END_EXCEPTION_REGION(void);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Rotation matrix to quaternion
|
||||
ASSIMP_API void aiCreateQuaternionFromMatrix(aiQuaternion* quat,const aiMatrix3x3* mat)
|
||||
{
|
||||
ai_assert( NULL != quat );
|
||||
ai_assert( NULL != mat );
|
||||
*quat = aiQuaternion(*mat);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Matrix decomposition
|
||||
ASSIMP_API void aiDecomposeMatrix(const aiMatrix4x4* mat,aiVector3D* scaling,
|
||||
aiQuaternion* rotation,
|
||||
aiVector3D* position)
|
||||
{
|
||||
ai_assert( NULL != rotation );
|
||||
ai_assert( NULL != position );
|
||||
ai_assert( NULL != scaling );
|
||||
ai_assert( NULL != mat );
|
||||
mat->Decompose(*scaling,*rotation,*position);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Matrix transpose
|
||||
ASSIMP_API void aiTransposeMatrix3(aiMatrix3x3* mat)
|
||||
{
|
||||
ai_assert(NULL != mat);
|
||||
mat->Transpose();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API void aiTransposeMatrix4(aiMatrix4x4* mat)
|
||||
{
|
||||
ai_assert(NULL != mat);
|
||||
mat->Transpose();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Vector transformation
|
||||
ASSIMP_API void aiTransformVecByMatrix3(aiVector3D* vec,
|
||||
const aiMatrix3x3* mat)
|
||||
{
|
||||
ai_assert( NULL != mat );
|
||||
ai_assert( NULL != vec);
|
||||
*vec *= (*mat);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API void aiTransformVecByMatrix4(aiVector3D* vec,
|
||||
const aiMatrix4x4* mat)
|
||||
{
|
||||
ai_assert( NULL != mat );
|
||||
ai_assert( NULL != vec );
|
||||
|
||||
*vec *= (*mat);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Matrix multiplication
|
||||
ASSIMP_API void aiMultiplyMatrix4(
|
||||
aiMatrix4x4* dst,
|
||||
const aiMatrix4x4* src)
|
||||
{
|
||||
ai_assert( NULL != dst );
|
||||
ai_assert( NULL != src );
|
||||
*dst = (*dst) * (*src);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API void aiMultiplyMatrix3(
|
||||
aiMatrix3x3* dst,
|
||||
const aiMatrix3x3* src)
|
||||
{
|
||||
ai_assert( NULL != dst );
|
||||
ai_assert( NULL != src );
|
||||
*dst = (*dst) * (*src);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Matrix identity
|
||||
ASSIMP_API void aiIdentityMatrix3(
|
||||
aiMatrix3x3* mat)
|
||||
{
|
||||
ai_assert(NULL != mat);
|
||||
*mat = aiMatrix3x3();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API void aiIdentityMatrix4(
|
||||
aiMatrix4x4* mat)
|
||||
{
|
||||
ai_assert(NULL != mat);
|
||||
*mat = aiMatrix4x4();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API C_STRUCT const aiImporterDesc* aiGetImporterDesc( const char *extension ) {
|
||||
if( NULL == extension ) {
|
||||
return NULL;
|
||||
}
|
||||
const aiImporterDesc *desc( NULL );
|
||||
std::vector< BaseImporter* > out;
|
||||
GetImporterInstanceList( out );
|
||||
for( size_t i = 0; i < out.size(); ++i ) {
|
||||
if( 0 == strncmp( out[ i ]->GetInfo()->mFileExtensions, extension, strlen( extension ) ) ) {
|
||||
desc = out[ i ]->GetInfo();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DeleteImporterInstanceList(out);
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
|
@ -320,7 +320,11 @@ std::string BaseImporter::GetExtension( const std::string& file ) {
|
|||
return false;
|
||||
}
|
||||
|
||||
#include "../contrib/utf8cpp/source/utf8.h"
|
||||
#ifdef ASSIMP_USE_HUNTER
|
||||
# include <utf8/utf8.h>
|
||||
#else
|
||||
# include "../contrib/utf8cpp/source/utf8.h"
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Convert to UTF8 data
|
|
@ -89,7 +89,7 @@ void BaseProcess::ExecuteOnScene( Importer* pImp)
|
|||
|
||||
// and kill the partially imported data
|
||||
delete pImp->Pimpl()->mScene;
|
||||
pImp->Pimpl()->mScene = NULL;
|
||||
pImp->Pimpl()->mScene = nullptr;
|
||||
}
|
||||
}
|
||||
|
|
@ -47,10 +47,6 @@ namespace Assimp {
|
|||
aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh)
|
||||
{
|
||||
aiAnimMesh *animesh = new aiAnimMesh;
|
||||
animesh->mVertices = NULL;
|
||||
animesh->mNormals = NULL;
|
||||
animesh->mTangents = NULL;
|
||||
animesh->mBitangents = NULL;
|
||||
animesh->mNumVertices = mesh->mNumVertices;
|
||||
if (mesh->mVertices) {
|
||||
animesh->mVertices = new aiVector3D[animesh->mNumVertices];
|
|
@ -61,15 +61,16 @@ Here we implement only the C++ interface (Assimp::Exporter).
|
|||
#include <assimp/mesh.h>
|
||||
#include <assimp/postprocess.h>
|
||||
#include <assimp/scene.h>
|
||||
|
||||
#include "DefaultProgressHandler.h"
|
||||
#include "BaseProcess.h"
|
||||
#include "JoinVerticesProcess.h"
|
||||
#include "MakeVerboseFormat.h"
|
||||
#include "ConvertToLHProcess.h"
|
||||
#include "PretransformVertices.h"
|
||||
#include <assimp/Exceptional.h>
|
||||
#include "ScenePrivate.h"
|
||||
|
||||
#include "Common/DefaultProgressHandler.h"
|
||||
#include "Common/BaseProcess.h"
|
||||
#include "Common/ScenePrivate.h"
|
||||
#include "PostProcessing/CalcTangentsProcess.h"
|
||||
#include "PostProcessing/MakeVerboseFormat.h"
|
||||
#include "PostProcessing/JoinVerticesProcess.h"
|
||||
#include "PostProcessing/ConvertToLHProcess.h"
|
||||
#include "PostProcessing/PretransformVertices.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
@ -101,6 +102,7 @@ void ExportSceneX3D(const char*, IOSystem*, const aiScene*, const ExportProperti
|
|||
void ExportSceneFBX(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||
void ExportSceneFBXA(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||
void ExportScene3MF( const char*, IOSystem*, const aiScene*, const ExportProperties* );
|
||||
void ExportAssimp2Json(const char* , IOSystem*, const aiScene* , const Assimp::ExportProperties*);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// global array of all export formats which Assimp supports in its current build
|
||||
|
@ -161,11 +163,11 @@ Exporter::ExportFormatEntry gExporters[] =
|
|||
#endif
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
|
||||
Exporter::ExportFormatEntry( "assbin", "Assimp Binary", "assbin" , &ExportSceneAssbin, 0 ),
|
||||
Exporter::ExportFormatEntry( "assbin", "Assimp Binary File", "assbin" , &ExportSceneAssbin, 0 ),
|
||||
#endif
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER
|
||||
Exporter::ExportFormatEntry( "assxml", "Assxml Document", "assxml" , &ExportSceneAssxml, 0 ),
|
||||
Exporter::ExportFormatEntry( "assxml", "Assimp XML Document", "assxml" , &ExportSceneAssxml, 0 ),
|
||||
#endif
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_EXPORTER
|
||||
|
@ -178,7 +180,11 @@ Exporter::ExportFormatEntry gExporters[] =
|
|||
#endif
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_3MF_EXPORTER
|
||||
Exporter::ExportFormatEntry( "3mf", "The 3MF-File-Format", "3mf", &ExportScene3MF, 0 )
|
||||
Exporter::ExportFormatEntry( "3mf", "The 3MF-File-Format", "3mf", &ExportScene3MF, 0 ),
|
||||
#endif
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_ASSJSON_EXPORTER
|
||||
Exporter::ExportFormatEntry( "assjson", "Assimp JSON Document", "json", &ExportAssimp2Json, 0)
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -288,7 +294,7 @@ void Exporter::SetProgressHandler(ProgressHandler* pHandler) {
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const aiExportDataBlob* Exporter::ExportToBlob( const aiScene* pScene, const char* pFormatId,
|
||||
unsigned int, const ExportProperties* /*pProperties*/ ) {
|
||||
unsigned int pPreprocessing, const ExportProperties* pProperties) {
|
||||
if (pimpl->blob) {
|
||||
delete pimpl->blob;
|
||||
pimpl->blob = nullptr;
|
||||
|
@ -298,7 +304,7 @@ const aiExportDataBlob* Exporter::ExportToBlob( const aiScene* pScene, const cha
|
|||
BlobIOSystem* blobio = new BlobIOSystem();
|
||||
pimpl->mIOSystem = std::shared_ptr<IOSystem>( blobio );
|
||||
|
||||
if (AI_SUCCESS != Export(pScene,pFormatId,blobio->GetMagicFileName())) {
|
||||
if (AI_SUCCESS != Export(pScene,pFormatId,blobio->GetMagicFileName(), pPreprocessing, pProperties)) {
|
||||
pimpl->mIOSystem = old;
|
||||
return nullptr;
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
// Definitions for the Interchange File Format (IFF)
|
||||
// Alexander Gessler, 2006
|
||||
// Adapted to Assimp August 2008
|
||||
|
||||
#ifndef AI_IFF_H_INCLUDED
|
||||
#define AI_IFF_H_INCLUDED
|
||||
|
||||
#include <assimp/ByteSwapper.h>
|
||||
|
||||
namespace Assimp {
|
||||
namespace IFF {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//! Describes an IFF chunk header
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
struct ChunkHeader
|
||||
{
|
||||
//! Type of the chunk header - FourCC
|
||||
uint32_t type;
|
||||
|
||||
//! Length of the chunk data, in bytes
|
||||
uint32_t length;
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//! Describes an IFF sub chunk header
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
struct SubChunkHeader
|
||||
{
|
||||
//! Type of the chunk header - FourCC
|
||||
uint32_t type;
|
||||
|
||||
//! Length of the chunk data, in bytes
|
||||
uint16_t length;
|
||||
};
|
||||
|
||||
|
||||
#define AI_IFF_FOURCC(a,b,c,d) ((uint32_t) (((uint8_t)a << 24u) | \
|
||||
((uint8_t)b << 16u) | ((uint8_t)c << 8u) | ((uint8_t)d)))
|
||||
|
||||
|
||||
#define AI_IFF_FOURCC_FORM AI_IFF_FOURCC('F','O','R','M')
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//! Load a chunk header
|
||||
//! @param outFile Pointer to the file data - points to the chunk data afterwards
|
||||
//! @return Copy of the chunk header
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
inline ChunkHeader LoadChunk(uint8_t*& outFile)
|
||||
{
|
||||
ChunkHeader head;
|
||||
::memcpy(&head.type, outFile, 4);
|
||||
outFile += 4;
|
||||
::memcpy(&head.length, outFile, 4);
|
||||
outFile += 4;
|
||||
AI_LSWAP4(head.length);
|
||||
AI_LSWAP4(head.type);
|
||||
return head;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//! Load a sub chunk header
|
||||
//! @param outFile Pointer to the file data - points to the chunk data afterwards
|
||||
//! @return Copy of the sub chunk header
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
inline SubChunkHeader LoadSubChunk(uint8_t*& outFile)
|
||||
{
|
||||
SubChunkHeader head;
|
||||
::memcpy(&head.type, outFile, 4);
|
||||
outFile += 4;
|
||||
::memcpy(&head.length, outFile, 2);
|
||||
outFile += 2;
|
||||
AI_LSWAP2(head.length);
|
||||
AI_LSWAP4(head.type);
|
||||
return head;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//! Read the file header and return the type of the file and its size
|
||||
//! @param outFile Pointer to the file data. The buffer must at
|
||||
//! least be 12 bytes large.
|
||||
//! @param fileType Receives the type of the file
|
||||
//! @return 0 if everything was OK, otherwise an error message
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
inline const char* ReadHeader(uint8_t* outFile, uint32_t& fileType)
|
||||
{
|
||||
ChunkHeader head = LoadChunk(outFile);
|
||||
if(AI_IFF_FOURCC_FORM != head.type)
|
||||
{
|
||||
return "The file is not an IFF file: FORM chunk is missing";
|
||||
}
|
||||
::memcpy(&fileType, outFile, 4);
|
||||
AI_LSWAP4(fileType);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
|
||||
#endif // !! AI_IFF_H_INCLUDED
|
|
@ -64,15 +64,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// Internal headers
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Importer.h"
|
||||
#include <assimp/BaseImporter.h>
|
||||
#include "BaseProcess.h"
|
||||
#include "Common/Importer.h"
|
||||
#include "Common/BaseProcess.h"
|
||||
#include "Common/DefaultProgressHandler.h"
|
||||
#include "PostProcessing/ProcessHelper.h"
|
||||
#include "Common/ScenePreprocessor.h"
|
||||
#include "Common/ScenePrivate.h"
|
||||
|
||||
#include "DefaultProgressHandler.h"
|
||||
#include <assimp/BaseImporter.h>
|
||||
#include <assimp/GenericProperty.h>
|
||||
#include "ProcessHelper.h"
|
||||
#include "ScenePreprocessor.h"
|
||||
#include "ScenePrivate.h"
|
||||
#include <assimp/MemoryIOWrapper.h>
|
||||
#include <assimp/Profiler.h>
|
||||
#include <assimp/TinyFormatter.h>
|
||||
|
@ -86,7 +86,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <assimp/DefaultIOSystem.h>
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
|
||||
# include "ValidateDataStructure.h"
|
||||
# include "PostProcessing/ValidateDataStructure.h"
|
||||
#endif
|
||||
|
||||
using namespace Assimp::Profiling;
|
||||
|
@ -590,10 +590,12 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
|
|||
|
||||
// Find an worker class which can handle the file
|
||||
BaseImporter* imp = NULL;
|
||||
SetPropertyInteger("importerIndex", -1);
|
||||
for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) {
|
||||
|
||||
if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, false)) {
|
||||
imp = pimpl->mImporter[a];
|
||||
SetPropertyInteger("importerIndex", a);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -606,6 +608,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
|
|||
for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) {
|
||||
if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, true)) {
|
||||
imp = pimpl->mImporter[a];
|
||||
SetPropertyInteger("importerIndex", a);
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -56,146 +56,146 @@ corresponding preprocessor flag to selectively disable formats.
|
|||
// (include_new_importers_here)
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#ifndef ASSIMP_BUILD_NO_X_IMPORTER
|
||||
# include "XFileImporter.h"
|
||||
# include "X/XFileImporter.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
|
||||
# include "AMFImporter.hpp"
|
||||
# include "AMF/AMFImporter.hpp"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
|
||||
# include "3DSLoader.h"
|
||||
# include "3DS/3DSLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_MD3_IMPORTER
|
||||
# include "MD3Loader.h"
|
||||
# include "MD3/MD3Loader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_MDL_IMPORTER
|
||||
# include "MDLLoader.h"
|
||||
# include "MDL/MDLLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_MD2_IMPORTER
|
||||
# include "MD2Loader.h"
|
||||
# include "MD2/MD2Loader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_PLY_IMPORTER
|
||||
# include "PlyLoader.h"
|
||||
# include "Ply/PlyLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
|
||||
# include "ASELoader.h"
|
||||
# include "ASE/ASELoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_OBJ_IMPORTER
|
||||
# include "ObjFileImporter.h"
|
||||
# include "Obj/ObjFileImporter.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_HMP_IMPORTER
|
||||
# include "HMPLoader.h"
|
||||
# include "HMP/HMPLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_SMD_IMPORTER
|
||||
# include "SMDLoader.h"
|
||||
# include "SMD/SMDLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_MDC_IMPORTER
|
||||
# include "MDCLoader.h"
|
||||
# include "MDC/MDCLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_MD5_IMPORTER
|
||||
# include "MD5Loader.h"
|
||||
# include "MD5/MD5Loader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_STL_IMPORTER
|
||||
# include "STLLoader.h"
|
||||
# include "STL/STLLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_LWO_IMPORTER
|
||||
# include "LWOLoader.h"
|
||||
# include "LWO/LWOLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_DXF_IMPORTER
|
||||
# include "DXFLoader.h"
|
||||
# include "DXF/DXFLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_NFF_IMPORTER
|
||||
# include "NFFLoader.h"
|
||||
# include "NFF/NFFLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_RAW_IMPORTER
|
||||
# include "RawLoader.h"
|
||||
# include "Raw/RawLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_SIB_IMPORTER
|
||||
# include "SIBImporter.h"
|
||||
# include "SIB/SIBImporter.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_OFF_IMPORTER
|
||||
# include "OFFLoader.h"
|
||||
# include "OFF/OFFLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_AC_IMPORTER
|
||||
# include "ACLoader.h"
|
||||
# include "AC/ACLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_BVH_IMPORTER
|
||||
# include "BVHLoader.h"
|
||||
# include "BVH/BVHLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_IRRMESH_IMPORTER
|
||||
# include "IRRMeshLoader.h"
|
||||
# include "Irr/IRRMeshLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_IRR_IMPORTER
|
||||
# include "IRRLoader.h"
|
||||
# include "Irr/IRRLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_Q3D_IMPORTER
|
||||
# include "Q3DLoader.h"
|
||||
# include "Q3D/Q3DLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_B3D_IMPORTER
|
||||
# include "B3DImporter.h"
|
||||
# include "B3D/B3DImporter.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_COLLADA_IMPORTER
|
||||
# include "ColladaLoader.h"
|
||||
# include "Collada/ColladaLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_TERRAGEN_IMPORTER
|
||||
# include "TerragenLoader.h"
|
||||
# include "Terragen/TerragenLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_CSM_IMPORTER
|
||||
# include "CSMLoader.h"
|
||||
# include "CSM/CSMLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_3D_IMPORTER
|
||||
# include "UnrealLoader.h"
|
||||
# include "Unreal/UnrealLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_LWS_IMPORTER
|
||||
# include "LWSLoader.h"
|
||||
# include "LWS/LWSLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
|
||||
# include "OgreImporter.h"
|
||||
# include "Ogre/OgreImporter.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_OPENGEX_IMPORTER
|
||||
# include "OpenGEXImporter.h"
|
||||
# include "OpenGEX/OpenGEXImporter.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_MS3D_IMPORTER
|
||||
# include "MS3DLoader.h"
|
||||
# include "MS3D/MS3DLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_COB_IMPORTER
|
||||
# include "COBLoader.h"
|
||||
# include "COB/COBLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
|
||||
# include "BlenderLoader.h"
|
||||
# include "Blender/BlenderLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER
|
||||
# include "Q3BSPFileImporter.h"
|
||||
# include "Q3BSP/Q3BSPFileImporter.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_NDO_IMPORTER
|
||||
# include "NDOLoader.h"
|
||||
# include "NDO/NDOLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
|
||||
# include "Importer/IFC/IFCLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_XGL_IMPORTER
|
||||
# include "XGLLoader.h"
|
||||
# include "XGL/XGLLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
|
||||
# include "FBXImporter.h"
|
||||
# include "FBX/FBXImporter.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
|
||||
# include "AssbinLoader.h"
|
||||
# include "Assbin/AssbinLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER
|
||||
# include "glTFImporter.h"
|
||||
# include "glTF2Importer.h"
|
||||
# include "glTF/glTFImporter.h"
|
||||
# include "glTF2/glTF2Importer.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_C4D_IMPORTER
|
||||
# include "C4DImporter.h"
|
||||
# include "C4D/C4DImporter.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_3MF_IMPORTER
|
||||
# include "D3MFImporter.h"
|
||||
# include "3MF/D3MFImporter.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
# include "X3DImporter.hpp"
|
||||
# include "X3D/X3DImporter.hpp"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_MMD_IMPORTER
|
||||
# include "MMDImporter.h"
|
||||
# include "MMD/MMDImporter.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_STEP_IMPORTER
|
||||
# include "Importer/StepFile/StepFileImporter.h"
|
||||
|
@ -364,7 +364,7 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out)
|
|||
void DeleteImporterInstanceList(std::vector< BaseImporter* >& deleteList){
|
||||
for(size_t i= 0; i<deleteList.size();++i){
|
||||
delete deleteList[i];
|
||||
deleteList[i]=NULL;
|
||||
deleteList[i]=nullptr;
|
||||
}//for
|
||||
}
|
||||
|
|
@ -48,89 +48,93 @@ directly (unless you are adding new steps), instead use the
|
|||
corresponding preprocessor flag to selectively disable steps.
|
||||
*/
|
||||
|
||||
#include "ProcessHelper.h"
|
||||
#include "PostProcessing/ProcessHelper.h"
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_CALCTANGENTS_PROCESS
|
||||
# include "CalcTangentsProcess.h"
|
||||
# include "PostProcessing/CalcTangentsProcess.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_JOINVERTICES_PROCESS
|
||||
# include "JoinVerticesProcess.h"
|
||||
# include "PostProcessing/JoinVerticesProcess.h"
|
||||
#endif
|
||||
#if !(defined ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS && defined ASSIMP_BUILD_NO_FLIPUVS_PROCESS && defined ASSIMP_BUILD_NO_FLIPWINDINGORDER_PROCESS)
|
||||
# include "ConvertToLHProcess.h"
|
||||
# include "PostProcessing/ConvertToLHProcess.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_TRIANGULATE_PROCESS
|
||||
# include "TriangulateProcess.h"
|
||||
# include "PostProcessing/TriangulateProcess.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_DROPFACENORMALS_PROCESS
|
||||
# include "DropFaceNormalsProcess.h"
|
||||
# include "PostProcessing/DropFaceNormalsProcess.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_GENFACENORMALS_PROCESS
|
||||
# include "GenFaceNormalsProcess.h"
|
||||
# include "PostProcessing/GenFaceNormalsProcess.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_GENVERTEXNORMALS_PROCESS
|
||||
# include "GenVertexNormalsProcess.h"
|
||||
# include "PostProcessing/GenVertexNormalsProcess.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_REMOVEVC_PROCESS
|
||||
# include "RemoveVCProcess.h"
|
||||
# include "PostProcessing/RemoveVCProcess.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_SPLITLARGEMESHES_PROCESS
|
||||
# include "SplitLargeMeshes.h"
|
||||
# include "PostProcessing/SplitLargeMeshes.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_PRETRANSFORMVERTICES_PROCESS
|
||||
# include "PretransformVertices.h"
|
||||
# include "PostProcessing/PretransformVertices.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_LIMITBONEWEIGHTS_PROCESS
|
||||
# include "LimitBoneWeightsProcess.h"
|
||||
# include "PostProcessing/LimitBoneWeightsProcess.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
|
||||
# include "ValidateDataStructure.h"
|
||||
# include "PostProcessing/ValidateDataStructure.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_IMPROVECACHELOCALITY_PROCESS
|
||||
# include "ImproveCacheLocality.h"
|
||||
# include "PostProcessing/ImproveCacheLocality.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_FIXINFACINGNORMALS_PROCESS
|
||||
# include "FixNormalsStep.h"
|
||||
# include "PostProcessing/FixNormalsStep.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_REMOVE_REDUNDANTMATERIALS_PROCESS
|
||||
# include "RemoveRedundantMaterials.h"
|
||||
# include "PostProcessing/RemoveRedundantMaterials.h"
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_EMBEDTEXTURES_PROCESS)
|
||||
# include "EmbedTexturesProcess.h"
|
||||
# include "PostProcessing/EmbedTexturesProcess.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_FINDINVALIDDATA_PROCESS
|
||||
# include "FindInvalidDataProcess.h"
|
||||
# include "PostProcessing/FindInvalidDataProcess.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_FINDDEGENERATES_PROCESS
|
||||
# include "FindDegenerates.h"
|
||||
# include "PostProcessing/FindDegenerates.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_SORTBYPTYPE_PROCESS
|
||||
# include "SortByPTypeProcess.h"
|
||||
# include "PostProcessing/SortByPTypeProcess.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_GENUVCOORDS_PROCESS
|
||||
# include "ComputeUVMappingProcess.h"
|
||||
# include "PostProcessing/ComputeUVMappingProcess.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_TRANSFORMTEXCOORDS_PROCESS
|
||||
# include "TextureTransform.h"
|
||||
# include "PostProcessing/TextureTransform.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_FINDINSTANCES_PROCESS
|
||||
# include "FindInstancesProcess.h"
|
||||
# include "PostProcessing/FindInstancesProcess.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_OPTIMIZEMESHES_PROCESS
|
||||
# include "OptimizeMeshes.h"
|
||||
# include "PostProcessing/OptimizeMeshes.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_OPTIMIZEGRAPH_PROCESS
|
||||
# include "OptimizeGraph.h"
|
||||
# include "PostProcessing/OptimizeGraph.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_SPLITBYBONECOUNT_PROCESS
|
||||
# include "SplitByBoneCountProcess.h"
|
||||
# include "Common/SplitByBoneCountProcess.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_DEBONE_PROCESS
|
||||
# include "DeboneProcess.h"
|
||||
# include "PostProcessing/DeboneProcess.h"
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS)
|
||||
# include "ScaleProcess.h"
|
||||
# include "PostProcessing/ScaleProcess.h"
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_GENBOUNDINGBOXES_PROCESS)
|
||||
# include "PostProcessing/GenBoundingBoxesProcess.h"
|
||||
#endif
|
||||
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
|
@ -246,6 +250,9 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out)
|
|||
#if (!defined ASSIMP_BUILD_NO_IMPROVECACHELOCALITY_PROCESS)
|
||||
out.push_back( new ImproveCacheLocalityProcess());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_GENBOUNDINGBOXES_PROCESS)
|
||||
out.push_back(new GenBoundingBoxesProcess);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
|
@ -43,9 +43,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <assimp/Subdivision.h>
|
||||
#include <assimp/SceneCombiner.h>
|
||||
#include <assimp/SpatialSort.h>
|
||||
#include "ProcessHelper.h"
|
||||
#include <assimp/Vertex.h>
|
||||
#include <assimp/ai_assert.h>
|
||||
|
||||
#include "PostProcessing/ProcessHelper.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
using namespace Assimp;
|
||||
|
@ -56,8 +58,7 @@ void mydummy() {}
|
|||
* implementation is basing on recursive refinement. Directly evaluating the result is also
|
||||
* possible and much quicker, but it depends on lengthy matrix lookup tables. */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
class CatmullClarkSubdivider : public Subdivider
|
||||
{
|
||||
class CatmullClarkSubdivider : public Subdivider {
|
||||
public:
|
||||
void Subdivide (aiMesh* mesh, aiMesh*& out, unsigned int num, bool discard_input);
|
||||
void Subdivide (aiMesh** smesh, size_t nmesh,
|
|
@ -134,7 +134,7 @@ ASSIMP_API aiScene::aiScene()
|
|||
, mCameras(nullptr)
|
||||
, mMetaData(nullptr)
|
||||
, mPrivate(new Assimp::ScenePrivateData()) {
|
||||
// empty
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
|
@ -0,0 +1,196 @@
|
|||
#ifndef INCLUDED_ASSBIN_CHUNKS_H
|
||||
#define INCLUDED_ASSBIN_CHUNKS_H
|
||||
|
||||
#define ASSBIN_VERSION_MAJOR 1
|
||||
#define ASSBIN_VERSION_MINOR 0
|
||||
|
||||
/**
|
||||
@page assfile .ASS File formats
|
||||
|
||||
@section over Overview
|
||||
Assimp provides its own interchange format, which is intended to applications which need
|
||||
to serialize 3D-models and to reload them quickly. Assimp's file formats are designed to
|
||||
be read by Assimp itself. They encode additional information needed by Assimp to optimize
|
||||
its postprocessing pipeline. If you once apply specific steps to a scene, then save it
|
||||
and reread it from an ASS format using the same post processing settings, they won't
|
||||
be executed again.
|
||||
|
||||
The format comes in two flavours: XML and binary - both of them hold a complete dump of
|
||||
the 'aiScene' data structure returned by the APIs. The focus for the binary format
|
||||
(<tt>.assbin</tt>) is fast loading. Optional deflate compression helps reduce file size. The XML
|
||||
flavour, <tt>.assxml</tt> or simply .xml, is just a plain-to-xml conversion of aiScene.
|
||||
|
||||
ASSBIN is Assimp's binary interchange format. assimp_cmd (<tt><root>/tools/assimp_cmd</tt>) is able to
|
||||
write it and the core library provides a loader for it.
|
||||
|
||||
@section assxml XML File format
|
||||
|
||||
The format is pretty much self-explanatory due to its similarity to the in-memory aiScene structure.
|
||||
With few exceptions, C structures are wrapped in XML elements.
|
||||
|
||||
The DTD for ASSXML can be found in <tt><root>/doc/AssXML_Scheme.xml</tt>. Or have look
|
||||
at the output files generated by assimp_cmd.
|
||||
|
||||
@section assbin Binary file format
|
||||
|
||||
The ASSBIN file format is composed of chunks to represent the hierarchical aiScene data structure.
|
||||
This makes the format extensible and allows backward-compatibility with future data structure
|
||||
versions. The <tt><root>/code/assbin_chunks.h</tt> header contains some magic constants
|
||||
for use by stand-alone ASSBIN loaders. Also, Assimp's own file writer can be found
|
||||
in <tt><root>/tools/assimp_cmd/WriteDumb.cpp</tt> (yes, the 'b' is no typo ...).
|
||||
|
||||
@verbatim
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
1. File structure:
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
----------------------
|
||||
| Header (512 bytes) |
|
||||
----------------------
|
||||
| Variable chunks |
|
||||
----------------------
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
2. Definitions:
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
integer is four bytes wide, stored in little-endian byte order.
|
||||
short is two bytes wide, stored in little-endian byte order.
|
||||
byte is a single byte.
|
||||
string is an integer n followed by n UTF-8 characters, not terminated by zero
|
||||
float is an IEEE 754 single-precision floating-point value
|
||||
double is an IEEE 754 double-precision floating-point value
|
||||
t[n] is an array of n elements of type t
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
2. Header:
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
byte[44] Magic identification string for ASSBIN files.
|
||||
'ASSIMP.binary'
|
||||
|
||||
integer Major version of the Assimp library which wrote the file
|
||||
integer Minor version of the Assimp library which wrote the file
|
||||
match these against ASSBIN_VERSION_MAJOR and ASSBIN_VERSION_MINOR
|
||||
|
||||
integer SVN revision of the Assimp library (intended for our internal
|
||||
debugging - if you write Ass files from your own APPs, set this value to 0.
|
||||
integer Assimp compile flags
|
||||
|
||||
short 0 for normal files, 1 for shortened dumps for regression tests
|
||||
these should have the file extension assbin.regress
|
||||
|
||||
short 1 if the data after the header is compressed with the DEFLATE algorithm,
|
||||
0 for uncompressed files.
|
||||
For compressed files, the first integer after the header is
|
||||
always the uncompressed data size
|
||||
|
||||
byte[256] Zero-terminated source file name, UTF-8
|
||||
byte[128] Zero-terminated command line parameters passed to assimp_cmd, UTF-8
|
||||
|
||||
byte[64] Reserved for future use
|
||||
---> Total length: 512 bytes
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
3. Chunks:
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
integer Magic chunk ID (ASSBIN_CHUNK_XXX)
|
||||
integer Chunk data length, in bytes
|
||||
(unknown chunks are possible, a good reader skips over them)
|
||||
(chunk-data-length does not include the first two integers)
|
||||
|
||||
byte[n] chunk-data-length bytes of data, depending on the chunk type
|
||||
|
||||
Chunks can contain nested chunks. Nested chunks are ALWAYS at the end of the chunk,
|
||||
their size is included in chunk-data-length.
|
||||
|
||||
The chunk layout for all ASSIMP data structures is derived from their C declarations.
|
||||
The general 'rule' to get from Assimp headers to the serialized layout is:
|
||||
|
||||
1. POD members (i.e. aiMesh::mPrimitiveTypes, aiMesh::mNumVertices),
|
||||
in order of declaration.
|
||||
|
||||
2. Array-members (aiMesh::mFaces, aiMesh::mVertices, aiBone::mWeights),
|
||||
in order of declaration.
|
||||
|
||||
2. Object array members (i.e aiMesh::mBones, aiScene::mMeshes) are stored in
|
||||
subchunks directly following the data written in 1.) and 2.)
|
||||
|
||||
|
||||
Of course, there are some exceptions to this general order:
|
||||
|
||||
[[aiScene]]
|
||||
|
||||
- The root node holding the scene structure is naturally stored in
|
||||
a ASSBIN_CHUNK_AINODE subchunk following 1.) and 2.) (which is
|
||||
empty for aiScene).
|
||||
|
||||
[[aiMesh]]
|
||||
|
||||
- mTextureCoords and mNumUVComponents are serialized as follows:
|
||||
|
||||
[number of used uv channels times]
|
||||
integer mNumUVComponents[n]
|
||||
float mTextureCoords[n][3]
|
||||
|
||||
-> more than AI_MAX_TEXCOORD_CHANNELS can be stored. This allows Assimp
|
||||
builds with different settings for AI_MAX_TEXCOORD_CHANNELS to exchange
|
||||
data.
|
||||
-> the on-disk format always uses 3 floats to write UV coordinates.
|
||||
If mNumUVComponents[0] is 1, the corresponding mTextureCoords array
|
||||
consists of 3 floats.
|
||||
|
||||
- The array member block of aiMesh is prefixed with an integer that specifies
|
||||
the kinds of vertex components actually present in the mesh. This is a
|
||||
bitwise combination of the ASSBIN_MESH_HAS_xxx constants.
|
||||
|
||||
[[aiFace]]
|
||||
|
||||
- mNumIndices is stored as short
|
||||
- mIndices are written as short, if aiMesh::mNumVertices<65536
|
||||
|
||||
[[aiNode]]
|
||||
|
||||
- mParent is omitted
|
||||
|
||||
[[aiLight]]
|
||||
|
||||
- mAttenuationXXX not written if aiLight::mType == aiLightSource_DIRECTIONAL
|
||||
- mAngleXXX not written if aiLight::mType != aiLightSource_SPOT
|
||||
|
||||
[[aiMaterial]]
|
||||
|
||||
- mNumAllocated is omitted, for obvious reasons :-)
|
||||
|
||||
|
||||
@endverbatim*/
|
||||
|
||||
|
||||
#define ASSBIN_HEADER_LENGTH 512
|
||||
|
||||
// these are the magic chunk identifiers for the binary ASS file format
|
||||
#define ASSBIN_CHUNK_AICAMERA 0x1234
|
||||
#define ASSBIN_CHUNK_AILIGHT 0x1235
|
||||
#define ASSBIN_CHUNK_AITEXTURE 0x1236
|
||||
#define ASSBIN_CHUNK_AIMESH 0x1237
|
||||
#define ASSBIN_CHUNK_AINODEANIM 0x1238
|
||||
#define ASSBIN_CHUNK_AISCENE 0x1239
|
||||
#define ASSBIN_CHUNK_AIBONE 0x123a
|
||||
#define ASSBIN_CHUNK_AIANIMATION 0x123b
|
||||
#define ASSBIN_CHUNK_AINODE 0x123c
|
||||
#define ASSBIN_CHUNK_AIMATERIAL 0x123d
|
||||
#define ASSBIN_CHUNK_AIMATERIALPROPERTY 0x123e
|
||||
|
||||
#define ASSBIN_MESH_HAS_POSITIONS 0x1
|
||||
#define ASSBIN_MESH_HAS_NORMALS 0x2
|
||||
#define ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS 0x4
|
||||
#define ASSBIN_MESH_HAS_TEXCOORD_BASE 0x100
|
||||
#define ASSBIN_MESH_HAS_COLOR_BASE 0x10000
|
||||
|
||||
#define ASSBIN_MESH_HAS_TEXCOORD(n) (ASSBIN_MESH_HAS_TEXCOORD_BASE << n)
|
||||
#define ASSBIN_MESH_HAS_COLOR(n) (ASSBIN_MESH_HAS_COLOR_BASE << n)
|
||||
|
||||
|
||||
#endif // INCLUDED_ASSBIN_CHUNKS_H
|
|
@ -98,7 +98,7 @@ namespace FBX {
|
|||
// return (flags & to_check) != 0;
|
||||
//}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Token::Token(const char* sbegin, const char* send, TokenType type, unsigned int offset)
|
||||
Token::Token(const char* sbegin, const char* send, TokenType type, size_t offset)
|
||||
:
|
||||
#ifdef DEBUG
|
||||
contents(sbegin, static_cast<size_t>(send-sbegin)),
|
||||
|
@ -122,18 +122,18 @@ namespace {
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// signal tokenization error, this is always unrecoverable. Throws DeadlyImportError.
|
||||
AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int offset) AI_WONT_RETURN_SUFFIX;
|
||||
AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int offset)
|
||||
AI_WONT_RETURN void TokenizeError(const std::string& message, size_t offset) AI_WONT_RETURN_SUFFIX;
|
||||
AI_WONT_RETURN void TokenizeError(const std::string& message, size_t offset)
|
||||
{
|
||||
throw DeadlyImportError(Util::AddOffset("FBX-Tokenize",message,offset));
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
uint32_t Offset(const char* begin, const char* cursor) {
|
||||
size_t Offset(const char* begin, const char* cursor) {
|
||||
ai_assert(begin <= cursor);
|
||||
|
||||
return static_cast<unsigned int>(cursor - begin);
|
||||
return cursor - begin;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -424,7 +424,7 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor,
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// TODO: Test FBX Binary files newer than the 7500 version to check if the 64 bits address behaviour is consistent
|
||||
void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int length)
|
||||
void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length)
|
||||
{
|
||||
ai_assert(input);
|
||||
|
|
@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||
|
||||
|
||||
namespace Assimp {
|
||||
namespace FBX
|
||||
{
|
||||
const std::string NULL_RECORD = { // 13 null bytes
|
||||
|
@ -80,7 +80,7 @@ namespace FBX
|
|||
TransformInheritance_MAX // end-of-enum sentinel
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||
|
||||
#endif // AI_FBXCOMMON_H_INC
|
|
@ -67,6 +67,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
|
||||
namespace Assimp {
|
||||
namespace FBX {
|
||||
|
||||
|
@ -76,20 +77,21 @@ namespace Assimp {
|
|||
|
||||
#define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000L
|
||||
|
||||
FBXConverter::FBXConverter(aiScene* out, const Document& doc)
|
||||
: defaultMaterialIndex()
|
||||
, lights()
|
||||
, cameras()
|
||||
, textures()
|
||||
, materials_converted()
|
||||
, textures_converted()
|
||||
, meshes_converted()
|
||||
, node_anim_chain_bits()
|
||||
, mNodeNameInstances()
|
||||
, mNodeNames()
|
||||
, anim_fps()
|
||||
, out(out)
|
||||
, doc(doc) {
|
||||
FBXConverter::FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones, FbxUnit unit )
|
||||
: defaultMaterialIndex()
|
||||
, lights()
|
||||
, cameras()
|
||||
, textures()
|
||||
, materials_converted()
|
||||
, textures_converted()
|
||||
, meshes_converted()
|
||||
, node_anim_chain_bits()
|
||||
, mNodeNames()
|
||||
, anim_fps()
|
||||
, out(out)
|
||||
, doc(doc)
|
||||
, mRemoveEmptyBones( removeEmptyBones )
|
||||
, mCurrentUnit(FbxUnit::cm) {
|
||||
// animations need to be converted first since this will
|
||||
// populate the node_anim_chain_bits map, which is needed
|
||||
// to determine which nodes need to be generated.
|
||||
|
@ -117,6 +119,7 @@ namespace Assimp {
|
|||
|
||||
ConvertGlobalSettings();
|
||||
TransferDataToScene();
|
||||
ConvertToUnitScale(unit);
|
||||
|
||||
// if we didn't read any meshes set the AI_SCENE_FLAGS_INCOMPLETE
|
||||
// to make sure the scene passes assimp's validation. FBX files
|
||||
|
@ -138,12 +141,46 @@ namespace Assimp {
|
|||
|
||||
void FBXConverter::ConvertRootNode() {
|
||||
out->mRootNode = new aiNode();
|
||||
out->mRootNode->mName.Set("RootNode");
|
||||
std::string unique_name;
|
||||
GetUniqueName("RootNode", unique_name);
|
||||
out->mRootNode->mName.Set(unique_name);
|
||||
|
||||
// root has ID 0
|
||||
ConvertNodes(0L, *out->mRootNode);
|
||||
}
|
||||
|
||||
static std::string getAncestorBaseName(const aiNode* node)
|
||||
{
|
||||
const char* nodeName = nullptr;
|
||||
size_t length = 0;
|
||||
while (node && (!nodeName || length == 0))
|
||||
{
|
||||
nodeName = node->mName.C_Str();
|
||||
length = node->mName.length;
|
||||
node = node->mParent;
|
||||
}
|
||||
|
||||
if (!nodeName || length == 0)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
// could be std::string_view if c++17 available
|
||||
return std::string(nodeName, length);
|
||||
}
|
||||
|
||||
// Make unique name
|
||||
std::string FBXConverter::MakeUniqueNodeName(const Model* const model, const aiNode& parent)
|
||||
{
|
||||
std::string original_name = FixNodeName(model->Name());
|
||||
if (original_name.empty())
|
||||
{
|
||||
original_name = getAncestorBaseName(&parent);
|
||||
}
|
||||
std::string unique_name;
|
||||
GetUniqueName(original_name, unique_name);
|
||||
return unique_name;
|
||||
}
|
||||
|
||||
void FBXConverter::ConvertNodes(uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform) {
|
||||
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(id, "Model");
|
||||
|
||||
|
@ -175,35 +212,18 @@ namespace Assimp {
|
|||
|
||||
aiMatrix4x4 new_abs_transform = parent_transform;
|
||||
|
||||
std::string unique_name = MakeUniqueNodeName(model, parent);
|
||||
|
||||
// even though there is only a single input node, the design of
|
||||
// assimp (or rather: the complicated transformation chain that
|
||||
// is employed by fbx) means that we may need multiple aiNode's
|
||||
// to represent a fbx node's transformation.
|
||||
GenerateTransformationNodeChain(*model, nodes_chain, post_nodes_chain);
|
||||
const bool need_additional_node = GenerateTransformationNodeChain(*model, unique_name, nodes_chain, post_nodes_chain);
|
||||
|
||||
ai_assert(nodes_chain.size());
|
||||
|
||||
std::string original_name = FixNodeName(model->Name());
|
||||
|
||||
// check if any of the nodes in the chain has the name the fbx node
|
||||
// is supposed to have. If there is none, add another node to
|
||||
// preserve the name - people might have scripts etc. that rely
|
||||
// on specific node names.
|
||||
aiNode* name_carrier = NULL;
|
||||
for (aiNode* prenode : nodes_chain) {
|
||||
if (!strcmp(prenode->mName.C_Str(), original_name.c_str())) {
|
||||
name_carrier = prenode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!name_carrier) {
|
||||
std::string old_original_name = original_name;
|
||||
GetUniqueName(old_original_name, original_name);
|
||||
nodes_chain.push_back(new aiNode(original_name));
|
||||
}
|
||||
else {
|
||||
original_name = nodes_chain.back()->mName.C_Str();
|
||||
if (need_additional_node) {
|
||||
nodes_chain.push_back(new aiNode(unique_name));
|
||||
}
|
||||
|
||||
//setup metadata on newest node
|
||||
|
@ -265,11 +285,11 @@ namespace Assimp {
|
|||
ConvertNodes(model->ID(), *last_parent, new_abs_transform);
|
||||
|
||||
if (doc.Settings().readLights) {
|
||||
ConvertLights(*model, original_name);
|
||||
ConvertLights(*model, unique_name);
|
||||
}
|
||||
|
||||
if (doc.Settings().readCameras) {
|
||||
ConvertCameras(*model, original_name);
|
||||
ConvertCameras(*model, unique_name);
|
||||
}
|
||||
|
||||
nodes.push_back(nodes_chain.front());
|
||||
|
@ -387,6 +407,7 @@ namespace Assimp {
|
|||
break;
|
||||
default:
|
||||
ai_assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -399,11 +420,6 @@ namespace Assimp {
|
|||
|
||||
out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight();
|
||||
|
||||
//cameras are defined along positive x direction
|
||||
/*out_camera->mPosition = cam.Position();
|
||||
out_camera->mLookAt = (cam.InterestPosition() - out_camera->mPosition).Normalize();
|
||||
out_camera->mUp = cam.UpVector();*/
|
||||
|
||||
out_camera->mPosition = aiVector3D(0.0f);
|
||||
out_camera->mLookAt = aiVector3D(1.0f, 0.0f, 0.0f);
|
||||
out_camera->mUp = aiVector3D(0.0f, 1.0f, 0.0f);
|
||||
|
@ -421,21 +437,16 @@ namespace Assimp {
|
|||
void FBXConverter::GetUniqueName(const std::string &name, std::string &uniqueName)
|
||||
{
|
||||
uniqueName = name;
|
||||
int i = 0;
|
||||
auto it = mNodeNameInstances.find(name); // duplicate node name instance count
|
||||
if (it != mNodeNameInstances.end())
|
||||
auto it_pair = mNodeNames.insert({ name, 0 }); // duplicate node name instance count
|
||||
unsigned int& i = it_pair.first->second;
|
||||
while (!it_pair.second)
|
||||
{
|
||||
i = it->second;
|
||||
while (mNodeNames.find(uniqueName) != mNodeNames.end())
|
||||
{
|
||||
i++;
|
||||
std::stringstream ext;
|
||||
ext << name << std::setfill('0') << std::setw(3) << i;
|
||||
uniqueName = ext.str();
|
||||
}
|
||||
i++;
|
||||
std::ostringstream ext;
|
||||
ext << name << std::setfill('0') << std::setw(3) << i;
|
||||
uniqueName = ext.str();
|
||||
it_pair = mNodeNames.insert({ uniqueName, 0 });
|
||||
}
|
||||
mNodeNameInstances[name] = i;
|
||||
mNodeNames.insert(uniqueName);
|
||||
}
|
||||
|
||||
const char* FBXConverter::NameTransformationComp(TransformationComp comp) {
|
||||
|
@ -651,8 +662,7 @@ namespace Assimp {
|
|||
if ((v - all_ones).SquareLength() > zero_epsilon) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (ok) {
|
||||
} else if (ok) {
|
||||
if (v.SquareLength() > zero_epsilon) {
|
||||
return true;
|
||||
}
|
||||
|
@ -667,7 +677,7 @@ namespace Assimp {
|
|||
return name + std::string(MAGIC_NODE_TAG) + "_" + NameTransformationComp(comp);
|
||||
}
|
||||
|
||||
void FBXConverter::GenerateTransformationNodeChain(const Model& model, std::vector<aiNode*>& output_nodes,
|
||||
bool FBXConverter::GenerateTransformationNodeChain(const Model& model, const std::string& name, std::vector<aiNode*>& output_nodes,
|
||||
std::vector<aiNode*>& post_output_nodes) {
|
||||
const PropertyTable& props = model.Props();
|
||||
const Model::RotOrder rot = model.RotationOrder();
|
||||
|
@ -782,8 +792,6 @@ namespace Assimp {
|
|||
// not be guaranteed.
|
||||
ai_assert(NeedsComplexTransformationChain(model) == is_complex);
|
||||
|
||||
std::string name = FixNodeName(model.Name());
|
||||
|
||||
// now, if we have more than just Translation, Scaling and Rotation,
|
||||
// we need to generate a full node chain to accommodate for assimp's
|
||||
// lack to express pivots and offsets.
|
||||
|
@ -825,20 +833,20 @@ namespace Assimp {
|
|||
}
|
||||
|
||||
ai_assert(output_nodes.size());
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
// else, we can just multiply the matrices together
|
||||
aiNode* nd = new aiNode();
|
||||
output_nodes.push_back(nd);
|
||||
std::string uniqueName;
|
||||
GetUniqueName(name, uniqueName);
|
||||
|
||||
nd->mName.Set(uniqueName);
|
||||
// name passed to the method is already unique
|
||||
nd->mName.Set(name);
|
||||
|
||||
for (const auto &transform : chain) {
|
||||
nd->mTransformation = nd->mTransformation * transform;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void FBXConverter::SetupNodeMetadata(const Model& model, aiNode& nd)
|
||||
|
@ -977,7 +985,9 @@ namespace Assimp {
|
|||
unsigned int epcount = 0;
|
||||
for (unsigned i = 0; i < indices.size(); i++)
|
||||
{
|
||||
if (indices[i] < 0) epcount++;
|
||||
if (indices[i] < 0) {
|
||||
epcount++;
|
||||
}
|
||||
}
|
||||
unsigned int pcount = static_cast<unsigned int>( indices.size() );
|
||||
unsigned int scount = out_mesh->mNumFaces = pcount - epcount;
|
||||
|
@ -1237,10 +1247,10 @@ namespace Assimp {
|
|||
ai_assert(count_faces);
|
||||
ai_assert(count_vertices);
|
||||
|
||||
// mapping from output indices to DOM indexing, needed to resolve weights
|
||||
// mapping from output indices to DOM indexing, needed to resolve weights or blendshapes
|
||||
std::vector<unsigned int> reverseMapping;
|
||||
|
||||
if (process_weights) {
|
||||
std::map<unsigned int, unsigned int> translateIndexMap;
|
||||
if (process_weights || mesh.GetBlendShapes().size() > 0) {
|
||||
reverseMapping.resize(count_vertices);
|
||||
}
|
||||
|
||||
|
@ -1347,6 +1357,7 @@ namespace Assimp {
|
|||
|
||||
if (reverseMapping.size()) {
|
||||
reverseMapping[cursor] = in_cursor;
|
||||
translateIndexMap[in_cursor] = cursor;
|
||||
}
|
||||
|
||||
out_mesh->mVertices[cursor] = vertices[in_cursor];
|
||||
|
@ -1378,6 +1389,50 @@ namespace Assimp {
|
|||
ConvertWeights(out_mesh, model, mesh, node_global_transform, index, &reverseMapping);
|
||||
}
|
||||
|
||||
std::vector<aiAnimMesh*> animMeshes;
|
||||
for (const BlendShape* blendShape : mesh.GetBlendShapes()) {
|
||||
for (const BlendShapeChannel* blendShapeChannel : blendShape->BlendShapeChannels()) {
|
||||
const std::vector<const ShapeGeometry*>& shapeGeometries = blendShapeChannel->GetShapeGeometries();
|
||||
for (size_t i = 0; i < shapeGeometries.size(); i++) {
|
||||
aiAnimMesh* animMesh = aiCreateAnimMesh(out_mesh);
|
||||
const ShapeGeometry* shapeGeometry = shapeGeometries.at(i);
|
||||
const std::vector<aiVector3D>& vertices = shapeGeometry->GetVertices();
|
||||
const std::vector<aiVector3D>& normals = shapeGeometry->GetNormals();
|
||||
const std::vector<unsigned int>& indices = shapeGeometry->GetIndices();
|
||||
animMesh->mName.Set(FixAnimMeshName(shapeGeometry->Name()));
|
||||
for (size_t j = 0; j < indices.size(); j++) {
|
||||
unsigned int index = indices.at(j);
|
||||
aiVector3D vertex = vertices.at(j);
|
||||
aiVector3D normal = normals.at(j);
|
||||
unsigned int count = 0;
|
||||
const unsigned int* outIndices = mesh.ToOutputVertexIndex(index, count);
|
||||
for (unsigned int k = 0; k < count; k++) {
|
||||
unsigned int outIndex = outIndices[k];
|
||||
if (translateIndexMap.find(outIndex) == translateIndexMap.end())
|
||||
continue;
|
||||
unsigned int index = translateIndexMap[outIndex];
|
||||
animMesh->mVertices[index] += vertex;
|
||||
if (animMesh->mNormals != nullptr) {
|
||||
animMesh->mNormals[index] += normal;
|
||||
animMesh->mNormals[index].NormalizeSafe();
|
||||
}
|
||||
}
|
||||
}
|
||||
animMesh->mWeight = shapeGeometries.size() > 1 ? blendShapeChannel->DeformPercent() / 100.0f : 1.0f;
|
||||
animMeshes.push_back(animMesh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const size_t numAnimMeshes = animMeshes.size();
|
||||
if (numAnimMeshes > 0) {
|
||||
out_mesh->mNumAnimMeshes = static_cast<unsigned int>(numAnimMeshes);
|
||||
out_mesh->mAnimMeshes = new aiAnimMesh*[numAnimMeshes];
|
||||
for (size_t i = 0; i < numAnimMeshes; i++) {
|
||||
out_mesh->mAnimMeshes[i] = animMeshes.at(i);
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<unsigned int>(meshes.size() - 1);
|
||||
}
|
||||
|
||||
|
@ -1407,7 +1462,7 @@ namespace Assimp {
|
|||
|
||||
const WeightIndexArray& indices = cluster->GetIndices();
|
||||
|
||||
if (indices.empty()) {
|
||||
if (indices.empty() && mRemoveEmptyBones ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1439,13 +1494,11 @@ namespace Assimp {
|
|||
|
||||
if (index_out_indices.back() == no_index_sentinel) {
|
||||
index_out_indices.back() = out_indices.size();
|
||||
|
||||
}
|
||||
|
||||
if (no_mat_check) {
|
||||
out_indices.push_back(out_idx[i]);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// this extra lookup is in O(logn), so the entire algorithm becomes O(nlogn)
|
||||
const std::vector<unsigned int>::iterator it = std::lower_bound(
|
||||
outputVertStartIndices->begin(),
|
||||
|
@ -1461,11 +1514,11 @@ namespace Assimp {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// if we found at least one, generate the output bones
|
||||
// XXX this could be heavily simplified by collecting the bone
|
||||
// data in a single step.
|
||||
if (ok) {
|
||||
if (ok && mRemoveEmptyBones) {
|
||||
ConvertCluster(bones, model, *cluster, out_indices, index_out_indices,
|
||||
count_out_indices, node_global_transform);
|
||||
}
|
||||
|
@ -1596,6 +1649,13 @@ namespace Assimp {
|
|||
out_mat->AddProperty(&str, AI_MATKEY_NAME);
|
||||
}
|
||||
|
||||
// Set the shading mode as best we can: The FBX specification only mentions Lambert and Phong, and only Phong is mentioned in Assimp's aiShadingMode enum.
|
||||
if (material.GetShadingModel() == "phong")
|
||||
{
|
||||
aiShadingMode shadingMode = aiShadingMode_Phong;
|
||||
out_mat->AddProperty<aiShadingMode>(&shadingMode, 1, AI_MATKEY_SHADING_MODEL);
|
||||
}
|
||||
|
||||
// shading stuff and colors
|
||||
SetShadingPropertiesCommon(out_mat, props);
|
||||
SetShadingPropertiesRaw( out_mat, props, material.Textures(), mesh );
|
||||
|
@ -1621,7 +1681,7 @@ namespace Assimp {
|
|||
out_tex->pcData = reinterpret_cast<aiTexel*>(const_cast<Video&>(video).RelinquishContent());
|
||||
|
||||
// try to extract a hint from the file extension
|
||||
const std::string& filename = video.FileName().empty() ? video.RelativeFilename() : video.FileName();
|
||||
const std::string& filename = video.RelativeFilename().empty() ? video.FileName() : video.RelativeFilename();
|
||||
std::string ext = BaseImporter::GetExtension(filename);
|
||||
|
||||
if (ext == "jpeg") {
|
||||
|
@ -1632,7 +1692,7 @@ namespace Assimp {
|
|||
memcpy(out_tex->achFormatHint, ext.c_str(), ext.size());
|
||||
}
|
||||
|
||||
out_tex->mFilename.Set(video.FileName().c_str());
|
||||
out_tex->mFilename.Set(filename.c_str());
|
||||
|
||||
return static_cast<unsigned int>(textures.size() - 1);
|
||||
}
|
||||
|
@ -1678,9 +1738,8 @@ namespace Assimp {
|
|||
}
|
||||
|
||||
void FBXConverter::TrySetTextureProperties(aiMaterial* out_mat, const TextureMap& textures,
|
||||
const std::string& propName,
|
||||
aiTextureType target, const MeshGeometry* const mesh)
|
||||
{
|
||||
const std::string& propName,
|
||||
aiTextureType target, const MeshGeometry* const mesh) {
|
||||
TextureMap::const_iterator it = textures.find(propName);
|
||||
if (it == textures.end()) {
|
||||
return;
|
||||
|
@ -3407,8 +3466,9 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa
|
|||
|
||||
na->mNumScalingKeys = static_cast<unsigned int>(keys.size());
|
||||
na->mScalingKeys = new aiVectorKey[keys.size()];
|
||||
if (keys.size() > 0)
|
||||
if (keys.size() > 0) {
|
||||
InterpolateKeys(na->mScalingKeys, keys, inputs, aiVector3D(1.0f, 1.0f, 1.0f), maxTime, minTime);
|
||||
}
|
||||
}
|
||||
|
||||
void FBXConverter::ConvertTranslationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
|
||||
|
@ -3472,6 +3532,46 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa
|
|||
out->mMetaData->Set(14, "CustomFrameRate", doc.GlobalSettings().CustomFrameRate());
|
||||
}
|
||||
|
||||
void FBXConverter::ConvertToUnitScale( FbxUnit unit ) {
|
||||
if (mCurrentUnit == unit) {
|
||||
return;
|
||||
}
|
||||
|
||||
ai_real scale = 1.0;
|
||||
if (mCurrentUnit == FbxUnit::cm) {
|
||||
if (unit == FbxUnit::m) {
|
||||
scale = (ai_real)0.01;
|
||||
} else if (unit == FbxUnit::km) {
|
||||
scale = (ai_real)0.00001;
|
||||
}
|
||||
} else if (mCurrentUnit == FbxUnit::m) {
|
||||
if (unit == FbxUnit::cm) {
|
||||
scale = (ai_real)100.0;
|
||||
} else if (unit == FbxUnit::km) {
|
||||
scale = (ai_real)0.001;
|
||||
}
|
||||
} else if (mCurrentUnit == FbxUnit::km) {
|
||||
if (unit == FbxUnit::cm) {
|
||||
scale = (ai_real)100000.0;
|
||||
} else if (unit == FbxUnit::m) {
|
||||
scale = (ai_real)1000.0;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto mesh : meshes) {
|
||||
if (nullptr == mesh) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mesh->HasPositions()) {
|
||||
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
|
||||
aiVector3D &pos = mesh->mVertices[i];
|
||||
pos *= scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FBXConverter::TransferDataToScene()
|
||||
{
|
||||
ai_assert(!out->mMeshes);
|
||||
|
@ -3525,9 +3625,9 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ConvertToAssimpScene(aiScene* out, const Document& doc)
|
||||
void ConvertToAssimpScene(aiScene* out, const Document& doc, bool removeEmptyBones, FbxUnit unit)
|
||||
{
|
||||
FBXConverter converter(out, doc);
|
||||
FBXConverter converter(out, doc, removeEmptyBones, unit);
|
||||
}
|
||||
|
||||
} // !FBX
|
|
@ -52,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "FBXUtil.h"
|
||||
#include "FBXProperties.h"
|
||||
#include "FBXImporter.h"
|
||||
|
||||
#include <assimp/anim.h>
|
||||
#include <assimp/material.h>
|
||||
#include <assimp/light.h>
|
||||
|
@ -76,12 +77,22 @@ namespace FBX {
|
|||
|
||||
class Document;
|
||||
|
||||
enum class FbxUnit {
|
||||
cm = 0,
|
||||
m,
|
||||
km,
|
||||
NumUnits,
|
||||
|
||||
Undefined
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert a FBX #Document to #aiScene
|
||||
* @param out Empty scene to be populated
|
||||
* @param doc Parsed FBX document
|
||||
* @param doc Parsed FBX document
|
||||
* @param removeEmptyBones Will remove bones, which do not have any references to vertices.
|
||||
*/
|
||||
void ConvertToAssimpScene(aiScene* out, const Document& doc);
|
||||
void ConvertToAssimpScene(aiScene* out, const Document& doc, bool removeEmptyBones, FbxUnit unit);
|
||||
|
||||
/** Dummy class to encapsulate the conversion process */
|
||||
class FBXConverter {
|
||||
|
@ -112,7 +123,7 @@ public:
|
|||
};
|
||||
|
||||
public:
|
||||
FBXConverter(aiScene* out, const Document& doc);
|
||||
FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones, FbxUnit unit);
|
||||
~FBXConverter();
|
||||
|
||||
private:
|
||||
|
@ -144,6 +155,11 @@ private:
|
|||
// while these would be allowed, they are a potential trouble spot so better not use them).
|
||||
const char* NameTransformationComp(TransformationComp comp);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns an unique name for a node or traverses up a hierarchy until a non-empty name is found and
|
||||
// then makes this name unique
|
||||
std::string MakeUniqueNodeName(const Model* const model, const aiNode& parent);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// note: this returns the REAL fbx property names
|
||||
const char* NameTransformationCompProperty(TransformationComp comp);
|
||||
|
@ -167,7 +183,7 @@ private:
|
|||
/**
|
||||
* note: memory for output_nodes will be managed by the caller
|
||||
*/
|
||||
void GenerateTransformationNodeChain(const Model& model, std::vector<aiNode*>& output_nodes, std::vector<aiNode*>& post_output_nodes);
|
||||
bool GenerateTransformationNodeChain(const Model& model, const std::string& name, std::vector<aiNode*>& output_nodes, std::vector<aiNode*>& post_output_nodes);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SetupNodeMetadata(const Model& model, aiNode& nd);
|
||||
|
@ -414,6 +430,10 @@ private:
|
|||
|
||||
void ConvertGlobalSettings();
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Will perform the conversion from a given unit to the requested unit.
|
||||
void ConvertToUnitScale(FbxUnit unit);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// copy generated meshes, animations, lights, cameras and textures to the output scene
|
||||
void TransferDataToScene();
|
||||
|
@ -443,16 +463,17 @@ private:
|
|||
NodeAnimBitMap node_anim_chain_bits;
|
||||
|
||||
// number of nodes with the same name
|
||||
using NodeAnimNameMap = std::unordered_map<std::string, unsigned int>;
|
||||
NodeAnimNameMap mNodeNameInstances;
|
||||
|
||||
using NodeNameCache = std::unordered_set<std::string>;
|
||||
using NodeNameCache = std::unordered_map<std::string, unsigned int>;
|
||||
NodeNameCache mNodeNames;
|
||||
|
||||
double anim_fps;
|
||||
|
||||
aiScene* const out;
|
||||
const FBX::Document& doc;
|
||||
|
||||
bool mRemoveEmptyBones;
|
||||
|
||||
FbxUnit mCurrentUnit;
|
||||
};
|
||||
|
||||
}
|
|
@ -627,7 +627,7 @@ public:
|
|||
return content;
|
||||
}
|
||||
|
||||
uint32_t ContentLength() const {
|
||||
uint64_t ContentLength() const {
|
||||
return contentLength;
|
||||
}
|
||||
|
||||
|
@ -643,7 +643,7 @@ private:
|
|||
std::string fileName;
|
||||
std::shared_ptr<const PropertyTable> props;
|
||||
|
||||
uint32_t contentLength;
|
||||
uint64_t contentLength;
|
||||
uint8_t* content;
|
||||
};
|
||||
|
|
@ -54,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <sstream> // ostringstream
|
||||
#include <memory> // shared_ptr
|
||||
|
||||
namespace Assimp {
|
||||
// AddP70<type> helpers... there's no usable pattern here,
|
||||
// so all are defined as separate functions.
|
||||
// Even "animatable" properties are often completely different
|
||||
|
@ -252,7 +253,8 @@ void FBX::Node::DumpChildren(
|
|||
} else {
|
||||
std::ostringstream ss;
|
||||
DumpChildrenAscii(ss, indent);
|
||||
s.PutString(ss.str());
|
||||
if (ss.tellp() > 0)
|
||||
s.PutString(ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -266,7 +268,8 @@ void FBX::Node::End(
|
|||
} else {
|
||||
std::ostringstream ss;
|
||||
EndAscii(ss, indent, has_children);
|
||||
s.PutString(ss.str());
|
||||
if (ss.tellp() > 0)
|
||||
s.PutString(ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -367,7 +370,7 @@ void FBX::Node::EndBinary(
|
|||
bool has_children
|
||||
) {
|
||||
// if there were children, add a null record
|
||||
if (has_children) { s.PutString(FBX::NULL_RECORD); }
|
||||
if (has_children) { s.PutString(Assimp::FBX::NULL_RECORD); }
|
||||
|
||||
// now go back and write initial pos
|
||||
this->end_pos = s.Tell();
|
||||
|
@ -563,6 +566,6 @@ void FBX::Node::WritePropertyNode(
|
|||
FBX::Node::WritePropertyNodeAscii(name, v, s, indent);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||
#endif // ASSIMP_BUILD_NO_EXPORT
|
|
@ -54,16 +54,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Assimp {
|
||||
namespace FBX {
|
||||
class Node;
|
||||
}
|
||||
|
||||
class FBX::Node
|
||||
{
|
||||
public: // public data members
|
||||
class FBX::Node {
|
||||
public:
|
||||
// TODO: accessors
|
||||
std::string name; // node name
|
||||
std::vector<FBX::Property> properties; // node properties
|
||||
std::vector<FBX::FBXExportProperty> properties; // node properties
|
||||
std::vector<FBX::Node> children; // child nodes
|
||||
|
||||
// some nodes always pretend they have children...
|
||||
|
@ -214,7 +214,7 @@ public: // static member functions
|
|||
Assimp::StreamWriterLE& s,
|
||||
bool binary, int indent
|
||||
) {
|
||||
FBX::Property p(value);
|
||||
FBX::FBXExportProperty p(value);
|
||||
FBX::Node node(name, p);
|
||||
node.Dump(s, binary, indent);
|
||||
}
|
||||
|
@ -264,7 +264,7 @@ private: // static helper functions
|
|||
);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||
|
|
@ -52,187 +52,210 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <locale>
|
||||
#include <sstream> // ostringstream
|
||||
|
||||
namespace Assimp {
|
||||
namespace FBX {
|
||||
|
||||
// constructors for single element properties
|
||||
|
||||
FBX::Property::Property(bool v)
|
||||
: type('C'), data(1)
|
||||
{
|
||||
data = {uint8_t(v)};
|
||||
FBXExportProperty::FBXExportProperty(bool v)
|
||||
: type('C')
|
||||
, data(1) {
|
||||
data = {
|
||||
uint8_t(v)
|
||||
};
|
||||
}
|
||||
|
||||
FBX::Property::Property(int16_t v) : type('Y'), data(2)
|
||||
{
|
||||
FBXExportProperty::FBXExportProperty(int16_t v)
|
||||
: type('Y')
|
||||
, data(2) {
|
||||
uint8_t* d = data.data();
|
||||
(reinterpret_cast<int16_t*>(d))[0] = v;
|
||||
}
|
||||
|
||||
FBX::Property::Property(int32_t v) : type('I'), data(4)
|
||||
{
|
||||
FBXExportProperty::FBXExportProperty(int32_t v)
|
||||
: type('I')
|
||||
, data(4) {
|
||||
uint8_t* d = data.data();
|
||||
(reinterpret_cast<int32_t*>(d))[0] = v;
|
||||
}
|
||||
|
||||
FBX::Property::Property(float v) : type('F'), data(4)
|
||||
{
|
||||
FBXExportProperty::FBXExportProperty(float v)
|
||||
: type('F')
|
||||
, data(4) {
|
||||
uint8_t* d = data.data();
|
||||
(reinterpret_cast<float*>(d))[0] = v;
|
||||
}
|
||||
|
||||
FBX::Property::Property(double v) : type('D'), data(8)
|
||||
{
|
||||
FBXExportProperty::FBXExportProperty(double v)
|
||||
: type('D')
|
||||
, data(8) {
|
||||
uint8_t* d = data.data();
|
||||
(reinterpret_cast<double*>(d))[0] = v;
|
||||
}
|
||||
|
||||
FBX::Property::Property(int64_t v) : type('L'), data(8)
|
||||
{
|
||||
FBXExportProperty::FBXExportProperty(int64_t v)
|
||||
: type('L')
|
||||
, data(8) {
|
||||
uint8_t* d = data.data();
|
||||
(reinterpret_cast<int64_t*>(d))[0] = v;
|
||||
}
|
||||
|
||||
|
||||
// constructors for array-type properties
|
||||
|
||||
FBX::Property::Property(const char* c, bool raw)
|
||||
: Property(std::string(c), raw)
|
||||
{}
|
||||
FBXExportProperty::FBXExportProperty(const char* c, bool raw)
|
||||
: FBXExportProperty(std::string(c), raw) {
|
||||
// empty
|
||||
}
|
||||
|
||||
// strings can either be saved as "raw" (R) data, or "string" (S) data
|
||||
FBX::Property::Property(const std::string& s, bool raw)
|
||||
: type(raw ? 'R' : 'S'), data(s.size())
|
||||
{
|
||||
FBXExportProperty::FBXExportProperty(const std::string& s, bool raw)
|
||||
: type(raw ? 'R' : 'S')
|
||||
, data(s.size()) {
|
||||
for (size_t i = 0; i < s.size(); ++i) {
|
||||
data[i] = uint8_t(s[i]);
|
||||
}
|
||||
}
|
||||
|
||||
FBX::Property::Property(const std::vector<uint8_t>& r)
|
||||
: type('R'), data(r)
|
||||
{}
|
||||
FBXExportProperty::FBXExportProperty(const std::vector<uint8_t>& r)
|
||||
: type('R')
|
||||
, data(r) {
|
||||
// empty
|
||||
}
|
||||
|
||||
FBX::Property::Property(const std::vector<int32_t>& va)
|
||||
: type('i'), data(4*va.size())
|
||||
{
|
||||
FBXExportProperty::FBXExportProperty(const std::vector<int32_t>& va)
|
||||
: type('i')
|
||||
, data(4 * va.size() ) {
|
||||
int32_t* d = reinterpret_cast<int32_t*>(data.data());
|
||||
for (size_t i = 0; i < va.size(); ++i) { d[i] = va[i]; }
|
||||
for (size_t i = 0; i < va.size(); ++i) {
|
||||
d[i] = va[i];
|
||||
}
|
||||
}
|
||||
|
||||
FBX::Property::Property(const std::vector<int64_t>& va)
|
||||
: type('l'), data(8*va.size())
|
||||
{
|
||||
FBXExportProperty::FBXExportProperty(const std::vector<int64_t>& va)
|
||||
: type('l')
|
||||
, data(8 * va.size()) {
|
||||
int64_t* d = reinterpret_cast<int64_t*>(data.data());
|
||||
for (size_t i = 0; i < va.size(); ++i) { d[i] = va[i]; }
|
||||
for (size_t i = 0; i < va.size(); ++i) {
|
||||
d[i] = va[i];
|
||||
}
|
||||
}
|
||||
|
||||
FBX::Property::Property(const std::vector<float>& va)
|
||||
: type('f'), data(4*va.size())
|
||||
{
|
||||
FBXExportProperty::FBXExportProperty(const std::vector<float>& va)
|
||||
: type('f')
|
||||
, data(4 * va.size()) {
|
||||
float* d = reinterpret_cast<float*>(data.data());
|
||||
for (size_t i = 0; i < va.size(); ++i) { d[i] = va[i]; }
|
||||
for (size_t i = 0; i < va.size(); ++i) {
|
||||
d[i] = va[i];
|
||||
}
|
||||
}
|
||||
|
||||
FBX::Property::Property(const std::vector<double>& va)
|
||||
: type('d'), data(8*va.size())
|
||||
{
|
||||
FBXExportProperty::FBXExportProperty(const std::vector<double>& va)
|
||||
: type('d')
|
||||
, data(8 * va.size()) {
|
||||
double* d = reinterpret_cast<double*>(data.data());
|
||||
for (size_t i = 0; i < va.size(); ++i) { d[i] = va[i]; }
|
||||
for (size_t i = 0; i < va.size(); ++i) {
|
||||
d[i] = va[i];
|
||||
}
|
||||
}
|
||||
|
||||
FBX::Property::Property(const aiMatrix4x4& vm)
|
||||
: type('d'), data(8*16)
|
||||
{
|
||||
FBXExportProperty::FBXExportProperty(const aiMatrix4x4& vm)
|
||||
: type('d')
|
||||
, data(8 * 16) {
|
||||
double* d = reinterpret_cast<double*>(data.data());
|
||||
for (unsigned int c = 0; c < 4; ++c) {
|
||||
for (unsigned int r = 0; r < 4; ++r) {
|
||||
d[4*c+r] = vm[r][c];
|
||||
d[4 * c + r] = vm[r][c];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// public member functions
|
||||
|
||||
size_t FBX::Property::size()
|
||||
{
|
||||
size_t FBXExportProperty::size() {
|
||||
switch (type) {
|
||||
case 'C': case 'Y': case 'I': case 'F': case 'D': case 'L':
|
||||
return data.size() + 1;
|
||||
case 'S': case 'R':
|
||||
return data.size() + 5;
|
||||
case 'i': case 'd':
|
||||
return data.size() + 13;
|
||||
default:
|
||||
throw DeadlyExportError("Requested size on property of unknown type");
|
||||
case 'C':
|
||||
case 'Y':
|
||||
case 'I':
|
||||
case 'F':
|
||||
case 'D':
|
||||
case 'L':
|
||||
return data.size() + 1;
|
||||
case 'S':
|
||||
case 'R':
|
||||
return data.size() + 5;
|
||||
case 'i':
|
||||
case 'd':
|
||||
return data.size() + 13;
|
||||
default:
|
||||
throw DeadlyExportError("Requested size on property of unknown type");
|
||||
}
|
||||
}
|
||||
|
||||
void FBX::Property::DumpBinary(Assimp::StreamWriterLE &s)
|
||||
{
|
||||
void FBXExportProperty::DumpBinary(Assimp::StreamWriterLE& s) {
|
||||
s.PutU1(type);
|
||||
uint8_t* d = data.data();
|
||||
size_t N;
|
||||
switch (type) {
|
||||
case 'C': s.PutU1(*(reinterpret_cast<uint8_t*>(d))); return;
|
||||
case 'Y': s.PutI2(*(reinterpret_cast<int16_t*>(d))); return;
|
||||
case 'I': s.PutI4(*(reinterpret_cast<int32_t*>(d))); return;
|
||||
case 'F': s.PutF4(*(reinterpret_cast<float*>(d))); return;
|
||||
case 'D': s.PutF8(*(reinterpret_cast<double*>(d))); return;
|
||||
case 'L': s.PutI8(*(reinterpret_cast<int64_t*>(d))); return;
|
||||
case 'S':
|
||||
case 'R':
|
||||
s.PutU4(uint32_t(data.size()));
|
||||
for (size_t i = 0; i < data.size(); ++i) { s.PutU1(data[i]); }
|
||||
return;
|
||||
case 'i':
|
||||
N = data.size() / 4;
|
||||
s.PutU4(uint32_t(N)); // number of elements
|
||||
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
||||
// TODO: compress if large?
|
||||
s.PutU4(uint32_t(data.size())); // data size
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
s.PutI4((reinterpret_cast<int32_t*>(d))[i]);
|
||||
}
|
||||
return;
|
||||
case 'l':
|
||||
N = data.size() / 8;
|
||||
s.PutU4(uint32_t(N)); // number of elements
|
||||
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
||||
// TODO: compress if large?
|
||||
s.PutU4(uint32_t(data.size())); // data size
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
s.PutI8((reinterpret_cast<int64_t*>(d))[i]);
|
||||
}
|
||||
return;
|
||||
case 'f':
|
||||
N = data.size() / 4;
|
||||
s.PutU4(uint32_t(N)); // number of elements
|
||||
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
||||
// TODO: compress if large?
|
||||
s.PutU4(uint32_t(data.size())); // data size
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
s.PutF4((reinterpret_cast<float*>(d))[i]);
|
||||
}
|
||||
return;
|
||||
case 'd':
|
||||
N = data.size() / 8;
|
||||
s.PutU4(uint32_t(N)); // number of elements
|
||||
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
||||
// TODO: compress if large?
|
||||
s.PutU4(uint32_t(data.size())); // data size
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
s.PutF8((reinterpret_cast<double*>(d))[i]);
|
||||
}
|
||||
return;
|
||||
default:
|
||||
std::ostringstream err;
|
||||
err << "Tried to dump property with invalid type '";
|
||||
err << type << "'!";
|
||||
throw DeadlyExportError(err.str());
|
||||
case 'C': s.PutU1(*(reinterpret_cast<uint8_t*>(d))); return;
|
||||
case 'Y': s.PutI2(*(reinterpret_cast<int16_t*>(d))); return;
|
||||
case 'I': s.PutI4(*(reinterpret_cast<int32_t*>(d))); return;
|
||||
case 'F': s.PutF4(*(reinterpret_cast<float*>(d))); return;
|
||||
case 'D': s.PutF8(*(reinterpret_cast<double*>(d))); return;
|
||||
case 'L': s.PutI8(*(reinterpret_cast<int64_t*>(d))); return;
|
||||
case 'S':
|
||||
case 'R':
|
||||
s.PutU4(uint32_t(data.size()));
|
||||
for (size_t i = 0; i < data.size(); ++i) { s.PutU1(data[i]); }
|
||||
return;
|
||||
case 'i':
|
||||
N = data.size() / 4;
|
||||
s.PutU4(uint32_t(N)); // number of elements
|
||||
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
||||
// TODO: compress if large?
|
||||
s.PutU4(uint32_t(data.size())); // data size
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
s.PutI4((reinterpret_cast<int32_t*>(d))[i]);
|
||||
}
|
||||
return;
|
||||
case 'l':
|
||||
N = data.size() / 8;
|
||||
s.PutU4(uint32_t(N)); // number of elements
|
||||
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
||||
// TODO: compress if large?
|
||||
s.PutU4(uint32_t(data.size())); // data size
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
s.PutI8((reinterpret_cast<int64_t*>(d))[i]);
|
||||
}
|
||||
return;
|
||||
case 'f':
|
||||
N = data.size() / 4;
|
||||
s.PutU4(uint32_t(N)); // number of elements
|
||||
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
||||
// TODO: compress if large?
|
||||
s.PutU4(uint32_t(data.size())); // data size
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
s.PutF4((reinterpret_cast<float*>(d))[i]);
|
||||
}
|
||||
return;
|
||||
case 'd':
|
||||
N = data.size() / 8;
|
||||
s.PutU4(uint32_t(N)); // number of elements
|
||||
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
||||
// TODO: compress if large?
|
||||
s.PutU4(uint32_t(data.size())); // data size
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
s.PutF8((reinterpret_cast<double*>(d))[i]);
|
||||
}
|
||||
return;
|
||||
default:
|
||||
std::ostringstream err;
|
||||
err << "Tried to dump property with invalid type '";
|
||||
err << type << "'!";
|
||||
throw DeadlyExportError(err.str());
|
||||
}
|
||||
}
|
||||
|
||||
void FBX::Property::DumpAscii(Assimp::StreamWriterLE &outstream, int indent)
|
||||
{
|
||||
void FBXExportProperty::DumpAscii(Assimp::StreamWriterLE& outstream, int indent) {
|
||||
std::ostringstream ss;
|
||||
ss.imbue(std::locale::classic());
|
||||
ss.precision(15); // this seems to match official FBX SDK exports
|
||||
|
@ -240,8 +263,7 @@ void FBX::Property::DumpAscii(Assimp::StreamWriterLE &outstream, int indent)
|
|||
outstream.PutString(ss.str());
|
||||
}
|
||||
|
||||
void FBX::Property::DumpAscii(std::ostream& s, int indent)
|
||||
{
|
||||
void FBXExportProperty::DumpAscii(std::ostream& s, int indent) {
|
||||
// no writing type... or anything. just shove it into the stream.
|
||||
uint8_t* d = data.data();
|
||||
size_t N;
|
||||
|
@ -360,5 +382,8 @@ void FBX::Property::DumpAscii(std::ostream& s, int indent)
|
|||
}
|
||||
}
|
||||
|
||||
} // Namespace FBX
|
||||
} // Namespace Assimp
|
||||
|
||||
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||
#endif // ASSIMP_BUILD_NO_EXPORT
|
|
@ -47,7 +47,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||
|
||||
|
||||
#include <assimp/types.h> // aiMatrix4x4
|
||||
#include <assimp/StreamWriter.h> // StreamWriterLE
|
||||
|
||||
|
@ -56,11 +55,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <ostream>
|
||||
#include <type_traits> // is_void
|
||||
|
||||
namespace Assimp {
|
||||
namespace FBX {
|
||||
class Property;
|
||||
}
|
||||
|
||||
/** FBX::Property
|
||||
/** @brief FBX::Property
|
||||
*
|
||||
* Holds a value of any of FBX's recognized types,
|
||||
* each represented by a particular one-character code.
|
||||
|
@ -78,35 +76,34 @@ namespace FBX {
|
|||
* S : string (array of 1-byte char)
|
||||
* R : raw data (array of bytes)
|
||||
*/
|
||||
class FBX::Property
|
||||
{
|
||||
class FBXExportProperty {
|
||||
public:
|
||||
// constructors for basic types.
|
||||
// all explicit to avoid accidental typecasting
|
||||
explicit Property(bool v);
|
||||
explicit FBXExportProperty(bool v);
|
||||
// TODO: determine if there is actually a byte type,
|
||||
// or if this always means <bool>. 'C' seems to imply <char>,
|
||||
// so possibly the above was intended to represent both.
|
||||
explicit Property(int16_t v);
|
||||
explicit Property(int32_t v);
|
||||
explicit Property(float v);
|
||||
explicit Property(double v);
|
||||
explicit Property(int64_t v);
|
||||
explicit FBXExportProperty(int16_t v);
|
||||
explicit FBXExportProperty(int32_t v);
|
||||
explicit FBXExportProperty(float v);
|
||||
explicit FBXExportProperty(double v);
|
||||
explicit FBXExportProperty(int64_t v);
|
||||
// strings can either be stored as 'R' (raw) or 'S' (string) type
|
||||
explicit Property(const char* c, bool raw=false);
|
||||
explicit Property(const std::string& s, bool raw=false);
|
||||
explicit Property(const std::vector<uint8_t>& r);
|
||||
explicit Property(const std::vector<int32_t>& va);
|
||||
explicit Property(const std::vector<int64_t>& va);
|
||||
explicit Property(const std::vector<double>& va);
|
||||
explicit Property(const std::vector<float>& va);
|
||||
explicit Property(const aiMatrix4x4& vm);
|
||||
explicit FBXExportProperty(const char* c, bool raw = false);
|
||||
explicit FBXExportProperty(const std::string& s, bool raw = false);
|
||||
explicit FBXExportProperty(const std::vector<uint8_t>& r);
|
||||
explicit FBXExportProperty(const std::vector<int32_t>& va);
|
||||
explicit FBXExportProperty(const std::vector<int64_t>& va);
|
||||
explicit FBXExportProperty(const std::vector<double>& va);
|
||||
explicit FBXExportProperty(const std::vector<float>& va);
|
||||
explicit FBXExportProperty(const aiMatrix4x4& vm);
|
||||
|
||||
// this will catch any type not defined above,
|
||||
// so that we don't accidentally convert something we don't want.
|
||||
// for example (const char*) --> (bool)... seriously wtf C++
|
||||
template <class T>
|
||||
explicit Property(T v) : type('X') {
|
||||
explicit FBXExportProperty(T v) : type('X') {
|
||||
static_assert(std::is_void<T>::value, "TRIED TO CREATE FBX PROPERTY WITH UNSUPPORTED TYPE, CHECK YOUR PROPERTY INSTANTIATION");
|
||||
} // note: no line wrap so it appears verbatim on the compiler error
|
||||
|
||||
|
@ -114,9 +111,9 @@ public:
|
|||
size_t size();
|
||||
|
||||
// write this property node as binary data to the given stream
|
||||
void DumpBinary(Assimp::StreamWriterLE &s);
|
||||
void DumpAscii(Assimp::StreamWriterLE &s, int indent=0);
|
||||
void DumpAscii(std::ostream &s, int indent=0);
|
||||
void DumpBinary(Assimp::StreamWriterLE& s);
|
||||
void DumpAscii(Assimp::StreamWriterLE& s, int indent = 0);
|
||||
void DumpAscii(std::ostream& s, int indent = 0);
|
||||
// note: make sure the ostream is in classic "C" locale
|
||||
|
||||
private:
|
||||
|
@ -124,6 +121,9 @@ private:
|
|||
std::vector<uint8_t> data;
|
||||
};
|
||||
|
||||
} // Namespace FBX
|
||||
} // Namespace Assimp
|
||||
|
||||
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||
|
||||
#endif // AI_FBXEXPORTPROPERTY_H_INC
|
|
@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "FBXExportNode.h"
|
||||
#include "FBXExportProperty.h"
|
||||
#include "FBXCommon.h"
|
||||
#include "FBXUtil.h"
|
||||
|
||||
#include <assimp/version.h> // aiGetVersion
|
||||
#include <assimp/IOSystem.hpp>
|
||||
|
@ -73,7 +74,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
const ai_real DEG = ai_real( 57.29577951308232087679815481 ); // degrees per radian
|
||||
|
||||
using namespace Assimp;
|
||||
using namespace Assimp::FBX;
|
||||
|
||||
// some constants that we'll use for writing metadata
|
||||
namespace Assimp {
|
||||
namespace FBX {
|
||||
const std::string EXPORT_VERSION_STR = "7.4.0";
|
||||
const uint32_t EXPORT_VERSION_INT = 7400; // 7.4 == 2014/2015
|
||||
|
@ -92,11 +97,6 @@ namespace FBX {
|
|||
";------------------------------------------------------------------";
|
||||
}
|
||||
|
||||
using namespace Assimp;
|
||||
using namespace FBX;
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Worker function for exporting a scene to binary FBX.
|
||||
// Prototyped and registered in Exporter.cpp
|
||||
|
@ -121,6 +121,7 @@ namespace Assimp {
|
|||
IOSystem* pIOSystem,
|
||||
const aiScene* pScene,
|
||||
const ExportProperties* pProperties
|
||||
|
||||
){
|
||||
// initialize the exporter
|
||||
FBXExporter exporter(pScene, pProperties);
|
||||
|
@ -1218,6 +1219,16 @@ void FBXExporter::WriteObjects ()
|
|||
layer.AddChild(le);
|
||||
layer.Dump(outstream, binary, indent);
|
||||
|
||||
for(unsigned int lr = 1; lr < m->GetNumUVChannels(); ++ lr)
|
||||
{
|
||||
FBX::Node layerExtra("Layer", int32_t(1));
|
||||
layerExtra.AddChild("Version", int32_t(100));
|
||||
FBX::Node leExtra("LayerElement");
|
||||
leExtra.AddChild("Type", "LayerElementUV");
|
||||
leExtra.AddChild("TypedIndex", int32_t(lr));
|
||||
layerExtra.AddChild(leExtra);
|
||||
layerExtra.Dump(outstream, binary, indent);
|
||||
}
|
||||
// finish the node record
|
||||
indent = 1;
|
||||
n.End(outstream, binary, indent, true);
|
||||
|
@ -1393,10 +1404,6 @@ void FBXExporter::WriteObjects ()
|
|||
|
||||
// FbxVideo - stores images used by textures.
|
||||
for (const auto &it : uid_by_image) {
|
||||
if (it.first.compare(0, 1, "*") == 0) {
|
||||
// TODO: embedded textures
|
||||
continue;
|
||||
}
|
||||
FBX::Node n("Video");
|
||||
const int64_t& uid = it.second;
|
||||
const std::string name = ""; // TODO: ... name???
|
||||
|
@ -1406,7 +1413,33 @@ void FBXExporter::WriteObjects ()
|
|||
// TODO: get full path... relative path... etc... ugh...
|
||||
// for now just use the same path for everything,
|
||||
// and hopefully one of them will work out.
|
||||
const std::string& path = it.first;
|
||||
std::string path = it.first;
|
||||
// try get embedded texture
|
||||
const aiTexture* embedded_texture = mScene->GetEmbeddedTexture(it.first.c_str());
|
||||
if (embedded_texture != nullptr) {
|
||||
// change the path (use original filename, if available. If name is empty, concatenate texture index with file extension)
|
||||
std::stringstream newPath;
|
||||
if (embedded_texture->mFilename.length > 0) {
|
||||
newPath << embedded_texture->mFilename.C_Str();
|
||||
} else if (embedded_texture->achFormatHint[0]) {
|
||||
int texture_index = std::stoi(path.substr(1, path.size() - 1));
|
||||
newPath << texture_index << "." << embedded_texture->achFormatHint;
|
||||
}
|
||||
path = newPath.str();
|
||||
// embed the texture
|
||||
size_t texture_size = static_cast<size_t>(embedded_texture->mWidth * std::max(embedded_texture->mHeight, 1u));
|
||||
if (binary) {
|
||||
// embed texture as binary data
|
||||
std::vector<uint8_t> tex_data;
|
||||
tex_data.resize(texture_size);
|
||||
memcpy(&tex_data[0], (char*)embedded_texture->pcData, texture_size);
|
||||
n.AddChild("Content", tex_data);
|
||||
} else {
|
||||
// embed texture in base64 encoding
|
||||
std::string encoded_texture = FBX::Util::EncodeBase64((char*)embedded_texture->pcData, texture_size);
|
||||
n.AddChild("Content", encoded_texture);
|
||||
}
|
||||
}
|
||||
p.AddP70("Path", "KString", "XRefUrl", "", path);
|
||||
n.AddChild(p);
|
||||
n.AddChild("UseMipMap", int32_t(0));
|
||||
|
@ -1419,17 +1452,17 @@ void FBXExporter::WriteObjects ()
|
|||
// referenced by material_index/texture_type pairs.
|
||||
std::map<std::pair<size_t,size_t>,int64_t> texture_uids;
|
||||
const std::map<aiTextureType,std::string> prop_name_by_tt = {
|
||||
{aiTextureType_DIFFUSE, "DiffuseColor"},
|
||||
{aiTextureType_SPECULAR, "SpecularColor"},
|
||||
{aiTextureType_AMBIENT, "AmbientColor"},
|
||||
{aiTextureType_EMISSIVE, "EmissiveColor"},
|
||||
{aiTextureType_HEIGHT, "Bump"},
|
||||
{aiTextureType_NORMALS, "NormalMap"},
|
||||
{aiTextureType_SHININESS, "ShininessExponent"},
|
||||
{aiTextureType_OPACITY, "TransparentColor"},
|
||||
{aiTextureType_DIFFUSE, "DiffuseColor"},
|
||||
{aiTextureType_SPECULAR, "SpecularColor"},
|
||||
{aiTextureType_AMBIENT, "AmbientColor"},
|
||||
{aiTextureType_EMISSIVE, "EmissiveColor"},
|
||||
{aiTextureType_HEIGHT, "Bump"},
|
||||
{aiTextureType_NORMALS, "NormalMap"},
|
||||
{aiTextureType_SHININESS, "ShininessExponent"},
|
||||
{aiTextureType_OPACITY, "TransparentColor"},
|
||||
{aiTextureType_DISPLACEMENT, "DisplacementColor"},
|
||||
//{aiTextureType_LIGHTMAP, "???"},
|
||||
{aiTextureType_REFLECTION, "ReflectionColor"}
|
||||
{aiTextureType_REFLECTION, "ReflectionColor"}
|
||||
//{aiTextureType_UNKNOWN, ""}
|
||||
};
|
||||
for (size_t i = 0; i < mScene->mNumMaterials; ++i) {
|
||||
|
@ -1575,19 +1608,41 @@ void FBXExporter::WriteObjects ()
|
|||
// one sticky point is that the number of vertices may not match,
|
||||
// because assimp splits vertices by normal, uv, etc.
|
||||
|
||||
// functor for aiNode sorting
|
||||
struct SortNodeByName
|
||||
{
|
||||
bool operator()(const aiNode *lhs, const aiNode *rhs) const
|
||||
{
|
||||
return strcmp(lhs->mName.C_Str(), rhs->mName.C_Str()) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
// first we should mark the skeleton for each mesh.
|
||||
// the skeleton must include not only the aiBones,
|
||||
// but also all their parent nodes.
|
||||
// anything that affects the position of any bone node must be included.
|
||||
std::vector<std::set<const aiNode*>> skeleton_by_mesh(mScene->mNumMeshes);
|
||||
// Use SorNodeByName to make sure the exported result will be the same across all systems
|
||||
// Otherwise the aiNodes of the skeleton would be sorted based on the pointer address, which isn't consistent
|
||||
std::vector<std::set<const aiNode*, SortNodeByName>> skeleton_by_mesh(mScene->mNumMeshes);
|
||||
// at the same time we can build a list of all the skeleton nodes,
|
||||
// which will be used later to mark them as type "limbNode".
|
||||
std::unordered_set<const aiNode*> limbnodes;
|
||||
|
||||
//actual bone nodes in fbx, without parenting-up
|
||||
std::unordered_set<std::string> setAllBoneNamesInScene;
|
||||
for(unsigned int m = 0; m < mScene->mNumMeshes; ++ m)
|
||||
{
|
||||
aiMesh* pMesh = mScene->mMeshes[m];
|
||||
for(unsigned int b = 0; b < pMesh->mNumBones; ++ b)
|
||||
setAllBoneNamesInScene.insert(pMesh->mBones[b]->mName.data);
|
||||
}
|
||||
aiMatrix4x4 mxTransIdentity;
|
||||
|
||||
// and a map of nodes by bone name, as finding them is annoying.
|
||||
std::map<std::string,aiNode*> node_by_bone;
|
||||
for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
|
||||
const aiMesh* m = mScene->mMeshes[mi];
|
||||
std::set<const aiNode*> skeleton;
|
||||
std::set<const aiNode*, SortNodeByName> skeleton;
|
||||
for (size_t bi =0; bi < m->mNumBones; ++bi) {
|
||||
const aiBone* b = m->mBones[bi];
|
||||
const std::string name(b->mName.C_Str());
|
||||
|
@ -1626,6 +1681,11 @@ void FBXExporter::WriteObjects ()
|
|||
if (node_name.find(MAGIC_NODE_TAG) != std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
//not a bone in scene && no effect in transform
|
||||
if(setAllBoneNamesInScene.find(node_name)==setAllBoneNamesInScene.end()
|
||||
&& parent->mTransformation == mxTransIdentity) {
|
||||
continue;
|
||||
}
|
||||
// otherwise check if this is the root of the skeleton
|
||||
bool end = false;
|
||||
// is the mesh part of this node?
|
||||
|
@ -1728,7 +1788,7 @@ void FBXExporter::WriteObjects ()
|
|||
aiMatrix4x4 mesh_xform = get_world_transform(mesh_node, mScene);
|
||||
|
||||
// now make a subdeformer for each bone in the skeleton
|
||||
const std::set<const aiNode*> &skeleton = skeleton_by_mesh[mi];
|
||||
const std::set<const aiNode*, SortNodeByName> skeleton= skeleton_by_mesh[mi];
|
||||
for (const aiNode* bone_node : skeleton) {
|
||||
// if there's a bone for this node, find it
|
||||
const aiBone* b = nullptr;
|
||||
|
@ -1790,7 +1850,10 @@ void FBXExporter::WriteObjects ()
|
|||
|
||||
// this should be the same as the bone's mOffsetMatrix.
|
||||
// if it's not the same, the skeleton isn't in the bind pose.
|
||||
const float epsilon = 1e-4f; // some error is to be expected
|
||||
float epsilon = 1e-4f; // some error is to be expected
|
||||
float epsilon_custom = mProperties->GetPropertyFloat("BINDPOSE_EPSILON", -1);
|
||||
if(epsilon_custom > 0)
|
||||
epsilon = epsilon_custom;
|
||||
bool bone_xform_okay = true;
|
||||
if (b && ! tr.Equal(b->mOffsetMatrix, epsilon)) {
|
||||
not_in_bind_pose.insert(b);
|
||||
|
@ -2237,8 +2300,8 @@ void FBXExporter::WriteModelNode(
|
|||
|
||||
// not sure what these are for,
|
||||
// but they seem to be omnipresent
|
||||
m.AddChild("Shading", Property(true));
|
||||
m.AddChild("Culling", Property("CullingOff"));
|
||||
m.AddChild("Shading", FBXExportProperty(true));
|
||||
m.AddChild("Culling", FBXExportProperty("CullingOff"));
|
||||
|
||||
m.Dump(outstream, binary, 1);
|
||||
}
|
||||
|
@ -2351,7 +2414,7 @@ void FBXExporter::WriteModelNodes(
|
|||
na.AddProperties(
|
||||
node_attribute_uid, FBX::SEPARATOR + "NodeAttribute", "LimbNode"
|
||||
);
|
||||
na.AddChild("TypeFlags", Property("Skeleton"));
|
||||
na.AddChild("TypeFlags", FBXExportProperty("Skeleton"));
|
||||
na.Dump(outstream, binary, 1);
|
||||
// and connect them
|
||||
connections.emplace_back("C", "OO", node_attribute_uid, node_uid);
|
|
@ -53,19 +53,22 @@ namespace FBX {
|
|||
struct ImportSettings
|
||||
{
|
||||
ImportSettings()
|
||||
: strictMode(true)
|
||||
, readAllLayers(true)
|
||||
, readAllMaterials(false)
|
||||
, readMaterials(true)
|
||||
, readTextures(true)
|
||||
, readCameras(true)
|
||||
, readLights(true)
|
||||
, readAnimations(true)
|
||||
, readWeights(true)
|
||||
, preservePivots(true)
|
||||
, optimizeEmptyAnimationCurves(true)
|
||||
, useLegacyEmbeddedTextureNaming(false)
|
||||
{}
|
||||
: strictMode(true)
|
||||
, readAllLayers(true)
|
||||
, readAllMaterials(false)
|
||||
, readMaterials(true)
|
||||
, readTextures(true)
|
||||
, readCameras(true)
|
||||
, readLights(true)
|
||||
, readAnimations(true)
|
||||
, readWeights(true)
|
||||
, preservePivots(true)
|
||||
, optimizeEmptyAnimationCurves(true)
|
||||
, useLegacyEmbeddedTextureNaming(false)
|
||||
, removeEmptyBones( true )
|
||||
, convertToMeters( false ) {
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
/** enable strict mode:
|
||||
|
@ -141,8 +144,16 @@ struct ImportSettings
|
|||
bool optimizeEmptyAnimationCurves;
|
||||
|
||||
/** use legacy naming for embedded textures eg: (*0, *1, *2)
|
||||
**/
|
||||
*/
|
||||
bool useLegacyEmbeddedTextureNaming;
|
||||
|
||||
/** Empty bones shall be removed
|
||||
*/
|
||||
bool removeEmptyBones;
|
||||
|
||||
/** Set to true to perform a conversion from cm to meter after the import
|
||||
*/
|
||||
bool convertToMeters;
|
||||
};
|
||||
|
||||
|
|
@ -140,6 +140,8 @@ void FBXImporter::SetupProperties(const Importer* pImp)
|
|||
settings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true);
|
||||
settings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true);
|
||||
settings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false);
|
||||
settings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true);
|
||||
settings.convertToMeters = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -170,7 +172,7 @@ void FBXImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
|
|||
bool is_binary = false;
|
||||
if (!strncmp(begin,"Kaydara FBX Binary",18)) {
|
||||
is_binary = true;
|
||||
TokenizeBinary(tokens,begin,static_cast<unsigned int>(contents.size()));
|
||||
TokenizeBinary(tokens,begin,contents.size());
|
||||
}
|
||||
else {
|
||||
Tokenize(tokens,begin);
|
||||
|
@ -183,8 +185,12 @@ void FBXImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
|
|||
// take the raw parse-tree and convert it to a FBX DOM
|
||||
Document doc(parser,settings);
|
||||
|
||||
FbxUnit unit(FbxUnit::cm);
|
||||
if (settings.convertToMeters) {
|
||||
unit = FbxUnit::m;
|
||||
}
|
||||
// convert the FBX DOM to aiScene
|
||||
ConvertToAssimpScene(pScene,doc);
|
||||
ConvertToAssimpScene(pScene,doc, settings.removeEmptyBones, unit);
|
||||
|
||||
std::for_each(tokens.begin(),tokens.end(),Util::delete_fun<Token>());
|
||||
}
|
|
@ -316,7 +316,7 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std
|
|||
relativeFileName = ParseTokenAsString(GetRequiredToken(*RelativeFilename,0));
|
||||
}
|
||||
|
||||
if(Content) {
|
||||
if(Content && !Content->Tokens().empty()) {
|
||||
//this field is omitted when the embedded texture is already loaded, let's ignore if it's not found
|
||||
try {
|
||||
const Token& token = GetRequiredToken(*Content, 0);
|
||||
|
@ -326,16 +326,40 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std
|
|||
DOMError("embedded content is not surrounded by quotation marks", &element);
|
||||
}
|
||||
else {
|
||||
const char* encodedData = data + 1;
|
||||
size_t encodedDataLen = static_cast<size_t>(token.end() - token.begin());
|
||||
// search for last quotation mark
|
||||
while (encodedDataLen > 1 && encodedData[encodedDataLen] != '"')
|
||||
encodedDataLen--;
|
||||
if (encodedDataLen % 4 != 0) {
|
||||
DOMError("embedded content is invalid, needs to be in base64", &element);
|
||||
size_t targetLength = 0;
|
||||
auto numTokens = Content->Tokens().size();
|
||||
// First time compute size (it could be large like 64Gb and it is good to allocate it once)
|
||||
for (uint32_t tokenIdx = 0; tokenIdx < numTokens; ++tokenIdx)
|
||||
{
|
||||
const Token& dataToken = GetRequiredToken(*Content, tokenIdx);
|
||||
size_t tokenLength = dataToken.end() - dataToken.begin() - 2; // ignore double quotes
|
||||
const char* base64data = dataToken.begin() + 1;
|
||||
const size_t outLength = Util::ComputeDecodedSizeBase64(base64data, tokenLength);
|
||||
if (outLength == 0)
|
||||
{
|
||||
DOMError("Corrupted embedded content found", &element);
|
||||
}
|
||||
targetLength += outLength;
|
||||
}
|
||||
else {
|
||||
contentLength = Util::DecodeBase64(encodedData, encodedDataLen, content);
|
||||
if (targetLength == 0)
|
||||
{
|
||||
DOMError("Corrupted embedded content found", &element);
|
||||
}
|
||||
content = new uint8_t[targetLength];
|
||||
contentLength = static_cast<uint64_t>(targetLength);
|
||||
size_t dst_offset = 0;
|
||||
for (uint32_t tokenIdx = 0; tokenIdx < numTokens; ++tokenIdx)
|
||||
{
|
||||
const Token& dataToken = GetRequiredToken(*Content, tokenIdx);
|
||||
size_t tokenLength = dataToken.end() - dataToken.begin() - 2; // ignore double quotes
|
||||
const char* base64data = dataToken.begin() + 1;
|
||||
dst_offset += Util::DecodeBase64(base64data, tokenLength, content + dst_offset, targetLength - dst_offset);
|
||||
}
|
||||
if (targetLength != dst_offset)
|
||||
{
|
||||
delete[] content;
|
||||
contentLength = 0;
|
||||
DOMError("Corrupted embedded content found", &element);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -568,15 +568,15 @@ void MeshGeometry::ReadVertexDataColors(std::vector<aiColor4D>& colors_out, cons
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static const std::string TangentIndexToken = "TangentIndex";
|
||||
static const std::string TangentsIndexToken = "TangentsIndex";
|
||||
static const char *TangentIndexToken = "TangentIndex";
|
||||
static const char *TangentsIndexToken = "TangentsIndex";
|
||||
|
||||
void MeshGeometry::ReadVertexDataTangents(std::vector<aiVector3D>& tangents_out, const Scope& source,
|
||||
const std::string& MappingInformationType,
|
||||
const std::string& ReferenceInformationType)
|
||||
{
|
||||
const char * str = source.Elements().count( "Tangents" ) > 0 ? "Tangents" : "Tangent";
|
||||
const char * strIdx = source.Elements().count( "Tangents" ) > 0 ? TangentsIndexToken.c_str() : TangentIndexToken.c_str();
|
||||
const char * strIdx = source.Elements().count( "Tangents" ) > 0 ? TangentsIndexToken : TangentIndexToken;
|
||||
ResolveVertexDataArray(tangents_out,source,MappingInformationType,ReferenceInformationType,
|
||||
str,
|
||||
strIdx,
|
||||
|
@ -630,10 +630,11 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, cons
|
|||
materials_out.clear();
|
||||
}
|
||||
|
||||
m_materials.assign(m_vertices.size(),materials_out[0]);
|
||||
materials_out.resize(m_vertices.size());
|
||||
std::fill(materials_out.begin(), materials_out.end(), materials_out.at(0));
|
||||
}
|
||||
else if (MappingInformationType == "ByPolygon" && ReferenceInformationType == "IndexToDirect") {
|
||||
m_materials.resize(face_count);
|
||||
materials_out.resize(face_count);
|
||||
|
||||
if(materials_out.size() != face_count) {
|
||||
FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ")
|
|
@ -117,7 +117,7 @@ namespace FBX {
|
|||
Element::Element(const Token& key_token, Parser& parser)
|
||||
: key_token(key_token)
|
||||
{
|
||||
TokenPtr n = NULL;
|
||||
TokenPtr n = nullptr;
|
||||
do {
|
||||
n = parser.AdvanceToNextToken();
|
||||
if(!n) {
|
||||
|
@ -643,9 +643,9 @@ void ParseVectorDataArray(std::vector<aiVector3D>& out, const Element& el)
|
|||
if (type == 'd') {
|
||||
const double* d = reinterpret_cast<const double*>(&buff[0]);
|
||||
for (unsigned int i = 0; i < count3; ++i, d += 3) {
|
||||
out.push_back(aiVector3D(static_cast<float>(d[0]),
|
||||
static_cast<float>(d[1]),
|
||||
static_cast<float>(d[2])));
|
||||
out.push_back(aiVector3D(static_cast<ai_real>(d[0]),
|
||||
static_cast<ai_real>(d[1]),
|
||||
static_cast<ai_real>(d[2])));
|
||||
}
|
||||
// for debugging
|
||||
/*for ( size_t i = 0; i < out.size(); i++ ) {
|
||||
|
@ -963,7 +963,6 @@ void ParseVectorDataArray(std::vector<float>& out, const Element& el)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// read an array of uints
|
||||
void ParseVectorDataArray(std::vector<unsigned int>& out, const Element& el)
|
||||
|
@ -1280,7 +1279,6 @@ float ParseTokenAsFloat(const Token& t)
|
|||
return i;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// wrapper around ParseTokenAsInt() with ParseError handling
|
||||
int ParseTokenAsInt(const Token& t)
|
||||
|
@ -1293,8 +1291,6 @@ int ParseTokenAsInt(const Token& t)
|
|||
return i;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// wrapper around ParseTokenAsInt64() with ParseError handling
|
||||
int64_t ParseTokenAsInt64(const Token& t)
|
|
@ -93,7 +93,7 @@ public:
|
|||
Token(const char* sbegin, const char* send, TokenType type, unsigned int line, unsigned int column);
|
||||
|
||||
/** construct a binary token */
|
||||
Token(const char* sbegin, const char* send, TokenType type, unsigned int offset);
|
||||
Token(const char* sbegin, const char* send, TokenType type, size_t offset);
|
||||
|
||||
~Token();
|
||||
|
||||
|
@ -118,14 +118,14 @@ public:
|
|||
return type;
|
||||
}
|
||||
|
||||
unsigned int Offset() const {
|
||||
size_t Offset() const {
|
||||
ai_assert(IsBinary());
|
||||
return offset;
|
||||
}
|
||||
|
||||
unsigned int Line() const {
|
||||
ai_assert(!IsBinary());
|
||||
return line;
|
||||
return static_cast<unsigned int>(line);
|
||||
}
|
||||
|
||||
unsigned int Column() const {
|
||||
|
@ -147,8 +147,8 @@ private:
|
|||
const TokenType type;
|
||||
|
||||
union {
|
||||
const unsigned int line;
|
||||
unsigned int offset;
|
||||
size_t line;
|
||||
size_t offset;
|
||||
};
|
||||
const unsigned int column;
|
||||
};
|
||||
|
@ -178,7 +178,7 @@ void Tokenize(TokenList& output_tokens, const char* input);
|
|||
* @param input_buffer Binary input buffer to be processed.
|
||||
* @param length Length of input buffer, in bytes. There is no 0-terminal.
|
||||
* @throw DeadlyImportError if something goes wrong */
|
||||
void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int length);
|
||||
void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length);
|
||||
|
||||
|
||||
} // ! FBX
|
|
@ -86,7 +86,7 @@ const char* TokenTypeString(TokenType t)
|
|||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
std::string AddOffset(const std::string& prefix, const std::string& text, unsigned int offset)
|
||||
std::string AddOffset(const std::string& prefix, const std::string& text, size_t offset)
|
||||
{
|
||||
return static_cast<std::string>( (Formatter::format() << prefix << " (offset 0x" << std::hex << offset << ") " << text) );
|
||||
}
|
||||
|
@ -114,47 +114,126 @@ std::string AddTokenText(const std::string& prefix, const std::string& text, con
|
|||
text) );
|
||||
}
|
||||
|
||||
// Generated by this formula: T["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[i]] = i;
|
||||
static const uint8_t base64DecodeTable[128] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 64, 0, 0,
|
||||
0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
|
||||
0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 255, 255, 255,
|
||||
255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
|
||||
255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255
|
||||
};
|
||||
|
||||
uint8_t DecodeBase64(char ch)
|
||||
{
|
||||
return base64DecodeTable[size_t(ch)];
|
||||
const auto idx = static_cast<uint8_t>(ch);
|
||||
if (idx > 127)
|
||||
return 255;
|
||||
return base64DecodeTable[idx];
|
||||
}
|
||||
|
||||
size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out)
|
||||
size_t ComputeDecodedSizeBase64(const char* in, size_t inLength)
|
||||
{
|
||||
if (inLength < 4) {
|
||||
out = 0;
|
||||
if (inLength < 2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const size_t outLength = (inLength * 3) / 4;
|
||||
out = new uint8_t[outLength];
|
||||
memset(out, 0, outLength);
|
||||
|
||||
size_t i = 0;
|
||||
size_t j = 0;
|
||||
for (i = 0; i < inLength - 4; i += 4)
|
||||
const size_t equals = size_t(in[inLength - 1] == '=') + size_t(in[inLength - 2] == '=');
|
||||
const size_t full_length = (inLength * 3) >> 2; // div by 4
|
||||
if (full_length < equals)
|
||||
{
|
||||
uint8_t b0 = Util::DecodeBase64(in[i]);
|
||||
uint8_t b1 = Util::DecodeBase64(in[i + 1]);
|
||||
uint8_t b2 = Util::DecodeBase64(in[i + 2]);
|
||||
uint8_t b3 = Util::DecodeBase64(in[i + 3]);
|
||||
|
||||
out[j++] = (uint8_t)((b0 << 2) | (b1 >> 4));
|
||||
out[j++] = (uint8_t)((b1 << 4) | (b2 >> 2));
|
||||
out[j++] = (uint8_t)((b2 << 6) | b3);
|
||||
return 0;
|
||||
}
|
||||
return outLength;
|
||||
return full_length - equals;
|
||||
}
|
||||
|
||||
size_t DecodeBase64(const char* in, size_t inLength, uint8_t* out, size_t maxOutLength)
|
||||
{
|
||||
if (maxOutLength == 0 || inLength < 2) {
|
||||
return 0;
|
||||
}
|
||||
const size_t realLength = inLength - size_t(in[inLength - 1] == '=') - size_t(in[inLength - 2] == '=');
|
||||
size_t dst_offset = 0;
|
||||
int val = 0, valb = -8;
|
||||
for (size_t src_offset = 0; src_offset < realLength; ++src_offset)
|
||||
{
|
||||
const uint8_t table_value = Util::DecodeBase64(in[src_offset]);
|
||||
if (table_value == 255)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
val = (val << 6) + table_value;
|
||||
valb += 6;
|
||||
if (valb >= 0)
|
||||
{
|
||||
out[dst_offset++] = static_cast<uint8_t>((val >> valb) & 0xFF);
|
||||
valb -= 8;
|
||||
val &= 0xFFF;
|
||||
}
|
||||
}
|
||||
return dst_offset;
|
||||
}
|
||||
|
||||
static const char to_base64_string[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
char EncodeBase64(char byte)
|
||||
{
|
||||
return to_base64_string[(size_t)byte];
|
||||
}
|
||||
|
||||
/** Encodes a block of 4 bytes to base64 encoding
|
||||
*
|
||||
* @param bytes Bytes to encode.
|
||||
* @param out_string String to write encoded values to.
|
||||
* @param string_pos Position in out_string.*/
|
||||
void EncodeByteBlock(const char* bytes, std::string& out_string, size_t string_pos)
|
||||
{
|
||||
char b0 = (bytes[0] & 0xFC) >> 2;
|
||||
char b1 = (bytes[0] & 0x03) << 4 | ((bytes[1] & 0xF0) >> 4);
|
||||
char b2 = (bytes[1] & 0x0F) << 2 | ((bytes[2] & 0xC0) >> 6);
|
||||
char b3 = (bytes[2] & 0x3F);
|
||||
|
||||
out_string[string_pos + 0] = EncodeBase64(b0);
|
||||
out_string[string_pos + 1] = EncodeBase64(b1);
|
||||
out_string[string_pos + 2] = EncodeBase64(b2);
|
||||
out_string[string_pos + 3] = EncodeBase64(b3);
|
||||
}
|
||||
|
||||
std::string EncodeBase64(const char* data, size_t length)
|
||||
{
|
||||
// calculate extra bytes needed to get a multiple of 3
|
||||
size_t extraBytes = 3 - length % 3;
|
||||
|
||||
// number of base64 bytes
|
||||
size_t encodedBytes = 4 * (length + extraBytes) / 3;
|
||||
|
||||
std::string encoded_string(encodedBytes, '=');
|
||||
|
||||
// read blocks of 3 bytes
|
||||
for (size_t ib3 = 0; ib3 < length / 3; ib3++)
|
||||
{
|
||||
const size_t iByte = ib3 * 3;
|
||||
const size_t iEncodedByte = ib3 * 4;
|
||||
const char* currData = &data[iByte];
|
||||
|
||||
EncodeByteBlock(currData, encoded_string, iEncodedByte);
|
||||
}
|
||||
|
||||
// if size of data is not a multiple of 3, also encode the final bytes (and add zeros where needed)
|
||||
if (extraBytes > 0)
|
||||
{
|
||||
char finalBytes[4] = { 0,0,0,0 };
|
||||
memcpy(&finalBytes[0], &data[length - length % 3], length % 3);
|
||||
|
||||
const size_t iEncodedByte = encodedBytes - 4;
|
||||
EncodeByteBlock(&finalBytes[0], encoded_string, iEncodedByte);
|
||||
|
||||
// add '=' at the end
|
||||
for (size_t i = 0; i < 4 * extraBytes / 3; i++)
|
||||
encoded_string[encodedBytes - i - 1] = '=';
|
||||
}
|
||||
return encoded_string;
|
||||
}
|
||||
|
||||
} // !Util
|
|
@ -78,7 +78,7 @@ const char* TokenTypeString(TokenType t);
|
|||
* @param line Line index, 1-based
|
||||
* @param column Column index, 1-based
|
||||
* @return A string of the following format: {prefix} (offset 0x{offset}) {text}*/
|
||||
std::string AddOffset(const std::string& prefix, const std::string& text, unsigned int offset);
|
||||
std::string AddOffset(const std::string& prefix, const std::string& text, size_t offset);
|
||||
|
||||
|
||||
/** Format log/error messages using a given line location in the source file.
|
||||
|
@ -105,13 +105,30 @@ std::string AddTokenText(const std::string& prefix, const std::string& text, con
|
|||
* @return decoded byte value*/
|
||||
uint8_t DecodeBase64(char ch);
|
||||
|
||||
/** Compute decoded size of a Base64-encoded string
|
||||
*
|
||||
* @param in Characters to decode.
|
||||
* @param inLength Number of characters to decode.
|
||||
* @return size of the decoded data (number of bytes)*/
|
||||
size_t ComputeDecodedSizeBase64(const char* in, size_t inLength);
|
||||
|
||||
/** Decode a Base64-encoded string
|
||||
*
|
||||
* @param in Characters to decode.
|
||||
* @param inLength Number of characters to decode.
|
||||
* @param out Reference to pointer where we will store the decoded data.
|
||||
* @param out Pointer where we will store the decoded data.
|
||||
* @param maxOutLength Size of output buffer.
|
||||
* @return size of the decoded data (number of bytes)*/
|
||||
size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out);
|
||||
size_t DecodeBase64(const char* in, size_t inLength, uint8_t* out, size_t maxOutLength);
|
||||
|
||||
char EncodeBase64(char byte);
|
||||
|
||||
/** Encode bytes in base64-encoding
|
||||
*
|
||||
* @param data Binary data to encode.
|
||||
* @param inLength Number of bytes to encode.
|
||||
* @return base64-encoded string*/
|
||||
std::string EncodeBase64(const char* data, size_t length);
|
||||
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -41,15 +41,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#ifndef ASSIMP_BUILD_NO_MMD_IMPORTER
|
||||
|
||||
#include "MMDImporter.h"
|
||||
#include "MMDPmdParser.h"
|
||||
#include "MMDPmxParser.h"
|
||||
#include "MMDVmdParser.h"
|
||||
#include "ConvertToLHProcess.h"
|
||||
#include "MMD/MMDImporter.h"
|
||||
#include "MMD/MMDPmdParser.h"
|
||||
#include "MMD/MMDPmxParser.h"
|
||||
#include "MMD/MMDVmdParser.h"
|
||||
#include "PostProcessing/ConvertToLHProcess.h"
|
||||
|
||||
#include <assimp/DefaultIOSystem.h>
|
||||
#include <assimp/Importer.hpp>
|
||||
#include <assimp/ai_assert.h>
|
||||
#include <assimp/scene.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <memory>
|
|
@ -42,7 +42,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <utility>
|
||||
#include "MMDPmxParser.h"
|
||||
#include <assimp/StringUtils.h>
|
||||
#include "../contrib/utf8cpp/source/utf8.h"
|
||||
#ifdef ASSIMP_USE_HUNTER
|
||||
# include <utf8/utf8.h>
|
||||
#else
|
||||
# include "../contrib/utf8cpp/source/utf8.h"
|
||||
#endif
|
||||
#include <assimp/Exceptional.h>
|
||||
|
||||
namespace pmx
|
|
@ -96,12 +96,12 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat,
|
|||
ai_real* pOut,
|
||||
unsigned int* pMax)
|
||||
{
|
||||
ai_assert( pOut != NULL );
|
||||
ai_assert( pMat != NULL );
|
||||
ai_assert( pOut != nullptr );
|
||||
ai_assert( pMat != nullptr );
|
||||
|
||||
const aiMaterialProperty* prop;
|
||||
aiGetMaterialProperty(pMat,pKey,type,index, (const aiMaterialProperty**) &prop);
|
||||
if (!prop) {
|
||||
if ( nullptr == prop) {
|
||||
return AI_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -112,9 +112,11 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat,
|
|||
if (pMax) {
|
||||
iWrite = std::min(*pMax,iWrite); ;
|
||||
}
|
||||
for (unsigned int a = 0; a < iWrite;++a) {
|
||||
pOut[a] = static_cast<ai_real> ( reinterpret_cast<float*>(prop->mData)[a] );
|
||||
|
||||
for (unsigned int a = 0; a < iWrite; ++a) {
|
||||
pOut[ a ] = static_cast<ai_real> ( reinterpret_cast<float*>(prop->mData)[a] );
|
||||
}
|
||||
|
||||
if (pMax) {
|
||||
*pMax = iWrite;
|
||||
}
|
|
@ -42,11 +42,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
|
||||
/** @file Defines a post processing step to calculate tangents and
|
||||
bitangents on all imported meshes.*/
|
||||
bi-tangents on all imported meshes.*/
|
||||
#ifndef AI_CALCTANGENTSPROCESS_H_INC
|
||||
#define AI_CALCTANGENTSPROCESS_H_INC
|
||||
|
||||
#include "BaseProcess.h"
|
||||
#include "Common/BaseProcess.h"
|
||||
|
||||
struct aiMesh;
|
||||
|
|
@ -45,7 +45,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef AI_COMPUTEUVMAPPING_H_INC
|
||||
#define AI_COMPUTEUVMAPPING_H_INC
|
||||
|
||||
#include "BaseProcess.h"
|
||||
#include "Common/BaseProcess.h"
|
||||
|
||||
#include <assimp/mesh.h>
|
||||
#include <assimp/material.h>
|
||||
#include <assimp/types.h>
|
|
@ -52,7 +52,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#define AI_CONVERTTOLHPROCESS_H_INC
|
||||
|
||||
#include <assimp/types.h>
|
||||
#include "BaseProcess.h"
|
||||
|
||||
#include "Common/BaseProcess.h"
|
||||
|
||||
struct aiMesh;
|
||||
struct aiNodeAnim;
|
|
@ -44,17 +44,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef AI_DEBONEPROCESS_H_INC
|
||||
#define AI_DEBONEPROCESS_H_INC
|
||||
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include "BaseProcess.h"
|
||||
#include "Common/BaseProcess.h"
|
||||
|
||||
#include <assimp/mesh.h>
|
||||
#include <assimp/scene.h>
|
||||
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
#// Forward declarations
|
||||
class DeboneTest;
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
namespace Assimp {
|
||||
|
||||
#if (!defined AI_DEBONE_THRESHOLD)
|
||||
# define AI_DEBONE_THRESHOLD 1.0f
|
||||
|
@ -66,14 +67,11 @@ namespace Assimp
|
|||
* the bone are split from the mesh. The split off (new) mesh is boneless. At any
|
||||
* point in time, bones without affect upon a given mesh are to be removed.
|
||||
*/
|
||||
class DeboneProcess : public BaseProcess
|
||||
{
|
||||
class DeboneProcess : public BaseProcess {
|
||||
public:
|
||||
|
||||
DeboneProcess();
|
||||
~DeboneProcess();
|
||||
|
||||
public:
|
||||
// -------------------------------------------------------------------
|
||||
/** Returns whether the processing step is present in the given flag.
|
||||
* @param pFlags The processing flags the importer was called with.
|
||||
|
@ -91,7 +89,6 @@ public:
|
|||
void SetupProperties(const Importer* pImp);
|
||||
|
||||
protected:
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Executes the post processing step on the given imported data.
|
||||
* At the moment a process is not supposed to fail.
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue