- rework exporter interface to be based primarily on the existing IOSystem.
- implement ExportToBlob/aiExportToBlob via a custom IOSystem implementation. - split exporter C and C++ interfaces. + test cases for the exporter interface git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@913 67173fc5-114c-0410-ac8e-9d2fd5bffc1fpull/1/head
parent
32c8ca0a37
commit
621bdef663
108
code/Assimp.cpp
108
code/Assimp.cpp
|
@ -44,9 +44,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include "AssimpPCH.h"
|
#include "AssimpPCH.h"
|
||||||
#include "../include/assimp.h"
|
#include "../include/assimp.h"
|
||||||
#include "../include/aiFileIO.h"
|
|
||||||
|
|
||||||
#include "GenericProperty.h"
|
#include "GenericProperty.h"
|
||||||
|
#include "CInterfaceIOWrapper.h"
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
#ifdef AI_C_THREADSAFE
|
#ifdef AI_C_THREADSAFE
|
||||||
|
@ -58,6 +58,7 @@ using namespace Assimp;
|
||||||
|
|
||||||
namespace Assimp
|
namespace Assimp
|
||||||
{
|
{
|
||||||
|
|
||||||
/** Stores the importer objects for all active import processes */
|
/** Stores the importer objects for all active import processes */
|
||||||
typedef std::map<const aiScene*, Assimp::Importer*> ImporterMap;
|
typedef std::map<const aiScene*, Assimp::Importer*> ImporterMap;
|
||||||
|
|
||||||
|
@ -101,113 +102,8 @@ static boost::mutex gMutex;
|
||||||
static boost::mutex gLogStreamMutex;
|
static boost::mutex gLogStreamMutex;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class CIOSystemWrapper;
|
|
||||||
class CIOStreamWrapper;
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
// Custom IOStream implementation for the C-API
|
|
||||||
class CIOStreamWrapper : public IOStream
|
|
||||||
{
|
|
||||||
friend class CIOSystemWrapper;
|
|
||||||
public:
|
|
||||||
|
|
||||||
CIOStreamWrapper(aiFile* pFile)
|
|
||||||
: mFile(pFile)
|
|
||||||
{}
|
|
||||||
|
|
||||||
// ...................................................................
|
|
||||||
size_t Read(void* pvBuffer,
|
|
||||||
size_t pSize,
|
|
||||||
size_t pCount
|
|
||||||
){
|
|
||||||
// need to typecast here as C has no void*
|
|
||||||
return mFile->ReadProc(mFile,(char*)pvBuffer,pSize,pCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ...................................................................
|
|
||||||
size_t Write(const void* pvBuffer,
|
|
||||||
size_t pSize,
|
|
||||||
size_t pCount
|
|
||||||
){
|
|
||||||
// need to typecast here as C has no void*
|
|
||||||
return mFile->WriteProc(mFile,(const char*)pvBuffer,pSize,pCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ...................................................................
|
|
||||||
aiReturn Seek(size_t pOffset,
|
|
||||||
aiOrigin pOrigin
|
|
||||||
){
|
|
||||||
return mFile->SeekProc(mFile,pOffset,pOrigin);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ...................................................................
|
|
||||||
size_t Tell(void) const {
|
|
||||||
return mFile->TellProc(mFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ...................................................................
|
|
||||||
size_t FileSize() const {
|
|
||||||
return mFile->FileSizeProc(mFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ...................................................................
|
|
||||||
void Flush () {
|
|
||||||
return mFile->FlushProc(mFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
aiFile* mFile;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
// Custom IOStream implementation for the C-API
|
|
||||||
class CIOSystemWrapper : public IOSystem
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CIOSystemWrapper(aiFileIO* pFile)
|
|
||||||
: mFileSystem(pFile)
|
|
||||||
{}
|
|
||||||
|
|
||||||
// ...................................................................
|
|
||||||
bool Exists( const char* pFile) const {
|
|
||||||
CIOSystemWrapper* pip = const_cast<CIOSystemWrapper*>(this);
|
|
||||||
IOStream* p = pip->Open(pFile);
|
|
||||||
if (p){
|
|
||||||
pip->Close(p);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ...................................................................
|
|
||||||
char getOsSeparator() const {
|
|
||||||
#ifndef _WIN32
|
|
||||||
return '/';
|
|
||||||
#else
|
|
||||||
return '\\';
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// ...................................................................
|
|
||||||
IOStream* Open(const char* pFile,const char* pMode = "rb") {
|
|
||||||
aiFile* p = mFileSystem->OpenProc(mFileSystem,pFile,pMode);
|
|
||||||
if (!p) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return new CIOStreamWrapper(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ...................................................................
|
|
||||||
void Close( IOStream* pFile) {
|
|
||||||
if (!pFile) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mFileSystem->CloseProc(mFileSystem,((CIOStreamWrapper*) pFile)->mFile);
|
|
||||||
delete pFile;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
aiFileIO* mFileSystem;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Custom LogStream implementation for the C-API
|
// Custom LogStream implementation for the C-API
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
/*
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
Open Asset Import Library (ASSIMP)
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2010, ASSIMP Development 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 Development 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "AssimpPCH.h"
|
||||||
|
|
||||||
|
#ifndef ASSIMP_BUILD_NO_EXPORT
|
||||||
|
#include "CInterfaceIOWrapper.h"
|
||||||
|
|
||||||
|
using namespace Assimp;
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
ASSIMP_API size_t aiGetExportFormatCount(void)
|
||||||
|
{
|
||||||
|
return Exporter().GetExportFormatCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
ASSIMP_API const aiExportFormatDesc* aiGetExportFormatDescription( size_t pIndex)
|
||||||
|
{
|
||||||
|
return Exporter().GetExportFormatDescription(pIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
ASSIMP_API aiReturn aiExportScene( const aiScene* pScene, const char* pFormatId, const char* pFileName )
|
||||||
|
{
|
||||||
|
return ::aiExportSceneEx(pScene,pFormatId,pFileName,NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
ASSIMP_API aiReturn aiExportSceneEx( const aiScene* pScene, const char* pFormatId, const char* pFileName, aiFileIO* pIO)
|
||||||
|
{
|
||||||
|
Exporter exp;
|
||||||
|
|
||||||
|
if (pIO) {
|
||||||
|
exp.SetIOHandler(new CIOSystemWrapper(pIO));
|
||||||
|
}
|
||||||
|
return exp.Export(pScene,pFormatId,pFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
ASSIMP_API const C_STRUCT aiExportDataBlob* aiExportSceneToBlob( const aiScene* pScene, const char* pFormatId )
|
||||||
|
{
|
||||||
|
Exporter exp;
|
||||||
|
if (!exp.ExportToBlob(pScene,pFormatId)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
const aiExportDataBlob* blob = exp.GetOrphanedBlob();
|
||||||
|
ai_assert(blob);
|
||||||
|
|
||||||
|
return blob;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
ASSIMP_API C_STRUCT void aiReleaseExportData( const aiExportDataBlob* pData )
|
||||||
|
{
|
||||||
|
delete pData;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !ASSIMP_BUILD_NO_EXPORT
|
|
@ -0,0 +1,326 @@
|
||||||
|
/*
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
Open Asset Import Library (ASSIMP)
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Provides cheat implementations for IOSystem and IOStream to
|
||||||
|
* redirect exporter output to a blob chain.*/
|
||||||
|
|
||||||
|
#ifndef AI_BLOBIOSYSTEM_H_INCLUDED
|
||||||
|
#define AI_BLOBIOSYSTEM_H_INCLUDED
|
||||||
|
|
||||||
|
namespace Assimp {
|
||||||
|
class BlobIOSystem;
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------------
|
||||||
|
/** Redirect IOStream to a blob */
|
||||||
|
// --------------------------------------------------------------------------------------------
|
||||||
|
class BlobIOStream : public IOStream
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
BlobIOStream(BlobIOSystem* creator, const std::string& file, size_t initial = 4096)
|
||||||
|
: file_size()
|
||||||
|
, cursor()
|
||||||
|
, buffer()
|
||||||
|
, creator(creator)
|
||||||
|
, file(file)
|
||||||
|
, cur_size()
|
||||||
|
, initial(initial)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual ~BlobIOStream();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
aiExportDataBlob* GetBlob()
|
||||||
|
{
|
||||||
|
aiExportDataBlob* blob = new aiExportDataBlob();
|
||||||
|
blob->size = file_size;
|
||||||
|
blob->data = buffer;
|
||||||
|
|
||||||
|
buffer = NULL;
|
||||||
|
|
||||||
|
return blob;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
virtual size_t Read(void* pvBuffer,
|
||||||
|
size_t pSize,
|
||||||
|
size_t pCount)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
virtual size_t Write(const void* pvBuffer,
|
||||||
|
size_t pSize,
|
||||||
|
size_t pCount)
|
||||||
|
{
|
||||||
|
pSize *= pCount;
|
||||||
|
if (cursor + pSize > cur_size) {
|
||||||
|
Grow(cursor + pSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buffer+cursor, pvBuffer, pSize);
|
||||||
|
cursor += pSize;
|
||||||
|
|
||||||
|
file_size = std::max(file_size,cursor);
|
||||||
|
return pCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
virtual aiReturn Seek(size_t pOffset,
|
||||||
|
aiOrigin pOrigin)
|
||||||
|
{
|
||||||
|
switch(pOrigin)
|
||||||
|
{
|
||||||
|
case aiOrigin_CUR:
|
||||||
|
cursor += pOffset;
|
||||||
|
|
||||||
|
case aiOrigin_END:
|
||||||
|
cursor = file_size - pOffset;
|
||||||
|
|
||||||
|
case aiOrigin_SET:
|
||||||
|
cursor = pOffset;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return AI_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cursor > file_size) {
|
||||||
|
Grow(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
file_size = std::max(cursor,file_size);
|
||||||
|
return AI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
virtual size_t Tell() const
|
||||||
|
{
|
||||||
|
return cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
virtual size_t FileSize() const
|
||||||
|
{
|
||||||
|
return file_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
virtual void Flush()
|
||||||
|
{
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
void Grow(size_t need = 0)
|
||||||
|
{
|
||||||
|
// 1.5 and phi are very heap-friendly growth factors (the first
|
||||||
|
// allows for frequent re-use of heap blocks, the second
|
||||||
|
// forms a fibonacci sequence with similar characteristics -
|
||||||
|
// since this heavily depends on the heap implementation
|
||||||
|
// and other factors as well, i'll just go with 1.5 since
|
||||||
|
// it is quicker to compute).
|
||||||
|
size_t new_size = std::max(initial, std::max( need, cur_size+(cur_size>>1) ));
|
||||||
|
|
||||||
|
const uint8_t* const old = buffer;
|
||||||
|
buffer = new uint8_t[new_size];
|
||||||
|
|
||||||
|
if (old) {
|
||||||
|
memcpy(buffer,old,cur_size);
|
||||||
|
delete[] old;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_size = new_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
uint8_t* buffer;
|
||||||
|
size_t cur_size,file_size, cursor, initial;
|
||||||
|
|
||||||
|
const std::string file;
|
||||||
|
BlobIOSystem* const creator;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define AI_BLOBIO_MAGIC "$blobfile"
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------------
|
||||||
|
/** Redirect IOSystem to a blob */
|
||||||
|
// --------------------------------------------------------------------------------------------
|
||||||
|
class BlobIOSystem : public IOSystem
|
||||||
|
{
|
||||||
|
|
||||||
|
friend class BlobIOStream;
|
||||||
|
typedef std::pair<std::string, aiExportDataBlob*> BlobEntry;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
BlobIOSystem()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~BlobIOSystem()
|
||||||
|
{
|
||||||
|
BOOST_FOREACH(BlobEntry& blobby, blobs) {
|
||||||
|
delete blobby.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
const char* GetMagicFileName() const
|
||||||
|
{
|
||||||
|
return AI_BLOBIO_MAGIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
aiExportDataBlob* GetBlobChain()
|
||||||
|
{
|
||||||
|
// one must be the master
|
||||||
|
aiExportDataBlob* master = NULL, *cur;
|
||||||
|
BOOST_FOREACH(const BlobEntry& blobby, blobs) {
|
||||||
|
if (blobby.first == AI_BLOBIO_MAGIC) {
|
||||||
|
master = blobby.second;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!master) {
|
||||||
|
DefaultLogger::get()->error("BlobIOSystem: no data written or master file was not closed properly.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
master->name.Set("");
|
||||||
|
|
||||||
|
cur = master;
|
||||||
|
BOOST_FOREACH(const BlobEntry& blobby, blobs) {
|
||||||
|
if (blobby.second == master) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur->next = blobby.second;
|
||||||
|
cur = cur->next;
|
||||||
|
|
||||||
|
// extract the file extension from the file written
|
||||||
|
const std::string::size_type s = blobby.first.find_first_of('.');
|
||||||
|
cur->name.Set(s == std::string::npos ? blobby.first : blobby.first.substr(s+1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// give up blob ownership
|
||||||
|
blobs.clear();
|
||||||
|
return master;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
virtual bool Exists( const char* pFile) const {
|
||||||
|
return created.find(std::string(pFile)) != created.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
virtual char getOsSeparator() const {
|
||||||
|
return '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
virtual IOStream* Open(const char* pFile,
|
||||||
|
const char* pMode)
|
||||||
|
{
|
||||||
|
if (pMode[0] != 'w') {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
created.insert(std::string(pFile));
|
||||||
|
return new BlobIOStream(this,std::string(pFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
virtual void Close( IOStream* pFile)
|
||||||
|
{
|
||||||
|
delete pFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
void OnDestruct(const std::string& filename, BlobIOStream* child)
|
||||||
|
{
|
||||||
|
// we don't know in which the files are closed, so we
|
||||||
|
// can't reliably say that the first must be the master
|
||||||
|
// file ...
|
||||||
|
blobs.push_back( BlobEntry(filename,child->GetBlob()) );
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::set<std::string> created;
|
||||||
|
std::vector< BlobEntry > blobs;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------------
|
||||||
|
BlobIOStream :: ~BlobIOStream()
|
||||||
|
{
|
||||||
|
creator->OnDestruct(file,this);
|
||||||
|
delete[] buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // end Assimp
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,159 @@
|
||||||
|
/*
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
Open Asset Import Library (ASSIMP)
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 aiFileIO -> IOSystem wrapper*/
|
||||||
|
|
||||||
|
#ifndef AI_CIOSYSTEM_H_INCLUDED
|
||||||
|
#define AI_CIOSYSTEM_H_INCLUDED
|
||||||
|
|
||||||
|
#include "../include/aiFileIO.h"
|
||||||
|
|
||||||
|
namespace Assimp {
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
// Custom IOStream implementation for the C-API
|
||||||
|
class CIOStreamWrapper : public IOStream
|
||||||
|
{
|
||||||
|
friend class CIOSystemWrapper;
|
||||||
|
public:
|
||||||
|
|
||||||
|
CIOStreamWrapper(aiFile* pFile)
|
||||||
|
: mFile(pFile)
|
||||||
|
{}
|
||||||
|
|
||||||
|
// ...................................................................
|
||||||
|
size_t Read(void* pvBuffer,
|
||||||
|
size_t pSize,
|
||||||
|
size_t pCount
|
||||||
|
){
|
||||||
|
// need to typecast here as C has no void*
|
||||||
|
return mFile->ReadProc(mFile,(char*)pvBuffer,pSize,pCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...................................................................
|
||||||
|
size_t Write(const void* pvBuffer,
|
||||||
|
size_t pSize,
|
||||||
|
size_t pCount
|
||||||
|
){
|
||||||
|
// need to typecast here as C has no void*
|
||||||
|
return mFile->WriteProc(mFile,(const char*)pvBuffer,pSize,pCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...................................................................
|
||||||
|
aiReturn Seek(size_t pOffset,
|
||||||
|
aiOrigin pOrigin
|
||||||
|
){
|
||||||
|
return mFile->SeekProc(mFile,pOffset,pOrigin);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...................................................................
|
||||||
|
size_t Tell(void) const {
|
||||||
|
return mFile->TellProc(mFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...................................................................
|
||||||
|
size_t FileSize() const {
|
||||||
|
return mFile->FileSizeProc(mFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...................................................................
|
||||||
|
void Flush () {
|
||||||
|
return mFile->FlushProc(mFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
aiFile* mFile;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
// Custom IOStream implementation for the C-API
|
||||||
|
class CIOSystemWrapper : public IOSystem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CIOSystemWrapper(aiFileIO* pFile)
|
||||||
|
: mFileSystem(pFile)
|
||||||
|
{}
|
||||||
|
|
||||||
|
// ...................................................................
|
||||||
|
bool Exists( const char* pFile) const {
|
||||||
|
CIOSystemWrapper* pip = const_cast<CIOSystemWrapper*>(this);
|
||||||
|
IOStream* p = pip->Open(pFile);
|
||||||
|
if (p){
|
||||||
|
pip->Close(p);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...................................................................
|
||||||
|
char getOsSeparator() const {
|
||||||
|
#ifndef _WIN32
|
||||||
|
return '/';
|
||||||
|
#else
|
||||||
|
return '\\';
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...................................................................
|
||||||
|
IOStream* Open(const char* pFile,const char* pMode = "rb") {
|
||||||
|
aiFile* p = mFileSystem->OpenProc(mFileSystem,pFile,pMode);
|
||||||
|
if (!p) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return new CIOStreamWrapper(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...................................................................
|
||||||
|
void Close( IOStream* pFile) {
|
||||||
|
if (!pFile) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mFileSystem->CloseProc(mFileSystem,((CIOStreamWrapper*) pFile)->mFile);
|
||||||
|
delete pFile;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
aiFileIO* mFileSystem;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -48,16 +48,16 @@ namespace Assimp
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp
|
// Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp
|
||||||
void ExportSceneCollada( aiExportDataBlob* pBlob, const aiScene* pScene)
|
void ExportSceneCollada(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene)
|
||||||
{
|
{
|
||||||
// invoke the exporter
|
// invoke the exporter
|
||||||
ColladaExporter iDoTheExportThing( pScene);
|
ColladaExporter iDoTheExportThing( pScene);
|
||||||
|
|
||||||
// we're still here - export successfully completed. Load result into given blob
|
// we're still here - export successfully completed. Write result to the given IOSYstem
|
||||||
pBlob->size = iDoTheExportThing.mOutput.tellp();
|
boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
|
||||||
pBlob->data = new char[pBlob->size];
|
|
||||||
iDoTheExportThing.mOutput.seekg( 0);
|
// XXX maybe use a small wrapper around IOStream that behaves like std::stringstream in order to avoid the extra copy.
|
||||||
iDoTheExportThing.mOutput.read( (char*) pBlob->data, pBlob->size);
|
outfile->Write( iDoTheExportThing.mOutput.str().c_str(), iDoTheExportThing.mOutput.tellp(),1);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end of namespace Assimp
|
} // end of namespace Assimp
|
||||||
|
|
|
@ -65,6 +65,8 @@ public:
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef DeadlyImportError DeadlyExportError;
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
# pragma warning(default : 4275)
|
# pragma warning(default : 4275)
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -46,24 +46,26 @@ to the import interface (in fact, it is largely symmetric), the internal
|
||||||
implementations differs a lot. Exporters are considered stateless and are
|
implementations differs a lot. Exporters are considered stateless and are
|
||||||
simple callbacks which we maintain in a global list along with their
|
simple callbacks which we maintain in a global list along with their
|
||||||
description strings.
|
description strings.
|
||||||
|
|
||||||
|
Here we implement only the C++ interface (Assimp::Exporter).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "AssimpPCH.h"
|
#include "AssimpPCH.h"
|
||||||
|
|
||||||
#ifndef ASSIMP_BUILD_NO_EXPORT
|
#ifndef ASSIMP_BUILD_NO_EXPORT
|
||||||
|
|
||||||
#include "DefaultIOStream.h"
|
|
||||||
#include "DefaultIOSystem.h"
|
#include "DefaultIOSystem.h"
|
||||||
|
#include "BlobIOSystem.h"
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Exporter worker function prototypes. Should not be necessary to #ifndef them, it's just a prototype
|
// Exporter worker function prototypes. Should not be necessary to #ifndef them, it's just a prototype
|
||||||
void ExportSceneCollada(aiExportDataBlob*, const aiScene*);
|
void ExportSceneCollada(const char*,IOSystem*, const aiScene*);
|
||||||
void ExportScene3DS(aiExportDataBlob*, const aiScene*) { }
|
void ExportScene3DS(const char*, IOSystem*, const aiScene*) {}
|
||||||
|
|
||||||
/// Function pointer type of a Export worker function
|
/// Function pointer type of a Export worker function
|
||||||
typedef void (*fpExportFunc)(aiExportDataBlob*, const aiScene*);
|
typedef void (*fpExportFunc)(const char*,IOSystem*,const aiScene*);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
/// Internal description of an Assimp export format option
|
/// Internal description of an Assimp export format option
|
||||||
|
@ -76,10 +78,11 @@ struct ExportFormatEntry
|
||||||
fpExportFunc mExportFunction;
|
fpExportFunc mExportFunction;
|
||||||
|
|
||||||
// Constructor to fill all entries
|
// Constructor to fill all entries
|
||||||
ExportFormatEntry( const char* pId, const char* pDesc, fpExportFunc pFunction)
|
ExportFormatEntry( const char* pId, const char* pDesc, const char* pExtension, fpExportFunc pFunction)
|
||||||
{
|
{
|
||||||
mDescription.id = pId;
|
mDescription.id = pId;
|
||||||
mDescription.description = pDesc;
|
mDescription.description = pDesc;
|
||||||
|
mDescription.fileExtension = pExtension;
|
||||||
mExportFunction = pFunction;
|
mExportFunction = pFunction;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -89,11 +92,11 @@ struct ExportFormatEntry
|
||||||
ExportFormatEntry gExporters[] =
|
ExportFormatEntry gExporters[] =
|
||||||
{
|
{
|
||||||
#ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER
|
#ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER
|
||||||
ExportFormatEntry( "collada", "Collada .dae", &ExportSceneCollada),
|
ExportFormatEntry( "collada", "COLLADA - Digital Asset Exchange Schema", "dae", &ExportSceneCollada),
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER
|
#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER
|
||||||
ExportFormatEntry( "3ds", "Autodesk .3ds", &ExportScene3DS),
|
ExportFormatEntry( "3ds", "Autodesk 3DS (legacy format)", "3ds" , &ExportScene3DS),
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -121,6 +124,8 @@ public:
|
||||||
bool mIsDefaultIOHandler;
|
bool mIsDefaultIOHandler;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define ASSIMP_NUM_EXPORTERS (sizeof(gExporters)/sizeof(gExporters[0]))
|
||||||
|
|
||||||
} // end of namespace Assimp
|
} // end of namespace Assimp
|
||||||
|
|
||||||
|
|
||||||
|
@ -174,30 +179,43 @@ const aiExportDataBlob* Exporter :: ExportToBlob( const aiScene* pScene, const
|
||||||
pimpl->blob = NULL;
|
pimpl->blob = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO (ALEX)
|
|
||||||
|
|
||||||
boost::shared_ptr<IOSystem*> old = pimpl->mIOSystem;
|
boost::shared_ptr<IOSystem> old = pimpl->mIOSystem;
|
||||||
|
|
||||||
BlobIOSystem* blobio;
|
BlobIOSystem* blobio = new BlobIOSystem();
|
||||||
pimpl->mIOSystem = blobio = new BlobIOSystem();
|
pimpl->mIOSystem = boost::shared_ptr<IOSystem>( blobio );
|
||||||
|
|
||||||
if (AI_SUCCESS != Export(pScene,pFormatId)) {
|
if (AI_SUCCESS != Export(pScene,pFormatId,blobio->GetMagicFileName())) {
|
||||||
pimpl->mIOSystem = old;
|
pimpl->mIOSystem = old;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pimpl->blob = blobio->GetBlob();
|
pimpl->blob = blobio->GetBlobChain();
|
||||||
pimpl->mIOSystem = old;
|
pimpl->mIOSystem = old;
|
||||||
|
|
||||||
return pimpl->blob;
|
return pimpl->blob;
|
||||||
*/
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const char* pPath )
|
aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const char* pPath )
|
||||||
{
|
{
|
||||||
|
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||||
|
for (size_t i = 0; i < ASSIMP_NUM_EXPORTERS; ++i) {
|
||||||
|
if (!strcmp(gExporters[i].mDescription.id,pFormatId)) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
gExporters[i].mExportFunction(pPath,pimpl->mIOSystem.get(),pScene);
|
||||||
|
}
|
||||||
|
catch (DeadlyExportError& err) {
|
||||||
|
// XXX what to do with the error message? Maybe introduce extra member to hold it, similar to Assimp.Importer
|
||||||
|
DefaultLogger::get()->error(err.what());
|
||||||
|
return AI_FAILURE;
|
||||||
|
}
|
||||||
|
return AI_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ASSIMP_END_EXCEPTION_REGION(aiReturn);
|
||||||
return AI_FAILURE;
|
return AI_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,80 +237,20 @@ const aiExportDataBlob* Exporter :: GetOrphanedBlob() const
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
size_t Exporter :: aiGetExportFormatCount() const
|
size_t Exporter :: GetExportFormatCount() const
|
||||||
{
|
{
|
||||||
return ::aiGetExportFormatCount();
|
return ASSIMP_NUM_EXPORTERS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
const aiExportFormatDesc* Exporter :: aiGetExportFormatDescription( size_t pIndex ) const
|
const aiExportFormatDesc* Exporter :: GetExportFormatDescription( size_t pIndex ) const
|
||||||
{
|
{
|
||||||
return ::aiGetExportFormatDescription(pIndex);
|
if (pIndex >= ASSIMP_NUM_EXPORTERS) {
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
ASSIMP_API size_t aiGetExportFormatCount(void)
|
|
||||||
{
|
|
||||||
return sizeof( Assimp::gExporters) / sizeof( Assimp::ExportFormatEntry);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
ASSIMP_API const aiExportFormatDesc* aiGetExportFormatDescription( size_t pIndex)
|
|
||||||
{
|
|
||||||
if( pIndex >= aiGetExportFormatCount() )
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return &Assimp::gExporters[pIndex].mDescription;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
ASSIMP_API aiReturn aiExportScene( const aiScene* pScene, const char* pFormatId, const char* pFileName )
|
|
||||||
{
|
|
||||||
return ::aiExportSceneEx(pScene,pFormatId,pFileName,NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
ASSIMP_API aiReturn aiExportSceneEx( const aiScene* pScene, const char* pFormatId, const char* pFileName, const aiFileIO* pIO)
|
|
||||||
{
|
|
||||||
return AI_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
ASSIMP_API const C_STRUCT aiExportDataBlob* aiExportSceneToBlob( const aiScene* pScene, const char* pFormatId )
|
|
||||||
{
|
|
||||||
// find a suitable exporter
|
|
||||||
const Assimp::ExportFormatEntry* exporter = NULL;
|
|
||||||
for( size_t a = 0; a < aiGetExportFormatCount(); ++a )
|
|
||||||
{
|
|
||||||
if( strcmp( Assimp::gExporters[a].mDescription.id, pFormatId) == 0 )
|
|
||||||
exporter = Assimp::gExporters + a;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !exporter )
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
aiExportDataBlob* blob = new aiExportDataBlob;
|
|
||||||
exporter->mExportFunction( blob, pScene);
|
|
||||||
if( !blob->data || blob->size == 0 )
|
|
||||||
{
|
|
||||||
delete blob;
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return blob;
|
return &gExporters[pIndex].mDescription;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
ASSIMP_API C_STRUCT void aiReleaseExportData( const aiExportDataBlob* pData )
|
|
||||||
{
|
|
||||||
delete pData;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // !ASSIMP_BUILD_NO_EXPORT
|
#endif // !ASSIMP_BUILD_NO_EXPORT
|
||||||
|
|
|
@ -149,7 +149,7 @@ public:
|
||||||
/** @brief Compares two paths and check whether the point to
|
/** @brief Compares two paths and check whether the point to
|
||||||
* identical files.
|
* identical files.
|
||||||
*
|
*
|
||||||
* The dummy implementation of this virtual performs a
|
* The dummy implementation of this virtual member performs a
|
||||||
* case-insensitive comparison of the given strings. The default IO
|
* case-insensitive comparison of the given strings. The default IO
|
||||||
* system implementation uses OS mechanisms to convert relative into
|
* system implementation uses OS mechanisms to convert relative into
|
||||||
* absolute paths, so the result can be trusted.
|
* absolute paths, so the result can be trusted.
|
||||||
|
|
|
@ -91,6 +91,10 @@ ASSIMP_API const C_STRUCT aiExportFormatDesc* aiGetExportFormatDescription( size
|
||||||
* exported scene. The memory referred by this structure is owned by Assimp. Use aiReleaseExportedFile()
|
* exported scene. The memory referred by this structure is owned by Assimp. Use aiReleaseExportedFile()
|
||||||
* to free its resources. Don't try to free the memory on your side - it will crash for most build configurations
|
* to free its resources. Don't try to free the memory on your side - it will crash for most build configurations
|
||||||
* due to conflicting heaps.
|
* due to conflicting heaps.
|
||||||
|
*
|
||||||
|
* Blobs can be nested - each blob may reference another blob, which may in turn reference another blob and so on.
|
||||||
|
* This is used when exporters write more than one output file for a given #aiScene. See the remarks for
|
||||||
|
* #aiExportDataBlob::name for more information.
|
||||||
*/
|
*/
|
||||||
struct aiExportDataBlob
|
struct aiExportDataBlob
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -103,11 +107,28 @@ struct aiExportDataBlob
|
||||||
/// The data.
|
/// The data.
|
||||||
void* data;
|
void* data;
|
||||||
|
|
||||||
|
/** Name of the blob. An empty string always
|
||||||
|
indicates the first (and primary) blob,
|
||||||
|
which contains the actual file data.
|
||||||
|
Any other blobs are auxiliary files produced
|
||||||
|
by exporters (i.e. material files). Existence
|
||||||
|
of such files depends on the file format. Most
|
||||||
|
formats don't split assets across multiple files.
|
||||||
|
|
||||||
|
If used, blob names usually contain the file
|
||||||
|
extension that should be used when writing
|
||||||
|
the data to disc.
|
||||||
|
*/
|
||||||
|
aiString name;
|
||||||
|
|
||||||
|
/** Pointer to the next blob in the chain or NULL if there is none. */
|
||||||
|
aiExportDataBlob * next;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
/// Default constructor
|
/// Default constructor
|
||||||
aiExportDataBlob() { size = 0; data = NULL; }
|
aiExportDataBlob() { size = 0; data = next = NULL; }
|
||||||
/// Releases the data
|
/// Releases the data
|
||||||
~aiExportDataBlob() { delete static_cast<char*>( data ); }
|
~aiExportDataBlob() { delete static_cast<char*>( data ); delete next; }
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -137,7 +158,7 @@ ASSIMP_API aiReturn aiExportScene( const C_STRUCT aiScene* pScene, const char* p
|
||||||
* #aiExportSceneToBlob is provided as convienience function to export to memory buffers.
|
* #aiExportSceneToBlob is provided as convienience function to export to memory buffers.
|
||||||
* @return a status code indicating the result of the export
|
* @return a status code indicating the result of the export
|
||||||
*/
|
*/
|
||||||
ASSIMP_API aiReturn aiExportSceneEx( const C_STRUCT aiScene* pScene, const char* pFormatId, const char* pFileName, const C_STRUCT aiFileIO* pIO );
|
ASSIMP_API aiReturn aiExportSceneEx( const C_STRUCT aiScene* pScene, const char* pFormatId, const char* pFileName, C_STRUCT aiFileIO* pIO );
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------
|
||||||
/** Exports the given scene to a chosen file format. Returns the exported data as a binary blob which
|
/** Exports the given scene to a chosen file format. Returns the exported data as a binary blob which
|
||||||
|
|
|
@ -59,6 +59,16 @@ namespace Assimp {
|
||||||
*
|
*
|
||||||
* The interface is modelled after the importer interface and mostly
|
* The interface is modelled after the importer interface and mostly
|
||||||
* symmetric. The same rules for threading etc. apply.
|
* symmetric. The same rules for threading etc. apply.
|
||||||
|
*
|
||||||
|
* In a nutshell, there are two export interfaces: #Export, which writes the
|
||||||
|
* output file(s) either to the regular file system or to a user-supplied
|
||||||
|
* #IOSystem, and #ExportToBlob which returns a linked list of memory
|
||||||
|
* buffers (blob), each referring to one output file (in most cases
|
||||||
|
* there will be only one output file of course, but this extra complexity is
|
||||||
|
* needed since Assimp aims at supporting a wide range of file formats).
|
||||||
|
*
|
||||||
|
* #ExportToBlob is especially useful if you intend to work
|
||||||
|
* with the data in-memory.
|
||||||
*/
|
*/
|
||||||
class ASSIMP_API Exporter
|
class ASSIMP_API Exporter
|
||||||
// TODO: causes good ol' base class has no dll interface warning
|
// TODO: causes good ol' base class has no dll interface warning
|
||||||
|
@ -77,9 +87,11 @@ public:
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** Supplies a custom IO handler to the exporter to use to open and
|
/** Supplies a custom IO handler to the exporter to use to open and
|
||||||
* access files. If you need the exporter to use custion IO logic to
|
* access files.
|
||||||
* access the files, you need to supply a custom implementation of
|
*
|
||||||
* IOSystem and IOFile to the exporter.
|
* If you need #Export to use custom IO logic to access the files,
|
||||||
|
* you need to supply a custom implementation of IOSystem and
|
||||||
|
* IOFile to the exporter.
|
||||||
*
|
*
|
||||||
* #Exporter takes ownership of the object and will destroy it
|
* #Exporter takes ownership of the object and will destroy it
|
||||||
* afterwards. The previously assigned handler will be deleted.
|
* afterwards. The previously assigned handler will be deleted.
|
||||||
|
@ -124,7 +136,8 @@ public:
|
||||||
* export formats are available.
|
* export formats are available.
|
||||||
* @return the exported data or NULL in case of error.
|
* @return the exported data or NULL in case of error.
|
||||||
* @note If the Exporter instance did already hold a blob from
|
* @note If the Exporter instance did already hold a blob from
|
||||||
* a previous call to #ExportToBlob, it will be disposed. */
|
* a previous call to #ExportToBlob, it will be disposed.
|
||||||
|
* Any IO handlers set via #SetIOHandler are ignored here.*/
|
||||||
const aiExportDataBlob* ExportToBlob( const aiScene* pScene, const char* pFormatId );
|
const aiExportDataBlob* ExportToBlob( const aiScene* pScene, const char* pFormatId );
|
||||||
|
|
||||||
|
|
||||||
|
@ -155,7 +168,7 @@ public:
|
||||||
/** Returns the number of export file formats available in the current
|
/** Returns the number of export file formats available in the current
|
||||||
* Assimp build. Use #Exporter::GetExportFormatDescription to
|
* Assimp build. Use #Exporter::GetExportFormatDescription to
|
||||||
* retrieve infos of a specific export format */
|
* retrieve infos of a specific export format */
|
||||||
size_t aiGetExportFormatCount() const;
|
size_t GetExportFormatCount() const;
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
|
@ -166,7 +179,7 @@ public:
|
||||||
* for. Valid range is 0 to #Exporter::GetExportFormatCount
|
* for. Valid range is 0 to #Exporter::GetExportFormatCount
|
||||||
* @return A description of that specific export format.
|
* @return A description of that specific export format.
|
||||||
* NULL if pIndex is out of range. */
|
* NULL if pIndex is out of range. */
|
||||||
const aiExportFormatDesc* aiGetExportFormatDescription( size_t pIndex ) const;
|
const aiExportFormatDesc* GetExportFormatDescription( size_t pIndex ) const;
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
|
||||||
|
#include "UnitTestPCH.h"
|
||||||
|
#include "utExport.h"
|
||||||
|
|
||||||
|
#ifndef ASSIMP_BUILD_NO_EXPORT
|
||||||
|
|
||||||
|
CPPUNIT_TEST_SUITE_REGISTRATION (ExporterTest);
|
||||||
|
|
||||||
|
void ExporterTest :: setUp (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
ex = new Assimp::Exporter();
|
||||||
|
im = new Assimp::Importer();
|
||||||
|
|
||||||
|
pTest = im->ReadFile("../../test/models/X/test.x",0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ExporterTest :: tearDown (void)
|
||||||
|
{
|
||||||
|
delete ex;
|
||||||
|
delete im;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ExporterTest :: testExportToFile (void)
|
||||||
|
{
|
||||||
|
const char* file = "unittest_output.dae";
|
||||||
|
CPPUNIT_ASSERT_EQUAL(AI_SUCCESS,ex->Export(pTest,"collada",file));
|
||||||
|
|
||||||
|
// check if we can read it again
|
||||||
|
CPPUNIT_ASSERT(im->ReadFile(file,0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ExporterTest :: testExportToBlob (void)
|
||||||
|
{
|
||||||
|
const aiExportDataBlob* blob = ex->ExportToBlob(pTest,"collada");
|
||||||
|
CPPUNIT_ASSERT(blob);
|
||||||
|
CPPUNIT_ASSERT(blob->data);
|
||||||
|
CPPUNIT_ASSERT(blob->size > 0);
|
||||||
|
CPPUNIT_ASSERT(!blob->name.length);
|
||||||
|
|
||||||
|
// XXX test chained blobs (i.e. obj file with accompanying mtl script)
|
||||||
|
|
||||||
|
// check if we can read it again
|
||||||
|
CPPUNIT_ASSERT(im->ReadFileFromMemory(blob->data,blob->size,0,"dae"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ExporterTest :: testCppExportInterface (void)
|
||||||
|
{
|
||||||
|
CPPUNIT_ASSERT(ex->GetExportFormatCount() > 0);
|
||||||
|
for(size_t i = 0; i < ex->GetExportFormatCount(); ++i) {
|
||||||
|
const aiExportFormatDesc* const desc = ex->GetExportFormatDescription(i);
|
||||||
|
CPPUNIT_ASSERT(desc);
|
||||||
|
CPPUNIT_ASSERT(desc->description && strlen(desc->description));
|
||||||
|
CPPUNIT_ASSERT(desc->fileExtension && strlen(desc->fileExtension));
|
||||||
|
CPPUNIT_ASSERT(desc->id && strlen(desc->id));
|
||||||
|
}
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(ex->IsDefaultIOHandler());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ExporterTest :: testCExportInterface (void)
|
||||||
|
{
|
||||||
|
CPPUNIT_ASSERT(aiGetExportFormatCount() > 0);
|
||||||
|
for(size_t i = 0; i < aiGetExportFormatCount(); ++i) {
|
||||||
|
const aiExportFormatDesc* const desc = aiGetExportFormatDescription(i);
|
||||||
|
CPPUNIT_ASSERT(desc);
|
||||||
|
// rest has aleady been validated by testCppExportInterface
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,41 @@
|
||||||
|
#ifndef INCLUDED_UT_EXPORT_H
|
||||||
|
#define INCLUDED_UT_EXPORT_H
|
||||||
|
|
||||||
|
#ifndef ASSIMP_BUILD_NO_EXPORT
|
||||||
|
|
||||||
|
#include <export.h>
|
||||||
|
#include <export.hpp>
|
||||||
|
|
||||||
|
using namespace Assimp;
|
||||||
|
|
||||||
|
class ExporterTest : public CPPUNIT_NS :: TestFixture
|
||||||
|
{
|
||||||
|
CPPUNIT_TEST_SUITE (ExporterTest);
|
||||||
|
CPPUNIT_TEST (testExportToFile);
|
||||||
|
CPPUNIT_TEST (testExportToBlob);
|
||||||
|
CPPUNIT_TEST (testCppExportInterface);
|
||||||
|
CPPUNIT_TEST (testCExportInterface);
|
||||||
|
CPPUNIT_TEST_SUITE_END ();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void setUp (void);
|
||||||
|
void tearDown (void);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void testExportToFile (void);
|
||||||
|
void testExportToBlob (void);
|
||||||
|
void testCppExportInterface (void);
|
||||||
|
void testCExportInterface (void);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
|
||||||
|
const aiScene* pTest;
|
||||||
|
Assimp::Exporter* ex;
|
||||||
|
Assimp::Importer* im;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue