Merge branch 'master' into fix-2799-2785

pull/2801/head
Kim Kulling 2019-12-07 13:47:25 +01:00 committed by GitHub
commit f9e861527b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 850 additions and 307 deletions

View File

@ -5,8 +5,6 @@ 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,
@ -78,7 +76,6 @@ static const aiImporterDesc desc = {
"b3d"
};
// (fixme, Aramis) quick workaround to get rid of all those signed to unsigned warnings
#ifdef _MSC_VER
# pragma warning (disable: 4018)
#endif
@ -86,10 +83,8 @@ static const aiImporterDesc desc = {
//#define DEBUG_B3D
template<typename T>
void DeleteAllBarePointers(std::vector<T>& x)
{
for(auto p : x)
{
void DeleteAllBarePointers(std::vector<T>& x) {
for(auto p : x) {
delete p;
}
}
@ -102,10 +97,14 @@ B3DImporter::~B3DImporter()
bool B3DImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const{
size_t pos=pFile.find_last_of( '.' );
if( pos==string::npos ) return false;
if( pos==string::npos ) {
return false;
}
string ext=pFile.substr( pos+1 );
if( ext.size()!=3 ) return false;
if( ext.size()!=3 ) {
return false;
}
return (ext[0]=='b' || ext[0]=='B') && (ext[1]=='3') && (ext[2]=='d' || ext[2]=='D');
}
@ -117,30 +116,21 @@ const aiImporterDesc* B3DImporter::GetInfo () const
return &desc;
}
#ifdef DEBUG_B3D
extern "C"{ void _stdcall AllocConsole(); }
#endif
// ------------------------------------------------------------------------------------------------
void B3DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler){
#ifdef DEBUG_B3D
AllocConsole();
freopen( "conin$","r",stdin );
freopen( "conout$","w",stdout );
freopen( "conout$","w",stderr );
cout<<"Hello world from the B3DImporter!"<<endl;
#endif
std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
// Check whether we can read from the file
if( file.get() == NULL)
if( file.get() == nullptr) {
throw DeadlyImportError( "Failed to open B3D file " + pFile + ".");
}
// check whether the .b3d file is large enough to contain
// at least one chunk.
size_t fileSize = file->FileSize();
if( fileSize<8 ) throw DeadlyImportError( "B3D File is too small.");
if( fileSize<8 ) {
throw DeadlyImportError( "B3D File is too small.");
}
_pos=0;
_buf.resize( fileSize );
@ -158,14 +148,17 @@ AI_WONT_RETURN void B3DImporter::Oops(){
// ------------------------------------------------------------------------------------------------
AI_WONT_RETURN void B3DImporter::Fail( string str ){
#ifdef DEBUG_B3D
cout<<"Error in B3D file data: "<<str<<endl;
ASSIMP_LOG_ERROR_F("Error in B3D file data: ", str);
#endif
throw DeadlyImportError( "B3D Importer - error in B3D file data: "+str );
}
// ------------------------------------------------------------------------------------------------
int B3DImporter::ReadByte(){
if( _pos<_buf.size() ) return _buf[_pos++];
if( _pos<_buf.size() ) {
return _buf[_pos++];
}
Fail( "EOF" );
return 0;
}
@ -224,7 +217,9 @@ string B3DImporter::ReadString(){
string str;
while( _pos<_buf.size() ){
char c=(char)ReadByte();
if( !c ) return str;
if( !c ) {
return str;
}
str+=c;
}
Fail( "EOF" );
@ -238,7 +233,7 @@ string B3DImporter::ReadChunk(){
tag+=char( ReadByte() );
}
#ifdef DEBUG_B3D
// cout<<"ReadChunk:"<<tag<<endl;
ASSIMP_LOG_DEBUG_F("ReadChunk: ", tag);
#endif
unsigned sz=(unsigned)ReadInt();
_stack.push_back( _pos+sz );
@ -269,7 +264,6 @@ T *B3DImporter::to_array( const vector<T> &v ){
return p;
}
// ------------------------------------------------------------------------------------------------
template<class T>
T **unique_to_array( vector<std::unique_ptr<T> > &v ){
@ -283,7 +277,6 @@ T **unique_to_array( vector<std::unique_ptr<T> > &v ){
return p;
}
// ------------------------------------------------------------------------------------------------
void B3DImporter::ReadTEXS(){
while( ChunkSize() ){
@ -376,9 +369,13 @@ void B3DImporter::ReadVRTS(){
v.vertex=ReadVec3();
if( _vflags & 1 ) v.normal=ReadVec3();
if( _vflags & 1 ) {
v.normal=ReadVec3();
}
if( _vflags & 2 ) ReadQuat(); //skip v 4bytes...
if( _vflags & 2 ) {
ReadQuat(); //skip v 4bytes...
}
for( int i=0;i<_tcsets;++i ){
float t[4]={0,0,0,0};
@ -386,53 +383,55 @@ void B3DImporter::ReadVRTS(){
t[j]=ReadFloat();
}
t[1]=1-t[1];
if( !i ) v.texcoords=aiVector3D( t[0],t[1],t[2] );
if( !i ) {
v.texcoords=aiVector3D( t[0],t[1],t[2] );
}
}
}
}
// ------------------------------------------------------------------------------------------------
void B3DImporter::ReadTRIS( int v0 ){
int matid=ReadInt();
if( matid==-1 ){
matid=0;
}else if( matid<0 || matid>=(int)_materials.size() ){
void B3DImporter::ReadTRIS(int v0) {
int matid = ReadInt();
if (matid == -1) {
matid = 0;
} else if (matid < 0 || matid >= (int)_materials.size()) {
#ifdef DEBUG_B3D
cout<<"material id="<<matid<<endl;
ASSIMP_LOG_ERROR_F("material id=", matid);
#endif
Fail( "Bad material id" );
}
Fail("Bad material id");
}
std::unique_ptr<aiMesh> mesh(new aiMesh);
std::unique_ptr<aiMesh> mesh(new aiMesh);
mesh->mMaterialIndex=matid;
mesh->mNumFaces=0;
mesh->mPrimitiveTypes=aiPrimitiveType_TRIANGLE;
mesh->mMaterialIndex = matid;
mesh->mNumFaces = 0;
mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
int n_tris=ChunkSize()/12;
aiFace *face=mesh->mFaces=new aiFace[n_tris];
int n_tris = ChunkSize() / 12;
aiFace *face = mesh->mFaces = new aiFace[n_tris];
for( int i=0;i<n_tris;++i ){
int i0=ReadInt()+v0;
int i1=ReadInt()+v0;
int i2=ReadInt()+v0;
if( i0<0 || i0>=(int)_vertices.size() || i1<0 || i1>=(int)_vertices.size() || i2<0 || i2>=(int)_vertices.size() ){
for (int i = 0; i < n_tris; ++i) {
int i0 = ReadInt() + v0;
int i1 = ReadInt() + v0;
int i2 = ReadInt() + v0;
if (i0 < 0 || i0 >= (int)_vertices.size() || i1 < 0 || i1 >= (int)_vertices.size() || i2 < 0 || i2 >= (int)_vertices.size()) {
#ifdef DEBUG_B3D
cout<<"Bad triangle index: i0="<<i0<<", i1="<<i1<<", i2="<<i2<<endl;
ASSIMP_LOG_ERROR_F("Bad triangle index: i0=", i0, ", i1=", i1, ", i2=", i2);
#endif
Fail( "Bad triangle index" );
continue;
}
face->mNumIndices=3;
face->mIndices=new unsigned[3];
face->mIndices[0]=i0;
face->mIndices[1]=i1;
face->mIndices[2]=i2;
++mesh->mNumFaces;
++face;
}
Fail("Bad triangle index");
continue;
}
face->mNumIndices = 3;
face->mIndices = new unsigned[3];
face->mIndices[0] = i0;
face->mIndices[1] = i1;
face->mIndices[2] = i2;
++mesh->mNumFaces;
++face;
}
_meshes.emplace_back( std::move(mesh) );
_meshes.emplace_back(std::move(mesh));
}
// ------------------------------------------------------------------------------------------------
@ -453,29 +452,23 @@ void B3DImporter::ReadMESH(){
}
// ------------------------------------------------------------------------------------------------
void B3DImporter::ReadBONE( int id ){
while( ChunkSize() ){
int vertex=ReadInt();
float weight=ReadFloat();
if( vertex<0 || vertex>=(int)_vertices.size() ){
Fail( "Bad vertex index" );
}
void B3DImporter::ReadBONE(int id) {
while (ChunkSize()) {
int vertex = ReadInt();
float weight = ReadFloat();
if (vertex < 0 || vertex >= (int)_vertices.size()) {
Fail("Bad vertex index");
}
Vertex &v=_vertices[vertex];
int i;
for( i=0;i<4;++i ){
if( !v.weights[i] ){
v.bones[i]=id;
v.weights[i]=weight;
break;
}
}
#ifdef DEBUG_B3D
if( i==4 ){
cout<<"Too many bone weights"<<endl;
}
#endif
}
Vertex &v = _vertices[vertex];
for (int i = 0; i < 4; ++i) {
if (!v.weights[i]) {
v.bones[i] = id;
v.weights[i] = weight;
break;
}
}
}
}
// ------------------------------------------------------------------------------------------------
@ -633,11 +626,15 @@ void B3DImporter::ReadBB3D( aiScene *scene ){
}
ExitChunk();
if( !_nodes.size() ) Fail( "No nodes" );
if( !_nodes.size() ) {
Fail( "No nodes" );
}
if( !_meshes.size() ) Fail( "No meshes" );
if( !_meshes.size() ) {
Fail( "No meshes" );
}
//Fix nodes/meshes/bones
// Fix nodes/meshes/bones
for(size_t i=0;i<_nodes.size();++i ){
aiNode *node=_nodes[i];
@ -648,8 +645,12 @@ void B3DImporter::ReadBB3D( aiScene *scene ){
int n_verts=mesh->mNumVertices=n_tris * 3;
aiVector3D *mv=mesh->mVertices=new aiVector3D[ n_verts ],*mn=0,*mc=0;
if( _vflags & 1 ) mn=mesh->mNormals=new aiVector3D[ n_verts ];
if( _tcsets ) mc=mesh->mTextureCoords[0]=new aiVector3D[ n_verts ];
if( _vflags & 1 ) {
mn=mesh->mNormals=new aiVector3D[ n_verts ];
}
if( _tcsets ) {
mc=mesh->mTextureCoords[0]=new aiVector3D[ n_verts ];
}
aiFace *face=mesh->mFaces;

View File

@ -445,7 +445,7 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c
ExportProperties emptyProperties; // Never pass NULL ExportProperties so Exporters don't have to worry.
ExportProperties* pProp = pProperties ? (ExportProperties*)pProperties : &emptyProperties;
pProp->SetPropertyBool("bJoinIdenticalVertices", must_join_again);
pProp->SetPropertyBool("bJoinIdenticalVertices", pp & aiProcess_JoinIdenticalVertices);
exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProp);
pimpl->mProgressHandler->UpdateFileWrite(4, 4);

View File

@ -5,8 +5,6 @@ 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,
@ -78,6 +76,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/TinyFormatter.h>
#include <assimp/Exceptional.h>
#include <assimp/Profiler.h>
#include <assimp/commonMetaData.h>
#include <set>
#include <memory>
#include <cctype>
@ -119,7 +119,7 @@ void* AllocateFromAssimpHeap::operator new ( size_t num_bytes, const std::nothro
return AllocateFromAssimpHeap::operator new( num_bytes );
}
catch( ... ) {
return NULL;
return nullptr;
}
}
@ -134,9 +134,8 @@ void* AllocateFromAssimpHeap::operator new[] ( size_t num_bytes) {
void* AllocateFromAssimpHeap::operator new[] ( size_t num_bytes, const std::nothrow_t& ) throw() {
try {
return AllocateFromAssimpHeap::operator new[]( num_bytes );
}
catch( ... ) {
return NULL;
} catch( ... ) {
return nullptr;
}
}
@ -148,7 +147,7 @@ void AllocateFromAssimpHeap::operator delete[] ( void* data) {
// Importer constructor.
Importer::Importer()
: pimpl( new ImporterPimpl ) {
pimpl->mScene = NULL;
pimpl->mScene = nullptr;
pimpl->mErrorString = "";
// Allocate a default IO handler
@ -174,14 +173,14 @@ Importer::Importer()
// ------------------------------------------------------------------------------------------------
// Destructor of Importer
Importer::~Importer()
{
Importer::~Importer() {
// Delete all import plugins
DeleteImporterInstanceList(pimpl->mImporter);
// Delete all post-processing plug-ins
for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++)
for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); ++a ) {
delete pimpl->mPostProcessingSteps[a];
}
// Delete the assigned IO and progress handler
delete pimpl->mIOHandler;
@ -199,9 +198,9 @@ Importer::~Importer()
// ------------------------------------------------------------------------------------------------
// Register a custom post-processing step
aiReturn Importer::RegisterPPStep(BaseProcess* pImp)
{
ai_assert(NULL != pImp);
aiReturn Importer::RegisterPPStep(BaseProcess* pImp) {
ai_assert( nullptr != pImp );
ASSIMP_BEGIN_EXCEPTION_REGION();
pimpl->mPostProcessingSteps.push_back(pImp);
@ -213,9 +212,9 @@ aiReturn Importer::RegisterPPStep(BaseProcess* pImp)
// ------------------------------------------------------------------------------------------------
// Register a custom loader plugin
aiReturn Importer::RegisterLoader(BaseImporter* pImp)
{
ai_assert(NULL != pImp);
aiReturn Importer::RegisterLoader(BaseImporter* pImp) {
ai_assert(nullptr != pImp);
ASSIMP_BEGIN_EXCEPTION_REGION();
// --------------------------------------------------------------------
@ -242,13 +241,13 @@ aiReturn Importer::RegisterLoader(BaseImporter* pImp)
pimpl->mImporter.push_back(pImp);
ASSIMP_LOG_INFO_F("Registering custom importer for these file extensions: ", baked);
ASSIMP_END_EXCEPTION_REGION(aiReturn);
return AI_SUCCESS;
}
// ------------------------------------------------------------------------------------------------
// Unregister a custom loader plugin
aiReturn Importer::UnregisterLoader(BaseImporter* pImp)
{
aiReturn Importer::UnregisterLoader(BaseImporter* pImp) {
if(!pImp) {
// unregistering a NULL importer is no problem for us ... really!
return AI_SUCCESS;
@ -265,13 +264,13 @@ aiReturn Importer::UnregisterLoader(BaseImporter* pImp)
}
ASSIMP_LOG_WARN("Unable to remove custom importer: I can't find you ...");
ASSIMP_END_EXCEPTION_REGION(aiReturn);
return AI_FAILURE;
}
// ------------------------------------------------------------------------------------------------
// Unregister a custom loader plugin
aiReturn Importer::UnregisterPPStep(BaseProcess* pImp)
{
aiReturn Importer::UnregisterPPStep(BaseProcess* pImp) {
if(!pImp) {
// unregistering a NULL ppstep is no problem for us ... really!
return AI_SUCCESS;
@ -288,24 +287,22 @@ aiReturn Importer::UnregisterPPStep(BaseProcess* pImp)
}
ASSIMP_LOG_WARN("Unable to remove custom post-processing step: I can't find you ..");
ASSIMP_END_EXCEPTION_REGION(aiReturn);
return AI_FAILURE;
}
// ------------------------------------------------------------------------------------------------
// Supplies a custom IO handler to the importer to open and access files.
void Importer::SetIOHandler( IOSystem* pIOHandler)
{
void Importer::SetIOHandler( IOSystem* pIOHandler) {
ai_assert(nullptr != pimpl);
ASSIMP_BEGIN_EXCEPTION_REGION();
// If the new handler is zero, allocate a default IO implementation.
if (!pIOHandler)
{
if (!pIOHandler) {
// Release pointer in the possession of the caller
pimpl->mIOHandler = new DefaultIOSystem();
pimpl->mIsDefaultHandler = true;
}
// Otherwise register the custom handler
else if (pimpl->mIOHandler != pIOHandler)
{
} else if (pimpl->mIOHandler != pIOHandler) { // Otherwise register the custom handler
delete pimpl->mIOHandler;
pimpl->mIOHandler = pIOHandler;
pimpl->mIsDefaultHandler = false;
@ -316,29 +313,32 @@ void Importer::SetIOHandler( IOSystem* pIOHandler)
// ------------------------------------------------------------------------------------------------
// Get the currently set IO handler
IOSystem* Importer::GetIOHandler() const {
ai_assert(nullptr != pimpl);
return pimpl->mIOHandler;
}
// ------------------------------------------------------------------------------------------------
// Check whether a custom IO handler is currently set
bool Importer::IsDefaultIOHandler() const {
ai_assert(nullptr != pimpl);
return pimpl->mIsDefaultHandler;
}
// ------------------------------------------------------------------------------------------------
// Supplies a custom progress handler to get regular callbacks during importing
void Importer::SetProgressHandler ( ProgressHandler* pHandler ) {
ai_assert(nullptr != pimpl);
ASSIMP_BEGIN_EXCEPTION_REGION();
// If the new handler is zero, allocate a default implementation.
if (!pHandler)
{
if (!pHandler) {
// Release pointer in the possession of the caller
pimpl->mProgressHandler = new DefaultProgressHandler();
pimpl->mIsDefaultProgressHandler = true;
}
// Otherwise register the custom handler
else if (pimpl->mProgressHandler != pHandler)
{
} else if (pimpl->mProgressHandler != pHandler) { // Otherwise register the custom handler
delete pimpl->mProgressHandler;
pimpl->mProgressHandler = pHandler;
pimpl->mIsDefaultProgressHandler = false;
@ -349,19 +349,22 @@ void Importer::SetProgressHandler ( ProgressHandler* pHandler ) {
// ------------------------------------------------------------------------------------------------
// Get the currently set progress handler
ProgressHandler* Importer::GetProgressHandler() const {
ai_assert(nullptr != pimpl);
return pimpl->mProgressHandler;
}
// ------------------------------------------------------------------------------------------------
// Check whether a custom progress handler is currently set
bool Importer::IsDefaultProgressHandler() const {
ai_assert(nullptr != pimpl);
return pimpl->mIsDefaultProgressHandler;
}
// ------------------------------------------------------------------------------------------------
// Validate post process step flags
bool _ValidateFlags(unsigned int pFlags)
{
bool _ValidateFlags(unsigned int pFlags) {
if (pFlags & aiProcess_GenSmoothNormals && pFlags & aiProcess_GenNormals) {
ASSIMP_LOG_ERROR("#aiProcess_GenSmoothNormals and #aiProcess_GenNormals are incompatible");
return false;
@ -375,12 +378,13 @@ bool _ValidateFlags(unsigned int pFlags)
// ------------------------------------------------------------------------------------------------
// Free the current scene
void Importer::FreeScene( )
{
void Importer::FreeScene( ) {
ai_assert(nullptr != pimpl);
ASSIMP_BEGIN_EXCEPTION_REGION();
delete pimpl->mScene;
pimpl->mScene = NULL;
pimpl->mScene = nullptr;
pimpl->mErrorString = "";
ASSIMP_END_EXCEPTION_REGION(void);
@ -388,44 +392,48 @@ void Importer::FreeScene( )
// ------------------------------------------------------------------------------------------------
// Get the current error string, if any
const char* Importer::GetErrorString() const
{
/* Must remain valid as long as ReadFile() or FreeFile() are not called */
const char* Importer::GetErrorString() const {
ai_assert(nullptr != pimpl);
// Must remain valid as long as ReadFile() or FreeFile() are not called
return pimpl->mErrorString.c_str();
}
// ------------------------------------------------------------------------------------------------
// Enable extra-verbose mode
void Importer::SetExtraVerbose(bool bDo)
{
void Importer::SetExtraVerbose(bool bDo) {
ai_assert(nullptr != pimpl);
pimpl->bExtraVerbose = bDo;
}
// ------------------------------------------------------------------------------------------------
// Get the current scene
const aiScene* Importer::GetScene() const
{
const aiScene* Importer::GetScene() const {
ai_assert(nullptr != pimpl);
return pimpl->mScene;
}
// ------------------------------------------------------------------------------------------------
// Orphan the current scene and return it.
aiScene* Importer::GetOrphanedScene()
{
aiScene* Importer::GetOrphanedScene() {
ai_assert(nullptr != pimpl);
aiScene* s = pimpl->mScene;
ASSIMP_BEGIN_EXCEPTION_REGION();
pimpl->mScene = NULL;
pimpl->mScene = nullptr;
pimpl->mErrorString = ""; /* reset error string */
pimpl->mErrorString = ""; // reset error string
ASSIMP_END_EXCEPTION_REGION(aiScene*);
return s;
}
// ------------------------------------------------------------------------------------------------
// Validate post-processing flags
bool Importer::ValidateFlags(unsigned int pFlags) const
{
bool Importer::ValidateFlags(unsigned int pFlags) const {
ASSIMP_BEGIN_EXCEPTION_REGION();
// run basic checks for mutually exclusive flags
if(!_ValidateFlags(pFlags)) {
@ -467,8 +475,9 @@ bool Importer::ValidateFlags(unsigned int pFlags) const
const aiScene* Importer::ReadFileFromMemory( const void* pBuffer,
size_t pLength,
unsigned int pFlags,
const char* pHint /*= ""*/)
{
const char* pHint /*= ""*/) {
ai_assert(nullptr != pimpl);
ASSIMP_BEGIN_EXCEPTION_REGION();
if (!pHint) {
pHint = "";
@ -476,12 +485,12 @@ const aiScene* Importer::ReadFileFromMemory( const void* pBuffer,
if (!pBuffer || !pLength || strlen(pHint) > MaxLenHint ) {
pimpl->mErrorString = "Invalid parameters passed to ReadFileFromMemory()";
return NULL;
return nullptr;
}
// prevent deletion of the previous IOHandler
IOSystem* io = pimpl->mIOHandler;
pimpl->mIOHandler = NULL;
pimpl->mIOHandler = nullptr;
SetIOHandler(new MemoryIOSystem((const uint8_t*)pBuffer,pLength,io));
@ -493,13 +502,13 @@ const aiScene* Importer::ReadFileFromMemory( const void* pBuffer,
ReadFile(fbuff,pFlags);
SetIOHandler(io);
ASSIMP_END_EXCEPTION_REGION(const aiScene*);
ASSIMP_END_EXCEPTION_REGION_WITH_ERROR_STRING(const aiScene*, pimpl->mErrorString);
return pimpl->mScene;
}
// ------------------------------------------------------------------------------------------------
void WriteLogOpening(const std::string& file)
{
void WriteLogOpening(const std::string& file) {
ASSIMP_LOG_INFO_F("Load ", file);
// print a full version dump. This is nice because we don't
@ -550,8 +559,9 @@ void WriteLogOpening(const std::string& file)
// ------------------------------------------------------------------------------------------------
// Reads the given file and returns its contents if successful.
const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
{
const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) {
ai_assert(nullptr != pimpl);
ASSIMP_BEGIN_EXCEPTION_REGION();
const std::string pFile(_pFile);
@ -580,7 +590,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
pimpl->mErrorString = "Unable to open file \"" + pFile + "\".";
ASSIMP_LOG_ERROR(pimpl->mErrorString);
return NULL;
return nullptr;
}
std::unique_ptr<Profiler> profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME,0)?new Profiler():NULL);
@ -589,7 +599,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
}
// Find an worker class which can handle the file
BaseImporter* imp = NULL;
BaseImporter* imp = nullptr;
SetPropertyInteger("importerIndex", -1);
for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) {
@ -617,7 +627,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
if( !imp) {
pimpl->mErrorString = "No suitable reader found for the file format of file \"" + pFile + "\".";
ASSIMP_LOG_ERROR(pimpl->mErrorString);
return NULL;
return nullptr;
}
}
@ -633,7 +643,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
// Dispatch the reading to the worker class for this format
const aiImporterDesc *desc( imp->GetInfo() );
std::string ext( "unknown" );
if ( NULL != desc ) {
if ( nullptr != desc ) {
ext = desc->mName;
}
ASSIMP_LOG_INFO("Found a matching importer for this file format: " + ext + "." );
@ -654,15 +664,20 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
// If successful, apply all active post processing steps to the imported data
if( pimpl->mScene) {
if (!pimpl->mScene->mMetaData || !pimpl->mScene->mMetaData->HasKey(AI_METADATA_SOURCE_FORMAT)) {
if (!pimpl->mScene->mMetaData) {
pimpl->mScene->mMetaData = new aiMetadata;
}
pimpl->mScene->mMetaData->Add(AI_METADATA_SOURCE_FORMAT, aiString(ext));
}
#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
// The ValidateDS process is an exception. It is executed first, even before ScenePreprocessor is called.
if (pFlags & aiProcess_ValidateDataStructure)
{
if (pFlags & aiProcess_ValidateDataStructure) {
ValidateDSProcess ds;
ds.ExecuteOnScene (this);
if (!pimpl->mScene) {
return NULL;
return nullptr;
}
}
#endif // no validation
@ -695,8 +710,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
}
}
#ifdef ASSIMP_CATCH_GLOBAL_EXCEPTIONS
catch (std::exception &e)
{
catch (std::exception &e) {
#if (defined _MSC_VER) && (defined _CPPRTTI)
// if we have RTTI get the full name of the exception that occurred
pimpl->mErrorString = std::string(typeid( e ).name()) + ": " + e.what();
@ -705,24 +719,26 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
#endif
ASSIMP_LOG_ERROR(pimpl->mErrorString);
delete pimpl->mScene; pimpl->mScene = NULL;
delete pimpl->mScene; pimpl->mScene = nullptr;
}
#endif // ! ASSIMP_CATCH_GLOBAL_EXCEPTIONS
// either successful or failure - the pointer expresses it anyways
ASSIMP_END_EXCEPTION_REGION(const aiScene*);
ASSIMP_END_EXCEPTION_REGION_WITH_ERROR_STRING(const aiScene*, pimpl->mErrorString);
return pimpl->mScene;
}
// ------------------------------------------------------------------------------------------------
// Apply post-processing to the currently bound scene
const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
{
const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags) {
ai_assert(nullptr != pimpl);
ASSIMP_BEGIN_EXCEPTION_REGION();
// Return immediately if no scene is active
if (!pimpl->mScene) {
return NULL;
return nullptr;
}
// If no flags are given, return the current scene with no further action
@ -737,12 +753,11 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
// The ValidateDS process plays an exceptional role. It isn't contained in the global
// list of post-processing steps, so we need to call it manually.
if (pFlags & aiProcess_ValidateDataStructure)
{
if (pFlags & aiProcess_ValidateDataStructure) {
ValidateDSProcess ds;
ds.ExecuteOnScene (this);
if (!pimpl->mScene) {
return NULL;
return nullptr;
}
}
#endif // no validation
@ -762,11 +777,9 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
std::unique_ptr<Profiler> profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME,0)?new Profiler():NULL);
for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
BaseProcess* process = pimpl->mPostProcessingSteps[a];
pimpl->mProgressHandler->UpdatePostProcess(static_cast<int>(a), static_cast<int>(pimpl->mPostProcessingSteps.size()) );
if( process->IsActive( pFlags)) {
if (profiler) {
profiler->BeginRegion("postprocess");
}
@ -803,24 +816,28 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
static_cast<int>(pimpl->mPostProcessingSteps.size()) );
// update private scene flags
if( pimpl->mScene )
if( pimpl->mScene ) {
ScenePriv(pimpl->mScene)->mPPStepsApplied |= pFlags;
}
// clear any data allocated by post-process steps
pimpl->mPPShared->Clean();
ASSIMP_LOG_INFO("Leaving post processing pipeline");
ASSIMP_END_EXCEPTION_REGION(const aiScene*);
return pimpl->mScene;
}
// ------------------------------------------------------------------------------------------------
const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess, bool requestValidation ) {
ai_assert(nullptr != pimpl);
ASSIMP_BEGIN_EXCEPTION_REGION();
// Return immediately if no scene is active
if ( NULL == pimpl->mScene ) {
return NULL;
if ( nullptr == pimpl->mScene ) {
return nullptr;
}
// If no flags are given, return the current scene with no further action
@ -839,7 +856,7 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess
ValidateDSProcess ds;
ds.ExecuteOnScene( this );
if ( !pimpl->mScene ) {
return NULL;
return nullptr;
}
}
#endif // no validation
@ -890,46 +907,50 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess
// ------------------------------------------------------------------------------------------------
// Helper function to check whether an extension is supported by ASSIMP
bool Importer::IsExtensionSupported(const char* szExtension) const
{
bool Importer::IsExtensionSupported(const char* szExtension) const {
return nullptr != GetImporter(szExtension);
}
// ------------------------------------------------------------------------------------------------
size_t Importer::GetImporterCount() const
{
size_t Importer::GetImporterCount() const {
ai_assert(nullptr != pimpl);
return pimpl->mImporter.size();
}
// ------------------------------------------------------------------------------------------------
const aiImporterDesc* Importer::GetImporterInfo(size_t index) const
{
const aiImporterDesc* Importer::GetImporterInfo(size_t index) const {
ai_assert(nullptr != pimpl);
if (index >= pimpl->mImporter.size()) {
return NULL;
return nullptr;
}
return pimpl->mImporter[index]->GetInfo();
}
// ------------------------------------------------------------------------------------------------
BaseImporter* Importer::GetImporter (size_t index) const
{
BaseImporter* Importer::GetImporter (size_t index) const {
ai_assert(nullptr != pimpl);
if (index >= pimpl->mImporter.size()) {
return NULL;
return nullptr;
}
return pimpl->mImporter[index];
}
// ------------------------------------------------------------------------------------------------
// Find a loader plugin for a given file extension
BaseImporter* Importer::GetImporter (const char* szExtension) const
{
BaseImporter* Importer::GetImporter (const char* szExtension) const {
ai_assert(nullptr != pimpl);
return GetImporter(GetImporterIndex(szExtension));
}
// ------------------------------------------------------------------------------------------------
// Find a loader plugin for a given file extension
size_t Importer::GetImporterIndex (const char* szExtension) const {
ai_assert(nullptr != pimpl);
ai_assert(nullptr != szExtension);
ASSIMP_BEGIN_EXCEPTION_REGION();
@ -960,8 +981,9 @@ size_t Importer::GetImporterIndex (const char* szExtension) const {
// ------------------------------------------------------------------------------------------------
// Helper function to build a list of all file extensions supported by ASSIMP
void Importer::GetExtensionList(aiString& szOut) const
{
void Importer::GetExtensionList(aiString& szOut) const {
ai_assert(nullptr != pimpl);
ASSIMP_BEGIN_EXCEPTION_REGION();
std::set<std::string> str;
for (std::vector<BaseImporter*>::const_iterator i = pimpl->mImporter.begin();i != pimpl->mImporter.end();++i) {
@ -985,8 +1007,9 @@ void Importer::GetExtensionList(aiString& szOut) const
// ------------------------------------------------------------------------------------------------
// Set a configuration property
bool Importer::SetPropertyInteger(const char* szName, int iValue)
{
bool Importer::SetPropertyInteger(const char* szName, int iValue) {
ai_assert(nullptr != pimpl);
bool existing;
ASSIMP_BEGIN_EXCEPTION_REGION();
existing = SetGenericProperty<int>(pimpl->mIntProperties, szName,iValue);
@ -996,8 +1019,9 @@ bool Importer::SetPropertyInteger(const char* szName, int iValue)
// ------------------------------------------------------------------------------------------------
// Set a configuration property
bool Importer::SetPropertyFloat(const char* szName, ai_real iValue)
{
bool Importer::SetPropertyFloat(const char* szName, ai_real iValue) {
ai_assert(nullptr != pimpl);
bool existing;
ASSIMP_BEGIN_EXCEPTION_REGION();
existing = SetGenericProperty<ai_real>(pimpl->mFloatProperties, szName,iValue);
@ -1007,8 +1031,9 @@ bool Importer::SetPropertyFloat(const char* szName, ai_real iValue)
// ------------------------------------------------------------------------------------------------
// Set a configuration property
bool Importer::SetPropertyString(const char* szName, const std::string& value)
{
bool Importer::SetPropertyString(const char* szName, const std::string& value) {
ai_assert(nullptr != pimpl);
bool existing;
ASSIMP_BEGIN_EXCEPTION_REGION();
existing = SetGenericProperty<std::string>(pimpl->mStringProperties, szName,value);
@ -1018,8 +1043,9 @@ bool Importer::SetPropertyString(const char* szName, const std::string& value)
// ------------------------------------------------------------------------------------------------
// Set a configuration property
bool Importer::SetPropertyMatrix(const char* szName, const aiMatrix4x4& value)
{
bool Importer::SetPropertyMatrix(const char* szName, const aiMatrix4x4& value) {
ai_assert(nullptr != pimpl);
bool existing;
ASSIMP_BEGIN_EXCEPTION_REGION();
existing = SetGenericProperty<aiMatrix4x4>(pimpl->mMatrixProperties, szName,value);
@ -1029,40 +1055,43 @@ bool Importer::SetPropertyMatrix(const char* szName, const aiMatrix4x4& value)
// ------------------------------------------------------------------------------------------------
// Get a configuration property
int Importer::GetPropertyInteger(const char* szName,
int iErrorReturn /*= 0xffffffff*/) const
{
int Importer::GetPropertyInteger(const char* szName, int iErrorReturn /*= 0xffffffff*/) const {
ai_assert(nullptr != pimpl);
return GetGenericProperty<int>(pimpl->mIntProperties,szName,iErrorReturn);
}
// ------------------------------------------------------------------------------------------------
// Get a configuration property
ai_real Importer::GetPropertyFloat(const char* szName,
ai_real iErrorReturn /*= 10e10*/) const
{
ai_real Importer::GetPropertyFloat(const char* szName, ai_real iErrorReturn /*= 10e10*/) const {
ai_assert(nullptr != pimpl);
return GetGenericProperty<ai_real>(pimpl->mFloatProperties,szName,iErrorReturn);
}
// ------------------------------------------------------------------------------------------------
// Get a configuration property
const std::string Importer::GetPropertyString(const char* szName,
const std::string& iErrorReturn /*= ""*/) const
{
const std::string Importer::GetPropertyString(const char* szName, const std::string& iErrorReturn /*= ""*/) const {
ai_assert(nullptr != pimpl);
return GetGenericProperty<std::string>(pimpl->mStringProperties,szName,iErrorReturn);
}
// ------------------------------------------------------------------------------------------------
// Get a configuration property
const aiMatrix4x4 Importer::GetPropertyMatrix(const char* szName,
const aiMatrix4x4& iErrorReturn /*= aiMatrix4x4()*/) const
{
const aiMatrix4x4 Importer::GetPropertyMatrix(const char* szName, const aiMatrix4x4& iErrorReturn /*= aiMatrix4x4()*/) const {
ai_assert(nullptr != pimpl);
return GetGenericProperty<aiMatrix4x4>(pimpl->mMatrixProperties,szName,iErrorReturn);
}
// ------------------------------------------------------------------------------------------------
// Get the memory requirements of a single node
inline void AddNodeWeight(unsigned int& iScene,const aiNode* pcNode)
{
inline
void AddNodeWeight(unsigned int& iScene,const aiNode* pcNode) {
if ( nullptr == pcNode ) {
return;
}
iScene += sizeof(aiNode);
iScene += sizeof(unsigned int) * pcNode->mNumMeshes;
iScene += sizeof(void*) * pcNode->mNumChildren;
@ -1074,8 +1103,9 @@ inline void AddNodeWeight(unsigned int& iScene,const aiNode* pcNode)
// ------------------------------------------------------------------------------------------------
// Get the memory requirements of the scene
void Importer::GetMemoryRequirements(aiMemoryInfo& in) const
{
void Importer::GetMemoryRequirements(aiMemoryInfo& in) const {
ai_assert(nullptr != pimpl);
in = aiMemoryInfo();
aiScene* mScene = pimpl->mScene;
@ -1087,8 +1117,7 @@ void Importer::GetMemoryRequirements(aiMemoryInfo& in) const
in.total = sizeof(aiScene);
// add all meshes
for (unsigned int i = 0; i < mScene->mNumMeshes;++i)
{
for (unsigned int i = 0; i < mScene->mNumMeshes;++i) {
in.meshes += sizeof(aiMesh);
if (mScene->mMeshes[i]->HasPositions()) {
in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices;
@ -1105,14 +1134,16 @@ void Importer::GetMemoryRequirements(aiMemoryInfo& in) const
for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS;++a) {
if (mScene->mMeshes[i]->HasVertexColors(a)) {
in.meshes += sizeof(aiColor4D) * mScene->mMeshes[i]->mNumVertices;
} else {
break;
}
else break;
}
for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a) {
if (mScene->mMeshes[i]->HasTextureCoords(a)) {
in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices;
} else {
break;
}
else break;
}
if (mScene->mMeshes[i]->HasBones()) {
in.meshes += sizeof(void*) * mScene->mMeshes[i]->mNumBones;
@ -1131,8 +1162,9 @@ void Importer::GetMemoryRequirements(aiMemoryInfo& in) const
in.textures += sizeof(aiTexture);
if (pc->mHeight) {
in.textures += 4 * pc->mHeight * pc->mWidth;
} else {
in.textures += pc->mWidth;
}
else in.textures += pc->mWidth;
}
in.total += in.textures;

View File

@ -60,6 +60,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/scene.h>
#include <assimp/CreateAnimMesh.h>
#include <assimp/commonMetaData.h>
#include <assimp/StringUtils.h>
#include <tuple>
#include <memory>
@ -1597,12 +1599,11 @@ namespace Assimp {
aiBone *bone = nullptr;
if (bone_map.count(deformer_name)) {
std::cout << "retrieved bone from lookup " << bone_name.C_Str() << ". Deformer: " << deformer_name
<< std::endl;
bone = bone_map[deformer_name];
} else {
std::cout << "created new bone " << bone_name.C_Str() << ". Deformer: " << deformer_name << std::endl;
bone = new aiBone();
ASSIMP_LOG_DEBUG_F("retrieved bone from lookup ", bone_name.C_Str(), ". Deformer:", deformer_name);
bone = bone_map[deformer_name];
} else {
ASSIMP_LOG_DEBUG_F("created new bone ", bone_name.C_Str(), ". Deformer: ", deformer_name);
bone = new aiBone();
bone->mName = bone_name;
// store local transform link for post processing
@ -1648,7 +1649,7 @@ namespace Assimp {
bone_map.insert(std::pair<const std::string, aiBone *>(deformer_name, bone));
}
std::cout << "bone research: Indicies size: " << out_indices.size() << std::endl;
ASSIMP_LOG_DEBUG_F("bone research: Indicies size: ", out_indices.size());
// lookup must be populated in case something goes wrong
// this also allocates bones to mesh instance outside
@ -3604,7 +3605,9 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa
return;
}
out->mMetaData = aiMetadata::Alloc(15);
const bool hasGenerator = !doc.Creator().empty();
out->mMetaData = aiMetadata::Alloc(16 + (hasGenerator ? 1 : 0));
out->mMetaData->Set(0, "UpAxis", doc.GlobalSettings().UpAxis());
out->mMetaData->Set(1, "UpAxisSign", doc.GlobalSettings().UpAxisSign());
out->mMetaData->Set(2, "FrontAxis", doc.GlobalSettings().FrontAxis());
@ -3620,6 +3623,11 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa
out->mMetaData->Set(12, "TimeSpanStart", doc.GlobalSettings().TimeSpanStart());
out->mMetaData->Set(13, "TimeSpanStop", doc.GlobalSettings().TimeSpanStop());
out->mMetaData->Set(14, "CustomFrameRate", doc.GlobalSettings().CustomFrameRate());
out->mMetaData->Set(15, AI_METADATA_SOURCE_FORMAT_VERSION, aiString(to_string(doc.FBXVersion())));
if (hasGenerator)
{
out->mMetaData->Set(16, AI_METADATA_SOURCE_GENERATOR, aiString(doc.Creator()));
}
}
void FBXConverter::TransferDataToScene()

View File

@ -421,6 +421,8 @@ private:
double& minTime,
Model::RotOrder order);
// ------------------------------------------------------------------------------------------------
// Copy global geometric data and some information about the source asset into scene metadata.
void ConvertGlobalSettings();
// ------------------------------------------------------------------------------------------------

View File

@ -1860,6 +1860,7 @@ void FBXExporter::WriteObjects ()
sdnode.AddChild("Version", int32_t(100));
sdnode.AddChild("UserData", "", "");
std::set<int32_t> setWeightedVertex;
// add indices and weights, if any
if (b) {
std::vector<int32_t> subdef_indices;
@ -1867,7 +1868,8 @@ void FBXExporter::WriteObjects ()
int32_t last_index = -1;
for (size_t wi = 0; wi < b->mNumWeights; ++wi) {
int32_t vi = vertex_indices[b->mWeights[wi].mVertexId];
if (vi == last_index) {
bool bIsWeightedAlready = (setWeightedVertex.find(vi) != setWeightedVertex.end());
if (vi == last_index || bIsWeightedAlready) {
// only for vertices we exported to fbx
// TODO, FIXME: this assumes identically-located vertices
// will always deform in the same way.
@ -1877,6 +1879,7 @@ void FBXExporter::WriteObjects ()
// identical vertex.
continue;
}
setWeightedVertex.insert(vi);
subdef_indices.push_back(vi);
subdef_weights.push_back(b->mWeights[wi].mWeight);
last_index = vi;

View File

@ -586,7 +586,6 @@ void LWOImporter::GenerateNodeGraph(std::map<uint16_t,aiNode*>& apcNodes)
root->mName.Set("<LWORoot>");
//Set parent of all children, inserting pivots
//std::cout << "Set parent of all children" << std::endl;
std::map<uint16_t, aiNode*> mapPivot;
for (auto itapcNodes = apcNodes.begin(); itapcNodes != apcNodes.end(); ++itapcNodes) {
@ -618,7 +617,6 @@ void LWOImporter::GenerateNodeGraph(std::map<uint16_t,aiNode*>& apcNodes)
}
//Merge pivot map into node map
//std::cout << "Merge pivot map into node map" << std::endl;
for (auto itMapPivot = mapPivot.begin(); itMapPivot != mapPivot.end(); ++itMapPivot) {
apcNodes[itMapPivot->first] = itMapPivot->second;
}

View File

@ -362,8 +362,8 @@ namespace glTF
ComponentType componentType; //!< The datatype of components in the attribute. (required)
unsigned int count; //!< The number of attributes referenced by this accessor. (required)
AttribType::Value type; //!< Specifies if the attribute is a scalar, vector, or matrix. (required)
std::vector<float> max; //!< Maximum value of each component in this attribute.
std::vector<float> min; //!< Minimum value of each component in this attribute.
std::vector<double> max; //!< Maximum value of each component in this attribute.
std::vector<double> min; //!< Minimum value of each component in this attribute.
unsigned int GetNumComponents();
unsigned int GetBytesPerComponent();

View File

@ -54,9 +54,9 @@ namespace glTF {
namespace {
template<size_t N>
template<typename T, size_t N>
inline
Value& MakeValue(Value& val, float(&r)[N], MemoryPoolAllocator<>& al) {
Value& MakeValue(Value& val, T(&r)[N], MemoryPoolAllocator<>& al) {
val.SetArray();
val.Reserve(N, al);
for (decltype(N) i = 0; i < N; ++i) {
@ -65,8 +65,9 @@ namespace glTF {
return val;
}
template<typename T>
inline
Value& MakeValue(Value& val, const std::vector<float> & r, MemoryPoolAllocator<>& al) {
Value& MakeValue(Value& val, const std::vector<T> & r, MemoryPoolAllocator<>& al) {
val.SetArray();
val.Reserve(static_cast<rapidjson::SizeType>(r.size()), al);
for (unsigned int i = 0; i < r.size(); ++i) {
@ -75,6 +76,16 @@ namespace glTF {
return val;
}
template<typename C, typename T>
inline Value& MakeValueCast(Value& val, const std::vector<T> & r, MemoryPoolAllocator<>& al) {
val.SetArray();
val.Reserve(static_cast<rapidjson::SizeType>(r.size()), al);
for (unsigned int i = 0; i < r.size(); ++i) {
val.PushBack(static_cast<C>(r[i]), al);
}
return val;
}
template<class T>
inline void AddRefsVector(Value& obj, const char* fieldId, std::vector< Ref<T> >& v, MemoryPoolAllocator<>& al) {
if (v.empty()) return;
@ -100,8 +111,13 @@ namespace glTF {
obj.AddMember("type", StringRef(AttribType::ToString(a.type)), w.mAl);
Value vTmpMax, vTmpMin;
obj.AddMember("max", MakeValue(vTmpMax, a.max, w.mAl), w.mAl);
obj.AddMember("min", MakeValue(vTmpMin, a.min, w.mAl), w.mAl);
if (a.componentType == ComponentType_FLOAT) {
obj.AddMember("max", MakeValue(vTmpMax, a.max, w.mAl), w.mAl);
obj.AddMember("min", MakeValue(vTmpMin, a.min, w.mAl), w.mAl);
} else {
obj.AddMember("max", MakeValueCast<int64_t>(vTmpMax, a.max, w.mAl), w.mAl);
obj.AddMember("min", MakeValueCast<int64_t>(vTmpMin, a.min, w.mAl), w.mAl);
}
}
inline void Write(Value& obj, Animation& a, AssetWriter& w)

View File

@ -58,6 +58,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Header files, standard library.
#include <memory>
#include <limits>
#include <inttypes.h>
#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
@ -173,6 +174,62 @@ static void IdentityMatrix4(glTF::mat4& o)
o[12] = 0; o[13] = 0; o[14] = 0; o[15] = 1;
}
template<typename T>
void SetAccessorRange(Ref<Accessor> acc, void* data, unsigned int count,
unsigned int numCompsIn, unsigned int numCompsOut)
{
ai_assert(numCompsOut <= numCompsIn);
// Allocate and initialize with large values.
for (unsigned int i = 0 ; i < numCompsOut ; i++) {
acc->min.push_back( std::numeric_limits<double>::max());
acc->max.push_back(-std::numeric_limits<double>::max());
}
size_t totalComps = count * numCompsIn;
T* buffer_ptr = static_cast<T*>(data);
T* buffer_end = buffer_ptr + totalComps;
// Search and set extreme values.
for (; buffer_ptr < buffer_end ; buffer_ptr += numCompsIn) {
for (unsigned int j = 0 ; j < numCompsOut ; j++) {
double valueTmp = buffer_ptr[j];
if (valueTmp < acc->min[j]) {
acc->min[j] = valueTmp;
}
if (valueTmp > acc->max[j]) {
acc->max[j] = valueTmp;
}
}
}
}
inline void SetAccessorRange(ComponentType compType, Ref<Accessor> acc, void* data,
unsigned int count, unsigned int numCompsIn, unsigned int numCompsOut)
{
switch (compType) {
case ComponentType_SHORT:
SetAccessorRange<short>(acc, data, count, numCompsIn, numCompsOut);
return;
case ComponentType_UNSIGNED_SHORT:
SetAccessorRange<unsigned short>(acc, data, count, numCompsIn, numCompsOut);
return;
case ComponentType_UNSIGNED_INT:
SetAccessorRange<unsigned int>(acc, data, count, numCompsIn, numCompsOut);
return;
case ComponentType_FLOAT:
SetAccessorRange<float>(acc, data, count, numCompsIn, numCompsOut);
return;
case ComponentType_BYTE:
SetAccessorRange<int8_t>(acc, data, count, numCompsIn, numCompsOut);
return;
case ComponentType_UNSIGNED_BYTE:
SetAccessorRange<uint8_t>(acc, data, count, numCompsIn, numCompsOut);
return;
}
}
inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& buffer,
unsigned int count, void* data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, bool isIndices = false)
{
@ -206,33 +263,7 @@ inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& bu
acc->type = typeOut;
// calculate min and max values
{
// Allocate and initialize with large values.
float float_MAX = 10000000000000.0f;
for (unsigned int i = 0 ; i < numCompsOut ; i++) {
acc->min.push_back( float_MAX);
acc->max.push_back(-float_MAX);
}
// Search and set extreme values.
float valueTmp;
for (unsigned int i = 0 ; i < count ; i++) {
for (unsigned int j = 0 ; j < numCompsOut ; j++) {
if (numCompsOut == 1) {
valueTmp = static_cast<unsigned short*>(data)[i];
} else {
valueTmp = static_cast<aiVector3D*>(data)[i][j];
}
if (valueTmp < acc->min[j]) {
acc->min[j] = valueTmp;
}
if (valueTmp > acc->max[j]) {
acc->max[j] = valueTmp;
}
}
}
}
SetAccessorRange(compType, acc, data, count, numCompsIn, numCompsOut);
// copy the data
acc->WriteData(count, data, numCompsIn*bytesPerComp);

View File

@ -54,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/ai_assert.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/importerdesc.h>
#include <assimp/commonMetaData.h>
#include <memory>
@ -697,6 +698,25 @@ void glTFImporter::ImportEmbeddedTextures(glTF::Asset& r)
}
}
void glTFImporter::ImportCommonMetadata(glTF::Asset& a)
{
ai_assert(mScene->mMetaData == nullptr);
const bool hasVersion = !a.asset.version.empty();
const bool hasGenerator = !a.asset.generator.empty();
if (hasVersion || hasGenerator)
{
mScene->mMetaData = new aiMetadata;
if (hasVersion)
{
mScene->mMetaData->Add(AI_METADATA_SOURCE_FORMAT_VERSION, aiString(a.asset.version));
}
if (hasGenerator)
{
mScene->mMetaData->Add(AI_METADATA_SOURCE_GENERATOR, aiString(a.asset.generator));
}
}
}
void glTFImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
{
// clean all member arrays
@ -723,7 +743,7 @@ void glTFImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOS
ImportLights(asset);
ImportNodes(asset);
ImportCommonMetadata(asset);
if (pScene->mNumMeshes == 0) {
pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;

View File

@ -83,7 +83,7 @@ private:
void ImportCameras(glTF::Asset& a);
void ImportLights(glTF::Asset& a);
void ImportNodes(glTF::Asset& a);
void ImportCommonMetadata(glTF::Asset& a);
};
} // Namespace assimp

View File

@ -387,8 +387,8 @@ namespace glTF2
ComponentType componentType; //!< The datatype of components in the attribute. (required)
size_t count; //!< The number of attributes referenced by this accessor. (required)
AttribType::Value type; //!< Specifies if the attribute is a scalar, vector, or matrix. (required)
std::vector<float> max; //!< Maximum value of each component in this attribute.
std::vector<float> min; //!< Minimum value of each component in this attribute.
std::vector<double> max; //!< Maximum value of each component in this attribute.
std::vector<double> min; //!< Minimum value of each component in this attribute.
unsigned int GetNumComponents();
unsigned int GetBytesPerComponent();

View File

@ -270,13 +270,14 @@ Ref<T> LazyDict<T>::Retrieve(unsigned int i)
throw DeadlyImportError("GLTF: Object at index \"" + to_string(i) + "\" is not a JSON object");
}
T* inst = new T();
// Unique ptr prevents memory leak in case of Read throws an exception
auto inst = std::unique_ptr<T>(new T());
inst->id = std::string(mDictId) + "_" + to_string(i);
inst->oIndex = i;
ReadMember(obj, "name", inst->name);
inst->Read(obj, mAsset);
return Add(inst);
return Add(inst.release());
}
template<class T>

View File

@ -54,8 +54,8 @@ namespace glTF2 {
namespace {
template<size_t N>
inline Value& MakeValue(Value& val, float(&r)[N], MemoryPoolAllocator<>& al) {
template<typename T, size_t N>
inline Value& MakeValue(Value& val, T(&r)[N], MemoryPoolAllocator<>& al) {
val.SetArray();
val.Reserve(N, al);
for (decltype(N) i = 0; i < N; ++i) {
@ -64,7 +64,8 @@ namespace glTF2 {
return val;
}
inline Value& MakeValue(Value& val, const std::vector<float> & r, MemoryPoolAllocator<>& al) {
template<typename T>
inline Value& MakeValue(Value& val, const std::vector<T> & r, MemoryPoolAllocator<>& al) {
val.SetArray();
val.Reserve(static_cast<rapidjson::SizeType>(r.size()), al);
for (unsigned int i = 0; i < r.size(); ++i) {
@ -73,8 +74,19 @@ namespace glTF2 {
return val;
}
inline Value& MakeValue(Value& val, float r, MemoryPoolAllocator<>& /*al*/) {
val.SetDouble(r);
template<typename C, typename T>
inline Value& MakeValueCast(Value& val, const std::vector<T> & r, MemoryPoolAllocator<>& al) {
val.SetArray();
val.Reserve(static_cast<rapidjson::SizeType>(r.size()), al);
for (unsigned int i = 0; i < r.size(); ++i) {
val.PushBack(static_cast<C>(r[i]), al);
}
return val;
}
template<typename T>
inline Value& MakeValue(Value& val, T r, MemoryPoolAllocator<>& /*al*/) {
val.Set(r);
return val;
}
@ -104,8 +116,13 @@ namespace glTF2 {
obj.AddMember("type", StringRef(AttribType::ToString(a.type)), w.mAl);
Value vTmpMax, vTmpMin;
obj.AddMember("max", MakeValue(vTmpMax, a.max, w.mAl), w.mAl);
obj.AddMember("min", MakeValue(vTmpMin, a.min, w.mAl), w.mAl);
if (a.componentType == ComponentType_FLOAT) {
obj.AddMember("max", MakeValue(vTmpMax, a.max, w.mAl), w.mAl);
obj.AddMember("min", MakeValue(vTmpMin, a.min, w.mAl), w.mAl);
} else {
obj.AddMember("max", MakeValueCast<int64_t>(vTmpMax, a.max, w.mAl), w.mAl);
obj.AddMember("min", MakeValueCast<int64_t>(vTmpMin, a.min, w.mAl), w.mAl);
}
}
inline void Write(Value& obj, Animation& a, AssetWriter& w)

View File

@ -58,6 +58,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Header files, standard library.
#include <memory>
#include <limits>
#include <inttypes.h>
using namespace rapidjson;
@ -152,6 +153,62 @@ static void IdentityMatrix4(mat4& o) {
o[12] = 0; o[13] = 0; o[14] = 0; o[15] = 1;
}
template<typename T>
void SetAccessorRange(Ref<Accessor> acc, void* data, size_t count,
unsigned int numCompsIn, unsigned int numCompsOut)
{
ai_assert(numCompsOut <= numCompsIn);
// Allocate and initialize with large values.
for (unsigned int i = 0 ; i < numCompsOut ; i++) {
acc->min.push_back( std::numeric_limits<double>::max());
acc->max.push_back(-std::numeric_limits<double>::max());
}
size_t totalComps = count * numCompsIn;
T* buffer_ptr = static_cast<T*>(data);
T* buffer_end = buffer_ptr + totalComps;
// Search and set extreme values.
for (; buffer_ptr < buffer_end ; buffer_ptr += numCompsIn) {
for (unsigned int j = 0 ; j < numCompsOut ; j++) {
double valueTmp = buffer_ptr[j];
if (valueTmp < acc->min[j]) {
acc->min[j] = valueTmp;
}
if (valueTmp > acc->max[j]) {
acc->max[j] = valueTmp;
}
}
}
}
inline void SetAccessorRange(ComponentType compType, Ref<Accessor> acc, void* data,
size_t count, unsigned int numCompsIn, unsigned int numCompsOut)
{
switch (compType) {
case ComponentType_SHORT:
SetAccessorRange<short>(acc, data, count, numCompsIn, numCompsOut);
return;
case ComponentType_UNSIGNED_SHORT:
SetAccessorRange<unsigned short>(acc, data, count, numCompsIn, numCompsOut);
return;
case ComponentType_UNSIGNED_INT:
SetAccessorRange<unsigned int>(acc, data, count, numCompsIn, numCompsOut);
return;
case ComponentType_FLOAT:
SetAccessorRange<float>(acc, data, count, numCompsIn, numCompsOut);
return;
case ComponentType_BYTE:
SetAccessorRange<int8_t>(acc, data, count, numCompsIn, numCompsOut);
return;
case ComponentType_UNSIGNED_BYTE:
SetAccessorRange<uint8_t>(acc, data, count, numCompsIn, numCompsOut);
return;
}
}
inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& buffer,
size_t count, void* data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, bool isIndices = false)
{
@ -187,33 +244,7 @@ inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& bu
acc->type = typeOut;
// calculate min and max values
{
// Allocate and initialize with large values.
float float_MAX = 10000000000000.0f;
for (unsigned int i = 0 ; i < numCompsOut ; i++) {
acc->min.push_back( float_MAX);
acc->max.push_back(-float_MAX);
}
// Search and set extreme values.
float valueTmp;
for (unsigned int i = 0 ; i < count ; i++) {
for (unsigned int j = 0 ; j < numCompsOut ; j++) {
if (numCompsOut == 1) {
valueTmp = static_cast<unsigned short*>(data)[i];
} else {
valueTmp = static_cast<aiVector3D*>(data)[i][j];
}
if (valueTmp < acc->min[j]) {
acc->min[j] = valueTmp;
}
if (valueTmp > acc->max[j]) {
acc->max[j] = valueTmp;
}
}
}
}
SetAccessorRange(compType, acc, data, count, numCompsIn, numCompsOut);
// copy the data
acc->WriteData(count, data, numCompsIn*bytesPerComp);

View File

@ -55,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/Importer.hpp>
#include <assimp/commonMetaData.h>
#include <memory>
#include <unordered_map>
@ -1301,6 +1302,24 @@ void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) {
}
}
void glTF2Importer::ImportCommonMetadata(glTF2::Asset& a) {
ai_assert(mScene->mMetaData == nullptr);
const bool hasVersion = !a.asset.version.empty();
const bool hasGenerator = !a.asset.generator.empty();
if (hasVersion || hasGenerator)
{
mScene->mMetaData = new aiMetadata;
if (hasVersion)
{
mScene->mMetaData->Add(AI_METADATA_SOURCE_FORMAT_VERSION, aiString(a.asset.version));
}
if (hasGenerator)
{
mScene->mMetaData->Add(AI_METADATA_SOURCE_GENERATOR, aiString(a.asset.generator));
}
}
}
void glTF2Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
// clean all member arrays
meshOffsets.clear();
@ -1328,6 +1347,8 @@ void glTF2Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IO
ImportAnimations(asset);
ImportCommonMetadata(asset);
if (pScene->mNumMeshes == 0) {
pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
}

View File

@ -84,6 +84,7 @@ private:
void ImportLights(glTF2::Asset& a);
void ImportNodes(glTF2::Asset& a);
void ImportAnimations(glTF2::Asset& a);
void ImportCommonMetadata(glTF2::Asset& a);
};
} // Namespace assimp

View File

@ -119,6 +119,16 @@ struct ExceptionSwallower<void> {
{\
try {
#define ASSIMP_END_EXCEPTION_REGION_WITH_ERROR_STRING(type, ASSIMP_END_EXCEPTION_REGION_errorString)\
} catch(const DeadlyImportError& e) {\
ASSIMP_END_EXCEPTION_REGION_errorString = e.what();\
return ExceptionSwallower<type>()();\
} catch(...) {\
ASSIMP_END_EXCEPTION_REGION_errorString = "Unknown exception";\
return ExceptionSwallower<type>()();\
}\
}
#define ASSIMP_END_EXCEPTION_REGION(type)\
} catch(...) {\
return ExceptionSwallower<type>()();\

View File

@ -72,7 +72,7 @@ for(LineSplitter splitter(stream);splitter;++splitter) {
if (strtol(splitter[2]) > 5) { .. }
}
std::cout << "Current line is: " << splitter.get_index() << std::endl;
ASSIMP_LOG_DEBUG_F("Current line is: ", splitter.get_index());
}
@endcode
*/

View File

@ -0,0 +1,63 @@
/*
---------------------------------------------------------------------------
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 commonMetaData.h
* @brief Defines a set of common scene metadata keys.
*/
#pragma once
#ifndef AI_COMMONMETADATA_H_INC
#define AI_COMMONMETADATA_H_INC
/// Scene metadata holding the name of the importer which loaded the source asset.
/// This is always present if the scene was created from an imported asset.
#define AI_METADATA_SOURCE_FORMAT "SourceAsset_Format"
/// Scene metadata holding the version of the source asset as a string, if available.
/// Not all formats add this metadata.
#define AI_METADATA_SOURCE_FORMAT_VERSION "SourceAsset_FormatVersion"
/// Scene metadata holding the name of the software which generated the source asset, if available.
/// Not all formats add this metadata.
#define AI_METADATA_SOURCE_GENERATOR "SourceAsset_Generator"
#endif

View File

@ -286,8 +286,8 @@ struct aiMetadata {
new_values[i] = mValues[i];
}
delete mKeys;
delete mValues;
delete[] mKeys;
delete[] mValues;
mKeys = new_keys;
mValues = new_values;
@ -377,6 +377,23 @@ struct aiMetadata {
return true;
}
/// Check whether there is a metadata entry for the given key.
/// \param [in] Key - the key value value to check for.
inline
bool HasKey(const char* key) {
if ( nullptr == key ) {
return false;
}
// Search for the given key
for (unsigned int i = 0; i < mNumProperties; ++i) {
if ( 0 == strncmp(mKeys[i].C_Str(), key, mKeys[i].length ) ) {
return true;
}
}
return false;
}
#endif // __cplusplus
};

View File

@ -0,0 +1,181 @@
{
"asset": {
"generator": "COLLADA2GLTF",
"version": "2.0"
},
"scene": 0,
"scenes": [
{
"nodes": [
0
]
}
],
"nodes": [
{
"children": [
1
],
"matrix": [
1.0,
0.0,
0.0,
0.0,
0.0,
0.0,
-1.0,
0.0,
0.0,
1.0,
0.0,
0.0,
0.0,
0.0,
0.0,
1.0
]
},
{
"mesh": 0
}
],
"meshes": [
{
"primitives": [
{
"attributes": {
"NORMAL": 1,
"POSITION": 2,
"TEXCOORD_0": 3
},
"indices": 0,
"mode": 4,
"material": 0
}
],
"name": "Mesh"
}
],
"accessors": [
{
"bufferView": 0,
"byteOffset": 0,
"componentType": 5123,
"count": 36,
"max": [
23
],
"min": [
0
],
"type": "SCALAR"
},
{
"bufferView": 1,
"byteOffset": 0,
"componentType": 5126,
"count": 24,
"max": [
1.0,
1.0,
1.0
],
"min": [
-1.0,
-1.0,
-1.0
],
"type": "VEC3"
},
{
"bufferView": 1,
"byteOffset": 288,
"componentType": 5126,
"count": 24,
"max": [
0.5,
0.5,
0.5
],
"min": [
-0.5,
-0.5,
-0.5
],
"type": "VEC3"
},
{
"bufferView": 2,
"byteOffset": 0,
"componentType": 5126,
"count": 24,
"max": [
6.0,
1.0
],
"min": [
0.0,
0.0
],
"type": "VEC2"
}
],
"materials": [
{
"pbrMetallicRoughness": {
"baseColorTexture": {
"index": 0
},
"metallicFactor": 0.0
},
"name": "Texture"
}
],
"textures": [
{
"sampler": 0,
"source": 0
}
],
"images": [
{
"uri": "CesiumLogoFlat.png"
}
],
"samplers": [
{
"magFilter": 9729,
"minFilter": 9986,
"wrapS": 33648,
"wrapT": 33071
}
],
"bufferViews": [
{
"buffer": 0,
"byteOffset": 768,
"byteLength": 72,
"target": 34963
},
{
"buffer": 0,
"byteOffset": 0,
"byteLength": 576,
"byteStride": 12,
"target": 34962
},
{
"buffer": 0,
"byteOffset": 576,
"byteLength": 192,
"byteStride": 8,
"target": 34962
}
],
"buffers": [
{
"byteLength": 840,
"uri": "BoxTextured0.bin"
}
]
}

View File

@ -50,6 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/material.h>
#include <assimp/scene.h>
#include <assimp/types.h>
#include <assimp/commonMetaData.h>
using namespace Assimp;
@ -283,3 +284,29 @@ TEST_F(utFBXImporterExporter, importOrphantEmbeddedTextureTest) {
ASSERT_TRUE(scene->mTextures[0]->pcData);
ASSERT_EQ(9026u, scene->mTextures[0]->mWidth) << "FBX ASCII base64 compression used for a texture.";
}
TEST_F(utFBXImporterExporter, sceneMetadata) {
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/global_settings.fbx",
aiProcess_ValidateDataStructure);
ASSERT_NE(scene, nullptr);
ASSERT_NE(scene->mMetaData, nullptr);
{
ASSERT_TRUE(scene->mMetaData->HasKey(AI_METADATA_SOURCE_FORMAT));
aiString format;
ASSERT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_FORMAT, format));
ASSERT_EQ(strcmp(format.C_Str(), "Autodesk FBX Importer"), 0);
}
{
ASSERT_TRUE(scene->mMetaData->HasKey(AI_METADATA_SOURCE_FORMAT_VERSION));
aiString version;
ASSERT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_FORMAT_VERSION, version));
ASSERT_EQ(strcmp(version.C_Str(), "7400"), 0);
}
{
ASSERT_TRUE(scene->mMetaData->HasKey(AI_METADATA_SOURCE_GENERATOR));
aiString generator;
ASSERT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_GENERATOR, generator));
ASSERT_EQ(strncmp(generator.C_Str(), "Blender", 7), 0);
}
}

View File

@ -45,6 +45,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/Exporter.hpp>
#include <assimp/postprocess.h>
#include <assimp/scene.h>
#include <assimp/commonMetaData.h>
#include <array>
using namespace Assimp;
@ -426,4 +428,39 @@ TEST_F( utglTF2ImportExport, crash_in_anim_mesh_destructor ) {
ASSERT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "glb2", ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Sample-Models/AnimatedMorphCube-glTF/AnimatedMorphCube_out.glTF"));
}
TEST_F(utglTF2ImportExport, error_string_preserved) {
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/MissingBin/BoxTextured.gltf",
aiProcess_ValidateDataStructure);
ASSERT_EQ(nullptr, scene);
std::string error = importer.GetErrorString();
ASSERT_NE(error.find("BoxTextured0.bin"), std::string::npos) << "Error string should contain an error about missing .bin file";
}
#endif // ASSIMP_BUILD_NO_EXPORT
TEST_F(utglTF2ImportExport, sceneMetadata) {
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf",
aiProcess_ValidateDataStructure);
ASSERT_NE(scene, nullptr);
ASSERT_NE(scene->mMetaData, nullptr);
{
ASSERT_TRUE(scene->mMetaData->HasKey(AI_METADATA_SOURCE_FORMAT));
aiString format;
ASSERT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_FORMAT, format));
ASSERT_EQ(strcmp(format.C_Str(), "glTF2 Importer"), 0);
}
{
ASSERT_TRUE(scene->mMetaData->HasKey(AI_METADATA_SOURCE_FORMAT_VERSION));
aiString version;
ASSERT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_FORMAT_VERSION, version));
ASSERT_EQ(strcmp(version.C_Str(), "2.0"), 0);
}
{
ASSERT_TRUE(scene->mMetaData->HasKey(AI_METADATA_SOURCE_GENERATOR));
aiString generator;
ASSERT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_GENERATOR, generator));
ASSERT_EQ(strcmp(generator.C_Str(), "COLLADA2GLTF"), 0);
}
}

View File

@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/postprocess.h>
#include <assimp/scene.h>
#include <assimp/commonMetaData.h>
using namespace Assimp;
@ -85,3 +86,28 @@ TEST_F(utglTFImportExport, incorrect_vertex_arrays) {
EXPECT_EQ(scene->mMeshes[7]->mNumVertices, 35u);
EXPECT_EQ(scene->mMeshes[7]->mNumFaces, 17u);
}
TEST_F(utglTFImportExport, sceneMetadata) {
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF/TwoBoxes/TwoBoxes.gltf", aiProcess_ValidateDataStructure);
ASSERT_TRUE(scene);
ASSERT_TRUE(scene->mMetaData);
{
ASSERT_TRUE(scene->mMetaData->HasKey(AI_METADATA_SOURCE_FORMAT));
aiString format;
ASSERT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_FORMAT, format));
ASSERT_EQ(strcmp(format.C_Str(), "glTF Importer"), 0);
}
{
ASSERT_TRUE(scene->mMetaData->HasKey(AI_METADATA_SOURCE_FORMAT_VERSION));
aiString version;
ASSERT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_FORMAT_VERSION, version));
ASSERT_EQ(strcmp(version.C_Str(), "1.0"), 0);
}
{
ASSERT_TRUE(scene->mMetaData->HasKey(AI_METADATA_SOURCE_GENERATOR));
aiString generator;
ASSERT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_GENERATOR, generator));
ASSERT_EQ(strncmp(generator.C_Str(), "collada2gltf", 12), 0);
}
}