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
This commit is contained in:
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

@@ -42,6 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Implementation of the MD2 importer class */
#include "MD2Loader.h"
#include "MaterialSystem.h"
#include "ByteSwap.h"
#include "MD2NormalTable.h" // shouldn't be included by other units
#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/aiAssert.h"
#include "../include/DefaultLogger.h"
#include "../include/assimp.hpp"
#include <boost/scoped_ptr.hpp>
@@ -110,6 +112,18 @@ bool MD2Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
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
void MD2Importer::ValidateHeader( )
{
@@ -117,9 +131,6 @@ void MD2Importer::ValidateHeader( )
if (this->m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_BE &&
this->m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_LE)
{
delete[] this->mBuffer;
AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
char szBuffer[5];
szBuffer[0] = ((char*)&this->m_pcHeader->magic)[0];
szBuffer[1] = ((char*)&this->m_pcHeader->magic)[1];
@@ -133,27 +144,22 @@ void MD2Importer::ValidateHeader( )
// check file format version
if (this->m_pcHeader->version != 8)
{
DefaultLogger::get()->warn( "Unsupported md2 file version. Continuing happily ...");
}
/* to be validated:
int32_t offsetSkins;
int32_t offsetTexCoords;
int32_t offsetTriangles;
int32_t offsetFrames;
//int32_t offsetGlCommands;
int32_t offsetEnd;
*/
// check some values whether they are valid
if (0 == this->m_pcHeader->numFrames)
throw new ImportErrorException( "Invalid md2 file: NUM_FRAMES is 0");
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 ||
if (this->m_pcHeader->offsetEnd > (int32_t)fileSize)
throw new ImportErrorException( "Invalid md2 file: File is too small");
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)
{
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)
@@ -162,27 +168,27 @@ void MD2Importer::ValidateHeader( )
DefaultLogger::get()->warn("The model contains more frames than Quake 2 supports");
if (this->m_pcHeader->numVertices > AI_MD2_MAX_VERTS)
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.
void MD2Importer::InternReadFile(
const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
void MD2Importer::InternReadFile( const std::string& pFile,
aiScene* pScene, IOSystem* pIOHandler)
{
boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
// Check whether we can read from the file
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
// at least the file header
fileSize = (unsigned int)file->FileSize();
if( fileSize < sizeof(MD2::Header))
{
throw new ImportErrorException( "md2 File is too small.");
}
throw new ImportErrorException( "MD2 File is too small");
try
{
@@ -191,17 +197,30 @@ void MD2Importer::InternReadFile(
file->Read( (void*)mBuffer, 1, fileSize);
this->m_pcHeader = (const MD2::Header*)this->mBuffer;
this->ValidateHeader();
// check some values whether they are valid
if (0 == this->m_pcHeader->numFrames)
{
throw new ImportErrorException( "Invalid md2 file: NUM_FRAMES is 0");
}
if (this->m_pcHeader->offsetEnd > (int32_t)fileSize)
{
throw new ImportErrorException( "Invalid md2 file: File is too small");
}
#ifdef AI_BUILD_BIG_ENDIAN
ByteSwap::Swap4(&m_pcHeader->frameSize);
ByteSwap::Swap4(&m_pcHeader->magic);
ByteSwap::Swap4(&m_pcHeader->numFrames);
ByteSwap::Swap4(&m_pcHeader->numGlCommands);
ByteSwap::Swap4(&m_pcHeader->numSkins);
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
pScene->mNumMaterials = 1;
@@ -216,20 +235,43 @@ void MD2Importer::InternReadFile(
aiMesh* pcMesh = pScene->mMeshes[0] = new aiMesh();
// navigate to the begin of the frame data
const MD2::Frame* pcFrame = (const MD2::Frame*) (
(unsigned char*)this->m_pcHeader + this->m_pcHeader->offsetFrames);
const MD2::Frame* pcFrame = (const MD2::Frame*) ((uint8_t*)
this->m_pcHeader + this->m_pcHeader->offsetFrames);
pcFrame += this->configFrameID;
// navigate to the begin of the triangle data
MD2::Triangle* pcTriangles = (MD2::Triangle*) (
(unsigned char*)this->m_pcHeader + this->m_pcHeader->offsetTriangles);
MD2::Triangle* pcTriangles = (MD2::Triangle*) ((uint8_t*)
this->m_pcHeader + this->m_pcHeader->offsetTriangles);
// navigate to the begin of the tex coords data
const MD2::TexCoord* pcTexCoords = (const MD2::TexCoord*) (
(unsigned char*)this->m_pcHeader + this->m_pcHeader->offsetTexCoords);
const MD2::TexCoord* pcTexCoords = (const MD2::TexCoord*) ((uint8_t*)
this->m_pcHeader + this->m_pcHeader->offsetTexCoords);
// navigate to the begin of the vertex data
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->mFaces = new aiFace[this->m_pcHeader->numTriangles];