Definitios for MDC and MDR added; MD2 loader is ready for BigEndian now, MD3 too. MD2 and MD3 keyframe option added, not yet implemented for MD3.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@101 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
pull/1/head
aramis_acg 2008-08-08 23:58:40 +00:00
parent 6fe8c867e8
commit c88ae2a0be
7 changed files with 645 additions and 84 deletions

View File

@ -110,6 +110,10 @@ using namespace Assimp::ASE;
} else bLastWasEndLine = false; \ } else bLastWasEndLine = false; \
++this->m_szFile; ++this->m_szFile;
#ifdef _MSC_VER
# define sprintf sprintf_s
#endif
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Parser::Parser (const char* szFile) Parser::Parser (const char* szFile)
{ {
@ -724,32 +728,20 @@ bool Parser::ParseString(std::string& out,const char* szName)
{ {
char szBuffer[1024]; char szBuffer[1024];
#if (!defined _MSC_VER) || ( _MSC_VER < 1400)
ai_assert(strlen(szName) < 750);
#endif
// NOTE: The name could also be the texture in some cases // NOTE: The name could also be the texture in some cases
// be prepared that this might occur ... // be prepared that this might occur ...
if (!SkipSpaces(this->m_szFile,&this->m_szFile)) if (!SkipSpaces(this->m_szFile,&this->m_szFile))
{ {
#if _MSC_VER >= 1400
sprintf_s(szBuffer,"Unable to parse %s block: Unexpected EOL",szName);
#else
sprintf(szBuffer,"Unable to parse %s block: Unexpected EOL",szName); sprintf(szBuffer,"Unable to parse %s block: Unexpected EOL",szName);
#endif
this->LogWarning(szBuffer); this->LogWarning(szBuffer);
return false; return false;
} }
// there must be " // there must be "
if ('\"' != *this->m_szFile) if ('\"' != *this->m_szFile)
{ {
#if _MSC_VER >= 1400
sprintf_s(szBuffer,"Unable to parse %s block: String is expected "
"to be enclosed in double quotation marks",szName);
#else
sprintf(szBuffer,"Unable to parse %s block: String is expected " sprintf(szBuffer,"Unable to parse %s block: String is expected "
"to be enclosed in double quotation marks",szName); "to be enclosed in double quotation marks",szName);
#endif
this->LogWarning(szBuffer); this->LogWarning(szBuffer);
return false; return false;
} }
@ -759,16 +751,10 @@ bool Parser::ParseString(std::string& out,const char* szName)
{ {
if ('\"' == *sz)break; if ('\"' == *sz)break;
else if ('\0' == sz) else if ('\0' == sz)
{ {
#if _MSC_VER >= 1400
sprintf_s(szBuffer,"Unable to parse %s block: String is expected to be "
"enclosed in double quotation marks but EOF was reached before a closing "
"quotation mark was found",szName);
#else
sprintf(szBuffer,"Unable to parse %s block: String is expected to be " sprintf(szBuffer,"Unable to parse %s block: String is expected to be "
"enclosed in double quotation marks but EOF was reached before a closing " "enclosed in double quotation marks but EOF was reached before a closing "
"quotation mark was found",szName); "quotation mark was found",szName);
#endif
this->LogWarning(szBuffer); this->LogWarning(szBuffer);
return false; return false;
} }

View File

@ -42,6 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Implementation of the MD2 importer class */ /** @file Implementation of the MD2 importer class */
#include "MD2Loader.h" #include "MD2Loader.h"
#include "MaterialSystem.h" #include "MaterialSystem.h"
#include "ByteSwap.h"
#include "MD2NormalTable.h" // shouldn't be included by other units #include "MD2NormalTable.h" // shouldn't be included by other units
#include "../include/IOStream.h" #include "../include/IOStream.h"
@ -50,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../include/aiScene.h" #include "../include/aiScene.h"
#include "../include/aiAssert.h" #include "../include/aiAssert.h"
#include "../include/DefaultLogger.h" #include "../include/DefaultLogger.h"
#include "../include/assimp.hpp"
#include <boost/scoped_ptr.hpp> #include <boost/scoped_ptr.hpp>
@ -110,6 +112,18 @@ bool MD2Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
return true; return true;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Setup configuration properties
void MD2Importer::SetupProperties(const Importer* pImp)
{
// The AI_CONFIG_IMPORT_MD2_KEYFRAME option overrides the
// AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
if(0xffffffff == (this->configFrameID = pImp->GetProperty(
AI_CONFIG_IMPORT_MD2_KEYFRAME,0xffffffff)))
{
this->configFrameID = pImp->GetProperty(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
}
}
// ------------------------------------------------------------------------------------------------
// Validate the file header // Validate the file header
void MD2Importer::ValidateHeader( ) void MD2Importer::ValidateHeader( )
{ {
@ -117,9 +131,6 @@ void MD2Importer::ValidateHeader( )
if (this->m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_BE && if (this->m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_BE &&
this->m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_LE) this->m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_LE)
{ {
delete[] this->mBuffer;
AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
char szBuffer[5]; char szBuffer[5];
szBuffer[0] = ((char*)&this->m_pcHeader->magic)[0]; szBuffer[0] = ((char*)&this->m_pcHeader->magic)[0];
szBuffer[1] = ((char*)&this->m_pcHeader->magic)[1]; szBuffer[1] = ((char*)&this->m_pcHeader->magic)[1];
@ -133,27 +144,22 @@ void MD2Importer::ValidateHeader( )
// check file format version // check file format version
if (this->m_pcHeader->version != 8) if (this->m_pcHeader->version != 8)
{
DefaultLogger::get()->warn( "Unsupported md2 file version. Continuing happily ..."); DefaultLogger::get()->warn( "Unsupported md2 file version. Continuing happily ...");
}
/* to be validated: // check some values whether they are valid
int32_t offsetSkins; if (0 == this->m_pcHeader->numFrames)
int32_t offsetTexCoords; throw new ImportErrorException( "Invalid md2 file: NUM_FRAMES is 0");
int32_t offsetTriangles;
int32_t offsetFrames;
//int32_t offsetGlCommands;
int32_t offsetEnd;
*/
if (this->m_pcHeader->offsetSkins + this->m_pcHeader->numSkins * sizeof (MD2::Skin) >= this->fileSize || if (this->m_pcHeader->offsetEnd > (int32_t)fileSize)
this->m_pcHeader->offsetTexCoords + this->m_pcHeader->numTexCoords * sizeof (MD2::TexCoord) >= this->fileSize || throw new ImportErrorException( "Invalid md2 file: File is too small");
this->m_pcHeader->offsetTriangles + this->m_pcHeader->numTriangles * sizeof (MD2::Triangle) >= this->fileSize ||
this->m_pcHeader->offsetFrames + this->m_pcHeader->numFrames * sizeof (MD2::Frame) >= this->fileSize || if (this->m_pcHeader->offsetSkins + this->m_pcHeader->numSkins * sizeof (MD2::Skin) >= this->fileSize ||
this->m_pcHeader->offsetTexCoords + this->m_pcHeader->numTexCoords * sizeof (MD2::TexCoord) >= this->fileSize ||
this->m_pcHeader->offsetTriangles + this->m_pcHeader->numTriangles * sizeof (MD2::Triangle) >= this->fileSize ||
this->m_pcHeader->offsetFrames + this->m_pcHeader->numFrames * sizeof (MD2::Frame) >= this->fileSize ||
this->m_pcHeader->offsetEnd > this->fileSize) this->m_pcHeader->offsetEnd > this->fileSize)
{ {
throw new ImportErrorException("Invalid MD2 header: some offsets are outside the file"); throw new ImportErrorException("Invalid MD2 header: some offsets are outside the file");
AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
} }
if (this->m_pcHeader->numSkins > AI_MD2_MAX_SKINS) if (this->m_pcHeader->numSkins > AI_MD2_MAX_SKINS)
@ -162,27 +168,27 @@ void MD2Importer::ValidateHeader( )
DefaultLogger::get()->warn("The model contains more frames than Quake 2 supports"); DefaultLogger::get()->warn("The model contains more frames than Quake 2 supports");
if (this->m_pcHeader->numVertices > AI_MD2_MAX_VERTS) if (this->m_pcHeader->numVertices > AI_MD2_MAX_VERTS)
DefaultLogger::get()->warn("The model contains more vertices than Quake 2 supports"); DefaultLogger::get()->warn("The model contains more vertices than Quake 2 supports");
if (this->m_pcHeader->numFrames >= this->configFrameID )
throw new ImportErrorException("The requested frame is not existing the file");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void MD2Importer::InternReadFile( void MD2Importer::InternReadFile( const std::string& pFile,
const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) aiScene* pScene, IOSystem* pIOHandler)
{ {
boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile)); boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
// Check whether we can read from the file // Check whether we can read from the file
if( file.get() == NULL) if( file.get() == NULL)
{ throw new ImportErrorException( "Failed to open MD2 file " + pFile + "");
throw new ImportErrorException( "Failed to open md2 file " + pFile + ".");
}
// check whether the md3 file is large enough to contain // check whether the md3 file is large enough to contain
// at least the file header // at least the file header
fileSize = (unsigned int)file->FileSize(); fileSize = (unsigned int)file->FileSize();
if( fileSize < sizeof(MD2::Header)) if( fileSize < sizeof(MD2::Header))
{ throw new ImportErrorException( "MD2 File is too small");
throw new ImportErrorException( "md2 File is too small.");
}
try try
{ {
@ -191,17 +197,30 @@ void MD2Importer::InternReadFile(
file->Read( (void*)mBuffer, 1, fileSize); file->Read( (void*)mBuffer, 1, fileSize);
this->m_pcHeader = (const MD2::Header*)this->mBuffer; this->m_pcHeader = (const MD2::Header*)this->mBuffer;
this->ValidateHeader();
// check some values whether they are valid #ifdef AI_BUILD_BIG_ENDIAN
if (0 == this->m_pcHeader->numFrames)
{ ByteSwap::Swap4(&m_pcHeader->frameSize);
throw new ImportErrorException( "Invalid md2 file: NUM_FRAMES is 0"); ByteSwap::Swap4(&m_pcHeader->magic);
} ByteSwap::Swap4(&m_pcHeader->numFrames);
if (this->m_pcHeader->offsetEnd > (int32_t)fileSize) ByteSwap::Swap4(&m_pcHeader->numGlCommands);
{ ByteSwap::Swap4(&m_pcHeader->numSkins);
throw new ImportErrorException( "Invalid md2 file: File is too small"); ByteSwap::Swap4(&m_pcHeader->numTexCoords);
} ByteSwap::Swap4(&m_pcHeader->numTriangles);
ByteSwap::Swap4(&m_pcHeader->numVertices);
ByteSwap::Swap4(&m_pcHeader->offsetEnd);
ByteSwap::Swap4(&m_pcHeader->offsetFrames);
ByteSwap::Swap4(&m_pcHeader->offsetGlCommands);
ByteSwap::Swap4(&m_pcHeader->offsetSkins);
ByteSwap::Swap4(&m_pcHeader->offsetTexCoords);
ByteSwap::Swap4(&m_pcHeader->offsetTriangles);
ByteSwap::Swap4(&m_pcHeader->skinHeight);
ByteSwap::Swap4(&m_pcHeader->skinWidth);
ByteSwap::Swap4(&m_pcHeader->version);
#endif
this->ValidateHeader();
// there won't be more than one mesh inside the file // there won't be more than one mesh inside the file
pScene->mNumMaterials = 1; pScene->mNumMaterials = 1;
@ -216,20 +235,43 @@ void MD2Importer::InternReadFile(
aiMesh* pcMesh = pScene->mMeshes[0] = new aiMesh(); aiMesh* pcMesh = pScene->mMeshes[0] = new aiMesh();
// navigate to the begin of the frame data // navigate to the begin of the frame data
const MD2::Frame* pcFrame = (const MD2::Frame*) ( const MD2::Frame* pcFrame = (const MD2::Frame*) ((uint8_t*)
(unsigned char*)this->m_pcHeader + this->m_pcHeader->offsetFrames); this->m_pcHeader + this->m_pcHeader->offsetFrames);
pcFrame += this->configFrameID;
// navigate to the begin of the triangle data // navigate to the begin of the triangle data
MD2::Triangle* pcTriangles = (MD2::Triangle*) ( MD2::Triangle* pcTriangles = (MD2::Triangle*) ((uint8_t*)
(unsigned char*)this->m_pcHeader + this->m_pcHeader->offsetTriangles); this->m_pcHeader + this->m_pcHeader->offsetTriangles);
// navigate to the begin of the tex coords data // navigate to the begin of the tex coords data
const MD2::TexCoord* pcTexCoords = (const MD2::TexCoord*) ( const MD2::TexCoord* pcTexCoords = (const MD2::TexCoord*) ((uint8_t*)
(unsigned char*)this->m_pcHeader + this->m_pcHeader->offsetTexCoords); this->m_pcHeader + this->m_pcHeader->offsetTexCoords);
// navigate to the begin of the vertex data // navigate to the begin of the vertex data
const MD2::Vertex* pcVerts = (const MD2::Vertex*) (pcFrame->vertices); const MD2::Vertex* pcVerts = (const MD2::Vertex*) (pcFrame->vertices);
#ifdef AI_BUILD_BIG_ENDIAN
for (uint32_t i = 0; i< m_pcHeader->numTriangles)
{
for (unsigned int p = 0; p < 3;++p)
{
ByteSwap::Swap2(& pcTriangles[i].textureIndices[p]);
ByteSwap::Swap2(& pcTriangles[i].vertexIndices[p]);
}
}
for (uint32_t i = 0; i < m_pcHeader->offsetTexCoords;++i)
{
ByteSwap::Swap2(& pcTexCoords[i].s);
ByteSwap::Swap2(& pcTexCoords[i].t);
}
ByteSwap::Swap4( & pcFrame->scale[0] );
ByteSwap::Swap4( & pcFrame->scale[1] );
ByteSwap::Swap4( & pcFrame->scale[2] );
ByteSwap::Swap4( & pcFrame->translate[0] );
ByteSwap::Swap4( & pcFrame->translate[1] );
ByteSwap::Swap4( & pcFrame->translate[2] );
#endif
pcMesh->mNumFaces = this->m_pcHeader->numTriangles; pcMesh->mNumFaces = this->m_pcHeader->numTriangles;
pcMesh->mFaces = new aiFace[this->m_pcHeader->numTriangles]; pcMesh->mFaces = new aiFace[this->m_pcHeader->numTriangles];

View File

@ -75,6 +75,14 @@ public:
* See BaseImporter::CanRead() for details. */ * See BaseImporter::CanRead() for details. */
bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const; bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const;
// -------------------------------------------------------------------
/** Called prior to ReadFile().
* The function is a request to the importer to update its configuration
* basing on the Importer's configuration property list.
*/
void SetupProperties(const Importer* pImp);
protected: protected:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
@ -101,6 +109,9 @@ protected:
protected: protected:
/** Configuration option: frame to be loaded */
unsigned int configFrameID;
/** Header of the MD2 file */ /** Header of the MD2 file */
const MD2::Header* m_pcHeader; const MD2::Header* m_pcHeader;

View File

@ -43,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "MD3Loader.h" #include "MD3Loader.h"
#include "MaterialSystem.h" #include "MaterialSystem.h"
#include "StringComparison.h" #include "StringComparison.h"
#include "ByteSwap.h"
#include "../include/IOStream.h" #include "../include/IOStream.h"
#include "../include/IOSystem.h" #include "../include/IOSystem.h"
@ -50,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../include/aiScene.h" #include "../include/aiScene.h"
#include "../include/aiAssert.h" #include "../include/aiAssert.h"
#include "../include/DefaultLogger.h" #include "../include/DefaultLogger.h"
#include "../include/assimp.hpp"
#include <boost/scoped_ptr.hpp> #include <boost/scoped_ptr.hpp>
@ -90,14 +92,19 @@ bool MD3Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void MD3Importer::ValidateHeaderOffsets() void MD3Importer::ValidateHeaderOffsets()
{ {
// check magic number
if (this->m_pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_BE &&
this->m_pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_LE)
throw new ImportErrorException( "Invalid MD3 file: Magic bytes not found");
// check file format version // check file format version
if (this->m_pcHeader->VERSION > 15) if (this->m_pcHeader->VERSION > 15)
DefaultLogger::get()->warn( "Unsupported md3 file version. Continuing happily ..."); DefaultLogger::get()->warn( "Unsupported MD3 file version. Continuing happily ...");
// check some values whether they are valid // check some values whether they are valid
if (0 == this->m_pcHeader->NUM_FRAMES) if (!this->m_pcHeader->NUM_FRAMES)
throw new ImportErrorException( "Invalid md3 file: NUM_FRAMES is 0"); throw new ImportErrorException( "Invalid MD3 file: NUM_FRAMES is 0");
if (0 == this->m_pcHeader->NUM_SURFACES) if (!this->m_pcHeader->NUM_SURFACES)
throw new ImportErrorException( "Invalid md3 file: NUM_SURFACES is 0"); throw new ImportErrorException( "Invalid md3 file: NUM_SURFACES is 0");
if (this->m_pcHeader->OFS_FRAMES >= this->fileSize || if (this->m_pcHeader->OFS_FRAMES >= this->fileSize ||
@ -106,6 +113,9 @@ void MD3Importer::ValidateHeaderOffsets()
{ {
throw new ImportErrorException("Invalid MD3 header: some offsets are outside the file"); throw new ImportErrorException("Invalid MD3 header: some offsets are outside the file");
} }
if (this->m_pcHeader->NUM_FRAMES >= this->configFrameID )
throw new ImportErrorException("The requested frame is not existing the file");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void MD3Importer::ValidateSurfaceHeaderOffsets(const MD3::Surface* pcSurf) void MD3Importer::ValidateSurfaceHeaderOffsets(const MD3::Surface* pcSurf)
@ -131,6 +141,18 @@ void MD3Importer::ValidateSurfaceHeaderOffsets(const MD3::Surface* pcSurf)
DefaultLogger::get()->warn("The model contains more frames than Quake 3 supports"); DefaultLogger::get()->warn("The model contains more frames than Quake 3 supports");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Setup configuration properties
void MD3Importer::SetupProperties(const Importer* pImp)
{
// The AI_CONFIG_IMPORT_MD3_KEYFRAME option overrides the
// AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
if(0xffffffff == (this->configFrameID = pImp->GetProperty(
AI_CONFIG_IMPORT_MD3_KEYFRAME,0xffffffff)))
{
this->configFrameID = pImp->GetProperty(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
}
}
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void MD3Importer::InternReadFile( void MD3Importer::InternReadFile(
const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
@ -139,17 +161,13 @@ void MD3Importer::InternReadFile(
// Check whether we can read from the file // Check whether we can read from the file
if( file.get() == NULL) if( file.get() == NULL)
{ throw new ImportErrorException( "Failed to open MD3 file " + pFile + ".");
throw new ImportErrorException( "Failed to open md3 file " + pFile + ".");
}
// check whether the md3 file is large enough to contain // check whether the md3 file is large enough to contain
// at least the file header // at least the file header
fileSize = (unsigned int)file->FileSize(); fileSize = (unsigned int)file->FileSize();
if( fileSize < sizeof(MD3::Header)) if( fileSize < sizeof(MD3::Header))
{ throw new ImportErrorException( "MD3 File is too small.");
throw new ImportErrorException( ".md3 File is too small.");
}
// allocate storage and copy the contents of the file to a memory buffer // allocate storage and copy the contents of the file to a memory buffer
this->mBuffer = new unsigned char[fileSize]; this->mBuffer = new unsigned char[fileSize];
@ -160,12 +178,22 @@ void MD3Importer::InternReadFile(
this->m_pcHeader = (const MD3::Header*)this->mBuffer; this->m_pcHeader = (const MD3::Header*)this->mBuffer;
// check magic number #ifdef AI_BUILD_BIG_ENDIAN
if (this->m_pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_BE &&
this->m_pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_LE) ByteSwap::Swap4(&m_pcHeader->VERSION);
{ ByteSwap::Swap4(&m_pcHeader->FLAGS);
throw new ImportErrorException( "Invalid md3 file: Magic bytes not found"); ByteSwap::Swap4(&m_pcHeader->IDENT);
} ByteSwap::Swap4(&m_pcHeader->NUM_FRAMES);
ByteSwap::Swap4(&m_pcHeader->NUM_SKINS);
ByteSwap::Swap4(&m_pcHeader->NUM_SURFACES);
ByteSwap::Swap4(&m_pcHeader->NUM_TAGS);
ByteSwap::Swap4(&m_pcHeader->OFS_EOF);
ByteSwap::Swap4(&m_pcHeader->OFS_FRAMES);
ByteSwap::Swap4(&m_pcHeader->OFS_SURFACES);
ByteSwap::Swap4(&m_pcHeader->OFS_TAGS);
#endif
// validate the header // validate the header
this->ValidateHeaderOffsets(); this->ValidateHeaderOffsets();
@ -190,33 +218,71 @@ void MD3Importer::InternReadFile(
unsigned int iDefaultMatIndex = 0xFFFFFFFF; unsigned int iDefaultMatIndex = 0xFFFFFFFF;
while (iNum-- > 0) while (iNum-- > 0)
{ {
#ifdef AI_BUILD_BIG_ENDIAN
ByteSwap::Swap4(pcSurfaces->FLAGS);
ByteSwap::Swap4(pcSurfaces->IDENT);
ByteSwap::Swap4(pcSurfaces->NUM_FRAMES);
ByteSwap::Swap4(pcSurfaces->NUM_SHADER);
ByteSwap::Swap4(pcSurfaces->NUM_TRIANGLES);
ByteSwap::Swap4(pcSurfaces->NUM_VERTICES);
ByteSwap::Swap4(pcSurfaces->OFS_END);
ByteSwap::Swap4(pcSurfaces->OFS_SHADERS);
ByteSwap::Swap4(pcSurfaces->OFS_ST);
ByteSwap::Swap4(pcSurfaces->OFS_TRIANGLES);
ByteSwap::Swap4(pcSurfaces->OFS_XYZNORMAL);
#endif
// validate the surface // validate the surface
this->ValidateSurfaceHeaderOffsets(pcSurfaces); this->ValidateSurfaceHeaderOffsets(pcSurfaces);
// navigate to the vertex list of the surface // navigate to the vertex list of the surface
const MD3::Vertex* pcVertices = (const MD3::Vertex*) const MD3::Vertex* pcVertices = (const MD3::Vertex*)
(((unsigned char*)pcSurfaces) + pcSurfaces->OFS_XYZNORMAL); (((uint8_t*)pcSurfaces) + pcSurfaces->OFS_XYZNORMAL);
// navigate to the triangle list of the surface // navigate to the triangle list of the surface
const MD3::Triangle* pcTriangles = (const MD3::Triangle*) const MD3::Triangle* pcTriangles = (const MD3::Triangle*)
(((unsigned char*)pcSurfaces) + pcSurfaces->OFS_TRIANGLES); (((uint8_t*)pcSurfaces) + pcSurfaces->OFS_TRIANGLES);
// navigate to the texture coordinate list of the surface // navigate to the texture coordinate list of the surface
const MD3::TexCoord* pcUVs = (const MD3::TexCoord*) const MD3::TexCoord* pcUVs = (const MD3::TexCoord*)
(((unsigned char*)pcSurfaces) + pcSurfaces->OFS_ST); (((uint8_t*)pcSurfaces) + pcSurfaces->OFS_ST);
// navigate to the shader list of the surface // navigate to the shader list of the surface
const MD3::Shader* pcShaders = (const MD3::Shader*) const MD3::Shader* pcShaders = (const MD3::Shader*)
(((unsigned char*)pcSurfaces) + pcSurfaces->OFS_SHADERS); (((uint8_t*)pcSurfaces) + pcSurfaces->OFS_SHADERS);
// if the submesh is empty ignore it // if the submesh is empty ignore it
if (0 == pcSurfaces->NUM_VERTICES || 0 == pcSurfaces->NUM_TRIANGLES) if (0 == pcSurfaces->NUM_VERTICES || 0 == pcSurfaces->NUM_TRIANGLES)
{ {
pcSurfaces = (const MD3::Surface*)(((unsigned char*)pcSurfaces) + pcSurfaces->OFS_END); pcSurfaces = (const MD3::Surface*)(((uint8_t*)pcSurfaces) + pcSurfaces->OFS_END);
pScene->mNumMeshes--; pScene->mNumMeshes--;
continue; continue;
} }
#ifdef AI_BUILD_BIG_ENDIAN
for (uint32_t i = 0; i < pcSurfaces->NUM_VERTICES;++i)
{
ByteSwap::Swap2( & pcVertices[i].NORMAL );
ByteSwap::Swap2( & pcVertices[i].X );
ByteSwap::Swap2( & pcVertices[i].Y );
ByteSwap::Swap2( & pcVertices[i].Z );
ByteSwap::Swap4( & pcUVs[i].U );
ByteSwap::Swap4( & pcUVs[i].U );
}
for (uint32_t i = 0; i < pcSurfaces->NUM_TRIANGLES;++i)
{
ByteSwap::Swap4(pcTriangles[i].INDEXES[0]);
ByteSwap::Swap4(pcTriangles[i].INDEXES[1]);
ByteSwap::Swap4(pcTriangles[i].INDEXES[2]);
}
#endif
// allocate the output mesh // allocate the output mesh
pScene->mMeshes[iNum] = new aiMesh(); pScene->mMeshes[iNum] = new aiMesh();
aiMesh* pcMesh = pScene->mMeshes[iNum]; aiMesh* pcMesh = pScene->mMeshes[iNum];
@ -358,7 +424,7 @@ void MD3Importer::InternReadFile(
pcHelper->AddProperty(&szName,AI_MATKEY_NAME); pcHelper->AddProperty(&szName,AI_MATKEY_NAME);
pScene->mMaterials[iNumMaterials] = (aiMaterial*)pcHelper; pScene->mMaterials[iNumMaterials] = (aiMaterial*)pcHelper;
pcMesh->mMaterialIndex = iNumMaterials++; iDefaultMatIndex = pcMesh->mMaterialIndex = iNumMaterials++;
} }
} }
else else
@ -384,7 +450,7 @@ void MD3Importer::InternReadFile(
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT); pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
pScene->mMaterials[iNumMaterials] = (aiMaterial*)pcHelper; pScene->mMaterials[iNumMaterials] = (aiMaterial*)pcHelper;
pcMesh->mMaterialIndex = iNumMaterials++; iDefaultMatIndex = pcMesh->mMaterialIndex = iNumMaterials++;
} }
} }
// go to the next surface // go to the next surface

View File

@ -78,6 +78,14 @@ public:
* See BaseImporter::CanRead() for details. */ * See BaseImporter::CanRead() for details. */
bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const; bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const;
// -------------------------------------------------------------------
/** Called prior to ReadFile().
* The function is a request to the importer to update its configuration
* basing on the Importer's configuration property list.
*/
void SetupProperties(const Importer* pImp);
protected: protected:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
@ -105,6 +113,9 @@ protected:
protected: protected:
/** Configuration option: frame to be loaded */
unsigned int configFrameID;
/** Header of the MD3 file */ /** Header of the MD3 file */
const MD3::Header* m_pcHeader; const MD3::Header* m_pcHeader;

208
code/MDCFileData.h 100644
View File

@ -0,0 +1,208 @@
/*
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 Defines the helper data structures for importing MDC files
**********************************************************************
File format specification:
http://themdcfile.planetwolfenstein.gamespy.com/MDC_File_Format.pdf
**********************************************************************
*/
#ifndef AI_MDCFILEHELPER_H_INC
#define AI_MDCFILEHELPER_H_INC
#include "../include/aiTypes.h"
#include "../include/aiMesh.h"
#include "../include/aiAnim.h"
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
# pragma pack(push,1)
# define PACK_STRUCT
#elif defined( __GNUC__ )
# define PACK_STRUCT __attribute__((packed))
#else
# error Compiler not supported
#endif
namespace Assimp {
namespace MDC {
#define AI_MDC_MAGIC_NUMBER_BE 'CPDI'
#define AI_MDC_MAGIC_NUMBER_LE 'IDPC'
// common limitations
#define AI_MDC_VERSION 2
#define AI_MDC_MAXQPATH 64
#define AI_MDC_MAX_BONES 128
#define AI_MDC_CVERT_BIAS 127.0f
#define AI_MDC_DELTA_SCALING 4.0f
#define AI_MDC_BASE_SCALING (1.0f / 64.0f)
// ---------------------------------------------------------------------------
/** \brief Data structure for a MDC file's main header
*/
struct Header
{
uint32_t ulIdent ;
uint32_t ulVersion ;
char ucName [ AI_MDC_MAXQPATH ] ;
uint32_t ulFlags ;
uint32_t ulNumFrames ;
uint32_t ulNumTags ;
uint32_t ulNumSurfaces ;
uint32_t ulNumSkins ;
uint32_t ulOffsetBorderFrames ;
uint32_t ulOffsetTagNames ;
uint32_t ulOffsetTagFrames ;
uint32_t ulOffsetSurfaces ;
uint32_t ulOffsetEnd ;
} PACK_STRUCT ;
// ---------------------------------------------------------------------------
/** \brief Data structure for a MDC file's surface header
*/
struct Surface
{
uint32_t ulIdent ;
char ucName [ AI_MDC_MAXQPATH ] ;
uint32_t ulFlags ;
uint32_t ulNumCompFrames ;
uint32_t ulNumBaseFrames ;
uint32_t ulNumShaders ;
uint32_t ulNumVertices ;
uint32_t ulNumTriangles ;
uint32_t ulOffsetTriangles ;
uint32_t ulOffsetShaders ;
uint32_t ulOffsetTexCoords ;
uint32_t ulOffsetBaseVerts ;
uint32_t ulOffsetCompVerts ;
uint32_t ulOffsetFrameBaseFrames ;
uint32_t ulOffsetFrameCompFrames ;
uint32_t ulOffsetEnd ;
} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \brief Data structure for a MDC frame
*/
struct Frame
{
//! bounding box minimum coords
aiVector3D bboxMin ;
//! bounding box maximum coords
aiVector3D bboxMax ;
//! local origin of the frame
aiVector3D localOrigin ;
//! radius of the BB
float radius ;
//! Name of the frame
char name [ 16 ] ;
} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \brief Data structure for a MDC triangle
*/
struct Triangle
{
uint32_t aiIndices[3];
} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \brief Data structure for a MDC texture coordinate
*/
struct TexturCoord
{
float u,v;
} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \brief Data structure for a MDC base vertex
*/
struct BaseVertex
{
int16_t x,y,z;
uint16_t normal;
} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \brief Data structure for a MDC compressed vertex
*/
struct CompressedVertex
{
uint8_t xd,yd,zd,nd;
} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \brief Data structure for a MDC shader
*/
struct Shader
{
char ucName [ AI_MDC_MAXQPATH ] ;
uint32_t ulPath;
} PACK_STRUCT;
// reset packing to the original value
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
# pragma pack( pop )
#endif
#undef PACK_STRUCT
// ---------------------------------------------------------------------------
/** Build a floating point vertex from the compressed data in MDC files
*/
void BuildVertex(const Frame& frame,
const BaseVertex& bvert,
const CompressedVertex& cvert,
aiVector3D& vXYZOut,
aiVector3D& vNorOut);
}}
#endif // !! AI_MDCFILEHELPER_H_INC

237
code/MDRFileData.h 100644
View File

@ -0,0 +1,237 @@
/*
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 Defines the helper data structures for importing MDR files */
#ifndef AI_MDRFILEHELPER_H_INC
#define AI_MDRFILEHELPER_H_INC
#include "../include/aiTypes.h"
#include "../include/aiMesh.h"
#include "../include/aiAnim.h"
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
# pragma pack(push,1)
# define PACK_STRUCT
#elif defined( __GNUC__ )
# define PACK_STRUCT __attribute__((packed))
#else
# error Compiler not supported
#endif
namespace Assimp {
namespace MDR {
#define AI_MDR_MAGIC_NUMBER_BE 'RDM5'
#define AI_MDR_MAGIC_NUMBER_LE '5MDR'
// common limitations
#define AI_MDR_VERSION 2
#define AI_MDR_MAXQPATH 64
#define AI_MDR_MAX_BONES 128
// ---------------------------------------------------------------------------
/** \brief Data structure for a vertex weight in a MDR file
*/
struct Weight
{
//! these are indexes into the boneReferences
//! not the global per-frame bone list
uint32_t boneIndex;
//! weight of this bone
float boneWeight;
//! offset of this bone
aiVector3D offset;
} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \brief Data structure for a vertex in a MDR file
*/
struct Vertex
{
aiVector3D normal;
aiVector2D texCoords;
uint32_t numWeights;
Weight weights[1]; // variable sized
} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \brief Data structure for a triangle in a MDR file
*/
struct Triangle
{
uint32_t indexes[3];
} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \brief Data structure for a surface in a MDR file
*/
struct Surface
{
uint32_t ident;
char name[AI_MDR_MAXQPATH]; // polyset name
char shader[AI_MDR_MAXQPATH];
uint32_t shaderIndex;
int32_t ofsHeader; // this will be a negative number
uint32_t numVerts;
uint32_t ofsVerts;
uint32_t numTriangles;
uint32_t ofsTriangles;
// Bone references are a set of ints representing all the bones
// present in any vertex weights for this surface. This is
// needed because a model may have surfaces that need to be
// drawn at different sort times, and we don't want to have
// to re-interpolate all the bones for each surface.
uint32_t numBoneReferences;
uint32_t ofsBoneReferences;
uint32_t ofsEnd; // next surface follows
} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \brief Data structure for a bone in a MDR file
*/
struct Bone
{
float matrix[3][4];
} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \brief Data structure for a frame in a MDR file
*/
struct Frame {
aiVector3D bounds[2]; // bounds of all surfaces of all LOD's for this frame
aiVector3D localOrigin; // midpoint of bounds, used for sphere cull
float radius; // dist from localOrigin to corner
char name[16];
Bone bones[1]; // [numBones]
} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \brief Data structure for a compressed bone in a MDR file
*/
struct CompBone
{
unsigned char Comp[24]; // MC_COMP_BYTES is in MatComp.h, but don't want to couple
} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \brief Data structure for a compressed frame in a MDR file
*/
struct CompFrame
{
aiVector3D bounds[2]; // bounds of all surfaces of all LOD's for this frame
aiVector3D localOrigin; // midpoint of bounds, used for sphere cull
float radius; // dist from localOrigin to corner
CompBone bones[1]; // [numBones]
} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \brief Data structure for a LOD in a MDR file
*/
struct LOD
{
uint32_t numSurfaces;
uint32_t ofsSurfaces; // first surface, others follow
uint32_t ofsEnd; // next lod follows
} ;
// ---------------------------------------------------------------------------
/** \brief Data structure for a tag (= attachment) in a MDR file
*/
struct Tag
{
uint32_t boneIndex;
char name[32];
} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \brief Header data structure for a MDR file
*/
struct Header
{
uint32_t ident;
uint32_t version;
char name[AI_MDR_MAXQPATH];
// frames and bones are shared by all levels of detail
int32_t numFrames;
uint32_t numBones;
uint32_t ofsFrames;
// each level of detail has completely separate sets of surfaces
uint32_t numLODs;
uint32_t ofsLODs;
uint32_t numTags;
uint32_t ofsTags;
uint32_t ofsEnd;
} PACK_STRUCT;
// reset packing to the original value
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
# pragma pack( pop )
#endif
#undef PACK_STRUCT
};
};
#endif // !! AI_MDRFILEHELPER_H_INC