|
@@ -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)
|
|
|
|
- throw new ImportErrorException( "Invalid md3 file: NUM_FRAMES is 0");
|
|
|
|
- if (0 == this->m_pcHeader->NUM_SURFACES)
|
|
|
|
|
|
+ if (!this->m_pcHeader->NUM_FRAMES)
|
|
|
|
+ throw new ImportErrorException( "Invalid MD3 file: NUM_FRAMES is 0");
|
|
|
|
+ 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
|
|
|
|
- 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");
|
|
|
|
- }
|
|
|
|
|
|
+#ifdef AI_BUILD_BIG_ENDIAN
|
|
|
|
+
|
|
|
|
+ ByteSwap::Swap4(&m_pcHeader->VERSION);
|
|
|
|
+ ByteSwap::Swap4(&m_pcHeader->FLAGS);
|
|
|
|
+ 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
|