Adding Importer::ReadFileFromMemory to make Chromanoid happy.

Updating unit test suite to verify the newly added stuff for correctness.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@444 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
pull/1/head
aramis_acg 2009-06-21 19:44:48 +00:00
parent a4d7871096
commit adb4ab602e
12 changed files with 456 additions and 66 deletions

View File

@ -264,7 +264,7 @@ const aiScene* aiImportFileEx( const char* pFile, unsigned int pFlags,
{ {
ai_assert(NULL != pFile); ai_assert(NULL != pFile);
// create an Importer for this file // create an Importer for this file
Assimp::Importer* imp = new Assimp::Importer; Assimp::Importer* imp = new Assimp::Importer();
#ifdef AI_C_THREADSAFE #ifdef AI_C_THREADSAFE
boost::mutex::scoped_lock lock(gMutex); boost::mutex::scoped_lock lock(gMutex);
@ -303,6 +303,49 @@ const aiScene* aiImportFileEx( const char* pFile, unsigned int pFlags,
return scene; return scene;
} }
// ------------------------------------------------------------------------------------------------
const aiScene* aiImportFileFromMemory(
const char* pBuffer,
unsigned int pLength,
unsigned int pFlags,
const char* pHint)
{
ai_assert(NULL != pBuffer && 0 != pLength);
// create an Importer for this file
Assimp::Importer* imp = new Assimp::Importer();
#ifdef AI_C_THREADSAFE
boost::mutex::scoped_lock lock(gMutex);
#endif
// copy the global property lists to the Importer instance
imp->pimpl->mIntProperties = gIntProperties;
imp->pimpl->mFloatProperties = gFloatProperties;
imp->pimpl->mStringProperties = gStringProperties;
#ifdef AI_C_THREADSAFE
lock.unlock();
#endif
// and have it read the file from the memory buffer
const aiScene* scene = imp->ReadFileFromMemory( pBuffer, pLength, pFlags,pHint);
// if succeeded, place it in the collection of active processes
if( scene) {
#ifdef AI_C_THREADSAFE
lock.lock();
#endif
gActiveImports[scene] = imp;
}
else {
// if failed, extract error code and destroy the import
gLastErrorString = imp->GetErrorString();
delete imp;
}
// return imported data. If the import failed the pointer is NULL anyways
return scene;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Releases all resources associated with the given import process. // Releases all resources associated with the given import process.
void aiReleaseImport( const aiScene* pScene) void aiReleaseImport( const aiScene* pScene)

View File

@ -53,11 +53,11 @@ using namespace Assimp;
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
DefaultIOStream::~DefaultIOStream() DefaultIOStream::~DefaultIOStream()
{ {
if (mFile) if (mFile) {
::fclose(mFile); ::fclose(mFile);
}
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
size_t DefaultIOStream::Read(void* pvBuffer, size_t DefaultIOStream::Read(void* pvBuffer,
size_t pSize, size_t pSize,
@ -67,7 +67,6 @@ size_t DefaultIOStream::Read(void* pvBuffer,
return (mFile ? ::fread(pvBuffer, pSize, pCount, mFile) : 0); return (mFile ? ::fread(pvBuffer, pSize, pCount, mFile) : 0);
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
size_t DefaultIOStream::Write(const void* pvBuffer, size_t DefaultIOStream::Write(const void* pvBuffer,
size_t pSize, size_t pSize,
@ -77,13 +76,13 @@ size_t DefaultIOStream::Write(const void* pvBuffer,
return (mFile ? ::fwrite(pvBuffer, pSize, pCount, mFile) : 0); return (mFile ? ::fwrite(pvBuffer, pSize, pCount, mFile) : 0);
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
aiReturn DefaultIOStream::Seek(size_t pOffset, aiReturn DefaultIOStream::Seek(size_t pOffset,
aiOrigin pOrigin) aiOrigin pOrigin)
{ {
if (!mFile) if (!mFile) {
return AI_FAILURE; return AI_FAILURE;
}
// Just to check whether our enum maps one to one with the CRT constants // Just to check whether our enum maps one to one with the CRT constants
BOOST_STATIC_ASSERT(aiOrigin_CUR == SEEK_CUR && BOOST_STATIC_ASSERT(aiOrigin_CUR == SEEK_CUR &&
@ -93,20 +92,21 @@ aiReturn DefaultIOStream::Seek(size_t pOffset,
return (0 == ::fseek(mFile, (long)pOffset,(int)pOrigin) ? AI_SUCCESS : AI_FAILURE); return (0 == ::fseek(mFile, (long)pOffset,(int)pOrigin) ? AI_SUCCESS : AI_FAILURE);
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
size_t DefaultIOStream::Tell() const size_t DefaultIOStream::Tell() const
{ {
if (!mFile)return 0; if (!mFile) {
return 0;
}
return ::ftell(mFile); return ::ftell(mFile);
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
size_t DefaultIOStream::FileSize() const size_t DefaultIOStream::FileSize() const
{ {
if (! mFile || mFilename.empty()) if (! mFile || mFilename.empty()) {
return 0; return 0;
}
if (0xffffffff == cachedSize) { if (0xffffffff == cachedSize) {
@ -131,8 +131,9 @@ size_t DefaultIOStream::FileSize() const
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
void DefaultIOStream::Flush() void DefaultIOStream::Flush()
{ {
if (mFile) if (mFile) {
::fflush(mFile); ::fflush(mFile);
}
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------

View File

@ -65,6 +65,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "GenericProperty.h" #include "GenericProperty.h"
#include "ProcessHelper.h" #include "ProcessHelper.h"
#include "ScenePreprocessor.h" #include "ScenePreprocessor.h"
#include "MemoryIOWrapper.h"
// ....................................................................................... // .......................................................................................
// Importers // Importers
@ -698,6 +699,37 @@ bool Importer::ValidateFlags(unsigned int pFlags)
return true; return true;
} }
// ------------------------------------------------------------------------------------------------
const aiScene* Importer::ReadFileFromMemory( const void* pBuffer,
size_t pLength,
unsigned int pFlags,
const char* pHint /*= ""*/)
{
if (!pHint) {
pHint = "";
}
if (!pBuffer || !pLength || strlen(pHint) > 100) {
pimpl->mErrorString = "Invalid parameters passed to ReadFileFromMemory()";
return NULL;
}
// prevent deletion of the previous IOHandler
IOSystem* io = pimpl->mIOHandler;
pimpl->mIOHandler = NULL;
SetIOHandler(new MemoryIOSystem((const uint8_t*)pBuffer,pLength));
// read the file and recover the previous IOSystem
char fbuff[128];
sprintf(fbuff,"%s.%s",AI_MEMORYIO_MAGIC_FILENAME,pHint);
ReadFile(fbuff,pFlags);
SetIOHandler(io);
return pimpl->mScene;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads the given file and returns its contents if successful. // 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)
@ -755,8 +787,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
} }
} }
// Put a proper error message if no suitable importer was found // Put a proper error message if no suitable importer was found
if( !imp) if( !imp) {
{
pimpl->mErrorString = "No suitable reader found for the file format of file \"" + pFile + "\"."; pimpl->mErrorString = "No suitable reader found for the file format of file \"" + pFile + "\".";
DefaultLogger::get()->error(pimpl->mErrorString); DefaultLogger::get()->error(pimpl->mErrorString);
return NULL; return NULL;

View File

@ -0,0 +1,179 @@
/*
Open Asset Import Library (ASSIMP)
----------------------------------------------------------------------
Copyright (c) 2006-2008, 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 MemoryIOWrapper.h
* Handy IOStream/IOSystem implemetation to read directly from a memory buffer */
#ifndef AI_MEMORYIOSTREAM_H_INC
#define AI_MEMORYIOSTREAM_H_INC
namespace Assimp {
#define AI_MEMORYIO_MAGIC_FILENAME "$$$___magic___$$$"
#define AI_MEMORYIO_MAGIC_FILENAME_LENGTH 17
// ----------------------------------------------------------------------------------
/** Implementation of IOStream to read directly from a memory buffer */
class MemoryIOStream : public IOStream {
friend class MemoryIOSystem;
protected:
MemoryIOStream (const uint8_t* buff, size_t len)
: buffer (buff), length(len), pos((size_t)0) {
}
public:
~MemoryIOStream () {
}
// -------------------------------------------------------------------
// Read from stream
size_t Read(void* pvBuffer, size_t pSize, size_t pCount) {
const size_t cnt = std::min(pCount,(length-pos)/pSize),ofs = pSize*cnt;
memcpy(pvBuffer,buffer+pos,ofs);
pos += ofs;
return cnt;
}
// -------------------------------------------------------------------
// Write to stream
size_t Write(const void* pvBuffer, size_t pSize,size_t pCount) {
ai_assert(false); // won't be needed
return 0;
}
// -------------------------------------------------------------------
// Seek specific position
aiReturn Seek(size_t pOffset, aiOrigin pOrigin) {
if (aiOrigin_SET == pOrigin) {
if (pOffset >= length) {
return AI_FAILURE;
}
pos = pOffset;
}
else if (aiOrigin_END == pOrigin) {
if (pOffset >= length) {
return AI_FAILURE;
}
pos = length-pOffset;
}
else {
if (pOffset+pos >= length) {
return AI_FAILURE;
}
pos += pOffset;
}
return AI_SUCCESS;
}
// -------------------------------------------------------------------
// Get current seek position
size_t Tell() const {
return pos;
}
// -------------------------------------------------------------------
// Get size of file
size_t FileSize() const {
return length;
}
// -------------------------------------------------------------------
// Flush file contents
void Flush() {
ai_assert(false); // won't be needed
}
private:
const uint8_t* buffer;
size_t length,pos;
};
// ---------------------------------------------------------------------------
/** Dummy IO system to read from a memory buffer */
class MemoryIOSystem : public IOSystem
{
public:
/** Constructor. */
MemoryIOSystem (const uint8_t* buff, size_t len)
: buffer (buff), length(len) {
}
/** Destructor. */
~MemoryIOSystem() {
}
// -------------------------------------------------------------------
/** Tests for the existence of a file at the given path. */
bool Exists( const char* pFile) const {
return !strncmp(pFile,AI_MEMORYIO_MAGIC_FILENAME,AI_MEMORYIO_MAGIC_FILENAME_LENGTH);
}
// -------------------------------------------------------------------
/** Returns the directory separator. */
char getOsSeparator() const {
return '/'; // why not? it doesn't care
}
// -------------------------------------------------------------------
/** Open a new file with a given path. */
IOStream* Open( const char* pFile, const char* pMode = "rb") {
if (strncmp(pFile,AI_MEMORYIO_MAGIC_FILENAME,AI_MEMORYIO_MAGIC_FILENAME_LENGTH)) {
return NULL;
}
return new MemoryIOStream(buffer,length);
}
// -------------------------------------------------------------------
/** Closes the given file and releases all resources associated with it. */
void Close( IOStream* pFile) {
}
// -------------------------------------------------------------------
/** Compare two paths */
bool ComparePaths (const char* one, const char* second) const {
return false;
}
private:
const uint8_t* buffer;
size_t length;
};
} // end namespace Assimp
#endif

View File

@ -57,10 +57,9 @@ VertexTriangleAdjacency::VertexTriangleAdjacency(aiFace *pcFaces,
{ {
// compute the number of referenced vertices if it wasn't specified by the caller // compute the number of referenced vertices if it wasn't specified by the caller
const aiFace* const pcFaceEnd = pcFaces + iNumFaces; const aiFace* const pcFaceEnd = pcFaces + iNumFaces;
if (!iNumVertices) if (!iNumVertices) {
{
for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace) for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace) {
{
ai_assert(3 == pcFace->mNumIndices); ai_assert(3 == pcFace->mNumIndices);
iNumVertices = std::max(iNumVertices,pcFace->mIndices[0]); iNumVertices = std::max(iNumVertices,pcFace->mIndices[0]);
iNumVertices = std::max(iNumVertices,pcFace->mIndices[1]); iNumVertices = std::max(iNumVertices,pcFace->mIndices[1]);
@ -70,17 +69,15 @@ VertexTriangleAdjacency::VertexTriangleAdjacency(aiFace *pcFaces,
unsigned int* pi; unsigned int* pi;
// allocate storage // allocate storage
if (bComputeNumTriangles) if (bComputeNumTriangles) {
{ pi = mLiveTriangles = new unsigned int[iNumVertices+1];
pi = this->mLiveTriangles = new unsigned int[iNumVertices+1]; memset(mLiveTriangles,0,sizeof(unsigned int)*(iNumVertices+1));
::memset(this->mLiveTriangles,0,sizeof(unsigned int)*(iNumVertices+1)); mOffsetTable = new unsigned int[iNumVertices+2]+1;
this->mOffsetTable = new unsigned int[iNumVertices+2]+1;
} }
else else {
{ pi = mOffsetTable = new unsigned int[iNumVertices+2]+1;
pi = this->mOffsetTable = new unsigned int[iNumVertices+2]+1; memset(mOffsetTable,0,sizeof(unsigned int)*(iNumVertices+1));
::memset(this->mOffsetTable,0,sizeof(unsigned int)*(iNumVertices+1)); mLiveTriangles = NULL; // important, otherwise the d'tor would crash
this->mLiveTriangles = NULL; // important, otherwise the d'tor would crash
} }
// get a pointer to the end of the buffer // get a pointer to the end of the buffer
@ -98,8 +95,8 @@ VertexTriangleAdjacency::VertexTriangleAdjacency(aiFace *pcFaces,
// second pass: compute the final offset table // second pass: compute the final offset table
unsigned int iSum = 0; unsigned int iSum = 0;
unsigned int* piCurOut = this->mOffsetTable; unsigned int* piCurOut = this->mOffsetTable;
for (unsigned int* piCur = pi; piCur != piEnd;++piCur,++piCurOut) for (unsigned int* piCur = pi; piCur != piEnd;++piCur,++piCurOut) {
{
unsigned int iLastSum = iSum; unsigned int iLastSum = iSum;
iSum += *piCur; iSum += *piCur;
*piCurOut = iLastSum; *piCurOut = iLastSum;
@ -109,27 +106,27 @@ VertexTriangleAdjacency::VertexTriangleAdjacency(aiFace *pcFaces,
// third pass: compute the final table // third pass: compute the final table
this->mAdjacencyTable = new unsigned int[iSum]; this->mAdjacencyTable = new unsigned int[iSum];
iSum = 0; iSum = 0;
for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace,++iSum) for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace,++iSum) {
{
unsigned int idx = pcFace->mIndices[0]; unsigned int idx = pcFace->mIndices[0];
this->mAdjacencyTable[pi[idx]++] = iSum; mAdjacencyTable[pi[idx]++] = iSum;
idx = pcFace->mIndices[1]; idx = pcFace->mIndices[1];
this->mAdjacencyTable[pi[idx]++] = iSum; mAdjacencyTable[pi[idx]++] = iSum;
idx = pcFace->mIndices[2]; idx = pcFace->mIndices[2];
this->mAdjacencyTable[pi[idx]++] = iSum; mAdjacencyTable[pi[idx]++] = iSum;
} }
// fourth pass: undo the offset computations made during the third pass // fourth pass: undo the offset computations made during the third pass
// We could do this in a separate buffer, but this would be TIMES slower. // We could do this in a separate buffer, but this would be TIMES slower.
--this->mOffsetTable; --mOffsetTable;
*this->mOffsetTable = 0u; *mOffsetTable = 0u;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
VertexTriangleAdjacency::~VertexTriangleAdjacency() VertexTriangleAdjacency::~VertexTriangleAdjacency()
{ {
// delete all allocated storage // delete allocated storage
delete[] this->mOffsetTable; delete[] mOffsetTable;
delete[] this->mAdjacencyTable; delete[] mAdjacencyTable;
delete[] this->mLiveTriangles; delete[] mLiveTriangles;
} }

View File

@ -77,10 +77,9 @@ public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** @brief Read from the file /** @brief Read from the file
* *
* See fread() for more details * See fread() for more details
* This fails for write-only files * This fails for write-only files */
*/
virtual size_t Read(void* pvBuffer, virtual size_t Read(void* pvBuffer,
size_t pSize, size_t pSize,
size_t pCount) = 0; size_t pCount) = 0;
@ -89,39 +88,34 @@ public:
/** @brief Write to the file /** @brief Write to the file
* *
* See fwrite() for more details * See fwrite() for more details
* This fails for read-only files * This fails for read-only files */
*/
virtual size_t Write(const void* pvBuffer, virtual size_t Write(const void* pvBuffer,
size_t pSize, size_t pSize,
size_t pCount) = 0; size_t pCount) = 0;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** @brief Set the read/write cursor of the file /** @brief Set the read/write cursor of the file
* *
* See fseek() for more details * Note that the offset is _negative_ for aiOrigin_END.
*/ * See fseek() for more details */
virtual aiReturn Seek(size_t pOffset, virtual aiReturn Seek(size_t pOffset,
aiOrigin pOrigin) = 0; aiOrigin pOrigin) = 0;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** @brief Get the current position of the read/write cursor /** @brief Get the current position of the read/write cursor
* *
* See ftell() for more details * See ftell() for more details */
*/
virtual size_t Tell() const = 0; virtual size_t Tell() const = 0;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** @brief Returns filesize /** @brief Returns filesize
* * Returns the filesize. */
* Returns the filesize.
*/
virtual size_t FileSize() const = 0; virtual size_t FileSize() const = 0;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** @brief Flush the contents of the file buffer (for writers) /** @brief Flush the contents of the file buffer (for writers)
* * See fflush() for more details.
* See fflush() for more details. */
*/
virtual void Flush() = 0; virtual void Flush() = 0;
}; //! class IOStream }; //! class IOStream

View File

@ -115,13 +115,48 @@ ASSIMP_API const C_STRUCT aiScene* aiImportFile(
* @param pFS aiFileIO structure. Will be used to open the model file itself * @param pFS aiFileIO structure. Will be used to open the model file itself
* and any other files the loader needs to open. * and any other files the loader needs to open.
* @return Pointer to the imported data or NULL if the import failed. * @return Pointer to the imported data or NULL if the import failed.
* @note Include <aiFileIO.h> for the definition of #aiFioeIO. * @note Include <aiFileIO.h> for the definition of #aiFileIO.
*/ */
ASSIMP_API const C_STRUCT aiScene* aiImportFileEx( ASSIMP_API const C_STRUCT aiScene* aiImportFileEx(
const char* pFile, const char* pFile,
unsigned int pFlags, unsigned int pFlags,
C_STRUCT aiFileIO* pFS); C_STRUCT aiFileIO* pFS);
// --------------------------------------------------------------------------------
/** Reads the given file from a given memory buffer,
*
* If the call succeeds, the contents of the file are returned as a pointer to an
* aiScene object. The returned data is intended to be read-only, the importer keeps
* ownership of the data and will destroy it upon destruction. If the import fails,
* NULL is returned.
* A human-readable error description can be retrieved by calling aiGetErrorString().
* @param pBuffer Pointer to the file data
* @param pLength Length of pBuffer, in bytes
* @param pFlags Optional post processing steps to be executed after
* a successful import. Provide a bitwise combination of the
* #aiPostProcessSteps flags. If you wish to inspect the imported
* scene first in order to fine-tune your post-processing setup,
* consider to use #aiApplyPostProcessing().
* @param pHint An additional hint to the library. If this is a non empty string,
* the library looks for a loader to support the file extension specified by pHint
* and passes the file to the first matching loader. If this loader is unable to
* completely the request, the library continues and tries to determine the file
* format on its own, a task that may or may not be successful.
* Check the return value, and you'll know ...
* @return A pointer to the imported data, NULL if the import failed.
*
* @note This is a straightforward way to decode models from memory buffers, but it
* doesn't handle model formats spreading their data across multiple files or even
* directories. Examples include OBJ or MD3, which outsource parts of their material
* stuff into external scripts. f you need the full functionality, provide a custom
* IOSystem to make Assimp find these files.
*/
ASSIMP_API const C_STRUCT aiScene* aiImportFileFromMemory(
const char* pBuffer,
unsigned int pLength,
unsigned int pFlags,
const char* pHint);
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
/** Apply post-processing to an already-imported scene. /** Apply post-processing to an already-imported scene.
* *

View File

@ -82,6 +82,8 @@ namespace Assimp {
struct aiScene; struct aiScene;
struct aiFileIO; struct aiFileIO;
extern "C" ASSIMP_API const aiScene* aiImportFileEx( const char*, unsigned int, aiFileIO*); extern "C" ASSIMP_API const aiScene* aiImportFileEx( const char*, unsigned int, aiFileIO*);
extern "C" ASSIMP_API const aiScene* aiImportFileFromMemory( const char*,
unsigned int,unsigned int,const char*);
namespace Assimp { namespace Assimp {
@ -109,12 +111,14 @@ namespace Assimp {
* @note One Importer instance is not thread-safe. If you use multiple * @note One Importer instance is not thread-safe. If you use multiple
* threads for loading, each thread should maintain its own Importer instance. * threads for loading, each thread should maintain its own Importer instance.
*/ */
class ASSIMP_API Importer class ASSIMP_API Importer {
{
// used internally // for internal use
friend class BaseProcess; friend class BaseProcess;
friend class BatchLoader; friend class BatchLoader;
friend const aiScene* ::aiImportFileEx( const char*, unsigned int, aiFileIO*); friend const aiScene* ::aiImportFileEx( const char*, unsigned int, aiFileIO*);
friend const aiScene* ::aiImportFileFromMemory( const char*,
unsigned int,unsigned int,const char*);
public: public:
@ -321,11 +325,52 @@ public:
* instance. Use GetOrphanedScene() to take ownership of it. * instance. Use GetOrphanedScene() to take ownership of it.
* *
* @note Assimp is able to determine the file format of a file * @note Assimp is able to determine the file format of a file
* automatically. However, you should make sure that the input file * automatically. However, to enable automatic detection of the file
* does not even have a file extension at all to enable this feature. * format, the input path *must* not have an extension at all.
*/ */
const aiScene* ReadFile( const char* pFile, unsigned int pFlags); const aiScene* ReadFile( const char* pFile, unsigned int pFlags);
// -------------------------------------------------------------------
/** Reads the given file from a memory buffer and returns its
* contents if successful.
*
* If the call succeeds, the contents of the file are returned as a
* pointer to an aiScene object. The returned data is intended to be
* read-only, the importer object keeps ownership of the data and will
* destroy it upon destruction. If the import fails, NULL is returned.
* A human-readable error description can be retrieved by calling
* GetErrorString(). The previous scene will be deleted during this call.
* Calling this method doesn't affect the active IOSystem.
* @param pBuffer Pointer to the file data
* @param pLength Length of pBuffer, in bytes
* @param pFlags Optional post processing steps to be executed after
* a successful import. Provide a bitwise combination of the
* #aiPostProcessSteps flags. If you wish to inspect the imported
* scene first in order to fine-tune your post-processing setup,
* consider to use #ApplyPostProcessing().
* @param pHint An additional hint to the library. If this is a non
* empty string, the library looks for a loader to support
* the file extension specified by pHint and passes the file to
* the first matching loader. If this loader is unable to completely
* the request, the library continues and tries to determine the
* file format on its own, a task that may or may not be successful.
* Check the return value, and you'll know ...
* @return A pointer to the imported data, NULL if the import failed.
* The pointer to the scene remains in possession of the Importer
* instance. Use GetOrphanedScene() to take ownership of it.
*
* @note This is a straightforward way to decode models from memory
* buffers, but it doesn't handle model formats spreading their
* data across multiple files or even directories. Examples include
* OBJ or MD3, which outsource parts of their material stuff into
* external scripts. f you need the full functionality, provide
* a custom IOSystem to make Assimp find these files.
*/
const aiScene* ReadFileFromMemory( const void* pBuffer,
size_t pLength,
unsigned int pFlags,
const char* pHint = "");
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Apply post-processing to an already-imported scene. /** Apply post-processing to an already-imported scene.
* *

View File

@ -5,7 +5,7 @@
// settings and displays it. // settings and displays it.
// //
// If you intend to _use_ this code sample in your app, do yourself a favour // If you intend to _use_ this code sample in your app, do yourself a favour
// and replace glVertex3D with VBOs ... // and replace immediate mode calls with VBOs ...
// //
// The vc8 solution links against assimp-release-dll_win32 - be sure to // The vc8 solution links against assimp-release-dll_win32 - be sure to
// have this configuration built. // have this configuration built.

View File

@ -3,6 +3,55 @@
#include "utImporter.h" #include "utImporter.h"
#define InputData_BLOCK_SIZE 1310
// test data for Importer::ReadFileFromMemory() - ./test/3DS/CameraRollAnim.3ds
static unsigned char InputData_abRawBlock[1310] = {
77,77,30,5,0,0,2,0,10,0,0,0,3,0,0,0,61,61,91,3,0,0,62,61,10,0,0,0,3,0,0,0,
0,1,10,0,0,0,0,0,128,63,0,64,254,2,0,0,66,111,120,48,49,0,0,65,242,2,0,0,16,65,64,1,
0,0,26,0,102,74,198,193,102,74,198,193,0,0,0,0,205,121,55,66,102,74,198,193,0,0,0,0,102,74,198,193,
138,157,184,65,0,0,0,0,205,121,55,66,138,157,184,65,0,0,0,0,102,74,198,193,102,74,198,193,90,252,26,66,
205,121,55,66,102,74,198,193,90,252,26,66,102,74,198,193,138,157,184,65,90,252,26,66,205,121,55,66,138,157,184,65,
90,252,26,66,102,74,198,193,102,74,198,193,0,0,0,0,205,121,55,66,102,74,198,193,0,0,0,0,205,121,55,66,
102,74,198,193,90,252,26,66,205,121,55,66,102,74,198,193,90,252,26,66,102,74,198,193,102,74,198,193,90,252,26,66,
102,74,198,193,102,74,198,193,0,0,0,0,205,121,55,66,138,157,184,65,0,0,0,0,205,121,55,66,102,74,198,193,
90,252,26,66,205,121,55,66,138,157,184,65,0,0,0,0,102,74,198,193,138,157,184,65,0,0,0,0,102,74,198,193,
138,157,184,65,90,252,26,66,102,74,198,193,138,157,184,65,90,252,26,66,205,121,55,66,138,157,184,65,90,252,26,66,
205,121,55,66,138,157,184,65,0,0,0,0,102,74,198,193,138,157,184,65,0,0,0,0,102,74,198,193,102,74,198,193,
90,252,26,66,102,74,198,193,102,74,198,193,90,252,26,66,102,74,198,193,138,157,184,65,0,0,0,0,64,65,216,0,
0,0,26,0,0,0,128,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,63,0,0,128,63,0,0,0,0,
0,0,128,63,0,0,0,0,0,0,0,0,0,0,128,63,0,0,0,0,0,0,0,0,0,0,128,63,0,0,128,63,
0,0,128,63,0,0,0,0,0,0,0,0,0,0,128,63,0,0,0,0,0,0,128,63,0,0,128,63,0,0,128,63,
0,0,128,63,0,0,0,0,0,0,128,63,0,0,0,0,0,0,0,0,0,0,128,63,0,0,0,0,0,0,0,0,
0,0,128,63,0,0,0,0,0,0,0,0,0,0,128,63,0,0,0,0,0,0,128,63,0,0,128,63,0,0,128,63,
0,0,128,63,0,0,0,0,0,0,128,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,63,
0,0,128,63,0,0,128,63,0,0,128,63,0,0,0,0,0,0,0,0,96,65,54,0,0,0,0,0,128,63,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,128,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,63,53,169,
40,65,176,205,90,191,0,0,0,0,32,65,158,0,0,0,12,0,0,0,2,0,3,0,6,0,3,0,1,0,0,0,
6,0,4,0,5,0,7,0,6,0,7,0,6,0,4,0,6,0,8,0,9,0,10,0,6,0,11,0,12,0,13,0,
6,0,1,0,14,0,7,0,6,0,7,0,15,0,1,0,6,0,16,0,17,0,18,0,6,0,19,0,20,0,21,0,
6,0,22,0,0,0,23,0,6,0,24,0,6,0,25,0,6,0,80,65,54,0,0,0,2,0,0,0,2,0,0,0,
4,0,0,0,4,0,0,0,8,0,0,0,8,0,0,0,16,0,0,0,16,0,0,0,32,0,0,0,32,0,0,0,
64,0,0,0,64,0,0,0,0,64,67,0,0,0,67,97,109,101,114,97,48,49,0,0,71,52,0,0,0,189,19,25,
195,136,104,81,64,147,56,182,65,96,233,20,194,67,196,97,190,147,56,182,65,0,0,0,0,85,85,85,66,32,71,14,
0,0,0,0,0,0,0,0,0,122,68,0,176,179,1,0,0,10,176,21,0,0,0,5,0,77,65,88,83,67,69,78,
69,0,44,1,0,0,8,176,14,0,0,0,0,0,0,0,44,1,0,0,9,176,10,0,0,0,128,2,0,0,2,176,
168,0,0,0,48,176,8,0,0,0,0,0,16,176,18,0,0,0,66,111,120,48,49,0,0,64,0,0,255,255,19,176,
18,0,0,0,0,0,0,128,0,0,0,128,0,0,0,128,32,176,38,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,0,0,0,0,0,0,0,0,0,53,169,40,65,176,205,90,191,0,0,0,0,33,176,42,0,0,0,0,0,0,0,
0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
34,176,38,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,128,63,0,0,
128,63,0,0,128,63,3,176,143,0,0,0,48,176,8,0,0,0,1,0,16,176,21,0,0,0,67,97,109,101,114,97,
48,49,0,0,64,0,0,255,255,32,176,38,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,0,0,189,19,25,195,136,104,81,64,147,56,182,65,35,176,30,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
0,0,0,0,0,0,0,0,0,0,0,52,66,36,176,40,0,0,0,0,0,0,0,0,0,120,0,0,0,2,0,0,
0,0,0,0,0,0,0,120,13,90,189,120,0,0,0,0,0,99,156,154,194,4,176,73,0,0,0,48,176,8,0,0,
0,2,0,16,176,21,0,0,0,67,97,109,101,114,97,48,49,0,0,64,0,0,255,255,32,176,38,0,0,0,0,0,
0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,96,233,20,194,67,196,97,190,147,56,182,65,
};
CPPUNIT_TEST_SUITE_REGISTRATION (ImporterTest); CPPUNIT_TEST_SUITE_REGISTRATION (ImporterTest);
#define AIUT_DEF_ERROR_TEXT "sorry, this is a test" #define AIUT_DEF_ERROR_TEXT "sorry, this is a test"
@ -44,6 +93,16 @@ void ImporterTest :: tearDown (void)
delete pImp; delete pImp;
} }
void ImporterTest :: testMemoryRead (void)
{
const aiScene* sc = pImp->ReadFileFromMemory(InputData_abRawBlock,InputData_BLOCK_SIZE,
aiProcessPreset_TargetRealtime_Quality,"3ds");
CPPUNIT_ASSERT(sc != NULL);
CPPUNIT_ASSERT(sc->mRootNode->mName == aiString("<3DSRoot>"));
CPPUNIT_ASSERT(sc->mNumMeshes == 1 && sc->mMeshes[0]->mNumVertices ==24 && sc->mMeshes[0]->mNumFaces ==12);
}
void ImporterTest :: testIntProperty (void) void ImporterTest :: testIntProperty (void)
{ {
bool b; bool b;

View File

@ -18,6 +18,7 @@ class ImporterTest : public CPPUNIT_NS :: TestFixture
CPPUNIT_TEST (testStringProperty); CPPUNIT_TEST (testStringProperty);
CPPUNIT_TEST (testPluginInterface); CPPUNIT_TEST (testPluginInterface);
CPPUNIT_TEST (testExtensionCheck); CPPUNIT_TEST (testExtensionCheck);
CPPUNIT_TEST (testMemoryRead);
CPPUNIT_TEST_SUITE_END (); CPPUNIT_TEST_SUITE_END ();
public: public:
@ -32,6 +33,7 @@ class ImporterTest : public CPPUNIT_NS :: TestFixture
void testPluginInterface (void); void testPluginInterface (void);
void testExtensionCheck (void); void testExtensionCheck (void);
void testMemoryRead (void);
private: private:

View File

@ -2307,6 +2307,10 @@
RelativePath="..\..\code\DefaultIOSystem.h" RelativePath="..\..\code\DefaultIOSystem.h"
> >
</File> </File>
<File
RelativePath="..\..\code\MemoryIOWrapper.h"
>
</File>
<File <File
RelativePath="..\..\code\StreamReader.h" RelativePath="..\..\code\StreamReader.h"
> >