Finished loading of MD2, MD3, MDL2, MDL3, MDL4, MDL5, MDL7, MDL. First WIP version of the SMD loader. Additionals checks added to the validation step.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@60 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
pull/1/head
aramis_acg 2008-06-22 10:09:26 +00:00
parent 758e092449
commit b422d4e303
90 changed files with 7349 additions and 2105 deletions

View File

@ -40,11 +40,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/** @file Implementation of the 3ds importer class */ /** @file Implementation of the 3ds importer class */
// internal headers
#include "3DSLoader.h" #include "3DSLoader.h"
#include "MaterialSystem.h" #include "MaterialSystem.h"
#include "TextureTransform.h" #include "TextureTransform.h"
#include "StringComparison.h" #include "StringComparison.h"
#include "qnan.h"
// public ASSIMP headers
#include "../include/DefaultLogger.h" #include "../include/DefaultLogger.h"
#include "../include/IOStream.h" #include "../include/IOStream.h"
#include "../include/IOSystem.h" #include "../include/IOSystem.h"
@ -52,7 +56,6 @@ 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 <boost/scoped_ptr.hpp>
using namespace Assimp; using namespace Assimp;
@ -427,10 +430,12 @@ void Dot3DSImporter::ConvertMeshes(aiScene* pcOut)
a != (*i).mFaceMaterials.end();++a,++iNum) a != (*i).mFaceMaterials.end();++a,++iNum)
{ {
// check range // check range
if ((*a) >= this->mScene->mMaterials.size()) if ((*a) >= this->mScene->mMaterials.size())
{ {
// use the last material instead DefaultLogger::get()->error("Face material index is out of range");
aiSplit[this->mScene->mMaterials.size()-1].push_back(iNum);
// use the last material instead
aiSplit[this->mScene->mMaterials.size()-1].push_back(iNum);
} }
else aiSplit[*a].push_back(iNum); else aiSplit[*a].push_back(iNum);
} }
@ -450,15 +455,15 @@ void Dot3DSImporter::ConvertMeshes(aiScene* pcOut)
p_pcOut->mColors[0] = (aiColor4D*)new std::string((*i).mName); p_pcOut->mColors[0] = (aiColor4D*)new std::string((*i).mName);
avOutMeshes.push_back(p_pcOut); avOutMeshes.push_back(p_pcOut);
// (code for keyframe animation. however, this is currently not supported by Assimp)
#if 0
if (bFirst) if (bFirst)
{ {
p_pcOut->mColors[1] = (aiColor4D*)new aiMatrix4x4(); p_pcOut->mColors[1] = (aiColor4D*)new aiMatrix4x4();
*((aiMatrix4x4*)p_pcOut->mColors[1]) = (*i).mMat; *((aiMatrix4x4*)p_pcOut->mColors[1]) = (*i).mMat;
bFirst = false; bFirst = false;
} }
#endif
// convert vertices // convert vertices
p_pcOut->mNumVertices = (unsigned int)aiSplit[p].size()*3; p_pcOut->mNumVertices = (unsigned int)aiSplit[p].size()*3;
@ -519,16 +524,6 @@ void Dot3DSImporter::ConvertMeshes(aiScene* pcOut)
// apply texture coordinate scalings // apply texture coordinate scalings
TextureTransform::BakeScaleNOffset ( p_pcOut, &this->mScene->mMaterials[ TextureTransform::BakeScaleNOffset ( p_pcOut, &this->mScene->mMaterials[
p_pcOut->mMaterialIndex] ); p_pcOut->mMaterialIndex] );
// setup bitflags to indicate which texture coordinate
// channels are used
p_pcOut->mNumUVComponents[0] = 2;
if (p_pcOut->HasTextureCoords(1))
p_pcOut->mNumUVComponents[1] = 2;
if (p_pcOut->HasTextureCoords(2))
p_pcOut->mNumUVComponents[2] = 2;
if (p_pcOut->HasTextureCoords(3))
p_pcOut->mNumUVComponents[3] = 2;
} }
} }
} }
@ -579,6 +574,8 @@ void Dot3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,Dot3DS::Node*
{ {
const unsigned int iIndex = iArray[i]; const unsigned int iIndex = iArray[i];
// (code for keyframe animation. however, this is currently not supported by Assimp)
#if 0
if (NULL != pcSOut->mMeshes[iIndex]->mColors[1]) if (NULL != pcSOut->mMeshes[iIndex]->mColors[1])
{ {
pcOut->mTransformation = *((aiMatrix4x4*) pcOut->mTransformation = *((aiMatrix4x4*)
@ -587,7 +584,7 @@ void Dot3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,Dot3DS::Node*
delete (aiMatrix4x4*)pcSOut->mMeshes[iIndex]->mColors[1]; delete (aiMatrix4x4*)pcSOut->mMeshes[iIndex]->mColors[1];
pcSOut->mMeshes[iIndex]->mColors[1] = NULL; pcSOut->mMeshes[iIndex]->mColors[1] = NULL;
} }
#endif
pcOut->mMeshes[i] = iIndex; pcOut->mMeshes[i] = iIndex;
} }
@ -681,11 +678,17 @@ void Dot3DSImporter::GenerateNodeGraph(aiScene* pcOut)
pcNode->mMeshes[0] = i; pcNode->mMeshes[0] = i;
pcNode->mNumMeshes = 1; pcNode->mNumMeshes = 1;
std::string s; char szBuffer[128];
std::stringstream ss(s); int iLen;
ss << "UNNAMED[" << i << + "]"; #if _MSC_VER >= 1400
iLen = sprintf_s(szBuffer,"UNNAMED_%i",i);
pcNode->mName.Set(s); #else
iLen = sprintf(szBuffer,"UNNAMED_%i",i);
#endif
ai_assert(0 < iLen);
::memcpy(pcNode->mName.data,szBuffer,iLen);
pcNode->mName.data[iLen] = '\0';
pcNode->mName.length = iLen;
// add the new child to the parent node // add the new child to the parent node
pcOut->mRootNode->mChildren[i] = pcNode; pcOut->mRootNode->mChildren[i] = pcNode;

View File

@ -93,10 +93,22 @@ public:
//! From AutoDesk 3ds SDK //! From AutoDesk 3ds SDK
typedef enum typedef enum
{ {
// translated to gouraud shading with wireframe active
Wire = 0, Wire = 0,
// if this material is set, no vertex normals will
// be calculated for the model. Face normals + gouraud
Flat = 1, Flat = 1,
// standard gouraud shading
Gouraud = 2, Gouraud = 2,
// phong shading
Phong = 3, Phong = 3,
// cooktorrance or anistropic phong shading ...
// the exact meaning is unknown, if you know it
// feel free to tell me ;-)
Metal = 4, Metal = 4,
// required by the ASE loader // required by the ASE loader
@ -127,7 +139,8 @@ public:
CHUNK_PERCENTF = 0x0031, // float4 percentage CHUNK_PERCENTF = 0x0031, // float4 percentage
// ************************************************************** // **************************************************************
// Unknown and ignored // Unknown and ignored. Possibly a chunk used by PROJ (
// Discreet 3DS max Project File)?
CHUNK_PRJ = 0xC23D, CHUNK_PRJ = 0xC23D,
// Unknown. Possibly a reference to an external .mli file? // Unknown. Possibly a reference to an external .mli file?
@ -387,9 +400,10 @@ struct Material
mTwoSided (false) mTwoSided (false)
{ {
static int iCnt = 0; static int iCnt = 0;
std::stringstream ss;
ss << "$$_UNNAMED_" << iCnt++ << "_$$"; char szTemp[128];
ss >> mName; sprintf(szTemp,"$$_UNNAMED_%i_$$",iCnt++);
mName = szTemp;
} }
//! Name of the material //! Name of the material
@ -442,9 +456,10 @@ struct Mesh
Mesh() Mesh()
{ {
static int iCnt = 0; static int iCnt = 0;
std::stringstream ss;
ss << "$$_UNNAMED_" << iCnt++ << "_$$"; char szTemp[128];
ss >> mName; sprintf(szTemp,"$$_UNNAMED_%i_$$",iCnt++);
mName = szTemp;
} }
//! Name of the mesh //! Name of the mesh
@ -481,9 +496,10 @@ struct Node
{ {
static int iCnt = 0; static int iCnt = 0;
std::stringstream ss;
ss << "$$_UNNAMED_" << iCnt++ << "_$$"; char szTemp[128];
ss >> mName; sprintf(szTemp,"$$_UNNAMED_%i_$$",iCnt++);
mName = szTemp;
mHierarchyPos = 0; mHierarchyPos = 0;
mHierarchyIndex = 0; mHierarchyIndex = 0;
@ -538,26 +554,6 @@ struct Scene
Node* pcRootNode; Node* pcRootNode;
}; };
// ---------------------------------------------------------------------------
inline bool is_qnan(float p_fIn)
{
// NOTE: Comparison against qnan is generally problematic
// because qnan == qnan is false AFAIK
union FTOINT
{
float fFloat;
int32_t iInt;
} one, two;
one.fFloat = std::numeric_limits<float>::quiet_NaN();
two.fFloat = p_fIn;
return (one.iInt == two.iInt);
}
// ---------------------------------------------------------------------------
inline bool is_not_qnan(float p_fIn)
{
return !is_qnan(p_fIn);
}
} // end of namespace Dot3DS } // end of namespace Dot3DS
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -40,11 +40,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/** @file Implementation of the 3ds importer class */ /** @file Implementation of the 3ds importer class */
// internal headers
#include "3DSLoader.h" #include "3DSLoader.h"
#include "MaterialSystem.h" #include "MaterialSystem.h"
#include "TextureTransform.h" #include "TextureTransform.h"
#include "StringComparison.h" #include "StringComparison.h"
#include "qnan.h"
// public ASSIMP headers
#include "../include/DefaultLogger.h" #include "../include/DefaultLogger.h"
#include "../include/IOStream.h" #include "../include/IOStream.h"
#include "../include/IOSystem.h" #include "../include/IOSystem.h"
@ -52,14 +56,17 @@ 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"
// boost headers
#include <boost/scoped_ptr.hpp> #include <boost/scoped_ptr.hpp>
using namespace Assimp; using namespace Assimp;
#define ASSIMP_3DS_WARN_CHUNK_OVERFLOW_MSG \ #if (!defined ASSIMP_3DS_WARN_CHUNK_OVERFLOW_MSG)
"WARNING: Size of chunk data plus size of " \ # define ASSIMP_3DS_WARN_CHUNK_OVERFLOW_MSG \
"subordinate chunks is larger than the size " \ "WARNING: Size of chunk data plus size of " \
"specified in the higher-level chunk header." \ "subordinate chunks is larger than the size " \
"specified in the top-level chunk header."
#endif
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
@ -92,22 +99,6 @@ bool Dot3DSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) co
return false; return false;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// recursively delete a given node
void DeleteNodeRecursively (aiNode* p_piNode)
{
if (!p_piNode)return;
if (p_piNode->mChildren)
{
for (unsigned int i = 0 ; i < p_piNode->mNumChildren;++i)
{
DeleteNodeRecursively(p_piNode->mChildren[i]);
}
}
delete p_piNode;
return;
}
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void Dot3DSImporter::InternReadFile( void Dot3DSImporter::InternReadFile(
const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
@ -125,7 +116,7 @@ void Dot3DSImporter::InternReadFile(
size_t fileSize = file->FileSize(); size_t fileSize = file->FileSize();
if( fileSize < 16) if( fileSize < 16)
{ {
throw new ImportErrorException( ".3ds File is too small."); throw new ImportErrorException( "3DS File is too small.");
} }
this->mScene = new Dot3DS::Scene(); this->mScene = new Dot3DS::Scene();
@ -780,8 +771,9 @@ void Dot3DSImporter::ParseFaceChunk(int* piRemaining)
case Dot3DSFile::CHUNK_FACEMAT: case Dot3DSFile::CHUNK_FACEMAT:
// at fist an asciiz with the material name // at fist an asciiz with the material name
while (*sz++ != '\0') while (*sz++)
{ {
// make sure we don't run over the end of the chunk
if (sz > pcCurNext-1)break; if (sz > pcCurNext-1)break;
} }
@ -800,7 +792,7 @@ void Dot3DSImporter::ParseFaceChunk(int* piRemaining)
break; break;
} }
} }
if (iIndex == 0xFFFFFFFF) if (0xFFFFFFFF == iIndex)
{ {
// this material is not known. Ignore this. We will later // this material is not known. Ignore this. We will later
// assign the default material to all faces using *this* // assign the default material to all faces using *this*
@ -818,13 +810,14 @@ void Dot3DSImporter::ParseFaceChunk(int* piRemaining)
// check range // check range
if (iTemp >= mMesh.mFaceMaterials.size()) if (iTemp >= mMesh.mFaceMaterials.size())
{ {
DefaultLogger::get()->error("Invalid face index in face material list");
mMesh.mFaceMaterials[mMesh.mFaceMaterials.size()-1] = iIndex; mMesh.mFaceMaterials[mMesh.mFaceMaterials.size()-1] = iIndex;
} }
else else
{ {
mMesh.mFaceMaterials[iTemp] = iIndex; mMesh.mFaceMaterials[iTemp] = iIndex;
} }
this->mCurrent += sizeof(uint16_t); this->mCurrent += sizeof(uint16_t);
} }
@ -959,8 +952,7 @@ void Dot3DSImporter::ParseMeshChunk(int* piRemaining)
} }
break; break;
#if (defined _DEBUG) #if 0
case Dot3DSFile::CHUNK_TXTINFO: case Dot3DSFile::CHUNK_TXTINFO:
// for debugging purposes. Read two bytes to determine the mapping type // for debugging purposes. Read two bytes to determine the mapping type

View File

@ -40,13 +40,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/** @file Implementation of the ASE importer class */ /** @file Implementation of the ASE importer class */
// internal headers
#include "ASELoader.h" #include "ASELoader.h"
#include "3DSSpatialSort.h" #include "3DSSpatialSort.h"
#include "MaterialSystem.h" #include "MaterialSystem.h"
#include "StringComparison.h" #include "StringComparison.h"
#include "TextureTransform.h" #include "TextureTransform.h"
#include "fast_atof.h"
// utilities
#include "fast_atof.h"
#include "qnan.h"
// ASSIMP public headers
#include "../include/IOStream.h" #include "../include/IOStream.h"
#include "../include/IOSystem.h" #include "../include/IOSystem.h"
#include "../include/aiMesh.h" #include "../include/aiMesh.h"

View File

@ -111,7 +111,7 @@ public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Imports the given file and returns the imported data. /** Imports the given file and returns the imported data.
* If the import succeeds, ownership of the data is transferred to * If the import succeeds, ownership of the data is transferred to
* the caller. If the import failes, NULL is returned. The function * the caller. If the import fails, NULL is returned. The function
* takes care that any partially constructed data is destroyed * takes care that any partially constructed data is destroyed
* beforehand. * beforehand.
* *
@ -154,7 +154,15 @@ protected:
* an error. If it terminates normally, the data in aiScene is * an error. If it terminates normally, the data in aiScene is
* expected to be correct. Override this function to implement the * expected to be correct. Override this function to implement the
* actual importing. * actual importing.
* * <br>
* The output scene must meet the following conditions:<br>
* - at least one mesh must be there<br>
* - at least a root node must be there<br>
* - at least one material must be there<br>
* - there may be no meshes with 0 vertices or faces<br>
* This won't be checked (except by the validation step), Assimp will
* crash if one of the conditions is not met!
*
* @param pFile Path of the file to be imported. * @param pFile Path of the file to be imported.
* @param pScene The scene object to hold the imported data. * @param pScene The scene object to hold the imported data.
* NULL is not a valid parameter. * NULL is not a valid parameter.

View File

@ -53,7 +53,7 @@ DefaultIOStream::~DefaultIOStream()
{ {
if (this->mFile) if (this->mFile)
{ {
fclose(this->mFile); ::fclose(this->mFile);
} }
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -61,20 +61,24 @@ size_t DefaultIOStream::Read(void* pvBuffer,
size_t pSize, size_t pSize,
size_t pCount) size_t pCount)
{ {
ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount);
if (!this->mFile) if (!this->mFile)
return 0; return 0;
return fread(pvBuffer, pSize, pCount, this->mFile); return ::fread(pvBuffer, pSize, pCount, this->mFile);
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
size_t DefaultIOStream::Write(const void* pvBuffer, size_t DefaultIOStream::Write(const void* pvBuffer,
size_t pSize, size_t pSize,
size_t pCount) size_t pCount)
{ {
ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount);
if (!this->mFile)return 0; if (!this->mFile)return 0;
fseek(mFile, 0, SEEK_SET); ::fseek(mFile, 0, SEEK_SET);
return fwrite(pvBuffer, pSize, pCount, this->mFile); return ::fwrite(pvBuffer, pSize, pCount, this->mFile);
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
aiReturn DefaultIOStream::Seek(size_t pOffset, aiReturn DefaultIOStream::Seek(size_t pOffset,
@ -82,7 +86,7 @@ aiReturn DefaultIOStream::Seek(size_t pOffset,
{ {
if (!this->mFile)return AI_FAILURE; if (!this->mFile)return AI_FAILURE;
return (0 == fseek(this->mFile, (long)pOffset, return (0 == ::fseek(this->mFile, (long)pOffset,
(aiOrigin_CUR == pOrigin ? SEEK_CUR : (aiOrigin_CUR == pOrigin ? SEEK_CUR :
(aiOrigin_END == pOrigin ? SEEK_END : SEEK_SET))) (aiOrigin_END == pOrigin ? SEEK_END : SEEK_SET)))
? AI_SUCCESS : AI_FAILURE); ? AI_SUCCESS : AI_FAILURE);
@ -92,7 +96,7 @@ size_t DefaultIOStream::Tell() const
{ {
if (!this->mFile)return 0; if (!this->mFile)return 0;
return ftell(this->mFile); return ::ftell(this->mFile);
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
size_t DefaultIOStream::FileSize() const size_t DefaultIOStream::FileSize() const

View File

@ -65,11 +65,11 @@ DefaultIOSystem::~DefaultIOSystem()
// Tests for the existence of a file at the given path. // Tests for the existence of a file at the given path.
bool DefaultIOSystem::Exists( const std::string& pFile) const bool DefaultIOSystem::Exists( const std::string& pFile) const
{ {
FILE* file = fopen( pFile.c_str(), "rb"); FILE* file = ::fopen( pFile.c_str(), "rb");
if( !file) if( !file)
return false; return false;
fclose( file); ::fclose( file);
return true; return true;
} }
@ -77,7 +77,7 @@ bool DefaultIOSystem::Exists( const std::string& pFile) const
// Open a new file with a given path. // Open a new file with a given path.
IOStream* DefaultIOSystem::Open( const std::string& strFile, const std::string& strMode) IOStream* DefaultIOSystem::Open( const std::string& strFile, const std::string& strMode)
{ {
FILE* file = fopen( strFile.c_str(), strMode.c_str()); FILE* file = ::fopen( strFile.c_str(), strMode.c_str());
if( NULL == file) if( NULL == file)
return NULL; return NULL;

449
code/HMPLoader.cpp 100644
View File

@ -0,0 +1,449 @@
/*
---------------------------------------------------------------------------
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 Implementation of the MDL importer class */
#include "MaterialSystem.h"
#include "HMPLoader.h"
#include "../include/DefaultLogger.h"
#include "../include/IOStream.h"
#include "../include/IOSystem.h"
#include "../include/aiMesh.h"
#include "../include/aiScene.h"
#include "../include/aiAssert.h"
#include <boost/scoped_ptr.hpp>
using namespace Assimp;
extern float g_avNormals[162][3];
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
HMPImporter::HMPImporter()
{
// nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
HMPImporter::~HMPImporter()
{
// nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool HMPImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
{
// simple check of file extension is enough for the moment
std::string::size_type pos = pFile.find_last_of('.');
// no file extension - can't read
if( pos == std::string::npos)
return false;
std::string extension = pFile.substr( pos);
if (extension.length() < 4)return false;
if (extension[0] != '.')return false;
if (extension[1] != 'h' && extension[1] != 'H')return false;
if (extension[2] != 'm' && extension[2] != 'M')return false;
if (extension[3] != 'p' && extension[3] != 'P')return false;
return true;
}
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
void HMPImporter::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 HMP file " + pFile + ".");
}
// check whether the ply file is large enough to contain
// at least the file header
size_t fileSize = file->FileSize();
if( fileSize < 50)
{
throw new ImportErrorException( ".hmp File is too small.");
}
// allocate storage and copy the contents of the file to a memory buffer
this->pScene = pScene;
this->pIOHandler = pIOHandler;
this->mBuffer = new unsigned char[fileSize+1];
file->Read( (void*)mBuffer, 1, fileSize);
this->iFileSize = (unsigned int)fileSize;
// determine the file subtype and call the appropriate member function
uint32_t iMagic = *((uint32_t*)this->mBuffer);
try {
// HMP4 format
if (AI_HMP_MAGIC_NUMBER_LE_4 == iMagic ||
AI_HMP_MAGIC_NUMBER_BE_4 == iMagic)
{
DefaultLogger::get()->debug("HMP subtype: 3D GameStudio A4, magic word is HMP4");
this->InternReadFile_HMP4();
}
// HMP5 format
else if (AI_HMP_MAGIC_NUMBER_LE_5 == iMagic ||
AI_HMP_MAGIC_NUMBER_BE_5 == iMagic)
{
DefaultLogger::get()->debug("HMP subtype: 3D GameStudio A5, magic word is HMP5");
this->InternReadFile_HMP5();
}
// HMP7 format
else if (AI_HMP_MAGIC_NUMBER_LE_7 == iMagic ||
AI_HMP_MAGIC_NUMBER_BE_7 == iMagic)
{
DefaultLogger::get()->debug("HMP subtype: 3D GameStudio A7, magic word is HMP7");
this->InternReadFile_HMP7();
}
else
{
// we're definitely unable to load this file
throw new ImportErrorException( "Unknown HMP subformat " + pFile +
". Magic word is not known");
}
} catch (ImportErrorException* ex) {
delete[] this->mBuffer;
throw ex;
}
// delete the file buffer
delete[] this->mBuffer;
return;
}
// ------------------------------------------------------------------------------------------------
void HMPImporter::InternReadFile_HMP4( )
{
throw new ImportErrorException("HMP4 is currently not supported");
}
// ------------------------------------------------------------------------------------------------
void HMPImporter::InternReadFile_HMP5( )
{
throw new ImportErrorException("HMP4 is currently not supported");
}
// ------------------------------------------------------------------------------------------------
void HMPImporter::InternReadFile_HMP7( )
{
if (120 > this->iFileSize)
{
throw new ImportErrorException("HMP7 file is too small (header size is "
"120 bytes, this file is smaller)");
}
// read the file header and skip everything to byte 84
const HMP::Header_HMP5* pcHeader = (const HMP::Header_HMP5*)this->mBuffer;
const unsigned char* szCurrent = (const unsigned char*)(this->mBuffer+84);
if (!pcHeader->ftrisize_x || !pcHeader->ftrisize_y ||
pcHeader->fnumverts_x < 1.0f || (pcHeader->numverts/pcHeader->fnumverts_x) < 1.0f ||
!pcHeader->numframes)
{
throw new ImportErrorException("One or more of the values in the HMP7 "
"file header are invalid.");
}
// generate an output mesh
this->pScene->mNumMeshes = 1;
this->pScene->mMeshes = new aiMesh*[1];
aiMesh* pcMesh = this->pScene->mMeshes[0] = new aiMesh();
pcMesh->mMaterialIndex = 0;
pcMesh->mVertices = new aiVector3D[pcHeader->numverts];
pcMesh->mNormals = new aiVector3D[pcHeader->numverts];
const unsigned int height = (unsigned int)(pcHeader->numverts / pcHeader->fnumverts_x);
const unsigned int width = (unsigned int)pcHeader->fnumverts_x;
// we don't need to generate texture coordinates if
// we have no textures in the file ...
if (pcHeader->numskins)
{
pcMesh->mTextureCoords[0] = new aiVector3D[pcHeader->numverts];
pcMesh->mNumUVComponents[0] = 2;
// now read the first skin and skip all others
this->ReadFirstSkin(pcHeader->numskins,szCurrent,&szCurrent);
}
else
{
// generate a default material
const int iMode = (int)aiShadingMode_Gouraud;
MaterialHelper* pcHelper = new MaterialHelper();
pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
aiColor3D clr;
clr.b = clr.g = clr.r = 0.7f;
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
clr.b = clr.g = clr.r = 0.05f;
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
aiString szName;
szName.Set(AI_DEFAULT_MATERIAL_NAME);
pcHelper->AddProperty(&szName,AI_MATKEY_NAME);
// add the material to the scene
this->pScene->mNumMaterials = 1;
this->pScene->mMaterials = new aiMaterial*[1];
this->pScene->mMaterials[0] = pcHelper;
}
// goto offset 120, I don't know why ...
// (fixme) is this the frame header? I assume yes since it starts
// with 2.
szCurrent += 36;
this->SizeCheck(szCurrent + sizeof(const HMP::Vertex_HMP7)*height*width);
// now load all vertices from the file
aiVector3D* pcVertOut = pcMesh->mVertices;
aiVector3D* pcNorOut = pcMesh->mNormals;
const HMP::Vertex_HMP7* src = (const HMP::Vertex_HMP7*) szCurrent;
for (unsigned int y = 0; y < height;++y)
{
for (unsigned int x = 0; x < width;++x)
{
pcVertOut->x = x * pcHeader->ftrisize_x;
pcVertOut->y = y * pcHeader->ftrisize_y;
// FIXME: What exctly is the correct scaling factor to use?
// possibly pcHeader->scale_origin[2] in combination with a
// signed interpretation of src->z?
pcVertOut->z = (((float)src->z / 0xffff)-0.5f) * pcHeader->ftrisize_x * 8.0f;
pcNorOut->x = ((float)src->normal_x / 0x80 ); // * pcHeader->scale_origin[0];
pcNorOut->y = ((float)src->normal_y / 0x80 ); // * pcHeader->scale_origin[1];
pcNorOut->z = 1.0f;
pcNorOut->Normalize();
++pcVertOut;++pcNorOut;++src;
}
}
// generate texture coordinates if necessary
if (pcHeader->numskins)
{
this->GenerateTextureCoords(width,height);
}
// now build a list of faces
const unsigned int iNumSquares = (width-1) * (height-1);
pcMesh->mNumFaces = iNumSquares << 1;
pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
pcMesh->mNumVertices = pcMesh->mNumFaces*3;
aiVector3D* pcVertices = new aiVector3D[pcMesh->mNumVertices];
aiVector3D* pcNormals = new aiVector3D[pcMesh->mNumVertices];
aiFace* pcFaceOut(pcMesh->mFaces);
pcVertOut = pcVertices;
pcNorOut = pcNormals;
aiVector3D* pcUVs = pcMesh->mTextureCoords[0] ? new aiVector3D[pcMesh->mNumVertices] : NULL;
aiVector3D* pcUVOut(pcUVs);
unsigned int iCurrent = 0;
for (unsigned int y = 0; y < height-1;++y)
{
for (unsigned int x = 0; x < width-1;++x)
{
// first triangle of the square
pcFaceOut->mNumIndices = 3;
pcFaceOut->mIndices = new unsigned int[3];
*pcVertOut++ = pcMesh->mVertices[y*width+x];
*pcVertOut++ = pcMesh->mVertices[y*width+x+1];
*pcVertOut++ = pcMesh->mVertices[(y+1)*width+x];
*pcNorOut++ = pcMesh->mNormals[y*width+x];
*pcNorOut++ = pcMesh->mNormals[y*width+x+1];
*pcNorOut++ = pcMesh->mNormals[(y+1)*width+x];
if (pcMesh->mTextureCoords[0])
{
*pcUVOut++ = pcMesh->mTextureCoords[0][y*width+x];
*pcUVOut++ = pcMesh->mTextureCoords[0][y*width+x+1];
*pcUVOut++ = pcMesh->mTextureCoords[0][(y+1)*width+x];
}
pcFaceOut->mIndices[2] = iCurrent++;
pcFaceOut->mIndices[1] = iCurrent++;
pcFaceOut->mIndices[0] = iCurrent++;
++pcFaceOut;
// second triangle of the square
pcFaceOut->mNumIndices = 3;
pcFaceOut->mIndices = new unsigned int[3];
*pcVertOut++ = pcMesh->mVertices[(y+1)*width+x];
*pcVertOut++ = pcMesh->mVertices[y*width+x+1];
*pcVertOut++ = pcMesh->mVertices[(y+1)*width+x+1];
*pcNorOut++ = pcMesh->mNormals[(y+1)*width+x];
*pcNorOut++ = pcMesh->mNormals[y*width+x+1];
*pcNorOut++ = pcMesh->mNormals[(y+1)*width+x+1];
if (pcMesh->mTextureCoords[0])
{
*pcUVOut++ = pcMesh->mTextureCoords[0][(y+1)*width+x];
*pcUVOut++ = pcMesh->mTextureCoords[0][y*width+x+1];
*pcUVOut++ = pcMesh->mTextureCoords[0][(y+1)*width+x+1];
}
pcFaceOut->mIndices[2] = iCurrent++;
pcFaceOut->mIndices[1] = iCurrent++;
pcFaceOut->mIndices[0] = iCurrent++;
++pcFaceOut;
}
}
delete[] pcMesh->mVertices;
pcMesh->mVertices = pcVertices;
delete[] pcMesh->mNormals;
pcMesh->mNormals = pcNormals;
if (pcMesh->mTextureCoords[0])
{
delete[] pcMesh->mTextureCoords[0];
pcMesh->mTextureCoords[0] = pcUVs;
}
// there is no nodegraph in HMP files. Simply assign the one mesh
// (no, not the one ring) to the root node
this->pScene->mRootNode = new aiNode();
this->pScene->mRootNode->mName.Set("terrain_root");
this->pScene->mRootNode->mNumMeshes = 1;
this->pScene->mRootNode->mMeshes = new unsigned int[1];
this->pScene->mRootNode->mMeshes[0] = 0;
return;
}
// ------------------------------------------------------------------------------------------------
void HMPImporter::ReadFirstSkin(unsigned int iNumSkins, const unsigned char* szCursor,
const unsigned char** szCursorOut)
{
ai_assert(0 != iNumSkins && NULL != szCursor);
// read the type of the skin ...
// sometimes we need to skip 12 bytes here, I don't know why ...
uint32_t iType = *((uint32_t*)szCursor);szCursor += sizeof(uint32_t);
if (0 == iType)
{
DefaultLogger::get()->warn("Skin type is 0. Skipping 12 bytes to "
"the next valid value, which seems to be the real skin type. "
"However, it is not known whether or not this is correct.");
szCursor += sizeof(uint32_t) * 2;
iType = *((uint32_t*)szCursor);szCursor += sizeof(uint32_t);
if (0 == iType)
{
throw new ImportErrorException("Unable to read HMP7 skin chunk");
}
}
// read width and height
uint32_t iWidth = *((uint32_t*)szCursor);szCursor += sizeof(uint32_t);
uint32_t iHeight = *((uint32_t*)szCursor);szCursor += sizeof(uint32_t);
// allocate an output material
MaterialHelper* pcMat = new MaterialHelper();
// read the skin, this works exactly as for MDL7
this->ParseSkinLump_3DGS_MDL7(szCursor,&szCursor,
pcMat,iType,iWidth,iHeight);
// now we need to skip any other skins ...
for (unsigned int i = 1; i< iNumSkins;++i)
{
iType = *((uint32_t*)szCursor);szCursor += sizeof(uint32_t);
iWidth = *((uint32_t*)szCursor);szCursor += sizeof(uint32_t);
iHeight = *((uint32_t*)szCursor);szCursor += sizeof(uint32_t);
this->SkipSkinLump_3DGS_MDL7(szCursor,&szCursor,
iType,iWidth,iHeight);
this->SizeCheck(szCursor);
}
// setup the material ...
this->pScene->mNumMaterials = 1;
this->pScene->mMaterials = new aiMaterial*[1];
this->pScene->mMaterials[0] = pcMat;
*szCursorOut = szCursor;
return;
}
// ------------------------------------------------------------------------------------------------
void HMPImporter::GenerateTextureCoords(
const unsigned int width, const unsigned int height)
{
ai_assert(NULL != this->pScene->mMeshes && NULL != this->pScene->mMeshes[0] &&
NULL != this->pScene->mMeshes[0]->mTextureCoords[0]);
aiVector3D* uv = this->pScene->mMeshes[0]->mTextureCoords[0];
const float fX = (1.0f / height) + (1.0f / height) / (height-1);
const float fY = (1.0f / width) + (1.0f / width) / (width-1);
for (unsigned int y = 0; y < height;++y)
{
for (unsigned int x = 0; x < width;++x)
{
uv->x = fX*x;
uv->y = 1.0f-fY*y;
++uv;
}
}
return;
}

208
code/HMPLoader.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 Definition of HMP importer class
//!
#ifndef AI_HMPLOADER_H_INCLUDED
#define AI_HMPLOADER_H_INCLUDED
#include "BaseImporter.h"
#include "../include/aiTypes.h"
#include "../include/aiTexture.h"
#include "../include/aiMaterial.h"
struct aiNode;
#include "MDLLoader.h"
namespace Assimp
{
class MaterialHelper;
#define AI_HMP_MAGIC_NUMBER_BE_4 'HMP4'
#define AI_HMP_MAGIC_NUMBER_LE_4 '4PMH'
#define AI_HMP_MAGIC_NUMBER_BE_5 'HMP5'
#define AI_HMP_MAGIC_NUMBER_LE_5 '5PMH'
#define AI_HMP_MAGIC_NUMBER_BE_7 'HMP7'
#define AI_HMP_MAGIC_NUMBER_LE_7 '7PMH'
namespace HMP
{
// ---------------------------------------------------------------------------
/** Data structure for the header of a HMP5 file.
* This is also used by HMP4 and HMP7, but with modifications
*/
struct Header_HMP5
{
int8_t ident[4]; // "HMP5"
int32_t version;
// ignored
float scale[3];
float scale_origin[3];
float boundingradius;
//! Size of one triangle in x direction
float ftrisize_x;
//! Size of one triangle in y direction
float ftrisize_y;
//! Number of vertices in x direction
float fnumverts_x;
//! Number of skins in the file
int32_t numskins;
// can ignore this?
int32_t skinwidth;
int32_t skinheight;
//!Number of vertices in the file
int32_t numverts;
// ignored and zero
int32_t numtris;
//! only one supported ...
int32_t numframes;
//! Always 0 ...
int32_t num_stverts;
int32_t flags;
float size;
};
// ---------------------------------------------------------------------------
/** Data structure for a terrain vertex in a HMP7 file
*/
struct Vertex_HMP7
{
uint16_t z;
int8_t normal_x,normal_y;
};
}; //! namespace HMP
// ---------------------------------------------------------------------------
/** Used to load 3D GameStudio HMP files (terrains)
*/
class HMPImporter : public MDLImporter
{
friend class Importer;
protected:
/** Constructor to be privately used by Importer */
HMPImporter();
/** Destructor, private as well */
~HMPImporter();
public:
// -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file.
* See BaseImporter::CanRead() for details. */
bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const;
protected:
// -------------------------------------------------------------------
/** Called by Importer::GetExtensionList() for each loaded importer.
* See BaseImporter::GetExtensionList() for details
*/
void GetExtensionList(std::string& append)
{
append.append("*.hmp");
}
// -------------------------------------------------------------------
/** Imports the given file into the given scene structure.
* See BaseImporter::InternReadFile() for details
*/
void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler);
protected:
// -------------------------------------------------------------------
/** Import a HMP4 file
*/
void InternReadFile_HMP4( );
// -------------------------------------------------------------------
/** Import a HMP5 file
*/
void InternReadFile_HMP5( );
// -------------------------------------------------------------------
/** Import a HMP7 file
*/
void InternReadFile_HMP7( );
// -------------------------------------------------------------------
/** Generate planar texture coordinates for a terrain
* \param width Width of the terrain, in vertices
* \param height Height of the terrain, in vertices
*/
void GenerateTextureCoords(const unsigned int width,
const unsigned int height);
// -------------------------------------------------------------------
/** Read the first skin from the file and skip all others ...
* \param iNumSkins Number of skins in the file
* \param szCursor Position of the first skin (offset 84)
*/
void ReadFirstSkin(unsigned int iNumSkins, const unsigned char* szCursor,
const unsigned char** szCursorOut);
private:
};
}; // end of namespace Assimp
#endif // AI_HMPIMPORTER_H_INC

View File

@ -54,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "DefaultIOStream.h" #include "DefaultIOStream.h"
#include "DefaultIOSystem.h" #include "DefaultIOSystem.h"
// Importers
#if (!defined AI_BUILD_NO_X_IMPORTER) #if (!defined AI_BUILD_NO_X_IMPORTER)
# include "XFileImporter.h" # include "XFileImporter.h"
#endif #endif
@ -81,18 +82,47 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#if (!defined AI_BUILD_NO_OBJ_IMPORTER) #if (!defined AI_BUILD_NO_OBJ_IMPORTER)
# include "ObjFileImporter.h" # include "ObjFileImporter.h"
#endif #endif
#if (!defined AI_BUILD_NO_HMP_IMPORTER)
# include "HMPLoader.h"
#endif
#if (!defined AI_BUILD_NO_SMD_IMPORTER)
# include "SMDLoader.h"
#endif
#include "CalcTangentsProcess.h" // PostProcess-Steps
#include "JoinVerticesProcess.h" #if (!defined AI_BUILD_NO_CALCTANGENTS_PROCESS)
#include "ConvertToLHProcess.h" # include "CalcTangentsProcess.h"
#include "TriangulateProcess.h" #endif
#include "GenFaceNormalsProcess.h" #if (!defined AI_BUILD_NO_JOINVERTICES_PROCESS)
#include "GenVertexNormalsProcess.h" # include "JoinVerticesProcess.h"
#include "KillNormalsProcess.h" #endif
#include "SplitLargeMeshes.h" #if (!defined AI_BUILD_NO_CONVERTTOLH_PROCESS)
#include "PretransformVertices.h" # include "ConvertToLHProcess.h"
#include "LimitBoneWeightsProcess.h" #endif
#include "ValidateDataStructure.h" #if (!defined AI_BUILD_NO_TRIANGULATE_PROCESS)
# include "TriangulateProcess.h"
#endif
#if (!defined AI_BUILD_NO_GENFACENORMALS_PROCESS)
# include "GenFaceNormalsProcess.h"
#endif
#if (!defined AI_BUILD_NO_GENVERTEXNORMALS_PROCESS)
# include "GenVertexNormalsProcess.h"
#endif
#if (!defined AI_BUILD_NO_KILLNORMALS_PROCESS)
# include "KillNormalsProcess.h"
#endif
#if (!defined AI_BUILD_NO_SPLITLARGEMESHES_PROCESS)
# include "SplitLargeMeshes.h"
#endif
#if (!defined AI_BUILD_NO_PRETRANSFORMVERTICES_PROCESS)
# include "PretransformVertices.h"
#endif
#if (!defined AI_BUILD_NO_LIMITBONEWEIGHTS_PROCESS)
# include "LimitBoneWeightsProcess.h"
#endif
#if (!defined AI_BUILD_NO_VALIDATEDS_PROCESS)
# include "ValidateDataStructure.h"
#endif
using namespace Assimp; using namespace Assimp;
@ -105,6 +135,7 @@ Importer::Importer() :
{ {
// allocate a default IO handler // allocate a default IO handler
mIOHandler = new DefaultIOSystem; mIOHandler = new DefaultIOSystem;
mIsDefaultHandler = true;
// add an instance of each worker class here // add an instance of each worker class here
#if (!defined AI_BUILD_NO_X_IMPORTER) #if (!defined AI_BUILD_NO_X_IMPORTER)
@ -134,20 +165,51 @@ Importer::Importer() :
#if (!defined AI_BUILD_NO_ASE_IMPORTER) #if (!defined AI_BUILD_NO_ASE_IMPORTER)
mImporter.push_back( new ASEImporter()); mImporter.push_back( new ASEImporter());
#endif #endif
#if (!defined AI_BUILD_NO_HMP_IMPORTER)
mImporter.push_back( new HMPImporter());
#endif
#if (!defined AI_BUILD_NO_SMD_IMPORTER)
mImporter.push_back( new SMDImporter());
#endif
// add an instance of each post processing step here in the order of sequence it is executed // add an instance of each post processing step here in the order
// of sequence it is executed
#if (!defined AI_BUILD_NO_VALIDATEDS_PROCESS)
mPostProcessingSteps.push_back( new ValidateDSProcess()); mPostProcessingSteps.push_back( new ValidateDSProcess());
#endif
#if (!defined AI_BUILD_NO_TRIANGULATE_PROCESS)
mPostProcessingSteps.push_back( new TriangulateProcess()); mPostProcessingSteps.push_back( new TriangulateProcess());
#endif
#if (!defined AI_BUILD_NO_PRETRANSFORMVERTICES_PROCESS)
mPostProcessingSteps.push_back( new PretransformVertices()); mPostProcessingSteps.push_back( new PretransformVertices());
#endif
#if (!defined AI_BUILD_NO_SPLITLARGEMESHES_PROCESS)
mPostProcessingSteps.push_back( new SplitLargeMeshesProcess_Triangle()); mPostProcessingSteps.push_back( new SplitLargeMeshesProcess_Triangle());
#endif
#if (!defined AI_BUILD_NO_KILLNORMALS_PROCESS)
mPostProcessingSteps.push_back( new KillNormalsProcess()); mPostProcessingSteps.push_back( new KillNormalsProcess());
#endif
#if (!defined AI_BUILD_NO_GENFACENORMALS_PROCESS)
mPostProcessingSteps.push_back( new GenFaceNormalsProcess()); mPostProcessingSteps.push_back( new GenFaceNormalsProcess());
#endif
#if (!defined AI_BUILD_NO_GENVERTEXNORMALS_PROCESS)
mPostProcessingSteps.push_back( new GenVertexNormalsProcess()); mPostProcessingSteps.push_back( new GenVertexNormalsProcess());
#endif
#if (!defined AI_BUILD_NO_CALCTANGENTS_PROCESS)
mPostProcessingSteps.push_back( new CalcTangentsProcess()); mPostProcessingSteps.push_back( new CalcTangentsProcess());
#endif
#if (!defined AI_BUILD_NO_JOINVERTICES_PROCESS)
mPostProcessingSteps.push_back( new JoinVerticesProcess()); mPostProcessingSteps.push_back( new JoinVerticesProcess());
#endif
#if (!defined AI_BUILD_NO_SPLITLARGEMESHES_PROCESS)
mPostProcessingSteps.push_back( new SplitLargeMeshesProcess_Vertex()); mPostProcessingSteps.push_back( new SplitLargeMeshesProcess_Vertex());
#endif
#if (!defined AI_BUILD_NO_CONVERTTOLH_PROCESS)
mPostProcessingSteps.push_back( new ConvertToLHProcess()); mPostProcessingSteps.push_back( new ConvertToLHProcess());
#endif
#if (!defined AI_BUILD_NO_LIMITBONEWEIGHTS_PROCESS)
mPostProcessingSteps.push_back( new LimitBoneWeightsProcess()); mPostProcessingSteps.push_back( new LimitBoneWeightsProcess());
#endif
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -170,19 +232,31 @@ Importer::~Importer()
// Supplies a custom IO handler to the importer to open and access files. // Supplies a custom IO handler to the importer to open and access files.
void Importer::SetIOHandler( IOSystem* pIOHandler) void Importer::SetIOHandler( IOSystem* pIOHandler)
{ {
if (NULL == pIOHandler) if (!pIOHandler)
{ {
delete mIOHandler; delete mIOHandler;
mIOHandler = new DefaultIOSystem(); mIOHandler = new DefaultIOSystem();
mIsDefaultHandler = true;
} }
else if (mIOHandler != pIOHandler) else if (mIOHandler != pIOHandler)
{ {
delete mIOHandler; delete mIOHandler;
mIOHandler = pIOHandler; mIOHandler = pIOHandler;
mIsDefaultHandler = false;
} }
return; return;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
IOSystem* Importer::GetIOHandler()
{
return mIOHandler;
}
// ------------------------------------------------------------------------------------------------
bool Importer::IsDefaultIOHandler()
{
return mIsDefaultHandler;
}
// ------------------------------------------------------------------------------------------------
// Validate post process step flags // Validate post process step flags
bool ValidateFlags(unsigned int pFlags) bool ValidateFlags(unsigned int pFlags)
{ {

View File

@ -1,20 +1,80 @@
/*
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.
----------------------------------------------------------------------
*/
/** Implementation of the LimitBoneWeightsProcess post processing step */ /** Implementation of the LimitBoneWeightsProcess post processing step */
#include <vector> #include <vector>
#include <assert.h> #include <assert.h>
#include "LimitBoneWeightsProcess.h" #include "LimitBoneWeightsProcess.h"
#include "../include/aiPostProcess.h" #include "../include/aiPostProcess.h"
#include "../include/aiMesh.h" #include "../include/aiMesh.h"
#include "../include/aiScene.h" #include "../include/aiScene.h"
#include "../include/DefaultLogger.h"
using namespace Assimp; using namespace Assimp;
/*static*/ unsigned int LimitBoneWeightsProcess::mMaxWeights = AI_LMW_MAX_WEIGHTS;
extern "C" {
// ------------------------------------------------------------------------------------------------
aiReturn aiSetBoneWeightLimit(unsigned int pLimit)
{
if (0 == pLimit)
{
LimitBoneWeightsProcess::mMaxWeights = 0xFFFFFFFF;
return AI_FAILURE;
}
LimitBoneWeightsProcess::mMaxWeights = pLimit;
DefaultLogger::get()->debug("aiSetBoneWeightLimit() - bone weight limit was changed");
return AI_SUCCESS;
}
};
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
LimitBoneWeightsProcess::LimitBoneWeightsProcess() LimitBoneWeightsProcess::LimitBoneWeightsProcess()
{ {
// TODO: (thom) make this configurable from somewhere?
mMaxWeights = 4;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -1,3 +1,43 @@
/*
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.
----------------------------------------------------------------------
*/
/** Defines a post processing step to limit the number of bones affecting a single vertex. */ /** Defines a post processing step to limit the number of bones affecting a single vertex. */
#ifndef AI_LIMITBONEWEIGHTSPROCESS_H_INC #ifndef AI_LIMITBONEWEIGHTSPROCESS_H_INC
#define AI_LIMITBONEWEIGHTSPROCESS_H_INC #define AI_LIMITBONEWEIGHTSPROCESS_H_INC
@ -9,6 +49,18 @@ struct aiMesh;
namespace Assimp namespace Assimp
{ {
// NOTE: If you change these limits, don't forget to change the
// corresponding values in all Assimp ports
// **********************************************************
// Java: PostProcessStep.java,
// PostProcessStep.DEFAULT_BONE_WEIGHT_LIMIT
// **********************************************************
#if (!defined AI_LMW_MAX_WEIGHTS)
# define AI_LMW_MAX_WEIGHTS 0x4
#endif // !! AI_LMW_MAX_WEIGHTS
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** This post processing step limits the number of bones affecting a vertex /** This post processing step limits the number of bones affecting a vertex
* to a certain maximum value. If a vertex is affected by more than that number * to a certain maximum value. If a vertex is affected by more than that number
@ -58,12 +110,14 @@ protected:
float mWeight; ///< Weight of that bone on this vertex float mWeight; ///< Weight of that bone on this vertex
Weight() { } Weight() { }
Weight( unsigned int pBone, float pWeight) { mBone = pBone; mWeight = pWeight; } Weight( unsigned int pBone, float pWeight) { mBone = pBone; mWeight = pWeight; }
/** Comparision operator to sort bone weights by descending weight */ /** Comparision operator to sort bone weights by descending weight */
bool operator < (const Weight& pWeight) const { return mWeight > pWeight.mWeight; } bool operator < (const Weight& pWeight) const { return mWeight > pWeight.mWeight; }
}; };
public:
/** Maximum number of bones influencing any single vertex. */ /** Maximum number of bones influencing any single vertex. */
unsigned int mMaxWeights; static unsigned int mMaxWeights;
}; };
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -80,34 +80,33 @@ namespace MD2
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \brief Data structure for the MD2 main header /** \brief Data structure for the MD2 main header
*/ */
// ---------------------------------------------------------------------------
struct Header struct Header
{ {
int32_t magic; uint32_t magic;
int32_t version; uint32_t version;
int32_t skinWidth; uint32_t skinWidth;
int32_t skinHeight; uint32_t skinHeight;
int32_t frameSize; uint32_t frameSize;
int32_t numSkins; uint32_t numSkins;
int32_t numVertices; uint32_t numVertices;
int32_t numTexCoords; uint32_t numTexCoords;
int32_t numTriangles; uint32_t numTriangles;
int32_t numGlCommands; uint32_t numGlCommands;
int32_t numFrames; uint32_t numFrames;
int32_t offsetSkins; uint32_t offsetSkins;
int32_t offsetTexCoords; uint32_t offsetTexCoords;
int32_t offsetTriangles; uint32_t offsetTriangles;
int32_t offsetFrames; uint32_t offsetFrames;
int32_t offsetGlCommands; uint32_t offsetGlCommands;
int32_t offsetEnd; uint32_t offsetEnd;
} PACK_STRUCT; } PACK_STRUCT;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \brief Data structure for a MD2 OpenGl draw command /** \brief Data structure for a MD2 OpenGl draw command
*/ */
// ---------------------------------------------------------------------------
struct GLCommand struct GLCommand
{ {
float s, t; float s, t;
@ -117,7 +116,6 @@ struct GLCommand
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \brief Data structure for a MD2 triangle /** \brief Data structure for a MD2 triangle
*/ */
// ---------------------------------------------------------------------------
struct Triangle struct Triangle
{ {
uint16_t vertexIndices[3]; uint16_t vertexIndices[3];
@ -127,7 +125,6 @@ struct Triangle
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \brief Data structure for a MD2 vertex /** \brief Data structure for a MD2 vertex
*/ */
// ---------------------------------------------------------------------------
struct Vertex struct Vertex
{ {
uint8_t vertex[3]; uint8_t vertex[3];
@ -137,7 +134,6 @@ struct Vertex
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \brief Data structure for a MD2 frame /** \brief Data structure for a MD2 frame
*/ */
// ---------------------------------------------------------------------------
struct Frame struct Frame
{ {
float scale[3]; float scale[3];
@ -149,7 +145,6 @@ struct Frame
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \brief Data structure for a MD2 texture coordinate /** \brief Data structure for a MD2 texture coordinate
*/ */
// ---------------------------------------------------------------------------
struct TexCoord struct TexCoord
{ {
int16_t s; int16_t s;
@ -159,7 +154,6 @@ struct TexCoord
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \brief Data structure for a MD2 skin /** \brief Data structure for a MD2 skin
*/ */
// ---------------------------------------------------------------------------
struct Skin struct Skin
{ {
char name[AI_MD2_MAXQPATH]; /* texture file name */ char name[AI_MD2_MAXQPATH]; /* texture file name */
@ -171,6 +165,14 @@ struct Skin
#endif #endif
#undef PACK_STRUCT #undef PACK_STRUCT
// ---------------------------------------------------------------------------
//! Lookup a normal vector from Quake's normal lookup table
//! \param index Input index (0-161)
//! \param vOut Receives the output normal
void LookupNormalIndex(uint8_t index,aiVector3D& vOut);
}; };
}; };

View File

@ -42,40 +42,42 @@ 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 "MD2NormalTable.h" // shouldn't be included by other units
#include "MD2NormalTable.h"
#include "../include/IOStream.h" #include "../include/IOStream.h"
#include "../include/IOSystem.h" #include "../include/IOSystem.h"
#include "../include/aiMesh.h" #include "../include/aiMesh.h"
#include "../include/aiScene.h" #include "../include/aiScene.h"
#include "../include/aiAssert.h" #include "../include/aiAssert.h"
#include "../include/DefaultLogger.h"
#include <boost/scoped_ptr.hpp> #include <boost/scoped_ptr.hpp>
using namespace Assimp; using namespace Assimp;
using namespace Assimp::MD2;
// helper macro to determine the size of an array
#if (!defined ARRAYSIZE)
# define ARRAYSIZE(_array) (int(sizeof(_array) / sizeof(_array[0])))
#endif
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
inline bool is_qnan(float p_fIn) // Helper function to lookup a normal in Quake 2's precalculated table
void MD2::LookupNormalIndex(uint8_t iNormalIndex,aiVector3D& vOut)
{ {
// NOTE: Comparison against qnan is generally problematic // make sure the normal index has a valid value
// because qnan == qnan is false AFAIK if (iNormalIndex >= ARRAYSIZE(g_avNormals))
union FTOINT
{ {
float fFloat; DefaultLogger::get()->warn("Index overflow in MDL7 normal vector list (the "
int32_t iInt; " LUT has only 162 entries). ");
} one, two;
one.fFloat = std::numeric_limits<float>::quiet_NaN();
two.fFloat = p_fIn;
return (one.iInt == two.iInt); iNormalIndex = ARRAYSIZE(g_avNormals) - 1;
} }
// ------------------------------------------------------------------------------------------------ vOut = *((const aiVector3D*)(&g_avNormals[iNormalIndex]));
inline bool is_not_qnan(float p_fIn)
{
return !is_qnan(p_fIn);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
MD2Importer::MD2Importer() MD2Importer::MD2Importer()
@ -99,12 +101,43 @@ bool MD2Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
return false; return false;
std::string extension = pFile.substr( pos); std::string extension = pFile.substr( pos);
// not brilliant but working ;-) if (extension.length() < 4)return false;
if( extension == ".md2" || extension == ".MD2" || if (extension[0] != '.')return false;
extension == ".mD2" || extension == ".Md2") if (extension[1] != 'm' && extension[1] != 'M')return false;
return true; if (extension[2] != 'd' && extension[2] != 'D')return false;
if (extension[3] != '2')return false;
return false; return true;
}
// ------------------------------------------------------------------------------------------------
// Validate the file header
void MD2Importer::ValidateHeader( )
{
/* to be validated:
int32_t offsetSkins;
int32_t offsetTexCoords;
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 ||
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");
delete[] this->mBuffer;
}
if (this->m_pcHeader->numSkins > AI_MD2_MAX_SKINS)
DefaultLogger::get()->warn("The model contains more skins than Quake 2 supports");
if ( this->m_pcHeader->numFrames > AI_MD2_MAX_FRAMES)
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");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
@ -121,10 +154,10 @@ void MD2Importer::InternReadFile(
// 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
size_t fileSize = 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.");
} }
// 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
@ -137,22 +170,26 @@ void MD2Importer::InternReadFile(
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;
throw new ImportErrorException( "Invalid md2 file: Magic bytes not found"); throw new ImportErrorException( "Invalid md2 file: Magic bytes not found");
} }
// check file format version // check file format version
if (this->m_pcHeader->version != 8) if (this->m_pcHeader->version != 8)
{ {
throw new ImportErrorException( "Unsupported md3 file version"); DefaultLogger::get()->warn( "Unsupported md2 file version. Continuing happily ...");
} }
this->ValidateHeader();
// check some values whether they are valid // check some values whether they are valid
if (0 == this->m_pcHeader->numFrames) if (0 == this->m_pcHeader->numFrames)
{ {
delete[] this->mBuffer;
throw new ImportErrorException( "Invalid md2 file: NUM_FRAMES is 0"); throw new ImportErrorException( "Invalid md2 file: NUM_FRAMES is 0");
} }
if (this->m_pcHeader->offsetEnd > (int32_t)fileSize) if (this->m_pcHeader->offsetEnd > (int32_t)fileSize)
{ {
delete[] this->mBuffer;
throw new ImportErrorException( "Invalid md2 file: File is too small"); throw new ImportErrorException( "Invalid md2 file: File is too small");
} }
@ -166,39 +203,35 @@ void MD2Importer::InternReadFile(
pScene->mMaterials[0] = new MaterialHelper(); pScene->mMaterials[0] = new MaterialHelper();
pScene->mNumMeshes = 1; pScene->mNumMeshes = 1;
pScene->mMeshes = new aiMesh*[1]; pScene->mMeshes = new aiMesh*[1];
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*) ((unsigned char*)this->m_pcHeader + const MD2::Frame* pcFrame = (const MD2::Frame*) (
this->m_pcHeader->offsetFrames); (unsigned char*)this->m_pcHeader + this->m_pcHeader->offsetFrames);
// navigate to the begin of the triangle data // navigate to the begin of the triangle data
MD2::Triangle* pcTriangles = (MD2::Triangle*) ((unsigned char*)this->m_pcHeader + MD2::Triangle* pcTriangles = (MD2::Triangle*) (
this->m_pcHeader->offsetTriangles); (unsigned char*)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*) ((unsigned char*)this->m_pcHeader + const MD2::TexCoord* pcTexCoords = (const MD2::TexCoord*) (
this->m_pcHeader->offsetTexCoords); (unsigned char*)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);
pScene->mMeshes[0]->mNumFaces = this->m_pcHeader->numTriangles; pcMesh->mNumFaces = this->m_pcHeader->numTriangles;
pScene->mMeshes[0]->mFaces = new aiFace[this->m_pcHeader->numTriangles]; pcMesh->mFaces = new aiFace[this->m_pcHeader->numTriangles];
// temporary vectors for position/texture coordinates/normals // allocate output storage
std::vector<aiVector3D> vPositions; pcMesh->mNumVertices = (unsigned int)pcMesh->mNumFaces*3;
std::vector<aiVector3D> vTexCoords; pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
std::vector<aiVector3D> vNormals; pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
vPositions.resize(pScene->mMeshes[0]->mNumFaces*3,aiVector3D());
vTexCoords.resize(pScene->mMeshes[0]->mNumFaces*3,aiVector3D(
std::numeric_limits<float>::quiet_NaN(),
std::numeric_limits<float>::quiet_NaN(),0.0f));
vNormals.resize(pScene->mMeshes[0]->mNumFaces*3,aiVector3D());
// not sure whether there are MD2 files without texture coordinates // not sure whether there are MD2 files without texture coordinates
if (0 != this->m_pcHeader->numTexCoords && 0 != this->m_pcHeader->numSkins) // NOTE: texture coordinates can be there without a texture,
// but a texture can't be there without a valid UV channel
if (this->m_pcHeader->numTexCoords && this->m_pcHeader->numSkins)
{ {
// navigate to the first texture associated with the mesh // navigate to the first texture associated with the mesh
const MD2::Skin* pcSkins = (const MD2::Skin*) ((unsigned char*)this->m_pcHeader + const MD2::Skin* pcSkins = (const MD2::Skin*) ((unsigned char*)this->m_pcHeader +
@ -216,12 +249,20 @@ void MD2Importer::InternReadFile(
clr.b = clr.g = clr.r = 0.05f; clr.b = clr.g = clr.r = 0.05f;
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT); pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
aiString szString; if (pcSkins->name[0])
const size_t iLen = strlen(pcSkins->name); {
memcpy(szString.data,pcSkins->name,iLen+1); aiString szString;
szString.length = iLen-1; const size_t iLen = ::strlen(pcSkins->name);
::memcpy(szString.data,pcSkins->name,iLen);
szString.data[iLen] = '\0';
szString.length = iLen;
pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0)); pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0));
}
else
{
DefaultLogger::get()->warn("Texture file name has zero length. It will be skipped.");
}
} }
else else
{ {
@ -237,13 +278,42 @@ void MD2Importer::InternReadFile(
clr.b = clr.g = clr.r = 0.05f; clr.b = clr.g = clr.r = 0.05f;
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT); pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
aiString szName;
szName.Set(AI_DEFAULT_MATERIAL_NAME);
pcHelper->AddProperty(&szName,AI_MATKEY_NAME);
} }
// now read all triangles of the first frame, apply scaling and translation // now read all triangles of the first frame, apply scaling and translation
unsigned int iCurrent = 0; unsigned int iCurrent = 0;
if (0 != this->m_pcHeader->numTexCoords) if (this->m_pcHeader->numTexCoords)
{ {
// allocate storage for texture coordinates, too
pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
pcMesh->mNumUVComponents[0] = 2;
// check whether the skin width or height are zero (this would
// cause a division through zero)
float fDivisorU;
if (!this->m_pcHeader->skinWidth)
{
DefaultLogger::get()->error("Skin width is zero but there are "
"valid absolute texture coordinates. Unable to compute "
"relative texture coordinates ranging from 0 to 1");
fDivisorU = 1.0f;
}
else fDivisorU = (float)this->m_pcHeader->skinWidth;
float fDivisorV;
if (!this->m_pcHeader->skinHeight)
{
DefaultLogger::get()->error("Skin height is zero but there are "
"valid absolute texture coordinates. Unable to compute "
"relative texture coordinates ranging from 0 to 1");
fDivisorV = 1.0f;
}
else fDivisorV = (float)this->m_pcHeader->skinHeight;
for (unsigned int i = 0; i < (unsigned int)this->m_pcHeader->numTriangles;++i) for (unsigned int i = 0; i < (unsigned int)this->m_pcHeader->numTriangles;++i)
{ {
@ -259,13 +329,16 @@ void MD2Importer::InternReadFile(
{ {
// validate vertex indices // validate vertex indices
if (pcTriangles[i].vertexIndices[c] >= this->m_pcHeader->numVertices) if (pcTriangles[i].vertexIndices[c] >= this->m_pcHeader->numVertices)
{
DefaultLogger::get()->error("Vertex index is outside the allowed range");
pcTriangles[i].vertexIndices[c] = this->m_pcHeader->numVertices-1; pcTriangles[i].vertexIndices[c] = this->m_pcHeader->numVertices-1;
}
// copy face indices // copy face indices
unsigned int iIndex = (unsigned int)pcTriangles[i].vertexIndices[c]; unsigned int iIndex = (unsigned int)pcTriangles[i].vertexIndices[c];
// read x,y, and z component of the vertex // read x,y, and z component of the vertex
aiVector3D& vec = vPositions[iCurrent]; aiVector3D& vec = pcMesh->mVertices[iCurrent];
vec.x = (float)pcVerts[iIndex].vertex[0] * pcFrame->scale[0]; vec.x = (float)pcVerts[iIndex].vertex[0] * pcFrame->scale[0];
vec.x += pcFrame->translate[0]; vec.x += pcFrame->translate[0];
@ -278,23 +351,28 @@ void MD2Importer::InternReadFile(
vec.y += pcFrame->translate[2]; vec.y += pcFrame->translate[2];
// read the normal vector from the precalculated normal table // read the normal vector from the precalculated normal table
vNormals[iCurrent] = *((const aiVector3D*)(&g_avNormals[std::min( aiVector3D& vNormal = pcMesh->mNormals[iCurrent];
int(pcVerts[iIndex].lightNormalIndex), LookupNormalIndex(pcVerts[iIndex].lightNormalIndex,vNormal);
int(sizeof(g_avNormals) / sizeof(g_avNormals[0]))-1)])); std::swap ( vNormal.y,vNormal.z );
std::swap ( vNormals[iCurrent].y,vNormals[iCurrent].z );
// validate texture coordinates // validate texture coordinates
if (pcTriangles[iIndex].textureIndices[c] >= this->m_pcHeader->numTexCoords) if (pcTriangles[iIndex].textureIndices[c] >= this->m_pcHeader->numTexCoords)
{
DefaultLogger::get()->error("UV index is outside the allowed range");
pcTriangles[iIndex].textureIndices[c] = this->m_pcHeader->numTexCoords-1; pcTriangles[iIndex].textureIndices[c] = this->m_pcHeader->numTexCoords-1;
}
aiVector3D* pcOut = &vTexCoords[iCurrent]; aiVector3D& pcOut = pcMesh->mTextureCoords[0][iCurrent];
float u,v; float u,v;
u = (float)pcTexCoords[pcTriangles[i].textureIndices[c]].s / this->m_pcHeader->skinWidth;
v = (float)pcTexCoords[pcTriangles[i].textureIndices[c]].t / this->m_pcHeader->skinHeight; // the texture coordinates are absolute values but we
pcOut->x = u; // need relative values between 0 and 1
pcOut->y = v; u = (float)pcTexCoords[pcTriangles[i].textureIndices[c]].s / fDivisorU;
v = (float)pcTexCoords[pcTriangles[i].textureIndices[c]].t / fDivisorV;
pcOut.x = u;
pcOut.y = 1.0f - v; // FIXME: Is this correct for MD2?
} }
// FIX: flip the face order for use with OpenGL
pScene->mMeshes[0]->mFaces[i].mIndices[0] = iTemp+2; pScene->mMeshes[0]->mFaces[i].mIndices[0] = iTemp+2;
pScene->mMeshes[0]->mFaces[i].mIndices[1] = iTemp+1; pScene->mMeshes[0]->mFaces[i].mIndices[1] = iTemp+1;
pScene->mMeshes[0]->mFaces[i].mIndices[2] = iTemp+0; pScene->mMeshes[0]->mFaces[i].mIndices[2] = iTemp+0;
@ -316,13 +394,16 @@ void MD2Importer::InternReadFile(
{ {
// validate vertex indices // validate vertex indices
if (pcTriangles[i].vertexIndices[c] >= this->m_pcHeader->numVertices) if (pcTriangles[i].vertexIndices[c] >= this->m_pcHeader->numVertices)
{
DefaultLogger::get()->error("Vertex index is outside the allowed range");
pcTriangles[i].vertexIndices[c] = this->m_pcHeader->numVertices-1; pcTriangles[i].vertexIndices[c] = this->m_pcHeader->numVertices-1;
}
// copy face indices // copy face indices
unsigned int iIndex = (unsigned int)pcTriangles[i].vertexIndices[c]; unsigned int iIndex = (unsigned int)pcTriangles[i].vertexIndices[c];
// read x,y, and z component of the vertex // read x,y, and z component of the vertex
aiVector3D& vec = vPositions[iCurrent]; aiVector3D& vec = pcMesh->mVertices[iCurrent];
vec.x = (float)pcVerts[iIndex].vertex[0] * pcFrame->scale[0]; vec.x = (float)pcVerts[iIndex].vertex[0] * pcFrame->scale[0];
vec.x += pcFrame->translate[0]; vec.x += pcFrame->translate[0];
@ -335,39 +416,17 @@ void MD2Importer::InternReadFile(
vec.y += pcFrame->translate[2]; vec.y += pcFrame->translate[2];
// read the normal vector from the precalculated normal table // read the normal vector from the precalculated normal table
vNormals[iCurrent] = *((const aiVector3D*)(&g_avNormals[std::min( aiVector3D& vNormal = pcMesh->mNormals[iCurrent];
int(pcVerts[iIndex].lightNormalIndex), LookupNormalIndex(pcVerts[iIndex].lightNormalIndex,vNormal);
int(sizeof(g_avNormals) / sizeof(g_avNormals[0]))-1)])); std::swap ( vNormal.y,vNormal.z );
std::swap ( vNormals[iCurrent].y,vNormals[iCurrent].z );
aiVector3D* pcOut = &vTexCoords[iCurrent];
pcOut->x = (float)pcTexCoords[pcTriangles[i].textureIndices[c]].s / this->m_pcHeader->skinWidth;
pcOut->y = (float)pcTexCoords[pcTriangles[i].textureIndices[c]].t / this->m_pcHeader->skinHeight;
} }
// FIX: flip the face order for use with OpenGL
pScene->mMeshes[0]->mFaces[i].mIndices[0] = iTemp+2; pScene->mMeshes[0]->mFaces[i].mIndices[0] = iTemp+2;
pScene->mMeshes[0]->mFaces[i].mIndices[1] = iTemp+1; pScene->mMeshes[0]->mFaces[i].mIndices[1] = iTemp+1;
pScene->mMeshes[0]->mFaces[i].mIndices[2] = iTemp+0; pScene->mMeshes[0]->mFaces[i].mIndices[2] = iTemp+0;
} }
} }
// delete the file buffer and return
// allocate output storage delete[] this->mBuffer;
pScene->mMeshes[0]->mNumVertices = (unsigned int)vPositions.size();
pScene->mMeshes[0]->mVertices = new aiVector3D[vPositions.size()];
pScene->mMeshes[0]->mNormals = new aiVector3D[vPositions.size()];
pScene->mMeshes[0]->mTextureCoords[0] = new aiVector3D[vPositions.size()];
// memcpy() the data to the c-syle arrays
memcpy(pScene->mMeshes[0]->mVertices, &vPositions[0],
vPositions.size() * sizeof(aiVector3D));
memcpy(pScene->mMeshes[0]->mNormals, &vNormals[0],
vPositions.size() * sizeof(aiVector3D));
if (0 != this->m_pcHeader->numTexCoords)
{
memcpy(pScene->mMeshes[0]->mTextureCoords[0], &vTexCoords[0],
vPositions.size() * sizeof(aiVector3D));
}
return; return;
} }

View File

@ -93,6 +93,12 @@ protected:
void InternReadFile( const std::string& pFile, aiScene* pScene, void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler); IOSystem* pIOHandler);
// -------------------------------------------------------------------
/** Validate the header of the file
*/
void ValidateHeader();
protected: protected:
/** Header of the MD2 file */ /** Header of the MD2 file */
@ -100,6 +106,9 @@ protected:
/** Buffer to hold the loaded file */ /** Buffer to hold the loaded file */
const unsigned char* mBuffer; const unsigned char* mBuffer;
/** Size of the file, in bytes */
unsigned int fileSize;
}; };
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -89,10 +89,10 @@ namespace MD3
struct Header struct Header
{ {
//! magic number //! magic number
int32_t IDENT; uint32_t IDENT;
//! file format version //! file format version
int32_t VERSION; uint32_t VERSION;
//! original name in .pak archive //! original name in .pak archive
unsigned char NAME[ AI_MD3_MAXQPATH ]; unsigned char NAME[ AI_MD3_MAXQPATH ];
@ -101,28 +101,28 @@ struct Header
int32_t FLAGS; int32_t FLAGS;
//! number of frames in the file //! number of frames in the file
int32_t NUM_FRAMES; uint32_t NUM_FRAMES;
//! number of tags in the file //! number of tags in the file
int32_t NUM_TAGS; uint32_t NUM_TAGS;
//! number of surfaces in the file //! number of surfaces in the file
int32_t NUM_SURFACES; uint32_t NUM_SURFACES;
//! number of skins in the file //! number of skins in the file
int32_t NUM_SKINS; uint32_t NUM_SKINS;
//! offset of the first frame //! offset of the first frame
int32_t OFS_FRAMES; uint32_t OFS_FRAMES;
//! offset of the first tag //! offset of the first tag
int32_t OFS_TAGS; uint32_t OFS_TAGS;
//! offset of the first surface //! offset of the first surface
int32_t OFS_SURFACES; uint32_t OFS_SURFACES;
//! end of file //! end of file
int32_t OFS_EOF; uint32_t OFS_EOF;
} PACK_STRUCT; } PACK_STRUCT;
@ -162,29 +162,29 @@ struct Surface
int32_t FLAGS; int32_t FLAGS;
//! number of frames in the surface //! number of frames in the surface
int32_t NUM_FRAMES; uint32_t NUM_FRAMES;
//! number of shaders in the surface //! number of shaders in the surface
int32_t NUM_SHADER; uint32_t NUM_SHADER;
//! number of vertices in the surface //! number of vertices in the surface
int32_t NUM_VERTICES; uint32_t NUM_VERTICES;
//! number of triangles in the surface //! number of triangles in the surface
int32_t NUM_TRIANGLES; uint32_t NUM_TRIANGLES;
//! offset to the triangle data //! offset to the triangle data
int32_t OFS_TRIANGLES; uint32_t OFS_TRIANGLES;
//! offset to the shader data //! offset to the shader data
int32_t OFS_SHADERS; uint32_t OFS_SHADERS;
//! offset to the texture coordinate data //! offset to the texture coordinate data
int32_t OFS_ST; uint32_t OFS_ST;
//! offset to the vertex/normal data //! offset to the vertex/normal data
int32_t OFS_XYZNORMAL; uint32_t OFS_XYZNORMAL;
//! offset to the end of the Surface object //! offset to the end of the Surface object
int32_t OFS_END; int32_t OFS_END;
@ -200,7 +200,7 @@ struct Shader
unsigned char NAME[ AI_MD3_MAXQPATH ]; unsigned char NAME[ AI_MD3_MAXQPATH ];
//! index of the shader //! index of the shader
int32_t SHADER_INDEX; uint32_t SHADER_INDEX;
} PACK_STRUCT; } PACK_STRUCT;
@ -211,7 +211,7 @@ struct Shader
struct Triangle struct Triangle
{ {
//! triangle indices //! triangle indices
int32_t INDEXES[3]; uint32_t INDEXES[3];
} PACK_STRUCT; } PACK_STRUCT;
@ -236,7 +236,7 @@ struct Vertex
int16_t X,Y,Z; int16_t X,Y,Z;
//! encoded normal vector //! encoded normal vector
int16_t NORMAL; uint16_t NORMAL;
} PACK_STRUCT; } PACK_STRUCT;
// reset packing to the original value // reset packing to the original value
@ -254,9 +254,9 @@ struct Vertex
* \note This has been taken from q3 source (misc_model.c) * \note This has been taken from q3 source (misc_model.c)
*/ */
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
inline void LatLngNormalToVec3(int16_t p_iNormal, float* p_afOut) inline void LatLngNormalToVec3(uint16_t p_iNormal, float* p_afOut)
{ {
float lat = (float)(( p_iNormal >> 8 ) & 0xff); float lat = (float)(( p_iNormal >> 8u ) & 0xff);
float lng = (float)(( p_iNormal & 0xff )); float lng = (float)(( p_iNormal & 0xff ));
lat *= 3.141926f/128.0f; lat *= 3.141926f/128.0f;
lng *= 3.141926f/128.0f; lng *= 3.141926f/128.0f;

View File

@ -49,6 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../include/aiMesh.h" #include "../include/aiMesh.h"
#include "../include/aiScene.h" #include "../include/aiScene.h"
#include "../include/aiAssert.h" #include "../include/aiAssert.h"
#include "../include/DefaultLogger.h"
#include <boost/scoped_ptr.hpp> #include <boost/scoped_ptr.hpp>
@ -78,12 +79,48 @@ bool MD3Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
return false; return false;
std::string extension = pFile.substr( pos); std::string extension = pFile.substr( pos);
// not brilliant but working ;-) if (extension.length() < 4)return false;
if( extension == ".md3" || extension == ".MD3" || if (extension[0] != '.')return false;
extension == ".mD3" || extension == ".Md3") if (extension[1] != 'm' && extension[1] != 'M')return false;
return true; if (extension[2] != 'd' && extension[2] != 'D')return false;
if (extension[3] != '3')return false;
return false; return true;
}
// ------------------------------------------------------------------------------------------------
void MD3Importer::ValidateHeaderOffsets()
{
if (this->m_pcHeader->OFS_FRAMES >= this->fileSize ||
this->m_pcHeader->OFS_SURFACES >= this->fileSize ||
this->m_pcHeader->OFS_EOF > this->fileSize)
{
delete[] this->mBuffer;
throw new ImportErrorException("Invalid MD3 header: some offsets are outside the file");
}
}
// ------------------------------------------------------------------------------------------------
void MD3Importer::ValidateSurfaceHeaderOffsets(const MD3::Surface* pcSurf)
{
// calculate the relative offset of the surface
int32_t ofs = int32_t((const unsigned char*)pcSurf-this->mBuffer);
if (pcSurf->OFS_TRIANGLES + ofs + pcSurf->NUM_TRIANGLES * sizeof(MD3::Triangle) > this->fileSize ||
pcSurf->OFS_SHADERS + ofs + pcSurf->NUM_SHADER * sizeof(MD3::Shader) > this->fileSize ||
pcSurf->OFS_ST + ofs + pcSurf->NUM_VERTICES * sizeof(MD3::TexCoord) > this->fileSize ||
pcSurf->OFS_XYZNORMAL + ofs + pcSurf->NUM_VERTICES * sizeof(MD3::Vertex) > this->fileSize)
{
delete[] this->mBuffer;
throw new ImportErrorException("Invalid MD3 surface header: some offsets are outside the file");
}
if (pcSurf->NUM_TRIANGLES > AI_MD3_MAX_TRIANGLES)
DefaultLogger::get()->warn("The model contains more triangles than Quake 3 supports");
if (pcSurf->NUM_SHADER > AI_MD3_MAX_SHADERS)
DefaultLogger::get()->warn("The model contains more shaders than Quake 3 supports");
if (pcSurf->NUM_VERTICES > AI_MD3_MAX_VERTS)
DefaultLogger::get()->warn("The model contains more vertices than Quake 3 supports");
if (pcSurf->NUM_FRAMES > AI_MD3_MAX_FRAMES)
DefaultLogger::get()->warn("The model contains more frames than Quake 3 supports");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
@ -100,7 +137,7 @@ void MD3Importer::InternReadFile(
// 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
size_t fileSize = 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.");
@ -116,28 +153,28 @@ void MD3Importer::InternReadFile(
if (this->m_pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_BE && if (this->m_pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_BE &&
this->m_pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_LE) this->m_pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_LE)
{ {
delete[] this->mBuffer;
throw new ImportErrorException( "Invalid md3 file: Magic bytes not found"); 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)
{ {
throw new ImportErrorException( "Unsupported md3 file version"); 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 (0 == this->m_pcHeader->NUM_FRAMES)
{ {
delete[] this->mBuffer;
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 (0 == this->m_pcHeader->NUM_SURFACES)
{ {
delete[] this->mBuffer;
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_EOF > (int32_t)fileSize) this->ValidateHeaderOffsets();
{
throw new ImportErrorException( "Invalid md3 file: File is too small");
}
// now navigate to the list of surfaces // now navigate to the list of surfaces
const MD3::Surface* pcSurfaces = (const MD3::Surface*) const MD3::Surface* pcSurfaces = (const MD3::Surface*)
@ -150,11 +187,19 @@ void MD3Importer::InternReadFile(
pScene->mNumMaterials = this->m_pcHeader->NUM_SURFACES; pScene->mNumMaterials = this->m_pcHeader->NUM_SURFACES;
pScene->mMaterials = new aiMaterial*[pScene->mNumMeshes]; pScene->mMaterials = new aiMaterial*[pScene->mNumMeshes];
// if an exception is thrown before the meshes are allocated ->
// otherwise the pointer value would be invalid and delete would crash
::memset(pScene->mMeshes,0,pScene->mNumMeshes*sizeof(aiMesh*));
::memset(pScene->mMaterials,0,pScene->mNumMaterials*sizeof(aiMaterial*));
unsigned int iNum = this->m_pcHeader->NUM_SURFACES; unsigned int iNum = this->m_pcHeader->NUM_SURFACES;
unsigned int iNumMaterials = 0; unsigned int iNumMaterials = 0;
unsigned int iDefaultMatIndex = 0xFFFFFFFF; unsigned int iDefaultMatIndex = 0xFFFFFFFF;
while (iNum-- > 0) while (iNum-- > 0)
{ {
// validate the surface
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); (((unsigned char*)pcSurfaces) + pcSurfaces->OFS_XYZNORMAL);
@ -171,7 +216,6 @@ void MD3Importer::InternReadFile(
const MD3::Shader* pcShaders = (const MD3::Shader*) const MD3::Shader* pcShaders = (const MD3::Shader*)
(((unsigned char*)pcSurfaces) + pcSurfaces->OFS_SHADERS); (((unsigned char*)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)
{ {
@ -185,14 +229,14 @@ void MD3Importer::InternReadFile(
aiMesh* pcMesh = pScene->mMeshes[iNum]; aiMesh* pcMesh = pScene->mMeshes[iNum];
pcMesh->mNumVertices = pcSurfaces->NUM_TRIANGLES*3; pcMesh->mNumVertices = pcSurfaces->NUM_TRIANGLES*3;
pcMesh->mNumBones = 0; //pcMesh->mNumBones = 0;
pcMesh->mColors[0] = pcMesh->mColors[1] = pcMesh->mColors[2] = pcMesh->mColors[3] = NULL; //pcMesh->mColors[0] = pcMesh->mColors[1] = pcMesh->mColors[2] = pcMesh->mColors[3] = NULL;
pcMesh->mNumFaces = pcSurfaces->NUM_TRIANGLES; pcMesh->mNumFaces = pcSurfaces->NUM_TRIANGLES;
pcMesh->mFaces = new aiFace[pcSurfaces->NUM_TRIANGLES]; pcMesh->mFaces = new aiFace[pcSurfaces->NUM_TRIANGLES];
pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices]; pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices]; pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices]; pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
pcMesh->mTextureCoords[1] = pcMesh->mTextureCoords[2] = pcMesh->mTextureCoords[3] = NULL; //pcMesh->mTextureCoords[1] = pcMesh->mTextureCoords[2] = pcMesh->mTextureCoords[3] = NULL;
pcMesh->mNumUVComponents[0] = 2; pcMesh->mNumUVComponents[0] = 2;
// fill in all triangles // fill in all triangles
@ -221,6 +265,7 @@ void MD3Importer::InternReadFile(
pcMesh->mTextureCoords[0][iCurrent].x = pcUVs[ pcTriangles->INDEXES[c]].U; pcMesh->mTextureCoords[0][iCurrent].x = pcUVs[ pcTriangles->INDEXES[c]].U;
pcMesh->mTextureCoords[0][iCurrent].y = 1.0f - pcUVs[ pcTriangles->INDEXES[c]].V; pcMesh->mTextureCoords[0][iCurrent].y = 1.0f - pcUVs[ pcTriangles->INDEXES[c]].V;
} }
// FIX: flip the face ordering for use with OpenGL
pcMesh->mFaces[i].mIndices[0] = iTemp+2; pcMesh->mFaces[i].mIndices[0] = iTemp+2;
pcMesh->mFaces[i].mIndices[1] = iTemp+1; pcMesh->mFaces[i].mIndices[1] = iTemp+1;
pcMesh->mFaces[i].mIndices[2] = iTemp+0; pcMesh->mFaces[i].mIndices[2] = iTemp+0;
@ -233,11 +278,11 @@ void MD3Importer::InternReadFile(
// make a relative path. // make a relative path.
// if the MD3's internal path itself and the given path are using // if the MD3's internal path itself and the given path are using
// the same directory remove it // the same directory remove it
const char* szEndDir1 = strrchr((const char*)this->m_pcHeader->NAME,'\\'); const char* szEndDir1 = ::strrchr((const char*)this->m_pcHeader->NAME,'\\');
if (!szEndDir1)szEndDir1 = strrchr((const char*)this->m_pcHeader->NAME,'/'); if (!szEndDir1)szEndDir1 = ::strrchr((const char*)this->m_pcHeader->NAME,'/');
const char* szEndDir2 = strrchr((const char*)pcShaders->NAME,'\\'); const char* szEndDir2 = ::strrchr((const char*)pcShaders->NAME,'\\');
if (!szEndDir2)szEndDir2 = strrchr((const char*)pcShaders->NAME,'/'); if (!szEndDir2)szEndDir2 = ::strrchr((const char*)pcShaders->NAME,'/');
if (szEndDir1 && szEndDir2) if (szEndDir1 && szEndDir2)
{ {
@ -276,7 +321,7 @@ void MD3Importer::InternReadFile(
aiString szOut; aiString szOut;
if(AI_SUCCESS == aiGetMaterialString ( (aiMaterial*)pScene->mMaterials[p], if(AI_SUCCESS == aiGetMaterialString ( (aiMaterial*)pScene->mMaterials[p],
AI_MATKEY_TEXBLEND_DIFFUSE(0),&szOut)) AI_MATKEY_TEXTURE_DIFFUSE(0),&szOut))
{ {
if (0 == ASSIMP_stricmp(szOut.data,szEndDir2)) if (0 == ASSIMP_stricmp(szOut.data,szEndDir2))
{ {
@ -294,25 +339,35 @@ void MD3Importer::InternReadFile(
if (szEndDir2) if (szEndDir2)
{ {
aiString szString; if (szEndDir2[0])
const size_t iLen = strlen(szEndDir2); {
memcpy(szString.data,szEndDir2,iLen+1); aiString szString;
szString.length = iLen-1; const size_t iLen = ::strlen(szEndDir2);
::memcpy(szString.data,szEndDir2,iLen);
szString.data[iLen] = '\0';
szString.length = iLen;
pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0)); pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0));
}
else
{
DefaultLogger::get()->warn("Texture file name has zero length. "
"It will be skipped.");
}
} }
int iMode = (int)aiShadingMode_Gouraud; int iMode = (int)aiShadingMode_Gouraud;
pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL); pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
// add a small ambient color value - Quake 3 seems to have one
aiColor3D clr; aiColor3D clr;
clr.b = clr.g = clr.r = 1.0f;
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
clr.b = clr.g = clr.r = 0.05f; clr.b = clr.g = clr.r = 0.05f;
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT); pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
aiString szName;
szName.Set(AI_DEFAULT_MATERIAL_NAME);
pcHelper->AddProperty(&szName,AI_MATKEY_NAME);
pScene->mMaterials[iNumMaterials] = (aiMaterial*)pcHelper; pScene->mMaterials[iNumMaterials] = (aiMaterial*)pcHelper;
pcMesh->mMaterialIndex = iNumMaterials++; pcMesh->mMaterialIndex = iNumMaterials++;
} }
@ -343,31 +398,27 @@ void MD3Importer::InternReadFile(
pcMesh->mMaterialIndex = iNumMaterials++; pcMesh->mMaterialIndex = iNumMaterials++;
} }
} }
// go to the next surface
pcSurfaces = (const MD3::Surface*)(((unsigned char*)pcSurfaces) + pcSurfaces->OFS_END); pcSurfaces = (const MD3::Surface*)(((unsigned char*)pcSurfaces) + pcSurfaces->OFS_END);
} }
if (0 == pScene->mNumMeshes) if (0 == pScene->mNumMeshes)
{ {
// cleanup before returning // cleanup before returning
delete pScene; delete[] this->mBuffer;
throw new ImportErrorException( "Invalid md3 file: File contains no valid mesh"); throw new ImportErrorException( "Invalid md3 file: File contains no valid mesh");
} }
pScene->mNumMaterials = iNumMaterials; pScene->mNumMaterials = iNumMaterials;
// now we need to generate an empty node graph // now we need to generate an empty node graph
pScene->mRootNode = new aiNode(); pScene->mRootNode = new aiNode();
pScene->mRootNode->mNumChildren = pScene->mNumMeshes; pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
pScene->mRootNode->mChildren = new aiNode*[pScene->mNumMeshes]; pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
for (unsigned int i = 0; i < pScene->mNumMeshes;++i) for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
{ pScene->mRootNode->mMeshes[i] = i;
pScene->mRootNode->mChildren[i] = new aiNode();
pScene->mRootNode->mChildren[i]->mParent = pScene->mRootNode;
pScene->mRootNode->mChildren[i]->mNumMeshes = 1;
pScene->mRootNode->mChildren[i]->mMeshes = new unsigned int[1];
pScene->mRootNode->mChildren[i]->mMeshes[0] = i;
}
// delete the file buffer and return
delete[] this->mBuffer; delete[] this->mBuffer;
return; return;
} }

View File

@ -96,6 +96,13 @@ protected:
void InternReadFile( const std::string& pFile, aiScene* pScene, void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler); IOSystem* pIOHandler);
// -------------------------------------------------------------------
/** Validate offsets in the header
*/
void ValidateHeaderOffsets();
void ValidateSurfaceHeaderOffsets(const MD3::Surface* pcSurfHeader);
protected: protected:
/** Header of the MD3 file */ /** Header of the MD3 file */
@ -103,6 +110,9 @@ protected:
/** Buffer to hold the loaded file */ /** Buffer to hold the loaded file */
const unsigned char* mBuffer; const unsigned char* mBuffer;
/** Size of the file, in bytes */
unsigned int fileSize;
}; };
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -109,7 +109,7 @@ void MD4Importer::InternReadFile(
size_t fileSize = file->FileSize(); size_t fileSize = file->FileSize();
if( fileSize < sizeof(MD4::Header)) if( fileSize < sizeof(MD4::Header))
{ {
throw new ImportErrorException( ".mdd File is too small."); throw new ImportErrorException( ".md4 File is too small.");
} }
return; return;
} }

View File

@ -43,8 +43,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//! @file Definition of in-memory structures for the MDL file format. //! @file Definition of in-memory structures for the MDL file format.
// //
// The specification has been taken from various sources on the internet. // The specification has been taken from various sources on the internet.
// http://tfc.duke.free.fr/coding/mdl-specs-en.html // - http://tfc.duke.free.fr/coding/mdl-specs-en.html
// - Conitec's MED SDK
// - Many quite long HEX-editor sessions
#ifndef AI_MDLFILEHELPER_H_INC #ifndef AI_MDLFILEHELPER_H_INC
#define AI_MDLFILEHELPER_H_INC #define AI_MDLFILEHELPER_H_INC
@ -67,15 +68,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# error Compiler not supported. Never do this again. # error Compiler not supported. Never do this again.
#endif #endif
namespace Assimp namespace Assimp {
{ namespace MDL {
namespace MDL
{
// magic bytes used in Quake 1 MDL meshes // magic bytes used in Quake 1 MDL meshes
#define AI_MDL_MAGIC_NUMBER_BE 'IDPO' #define AI_MDL_MAGIC_NUMBER_BE 'IDPO'
#define AI_MDL_MAGIC_NUMBER_LE 'OPDI' #define AI_MDL_MAGIC_NUMBER_LE 'OPDI'
// magic bytes used in GameStudio A<very low> MDL meshes
#define AI_MDL_MAGIC_NUMBER_BE_GS3 'MDL2'
#define AI_MDL_MAGIC_NUMBER_LE_GS3 '2LDM'
// magic bytes used in GameStudio A4 MDL meshes // magic bytes used in GameStudio A4 MDL meshes
#define AI_MDL_MAGIC_NUMBER_BE_GS4 'MDL3' #define AI_MDL_MAGIC_NUMBER_BE_GS4 'MDL3'
#define AI_MDL_MAGIC_NUMBER_LE_GS4 '3LDM' #define AI_MDL_MAGIC_NUMBER_LE_GS4 '3LDM'
@ -96,7 +99,7 @@ namespace MDL
// common limitations for Quake1 meshes. The loader does not check them, // common limitations for Quake1 meshes. The loader does not check them,
// but models should not exceed these limits. // (however it warns) but models should not exceed these limits.
#if (!defined AI_MDL_VERSION) #if (!defined AI_MDL_VERSION)
# define AI_MDL_VERSION 6 # define AI_MDL_VERSION 6
#endif #endif
@ -113,11 +116,25 @@ namespace MDL
# define AI_MDL_MAX_TRIANGLES 2048 # define AI_MDL_MAX_TRIANGLES 2048
#endif #endif
// helper macro that sets a pointer to NULL in debug builds
#if (!defined DEBUG_INVALIDATE_PTR)
# if (defined _DEBUG)
# define DEBUG_INVALIDATE_PTR(x) x = NULL;
# else
# define DEBUG_INVALIDATE_PTR(x)
# endif
#endif
// material key that is set for dummy materials that are
// just referencing another material
#if (!defined AI_MDL7_REFERRER_MATERIAL)
# define AI_MDL7_REFERRER_MATERIAL "&&&referrer&&&"
#endif
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \struct Header /** \struct Header
* \brief Data structure for the MDL main header * \brief Data structure for the MDL main header
*/ */
// ---------------------------------------------------------------------------
struct Header struct Header
{ {
//! magic number: "IDPO" //! magic number: "IDPO"
@ -157,12 +174,13 @@ struct Header
int32_t num_frames; int32_t num_frames;
//! 0 = synchron, 1 = random . Ignored //! 0 = synchron, 1 = random . Ignored
//! (MDLn formats: number of texture coordinates)
int32_t synctype; int32_t synctype;
//! State flag //! State flag
int32_t flags; int32_t flags;
//! ??? //! Could be the total size of the file (and not a float)
float size; float size;
} PACK_STRUCT; } PACK_STRUCT;
@ -171,7 +189,6 @@ struct Header
/** \struct Header_MDL7 /** \struct Header_MDL7
* \brief Data structure for the MDL 7 main header * \brief Data structure for the MDL 7 main header
*/ */
// ---------------------------------------------------------------------------
struct Header_MDL7 struct Header_MDL7
{ {
//! magic number: "MDL7" //! magic number: "MDL7"
@ -181,13 +198,13 @@ struct Header_MDL7
int32_t version; int32_t version;
//! Number of bones in file //! Number of bones in file
int32_t bones_num; uint32_t bones_num;
//! Number of groups in file //! Number of groups in file
int32_t groups_num; uint32_t groups_num;
//! Size of data in the file //! Size of data in the file
int32_t data_size; uint32_t data_size;
//! Ignored. Used to store entity specific information //! Ignored. Used to store entity specific information
int32_t entlump_size; int32_t entlump_size;
@ -195,45 +212,77 @@ struct Header_MDL7
//! Ignored. Used to store MED related data //! Ignored. Used to store MED related data
int32_t medlump_size; int32_t medlump_size;
// ------------------------------------------------------- //! Size of the Bone_MDL7 data structure used in the file
// Sizes of some file parts
uint16_t bone_stc_size; uint16_t bone_stc_size;
//! Size of the Skin_MDL 7 data structure used in the file
uint16_t skin_stc_size; uint16_t skin_stc_size;
//! Size of a single color (e.g. in a material)
uint16_t colorvalue_stc_size; uint16_t colorvalue_stc_size;
//! Size of the Material_MDL7 data structure used in the file
uint16_t material_stc_size; uint16_t material_stc_size;
//! Size of a texture coordinate set in the file
uint16_t skinpoint_stc_size; uint16_t skinpoint_stc_size;
//! Size of a triangle in the file
uint16_t triangle_stc_size; uint16_t triangle_stc_size;
//! Size of a normal vertex in the file
uint16_t mainvertex_stc_size; uint16_t mainvertex_stc_size;
//! Size of a per-frame animated vertex in the file
//! (this is not supported)
uint16_t framevertex_stc_size; uint16_t framevertex_stc_size;
//! Size of a bone animation matrix
uint16_t bonetrans_stc_size; uint16_t bonetrans_stc_size;
//! Size of the Frame_MDL7 data structure used in the file
uint16_t frame_stc_size; uint16_t frame_stc_size;
} PACK_STRUCT; } PACK_STRUCT;
#define AI_MDL7_MAX_BONENAMESIZE 20
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \struct Bone_MDL7 /** \struct Bone_MDL7
* \brief Bone in a MDL7 file * \brief Data structure for a bone in a MDL7 file
*/ */
// ---------------------------------------------------------------------------
struct Bone_MDL7 struct Bone_MDL7
{ {
//! Index of the parent bone of *this* bone. 0xffff means:
//! "hey, I have no parent, I'm an orphan"
uint16_t parent_index; uint16_t parent_index;
uint8_t _unused_[2]; // uint8_t _unused_[2];
//! Relative position of the bone (relative to the
//! parent bone)
float x,y,z; float x,y,z;
char name[AI_MDL7_MAX_BONENAMESIZE]; //! Optional name of the bone
}; char name[1 /* DUMMY SIZE */];
} PACK_STRUCT;
#define AI_MDL7_MAX_GROUPNAMESIZE 16 #if (!defined AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_20_CHARS)
# define AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_20_CHARS (16 + 20)
#endif
#if (!defined AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_32_CHARS)
# define AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_32_CHARS (16 + 32)
#endif
#if (!defined AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE)
# define AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE (16)
#endif
#if (!defined AI_MDL7_MAX_GROUPNAMESIZE)
# define AI_MDL7_MAX_GROUPNAMESIZE 16
#endif // ! AI_MDL7_MAX_GROUPNAMESIZE
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \struct Group_MDL7 /** \struct Group_MDL7
* \brief Group in a MDL7 file * \brief Group in a MDL7 file
*/ */
// ---------------------------------------------------------------------------
struct Group_MDL7 struct Group_MDL7
{ {
//! = '1' -> triangle based Mesh //! = '1' -> triangle based Mesh
@ -268,14 +317,14 @@ struct Group_MDL7
#define AI_MDL7_SKINTYPE_MATERIAL_ASCDEF 0x20 #define AI_MDL7_SKINTYPE_MATERIAL_ASCDEF 0x20
#define AI_MDL7_SKINTYPE_RGBFLAG 0x80 #define AI_MDL7_SKINTYPE_RGBFLAG 0x80
#if (!defined AI_MDL7_MAX_BONENAMESIZE)
#define AI_MDL7_MAX_BONENAMESIZE 20 # define AI_MDL7_MAX_BONENAMESIZE 20
#endif // !! AI_MDL7_MAX_BONENAMESIZE
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \struct Deformer_MDL7 /** \struct Deformer_MDL7
* \brief Deformer in a MDL7 file * \brief Deformer in a MDL7 file
*/ */
// ---------------------------------------------------------------------------
struct Deformer_MDL7 struct Deformer_MDL7
{ {
int8_t deformer_version; // 0 int8_t deformer_version; // 0
@ -291,7 +340,6 @@ struct Deformer_MDL7
/** \struct DeformerElement_MDL7 /** \struct DeformerElement_MDL7
* \brief Deformer element in a MDL7 file * \brief Deformer element in a MDL7 file
*/ */
// ---------------------------------------------------------------------------
struct DeformerElement_MDL7 struct DeformerElement_MDL7
{ {
//! bei deformer_typ==0 (==bones) element_index == bone index //! bei deformer_typ==0 (==bones) element_index == bone index
@ -305,7 +353,6 @@ struct DeformerElement_MDL7
/** \struct DeformerWeight_MDL7 /** \struct DeformerWeight_MDL7
* \brief Deformer weight in a MDL7 file * \brief Deformer weight in a MDL7 file
*/ */
// ---------------------------------------------------------------------------
struct DeformerWeight_MDL7 struct DeformerWeight_MDL7
{ {
//! for deformer_typ==0 (==bones) index == vertex index //! for deformer_typ==0 (==bones) index == vertex index
@ -313,27 +360,14 @@ struct DeformerWeight_MDL7
float weight; float weight;
} PACK_STRUCT; } PACK_STRUCT;
// maximum length of texture file name
#define AI_MDL7_MAX_TEXNAMESIZE 0x10
// don't know why this was in the original headers ... // don't know why this was in the original headers ...
// to be removed in future versions
typedef int32_t MD7_MATERIAL_ASCDEFSIZE; typedef int32_t MD7_MATERIAL_ASCDEFSIZE;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \struct Skin_MDL7 /** \struct ColorValue_MDL7
* \brief Skin in a MDL7 file * \brief Data structure for a color value in a MDL7 file
*/ */
// ---------------------------------------------------------------------------
struct Skin_MDL7
{
uint8_t typ;
int8_t _unused_[3];
int32_t width;
int32_t height;
char texture_name[AI_MDL7_MAX_TEXNAMESIZE];
} PACK_STRUCT;
struct ColorValue_MDL7 struct ColorValue_MDL7
{ {
float r,g,b,a; float r,g,b,a;
@ -341,9 +375,8 @@ struct ColorValue_MDL7
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \struct Material_MDL7 /** \struct Material_MDL7
* \brief Material in a MDL7 file * \brief Data structure for a Material in a MDL7 file
*/ */
// ---------------------------------------------------------------------------
struct Material_MDL7 struct Material_MDL7
{ {
//! Diffuse base color of the material //! Diffuse base color of the material
@ -365,9 +398,8 @@ struct Material_MDL7
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \struct Skin /** \struct Skin
* \brief Skin data structure #1 * \brief Skin data structure #1 - used by Quake1, MDL2, MDL3 and MDL4
*/ */
// ---------------------------------------------------------------------------
struct Skin struct Skin
{ {
//! 0 = single (Skin), 1 = group (GroupSkin) //! 0 = single (Skin), 1 = group (GroupSkin)
@ -387,12 +419,40 @@ struct Skin
uint8_t *data; uint8_t *data;
} PACK_STRUCT; } PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \struct Skin
* \brief Skin data structure #2 - used by MDL5, MDL6 and MDL7
* \see Skin
*/
struct Skin_MDL5 struct Skin_MDL5
{ {
int32_t size, width, height; int32_t size, width, height;
uint8_t *data; uint8_t *data;
} PACK_STRUCT; } PACK_STRUCT;
// maximum length of texture file name
#if (!defined AI_MDL7_MAX_TEXNAMESIZE)
# define AI_MDL7_MAX_TEXNAMESIZE 0x10
#endif
// ---------------------------------------------------------------------------
/** \struct Skin_MDL7
* \brief Skin data structure #3 - used by MDL7 and HMP7
*/
struct Skin_MDL7
{
uint8_t typ;
int8_t _unused_[3];
int32_t width;
int32_t height;
char texture_name[AI_MDL7_MAX_TEXNAMESIZE];
} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \struct RGB565
* \brief Data structure for a RGB565 pixel in a texture
*/
struct RGB565 struct RGB565
{ {
uint16_t r : 5; uint16_t r : 5;
@ -400,6 +460,10 @@ struct RGB565
uint16_t b : 5; uint16_t b : 5;
} PACK_STRUCT; } PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \struct ARGB4
* \brief Data structure for a ARGB4444 pixel in a texture
*/
struct ARGB4 struct ARGB4
{ {
uint16_t a : 4; uint16_t a : 4;
@ -412,7 +476,6 @@ struct ARGB4
/** \struct GroupSkin /** \struct GroupSkin
* \brief Skin data structure #2 (group of pictures) * \brief Skin data structure #2 (group of pictures)
*/ */
// ---------------------------------------------------------------------------
struct GroupSkin struct GroupSkin
{ {
//! 0 = single (Skin), 1 = group (GroupSkin) //! 0 = single (Skin), 1 = group (GroupSkin)
@ -430,9 +493,8 @@ struct GroupSkin
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \struct TexCoord /** \struct TexCoord
* \brief Texture coordinate data structure * \brief Texture coordinate data structure used by the Quake1 MDL format
*/ */
// ---------------------------------------------------------------------------
struct TexCoord struct TexCoord
{ {
//! Is the vertex on the noundary between front and back piece? //! Is the vertex on the noundary between front and back piece?
@ -445,7 +507,10 @@ struct TexCoord
int32_t t; int32_t t;
} PACK_STRUCT; } PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \struct TexCoord_MDL3
* \brief Data structure for an UV coordinate in the 3DGS MDL3 format
*/
struct TexCoord_MDL3 struct TexCoord_MDL3
{ {
//! position, horizontally in range 0..skinwidth-1 //! position, horizontally in range 0..skinwidth-1
@ -455,6 +520,10 @@ struct TexCoord_MDL3
int16_t v; int16_t v;
} PACK_STRUCT; } PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \struct TexCoord_MDL7
* \brief Data structure for an UV coordinate in the 3DGS MDL7 format
*/
struct TexCoord_MDL7 struct TexCoord_MDL7
{ {
//! position, horizontally in range 0..1 //! position, horizontally in range 0..1
@ -464,32 +533,13 @@ struct TexCoord_MDL7
float v; float v;
} PACK_STRUCT; } PACK_STRUCT;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \struct Triangle /** \struct SkinSet_MDL7
* \brief Triangle data structure * \brief Skin set data structure for the 3DGS MDL7 format
* MDL7 references UV coordinates per face via an index list.
* This allows the use of multiple skins per face with just one
* UV coordinate set.
*/ */
// ---------------------------------------------------------------------------
struct Triangle
{
//! 0 = backface, 1 = frontface
int32_t facesfront;
//! Vertex indices
int32_t vertex[3];
} PACK_STRUCT;
struct Triangle_MDL3
{
//! Index of 3 3D vertices in range 0..numverts
uint16_t index_xyz[3];
//! Index of 3 skin vertices in range 0..numskinverts
uint16_t index_uv[3];
} PACK_STRUCT;
struct SkinSet_MDL7 struct SkinSet_MDL7
{ {
//! Index into the UV coordinate list //! Index into the UV coordinate list
@ -499,7 +549,36 @@ struct SkinSet_MDL7
int32_t material; // size 4 int32_t material; // size 4
} PACK_STRUCT; } PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \struct Triangle
* \brief Triangle data structure for the Quake1 MDL format
*/
struct Triangle
{
//! 0 = backface, 1 = frontface
int32_t facesfront;
//! Vertex indices
int32_t vertex[3];
} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \struct Triangle_MDL3
* \brief Triangle data structure for the 3DGS MDL3 format
*/
struct Triangle_MDL3
{
//! Index of 3 3D vertices in range 0..numverts
uint16_t index_xyz[3];
//! Index of 3 skin vertices in range 0..numskinverts
uint16_t index_uv[3];
} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \struct Triangle_MDL7
* \brief Triangle data structure for the 3DGS MDL7 format
*/
struct Triangle_MDL7 struct Triangle_MDL7
{ {
//! Vertex indices //! Vertex indices
@ -509,6 +588,15 @@ struct Triangle_MDL7
SkinSet_MDL7 skinsets[2]; SkinSet_MDL7 skinsets[2];
} PACK_STRUCT; } PACK_STRUCT;
#if (!defined AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV)
# define AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV (6+sizeof(SkinSet_MDL7)-sizeof(uint32_t))
#endif
#if (!defined AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV_WITH_MATINDEX)
# define AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV_WITH_MATINDEX (6+sizeof(SkinSet_MDL7))
#endif
#if (!defined AI_MDL7_TRIANGLE_STD_SIZE_TWO_UV)
# define AI_MDL7_TRIANGLE_STD_SIZE_TWO_UV (6+2*sizeof(SkinSet_MDL7))
#endif
// Helper constants for Triangle::facesfront // Helper constants for Triangle::facesfront
#if (!defined AI_MDL_BACKFACE) #if (!defined AI_MDL_BACKFACE)
@ -522,7 +610,6 @@ struct Triangle_MDL7
/** \struct Vertex /** \struct Vertex
* \brief Vertex data structure * \brief Vertex data structure
*/ */
// ---------------------------------------------------------------------------
struct Vertex struct Vertex
{ {
uint8_t v[3]; uint8_t v[3];
@ -530,6 +617,7 @@ struct Vertex
} PACK_STRUCT; } PACK_STRUCT;
// ---------------------------------------------------------------------------
struct Vertex_MDL4 struct Vertex_MDL4
{ {
uint16_t v[3]; uint16_t v[3];
@ -544,13 +632,12 @@ struct Vertex_MDL4
/** \struct Vertex_MDL7 /** \struct Vertex_MDL7
* \brief Vertex data structure used in MDL7 files * \brief Vertex data structure used in MDL7 files
*/ */
// ---------------------------------------------------------------------------
struct Vertex_MDL7 struct Vertex_MDL7
{ {
float x,y,z; float x,y,z;
uint16_t vertindex; // = bone index uint16_t vertindex; // = bone index
union { union {
uint16_t norm162index; uint8_t norm162index;
float norm[3]; float norm[3];
}; };
} PACK_STRUCT; } PACK_STRUCT;
@ -560,7 +647,6 @@ struct Vertex_MDL7
/** \struct BoneTransform_MDL7 /** \struct BoneTransform_MDL7
* \brief bone transformation matrix structure used in MDL7 files * \brief bone transformation matrix structure used in MDL7 files
*/ */
// ---------------------------------------------------------------------------
struct BoneTransform_MDL7 struct BoneTransform_MDL7
{ {
//! 4*3 //! 4*3
@ -582,7 +668,6 @@ struct BoneTransform_MDL7
/** \struct Frame_MDL7 /** \struct Frame_MDL7
* \brief Frame data structure used by MDL7 files * \brief Frame data structure used by MDL7 files
*/ */
// ---------------------------------------------------------------------------
struct Frame_MDL7 struct Frame_MDL7
{ {
char frame_name[AI_MDL7_MAX_FRAMENAMESIZE]; char frame_name[AI_MDL7_MAX_FRAMENAMESIZE];
@ -595,7 +680,6 @@ struct Frame_MDL7
/** \struct SimpleFrame /** \struct SimpleFrame
* \brief Data structure for a simple frame * \brief Data structure for a simple frame
*/ */
// ---------------------------------------------------------------------------
struct SimpleFrame struct SimpleFrame
{ {
//! Minimum vertex of the bounding box //! Minimum vertex of the bounding box
@ -615,7 +699,6 @@ struct SimpleFrame
/** \struct Frame /** \struct Frame
* \brief Model frame data structure * \brief Model frame data structure
*/ */
// ---------------------------------------------------------------------------
struct Frame struct Frame
{ {
//! 0 = simple frame, !0 = group frame //! 0 = simple frame, !0 = group frame
@ -626,6 +709,7 @@ struct Frame
} PACK_STRUCT; } PACK_STRUCT;
// ---------------------------------------------------------------------------
struct SimpleFrame_MDLn_SP struct SimpleFrame_MDLn_SP
{ {
//! Minimum vertex of the bounding box //! Minimum vertex of the bounding box
@ -645,7 +729,6 @@ struct SimpleFrame_MDLn_SP
/** \struct GroupFrame /** \struct GroupFrame
* \brief Data structure for a group of frames * \brief Data structure for a group of frames
*/ */
// ---------------------------------------------------------------------------
struct GroupFrame struct GroupFrame
{ {
//! 0 = simple frame, !0 = group frame //! 0 = simple frame, !0 = group frame
@ -675,7 +758,6 @@ struct GroupFrame
/** \struct IntFace_MDL7 /** \struct IntFace_MDL7
* \brief Internal data structure to temporarily represent a face * \brief Internal data structure to temporarily represent a face
*/ */
// ---------------------------------------------------------------------------
struct IntFace_MDL7 struct IntFace_MDL7
{ {
// provide a constructor for our own convenience // provide a constructor for our own convenience
@ -700,7 +782,6 @@ struct IntFace_MDL7
* which has been created from two single materials along with the * which has been created from two single materials along with the
* original material indices. * original material indices.
*/ */
// ---------------------------------------------------------------------------
struct IntMaterial_MDL7 struct IntMaterial_MDL7
{ {
// provide a constructor for our own convenience // provide a constructor for our own convenience
@ -717,6 +798,188 @@ struct IntMaterial_MDL7
unsigned int iOldMatIndices[2]; unsigned int iOldMatIndices[2];
}; };
// ---------------------------------------------------------------------------
/** \struct IntBone_MDL7
* \brief Internal data structure to represent a bone in a MDL7 file with
* all of its animation channels assigned to it.
*/
struct IntBone_MDL7 : aiBone
{
//! Default constructor
IntBone_MDL7() : iParent (0xffff)
{
pkeyPositions.reserve(30);
pkeyScalings.reserve(30);
pkeyRotations.reserve(30);
}
//! Parent bone of the bone
uint64_t iParent;
//! Relative position of the bone
aiVector3D vPosition;
//! Array of position keys
std::vector<aiVectorKey> pkeyPositions;
//! Array of scaling keys
std::vector<aiVectorKey> pkeyScalings;
//! Array of rotation keys
std::vector<aiQuatKey> pkeyRotations;
};
// ---------------------------------------------------------------------------
//! Describes a MDL7 frame
struct IntFrameInfo_MDL7
{
//! Construction from an existing frame header
IntFrameInfo_MDL7(const MDL::Frame_MDL7* _pcFrame,unsigned int _iIndex)
: pcFrame(_pcFrame), iIndex(_iIndex)
{}
//! Index of the frame
unsigned int iIndex;
//! Points to the header of the frame
const MDL::Frame_MDL7* pcFrame;
};
// ---------------------------------------------------------------------------
//! Describes a MDL7 mesh group
struct IntGroupInfo_MDL7
{
//! Default constructor
IntGroupInfo_MDL7() :
iIndex(0),
pcGroup(NULL), pcGroupUVs(NULL),
pcGroupTris(NULL), pcGroupVerts(NULL)
{}
//! Construction from an existing group header
IntGroupInfo_MDL7(const MDL::Group_MDL7* _pcGroup,unsigned int _iIndex)
:
pcGroup(_pcGroup),iIndex(_iIndex)
{}
//! Index of the group
unsigned int iIndex;
//! Points to the header of the group
const MDL::Group_MDL7* pcGroup;
//! Points to the beginning of the uv coordinate section
const MDL::TexCoord_MDL7* pcGroupUVs;
//! Points to the beginning of the triangle section
const MDL::Triangle_MDL7* pcGroupTris;
//! Points to the beginning of the vertex section
const MDL::Vertex_MDL7* pcGroupVerts;
};
// ---------------------------------------------------------------------------
//! Holds the data that belongs to a MDL7 mesh group
struct IntGroupData_MDL7
{
IntGroupData_MDL7()
: pcFaces(NULL), bNeed2UV(false)
{}
//! Array of faces that belong to the group
MDL::IntFace_MDL7* pcFaces;
//! Array of vertex positions
std::vector<aiVector3D> vPositions;
//! Array of vertex normals
std::vector<aiVector3D> vNormals;
//! Array of bones indices
std::vector<unsigned int> aiBones;
//! First UV coordinate set
std::vector<aiVector3D> vTextureCoords1;
//! Optional second UV coordinate set
std::vector<aiVector3D> vTextureCoords2;
//! Specifies whether there are two texture
//! coordinate sets required
bool bNeed2UV;
};
// ---------------------------------------------------------------------------
//! Holds data from an MDL7 file that is shared by all mesh groups
struct IntSharedData_MDL7
{
//! Default constructor
IntSharedData_MDL7()
{
abNeedMaterials.reserve(10);
}
//! Destruction: properly delete all allocated resources
~IntSharedData_MDL7()
{
// kill all bones
if (this->apcOutBones)
{
for (unsigned int m = 0; m < iNum;++m)
delete this->apcOutBones[m];
delete[] this->apcOutBones;
}
}
//! Specifies which materials are used
std::vector<bool> abNeedMaterials;
//! List of all materials
std::vector<MaterialHelper*> pcMats;
//! List of all bones
IntBone_MDL7** apcOutBones;
//! number of bones
unsigned int iNum;
};
// ---------------------------------------------------------------------------
//! Contains input data for GenerateOutputMeshes_3DGS_MDL7
struct IntSplittedGroupData_MDL7
{
//! Construction from a given shared data set
IntSplittedGroupData_MDL7(IntSharedData_MDL7& _shared,
std::vector<aiMesh*>& _avOutList)
: shared(_shared), avOutList(_avOutList)
{
}
//! Destruction: properly delete all allocated resources
~IntSplittedGroupData_MDL7()
{
// kill all face lists
if(this->aiSplit)
{
for (unsigned int m = 0; m < shared.pcMats.size();++m)
delete this->aiSplit[m];
delete[] this->aiSplit;
}
}
//! Contains a list of all faces per material
std::vector<unsigned int>** aiSplit;
//! Shared data for all groups of the model
IntSharedData_MDL7& shared;
//! List of meshes
std::vector<aiMesh*>& avOutList;
};
};}; // end namespaces };}; // end namespaces
#endif // !! AI_MDLFILEHELPER_H_INC #endif // !! AI_MDLFILEHELPER_H_INC

File diff suppressed because it is too large Load Diff

View File

@ -61,6 +61,11 @@ class MaterialHelper;
using namespace MDL; using namespace MDL;
#if (!defined VALIDATE_FILE_SIZE)
# define VALIDATE_FILE_SIZE(msg) this->SizeCheck(msg,__FILE__,__LINE__)
#endif
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Used to load MDL files /** Used to load MDL files
*/ */
@ -104,120 +109,57 @@ protected:
protected: protected:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Import a quake 1 MDL file /** Import a quake 1 MDL file (IDPO)
*/ */
void InternReadFile_Quake1( ); void InternReadFile_Quake1( );
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Import a GameStudio A4/A5 file /** Import a GameStudio A4/A5 file (MDL 3,4,5)
*/ */
void InternReadFile_GameStudio( ); void InternReadFile_3DGS_MDL345( );
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Import a GameStudio A7 file /** Import a GameStudio A7 file (MDL 7)
*/ */
void InternReadFile_GameStudioA7( ); void InternReadFile_3DGS_MDL7( );
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Import a CS:S/HL2 MDL file /** Import a CS:S/HL2 MDL file (not fully implemented)
*/ */
void InternReadFile_HL2( ); void InternReadFile_HL2( );
// *******************************************************************
// Debugging/validation functions
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Load a paletized texture from the file and convert it to 32bpp /** Check whether a given position is inside the valid range
* Throw a new ImportErrorException if it is not
* \param szPos Cursor position
* \param szFile Name of the source file from which the function was called
* \param iLine Source code line from which the function was called
*/ */
void CreateTextureARGB8(const unsigned char* szData); void SizeCheck(const void* szPos);
void SizeCheck(const void* szPos, const char* szFile, unsigned int iLine);
// -------------------------------------------------------------------
/** Used to load textures from MDL3/4
* \param szData Input data
* \param iType Color data type
* \param piSkip Receive: Size to skip
*/
void CreateTextureARGB8_GS4(const unsigned char* szData,
unsigned int iType,
unsigned int* piSkip);
// -------------------------------------------------------------------
/** Used to load textures from MDL5
* \param szData Input data
* \param iType Color data type
* \param piSkip Receive: Size to skip
*/
void CreateTextureARGB8_GS5(const unsigned char* szData,
unsigned int iType,
unsigned int* piSkip);
// -------------------------------------------------------------------
/** Parse a skin lump in a MDL7 file with all of its features
* \param szCurrent Current data pointer
* \param szCurrentOut Output data pointer
* \param pcMats Material list for this group. To be filled ...
*/
void ParseSkinLump_GameStudioA7(
const unsigned char* szCurrent,
const unsigned char** szCurrentOut,
std::vector<MaterialHelper*>& pcMats);
// -------------------------------------------------------------------
/** Parse texture color data for MDL5, MDL6 and MDL7 formats
* \param szData Current data pointer
* \param iType type of the texture data. No DDS or external
* \param piSkip Receive the number of bytes to skip
* \param pcNew Must point to fully initialized data. Width and
* height must be set.
*/
void ParseTextureColorData(const unsigned char* szData,
unsigned int iType,
unsigned int* piSkip,
aiTexture* pcNew);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Validate the header data structure of a game studio MDL7 file /** Validate the header data structure of a game studio MDL7 file
* \param pcHeader Input header to be validated * \param pcHeader Input header to be validated
*/ */
void ValidateHeader_GameStudioA7(const MDL::Header_MDL7* pcHeader); void ValidateHeader_3DGS_MDL7(const MDL::Header_MDL7* pcHeader);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Join two materials / skins. Setup UV source ... etc /** Validate the header data structure of a Quake 1 model
* \param pcMat1 First input material * \param pcHeader Input header to be validated
* \param pcMat2 Second input material
* \param pcMatOut Output material instance to be filled. Must be empty
*/ */
void JoinSkins_GameStudioA7(MaterialHelper* pcMat1, void ValidateHeader_Quake1(const MDL::Header* pcHeader);
MaterialHelper* pcMat2,
MaterialHelper* pcMatOut);
// -------------------------------------------------------------------
/** Generate the final output meshes for a7 models
* \param aiSplit Face-per-material list
* \param pcMats List of all materials
* \param avOutList Output: List of all meshes
* \param pcFaces List of all input faces
* \param vPositions List of all input vectors
* \param vNormals List of all input normal vectors
* \param vTextureCoords1 List of all input UV coords #1
* \param vTextureCoords2 List of all input UV coords #2
*/
void GenerateOutputMeshes_GameStudioA7(
const std::vector<unsigned int>** aiSplit,
const std::vector<MaterialHelper*>& pcMats,
std::vector<aiMesh*>& avOutList,
const MDL::IntFace_MDL7* pcFaces,
const std::vector<aiVector3D>& vPositions,
const std::vector<aiVector3D>& vNormals,
const std::vector<aiVector3D>& vTextureCoords1,
const std::vector<aiVector3D>& vTextureCoords2);
// ------------------------------------------------------------------- // *******************************************************************
/** Calculate absolute bone animation matrices for each bone // Material import
* \param pcBones Pointer to the bone section in the file
* \param apcOutBones Output bones array
*/
void CalculateAbsBoneAnimMatrices(const MDL::Bone_MDL7* pcBones,
aiBone** apcOutBones);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Try to load a palette from the current directory (colormap.lmp) /** Try to load a palette from the current directory (colormap.lmp)
@ -230,6 +172,262 @@ protected:
*/ */
void FreePalette(const unsigned char* pszColorMap); void FreePalette(const unsigned char* pszColorMap);
// -------------------------------------------------------------------
/** Load a paletized texture from the file and convert it to 32bpp
*/
void CreateTextureARGB8_3DGS_MDL3(const unsigned char* szData);
// -------------------------------------------------------------------
/** Used to load textures from MDL3/4
* \param szData Input data
* \param iType Color data type
* \param piSkip Receive: Size to skip, in bytes
*/
void CreateTexture_3DGS_MDL4(const unsigned char* szData,
unsigned int iType,
unsigned int* piSkip);
// -------------------------------------------------------------------
/** Used to load textures from MDL5
* \param szData Input data
* \param iType Color data type
* \param piSkip Receive: Size to skip, in bytes
*/
void CreateTexture_3DGS_MDL5(const unsigned char* szData,
unsigned int iType,
unsigned int* piSkip);
// -------------------------------------------------------------------
/** Checks whether a texture can be replaced with a single color
* This is useful for all file formats before MDL7 (all those
* that are not containing material colors separate from textures).
* MED seems to write dummy 8x8 monochrome images instead.
* \param pcTexture Input texture
* \return aiColor.r is set to qnan if the function fails and no
* color can be found.
*/
aiColor4D ReplaceTextureWithColor(const aiTexture* pcTexture);
// *******************************************************************
// Quake1, MDL 3,4,5 import
// -------------------------------------------------------------------
/** Converts the absolute texture coordinates in MDL5 files to
* relative in a range between 0 and 1
*/
void CalculateUVCoordinates_MDL5();
// -------------------------------------------------------------------
/** Read an UV coordinate from the file. If the file format is not
* MDL5, the function calculates relative texture coordinates
* \param vOut Receives the output UV coord
* \param pcSrc UV coordinate buffer
* \param UV coordinate index
*/
void ImportUVCoordinate_3DGS_MDL345( aiVector3D& vOut,
const MDL::TexCoord_MDL3* pcSrc,
unsigned int iIndex);
// -------------------------------------------------------------------
/** Setup the material properties for Quake and MDL<7 models.
* These formats don't support more than one material per mesh,
* therefore the method processes only ONE skin and removes
* all others.
*/
void SetupMaterialProperties_3DGS_MDL5_Quake1( );
// *******************************************************************
// MDL7 import
// -------------------------------------------------------------------
/** Parse a skin lump in a MDL7/HMP7 file with all of its features
* variant 1: Current cursor position is the beginning of the skin header
* \param szCurrent Current data pointer
* \param szCurrentOut Output data pointer
* \param pcMats Material list for this group. To be filled ...
*/
void ParseSkinLump_3DGS_MDL7(
const unsigned char* szCurrent,
const unsigned char** szCurrentOut,
std::vector<MaterialHelper*>& pcMats);
// -------------------------------------------------------------------
/** Parse a skin lump in a MDL7/HMP7 file with all of its features
* variant 2: Current cursor position is the beginning of the skin data
* \param szCurrent Current data pointer
* \param szCurrentOut Output data pointer
* \param pcMatOut Output material
* \param iType header.typ
* \param iWidth header.width
* \param iHeight header.height
*/
void ParseSkinLump_3DGS_MDL7(
const unsigned char* szCurrent,
const unsigned char** szCurrentOut,
MaterialHelper* pcMatOut,
unsigned int iType,
unsigned int iWidth,
unsigned int iHeight);
// -------------------------------------------------------------------
/** Skip a skin lump in a MDL7/HMP7 file
* \param szCurrent Current data pointer
* \param szCurrentOut Output data pointer. Points to the byte just
* behind the last byte of the skin.
* \param iType header.typ
* \param iWidth header.width
* \param iHeight header.height
*/
void SkipSkinLump_3DGS_MDL7(const unsigned char* szCurrent,
const unsigned char** szCurrentOut,
unsigned int iType,
unsigned int iWidth,
unsigned int iHeight);
// -------------------------------------------------------------------
/** Parse texture color data for MDL5, MDL6 and MDL7 formats
* \param szData Current data pointer
* \param iType type of the texture data. No DDS or external
* \param piSkip Receive the number of bytes to skip
* \param pcNew Must point to fully initialized data. Width and
* height must be set. If pcNew->pcData is set to 0xffffffff,
* piSkip will receive the size of the texture, in bytes, but no
* color data will be read.
*/
void ParseTextureColorData(const unsigned char* szData,
unsigned int iType,
unsigned int* piSkip,
aiTexture* pcNew);
// -------------------------------------------------------------------
/** Join two materials / skins. Setup UV source ... etc
* \param pcMat1 First input material
* \param pcMat2 Second input material
* \param pcMatOut Output material instance to be filled. Must be empty
*/
void JoinSkins_3DGS_MDL7(MaterialHelper* pcMat1,
MaterialHelper* pcMat2,
MaterialHelper* pcMatOut);
// -------------------------------------------------------------------
/** Add a bone transformation key to an animation
* \param iTrafo Index of the transformation (always==frame index?)
* No need to validate this index, it is always valid.
* \param pcBoneTransforms Bone transformation for this index
* \param apcOutBones Output bones array
*/
void AddAnimationBoneTrafoKey_3DGS_MDL7(unsigned int iTrafo,
const MDL::BoneTransform_MDL7* pcBoneTransforms,
MDL::IntBone_MDL7** apcBonesOut);
// -------------------------------------------------------------------
/** Load the bone list of a MDL7 file
* \return If the bones could be loaded successfully, a valid
* array containing pointers to a temporary bone
* representation. NULL if the bones could not be loaded.
*/
MDL::IntBone_MDL7** LoadBones_3DGS_MDL7();
// -------------------------------------------------------------------
/** Load bone transformation keyframes from a file chunk
* \param groupInfo -> doc of data structure
* \param frame -> doc of data structure
* \param shared -> doc of data structure
*/
void ParseBoneTrafoKeys_3DGS_MDL7(
const MDL::IntGroupInfo_MDL7& groupInfo,
IntFrameInfo_MDL7& frame,
MDL::IntSharedData_MDL7& shared);
// -------------------------------------------------------------------
/** Calculate absolute bone animation matrices for each bone
* \param pcBones Pointer to the bone section in the file
* \param apcOutBones Output bones array
*/
void CalcAbsBoneMatrices_3DGS_MDL7(const MDL::Bone_MDL7* pcBones,
MDL::IntBone_MDL7** apcOutBones);
// -------------------------------------------------------------------
/** Add all bones to the nodegraph (as children of the root node)
* \param apcBonesOut List of bones
* \param pcParent Parent node. New nodes will be added to this node
* \param iParentIndex Index of the parent bone
*/
void AddBonesToNodeGraph_3DGS_MDL7(const MDL::IntBone_MDL7** apcBonesOut,
aiNode* pcParent,uint16_t iParentIndex);
// -------------------------------------------------------------------
/** Build output animations
* \param apcBonesOut List of bones
*/
void BuildOutputAnims_3DGS_MDL7(const MDL::IntBone_MDL7** apcBonesOut);
// -------------------------------------------------------------------
/** Handles materials that are just referencing another material
* There is no test file for this feature, but Conitec's doc
* say it is used.
*/
void HandleMaterialReferences_3DGS_MDL7();
// -------------------------------------------------------------------
/** Copies only the material that are referenced by at least one
* mesh to the final output material list. All other materials
* will be discarded.
* \param shared -> doc of data structure
*/
void CopyMaterials_3DGS_MDL7(MDL::IntSharedData_MDL7 &shared);
// -------------------------------------------------------------------
/** Process the frame section at the end of a group
* \param groupInfo -> doc of data structure
* \param shared -> doc of data structure
* \param szCurrent Pointer to the start of the frame section
* \param szCurrentOut Receives a pointer to the first byte of the
* next data section.
* \return false to read no further groups (a small workaround for
* some tiny and unsolved problems ... )
*/
bool ProcessFrames_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInfo,
MDL::IntSharedData_MDL7& shared,
const unsigned char* szCurrent,
const unsigned char** szCurrentOut);
// -------------------------------------------------------------------
/** Sort all faces by their materials. If the mesh is using
* multiple materials per face (that are blended together) the function
* might create new materials.
* \param groupInfo -> doc of data structure
* \param groupData -> doc of data structure
* \param splittedGroupData -> doc of data structure
*/
void SortByMaterials_3DGS_MDL7(
const MDL::IntGroupInfo_MDL7& groupInfo,
MDL::IntGroupData_MDL7& groupData,
MDL::IntSplittedGroupData_MDL7& splittedGroupData);
// -------------------------------------------------------------------
/** Read all faces and vertices from a MDL7 group. The function fills
* preallocated memory buffers.
* \param groupInfo -> doc of data structure
* \param groupData -> doc of data structure
*/
void ReadFaces_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInfo,
MDL::IntGroupData_MDL7& groupData);
// -------------------------------------------------------------------
/** Generate the final output meshes for a7 models
* \param groupData -> doc of data structure
* \param splittedGroupData -> doc of data structure
*/
void GenerateOutputMeshes_3DGS_MDL7(
MDL::IntGroupData_MDL7& groupData,
MDL::IntSplittedGroupData_MDL7& splittedGroupData);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Try to determine whether the normals of the model are flipped /** Try to determine whether the normals of the model are flipped
* Some MDL7 models seem to have flipped normals (and there is also * Some MDL7 models seem to have flipped normals (and there is also
@ -239,16 +437,13 @@ protected:
*/ */
void FlipNormals(aiMesh* pcMesh); void FlipNormals(aiMesh* pcMesh);
private: protected:
/** Header of the MDL file */
const MDL::Header* m_pcHeader;
/** Buffer to hold the loaded file */ /** Buffer to hold the loaded file */
unsigned char* mBuffer; unsigned char* mBuffer;
/** For GameStudio MDL files: The number in the magic /** For GameStudio MDL files: The number in the magic word, either 3,4 or 5
word, either 3,4 or 5*/ * (MDL7 doesn't need this, the format has a separate loader) */
unsigned int iGSFileVersion; unsigned int iGSFileVersion;
/** Output I/O handler. used to load external lmp files /** Output I/O handler. used to load external lmp files
@ -258,6 +453,10 @@ private:
/** Output scene to be filled /** Output scene to be filled
*/ */
aiScene* pScene; aiScene* pScene;
/** Size of the input file in bytes
*/
unsigned int iFileSize;
}; };
}; // end of namespace Assimp }; // end of namespace Assimp

View File

@ -0,0 +1,774 @@
/*
---------------------------------------------------------------------------
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 Implementation of the material part of the MDL importer class */
// internal headers
#include "MaterialSystem.h"
#include "MDLLoader.h"
#include "MDLDefaultColorMap.h"
#include "qnan.h"
// public ASSIMP headers
#include "../include/DefaultLogger.h"
#include "../include/IOStream.h"
#include "../include/IOSystem.h"
#include "../include/aiMesh.h"
#include "../include/aiScene.h"
#include "../include/aiAssert.h"
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
void MDLImporter::SearchPalette(const unsigned char** pszColorMap)
{
// now try to find the color map in the current directory
IOStream* pcStream = this->pIOHandler->Open("colormap.lmp","rb");
const unsigned char* szColorMap = (const unsigned char*)::g_aclrDefaultColorMap;
if(pcStream)
{
if (pcStream->FileSize() >= 768)
{
szColorMap = new unsigned char[256*3];
pcStream->Read(const_cast<unsigned char*>(szColorMap),256*3,1);
DefaultLogger::get()->info("Found valid colormap.lmp in directory. "
"It will be used to decode embedded textures in palletized formats.");
}
delete pcStream;
pcStream = NULL;
}
*pszColorMap = szColorMap;
return;
}
// ------------------------------------------------------------------------------------------------
void MDLImporter::FreePalette(const unsigned char* szColorMap)
{
if (szColorMap != (const unsigned char*)::g_aclrDefaultColorMap)
{
delete[] szColorMap;
}
return;
}
// ------------------------------------------------------------------------------------------------
aiColor4D MDLImporter::ReplaceTextureWithColor(const aiTexture* pcTexture)
{
ai_assert(NULL != pcTexture);
aiColor4D clrOut;
clrOut.r = std::numeric_limits<float>::quiet_NaN();
if (!pcTexture->mHeight || !pcTexture->mWidth)return clrOut;
const unsigned int iNumPixels = pcTexture->mHeight*pcTexture->mWidth;
const aiTexel* pcTexel = pcTexture->pcData+1;
const aiTexel* const pcTexelEnd = &pcTexture->pcData[iNumPixels];
while (pcTexel != pcTexelEnd)
{
if (*pcTexel != *(pcTexel-1))
{
pcTexel = NULL;break;
}
++pcTexel;
}
if (pcTexel)
{
clrOut.r = pcTexture->pcData->r / 255.0f;
clrOut.g = pcTexture->pcData->g / 255.0f;
clrOut.b = pcTexture->pcData->b / 255.0f;
clrOut.a = pcTexture->pcData->a / 255.0f;
}
return clrOut;
}
// ------------------------------------------------------------------------------------------------
void MDLImporter::CreateTextureARGB8_3DGS_MDL3(const unsigned char* szData)
{
const MDL::Header* pcHeader = (const MDL::Header*)this->mBuffer;
VALIDATE_FILE_SIZE(szData + pcHeader->skinwidth *
pcHeader->skinheight);
// allocate a new texture object
aiTexture* pcNew = new aiTexture();
pcNew->mWidth = pcHeader->skinwidth;
pcNew->mHeight = pcHeader->skinheight;
pcNew->pcData = new aiTexel[pcNew->mWidth * pcNew->mHeight];
const unsigned char* szColorMap;
this->SearchPalette(&szColorMap);
// copy texture data
for (unsigned int i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
{
const unsigned char val = szData[i];
const unsigned char* sz = &szColorMap[val*3];
pcNew->pcData[i].a = 0xFF;
pcNew->pcData[i].r = *sz++;
pcNew->pcData[i].g = *sz++;
pcNew->pcData[i].b = *sz;
}
this->FreePalette(szColorMap);
// store the texture
aiTexture** pc = this->pScene->mTextures;
this->pScene->mTextures = new aiTexture*[this->pScene->mNumTextures+1];
for (unsigned int i = 0; i < this->pScene->mNumTextures;++i)
this->pScene->mTextures[i] = pc[i];
this->pScene->mTextures[this->pScene->mNumTextures] = pcNew;
this->pScene->mNumTextures++;
delete[] pc;
return;
}
// ------------------------------------------------------------------------------------------------
void MDLImporter::CreateTexture_3DGS_MDL4(const unsigned char* szData,
unsigned int iType,
unsigned int* piSkip)
{
const MDL::Header* pcHeader = (const MDL::Header*)this->mBuffer;
ai_assert(NULL != piSkip);
if (iType == 1 || iType > 3)
{
DefaultLogger::get()->error("Unsupported texture file format");
return;
}
bool bNoRead = *piSkip == 0xffffffff;
// allocate a new texture object
aiTexture* pcNew = new aiTexture();
pcNew->mWidth = pcHeader->skinwidth;
pcNew->mHeight = pcHeader->skinheight;
if (bNoRead)pcNew->pcData = (aiTexel*)0xffffffff;
this->ParseTextureColorData(szData,iType,piSkip,pcNew);
// store the texture
if (!bNoRead)
{
if (!this->pScene->mNumTextures)
{
this->pScene->mNumTextures = 1;
this->pScene->mTextures = new aiTexture*[1];
this->pScene->mTextures[0] = pcNew;
}
else
{
aiTexture** pc = this->pScene->mTextures;
this->pScene->mTextures = new aiTexture*[this->pScene->mNumTextures+1];
for (unsigned int i = 0; i < this->pScene->mNumTextures;++i)
this->pScene->mTextures[i] = pc[i];
this->pScene->mTextures[this->pScene->mNumTextures] = pcNew;
this->pScene->mNumTextures++;
delete[] pc;
}
}
else delete pcNew;
return;
}
// ------------------------------------------------------------------------------------------------
void MDLImporter::ParseTextureColorData(const unsigned char* szData,
unsigned int iType,
unsigned int* piSkip,
aiTexture* pcNew)
{
// allocate storage for the texture image
if ((aiTexel*)0xffffffff != pcNew->pcData)
pcNew->pcData = new aiTexel[pcNew->mWidth * pcNew->mHeight];
// R5G6B5 format (with or without MIPs)
// ****************************************************************
if (2 == iType || 10 == iType)
{
VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*2);
// copy texture data
unsigned int i;
if ((aiTexel*)0xffffffff != pcNew->pcData)
{
for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
{
MDL::RGB565 val = ((MDL::RGB565*)szData)[i];
pcNew->pcData[i].a = 0xFF;
pcNew->pcData[i].r = (unsigned char)val.b << 3;
pcNew->pcData[i].g = (unsigned char)val.g << 2;
pcNew->pcData[i].b = (unsigned char)val.r << 3;
}
}
else i = pcNew->mWidth*pcNew->mHeight;
*piSkip = i * 2;
// apply MIP maps
if (10 == iType)
{
*piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 1;
VALIDATE_FILE_SIZE(szData + *piSkip);
}
}
// ARGB4 format (with or without MIPs)
// ****************************************************************
else if (3 == iType || 11 == iType)
{
VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*4);
// copy texture data
unsigned int i;
if ((aiTexel*)0xffffffff != pcNew->pcData)
{
for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
{
MDL::ARGB4 val = ((MDL::ARGB4*)szData)[i];
pcNew->pcData[i].a = (unsigned char)val.a << 4;
pcNew->pcData[i].r = (unsigned char)val.r << 4;
pcNew->pcData[i].g = (unsigned char)val.g << 4;
pcNew->pcData[i].b = (unsigned char)val.b << 4;
}
}
else i = pcNew->mWidth*pcNew->mHeight;
*piSkip = i * 2;
// apply MIP maps
if (11 == iType)
{
*piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 1;
VALIDATE_FILE_SIZE(szData + *piSkip);
}
}
// RGB8 format (with or without MIPs)
// ****************************************************************
else if (4 == iType || 12 == iType)
{
VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*3);
// copy texture data
unsigned int i;
if ((aiTexel*)0xffffffff != pcNew->pcData)
{
for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
{
const unsigned char* _szData = &szData[i*3];
pcNew->pcData[i].a = 0xFF;
pcNew->pcData[i].b = *_szData++;
pcNew->pcData[i].g = *_szData++;
pcNew->pcData[i].r = *_szData;
}
}
else i = pcNew->mWidth*pcNew->mHeight;
// apply MIP maps
*piSkip = i * 3;
if (12 == iType)
{
*piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) *3;
VALIDATE_FILE_SIZE(szData + *piSkip);
}
}
// ARGB8 format (with ir without MIPs)
// ****************************************************************
else if (5 == iType || 13 == iType)
{
VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*4);
// copy texture data
unsigned int i;
if ((aiTexel*)0xffffffff != pcNew->pcData)
{
for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
{
const unsigned char* _szData = &szData[i*4];
pcNew->pcData[i].b = *_szData++;
pcNew->pcData[i].g = *_szData++;
pcNew->pcData[i].r = *_szData++;
pcNew->pcData[i].a = *_szData;
}
}
else i = pcNew->mWidth*pcNew->mHeight;
// apply MIP maps
*piSkip = i << 2;
if (13 == iType)
{
*piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 2;
}
}
// palletized 8 bit texture. As for Quake 1
// ****************************************************************
else if (0 == iType)
{
VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight);
// copy texture data
unsigned int i;
if ((aiTexel*)0xffffffff != pcNew->pcData)
{
const unsigned char* szColorMap;
this->SearchPalette(&szColorMap);
for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
{
const unsigned char val = szData[i];
const unsigned char* sz = &szColorMap[val*3];
pcNew->pcData[i].a = 0xFF;
pcNew->pcData[i].r = *sz++;
pcNew->pcData[i].g = *sz++;
pcNew->pcData[i].b = *sz;
}
this->FreePalette(szColorMap);
}
else i = pcNew->mWidth*pcNew->mHeight;
*piSkip = i;
// FIXME: Also support for MIP maps?
}
return;
}
// ------------------------------------------------------------------------------------------------
void MDLImporter::CreateTexture_3DGS_MDL5(const unsigned char* szData,
unsigned int iType,
unsigned int* piSkip)
{
ai_assert(NULL != piSkip);
bool bNoRead = *piSkip == 0xffffffff;
// allocate a new texture object
aiTexture* pcNew = new aiTexture();
VALIDATE_FILE_SIZE(szData+8);
// first read the size of the texture
pcNew->mWidth = *((uint32_t*)szData);
szData += sizeof(uint32_t);
pcNew->mHeight = *((uint32_t*)szData);
szData += sizeof(uint32_t);
if (bNoRead)pcNew->pcData = (aiTexel*)0xffffffff;
// this should not occur - at least the docs say it shouldn't
// however, you can easily try out what MED does if you have
// a model with a DDS texture and export it to MDL5 ...
// yes, you're right. It embedds the DDS texture ... :cry:
if (6 == iType)
{
// this is a compressed texture in DDS format
*piSkip = pcNew->mWidth;
VALIDATE_FILE_SIZE(szData + *piSkip);
if (!bNoRead)
{
// place a hint and let the application know that it's
// a DDS file
pcNew->mHeight = 0;
pcNew->achFormatHint[0] = 'd';
pcNew->achFormatHint[1] = 'd';
pcNew->achFormatHint[2] = 's';
pcNew->achFormatHint[3] = '\0';
pcNew->pcData = (aiTexel*) new unsigned char[pcNew->mWidth];
::memcpy(pcNew->pcData,szData,pcNew->mWidth);
}
}
else
{
// parse the color data of the texture
this->ParseTextureColorData(szData,iType,
piSkip,pcNew);
}
*piSkip += sizeof(uint32_t) * 2;
if (!bNoRead)
{
// store the texture
if (!this->pScene->mNumTextures)
{
this->pScene->mNumTextures = 1;
this->pScene->mTextures = new aiTexture*[1];
this->pScene->mTextures[0] = pcNew;
}
else
{
aiTexture** pc = this->pScene->mTextures;
this->pScene->mTextures = new aiTexture*[this->pScene->mNumTextures+1];
for (unsigned int i = 0; i < this->pScene->mNumTextures;++i)
this->pScene->mTextures[i] = pc[i];
this->pScene->mTextures[this->pScene->mNumTextures] = pcNew;
this->pScene->mNumTextures++;
delete[] pc;
}
}
else delete pcNew;
return;
}
// ------------------------------------------------------------------------------------------------
void MDLImporter::ParseSkinLump_3DGS_MDL7(
const unsigned char* szCurrent,
const unsigned char** szCurrentOut,
MaterialHelper* pcMatOut,
unsigned int iType,
unsigned int iWidth,
unsigned int iHeight)
{
aiTexture* pcNew = NULL;
// get the type of the skin
unsigned int iMasked = (unsigned int)(iType & 0xF);
if (0x1 == iMasked)
{
// ***** REFERENCE TO ANOTHER SKIN INDEX *****
// NOTE: Documentation - if you can call it a documentation, I prefer
// the expression "rubbish" - states it is currently unused. However,
// I don't know what ideas the terrible developers of Conitec will
// have tomorrow, so Im going to implement it.
int referrer = (int)iWidth;
pcMatOut->AddProperty<int>(&referrer,1,AI_MDL7_REFERRER_MATERIAL);
}
else if (0x6 == iMasked)
{
// ***** EMBEDDED DDS FILE *****
if (1 != iHeight)
{
DefaultLogger::get()->warn("Found a reference to an embedded DDS texture, "
"but texture height is not equal to 1, which is not supported by MED");
}
pcNew = new aiTexture();
pcNew->mHeight = 0;
pcNew->mWidth = iWidth;
pcNew->achFormatHint[0] = 'd';
pcNew->achFormatHint[1] = 'd';
pcNew->achFormatHint[2] = 's';
pcNew->achFormatHint[3] = '\0';
pcNew->pcData = (aiTexel*) new unsigned char[pcNew->mWidth];
memcpy(pcNew->pcData,szCurrent,pcNew->mWidth);
szCurrent += iWidth;
}
if (0x7 == iMasked)
{
// ***** REFERENCE TO EXTERNAL FILE *****
if (1 != iHeight)
{
DefaultLogger::get()->warn("Found a reference to an external texture, "
"but texture height is not equal to 1, which is not supported by MED");
}
aiString szFile;
const size_t iLen = strlen((const char*)szCurrent);
size_t iLen2 = iLen+1;
iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2;
memcpy(szFile.data,(const char*)szCurrent,iLen2);
szFile.length = iLen;
szCurrent += iLen2;
// place this as diffuse texture
pcMatOut->AddProperty(&szFile,AI_MATKEY_TEXTURE_DIFFUSE(0));
}
else if (iMasked || !iType || (iType && iWidth && iHeight))
{
// ***** STANDARD COLOR TEXTURE *****
pcNew = new aiTexture();
if (!iHeight || !iWidth)
{
DefaultLogger::get()->warn("Found embedded texture, but its width "
"an height are both 0. Is this a joke?");
// generate an empty chess pattern
pcNew->mWidth = pcNew->mHeight = 8;
pcNew->pcData = new aiTexel[64];
for (unsigned int x = 0; x < 8;++x)
{
for (unsigned int y = 0; y < 8;++y)
{
bool bSet = false;
if (0 == x % 2 && 0 != y % 2 ||
0 != x % 2 && 0 == y % 2)bSet = true;
aiTexel* pc = &pcNew->pcData[y * 8 + x];
if (bSet)pc->r = pc->b = pc->g = 0xFF;
else pc->r = pc->b = pc->g = 0;
pc->a = 0xFF;
}
}
}
else
{
// it is a standard color texture. Fill in width and height
// and call the same function we used for loading MDL5 files
pcNew->mWidth = iWidth;
pcNew->mHeight = iHeight;
unsigned int iSkip = 0;
this->ParseTextureColorData(szCurrent,iMasked,&iSkip,pcNew);
// skip length of texture data
szCurrent += iSkip;
}
}
// sometimes there are MDL7 files which have a monochrome
// texture instead of material colors ... posssible they have
// been converted to MDL7 from other formats, such as MDL5
aiColor4D clrTexture = this->ReplaceTextureWithColor(pcNew);
// check whether a material definition is contained in the skin
if (iType & AI_MDL7_SKINTYPE_MATERIAL)
{
const MDL::Material_MDL7* pcMatIn = (const MDL::Material_MDL7*)szCurrent;
szCurrent = (unsigned char*)(pcMatIn+1);
VALIDATE_FILE_SIZE(szCurrent);
aiColor3D clrTemp;
#define COLOR_MULTIPLY_RGB() \
if (is_not_qnan(clrTexture.r)) \
{ \
clrTemp.r *= clrTexture.r; \
clrTemp.g *= clrTexture.g; \
clrTemp.b *= clrTexture.b; \
}
// read diffuse color
clrTemp.r = pcMatIn->Diffuse.r;
clrTemp.g = pcMatIn->Diffuse.g;
clrTemp.b = pcMatIn->Diffuse.b;
COLOR_MULTIPLY_RGB();
pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_DIFFUSE);
// read specular color
clrTemp.r = pcMatIn->Specular.r;
clrTemp.g = pcMatIn->Specular.g;
clrTemp.b = pcMatIn->Specular.b;
COLOR_MULTIPLY_RGB();
pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_SPECULAR);
// read ambient color
clrTemp.r = pcMatIn->Ambient.r;
clrTemp.g = pcMatIn->Ambient.g;
clrTemp.b = pcMatIn->Ambient.b;
COLOR_MULTIPLY_RGB();
pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_AMBIENT);
// read emissive color
clrTemp.r = pcMatIn->Emissive.r;
clrTemp.g = pcMatIn->Emissive.g;
clrTemp.b = pcMatIn->Emissive.b;
pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_EMISSIVE);
// FIX: Take the opacity from the ambient color
// the doc says something else, but it is fact that MED exports the
// opacity like this .... ARRRGGHH!
clrTemp.r = pcMatIn->Ambient.a;
if (is_not_qnan(clrTexture.r))clrTemp.r *= clrTexture.a;
pcMatOut->AddProperty<float>(&clrTemp.r,1,AI_MATKEY_OPACITY);
// read phong power
int iShadingMode = (int)aiShadingMode_Gouraud;
if (0.0f != pcMatIn->Power)
{
iShadingMode = (int)aiShadingMode_Phong;
pcMatOut->AddProperty<float>(&pcMatIn->Power,1,AI_MATKEY_SHININESS);
}
pcMatOut->AddProperty<int>(&iShadingMode,1,AI_MATKEY_SHADING_MODEL);
}
else if (is_not_qnan(clrTexture.r))
{
pcMatOut->AddProperty<aiColor4D>(&clrTexture,1,AI_MATKEY_COLOR_DIFFUSE);
pcMatOut->AddProperty<aiColor4D>(&clrTexture,1,AI_MATKEY_COLOR_SPECULAR);
}
// if the texture could be replaced by a single material color
// we don't need the texture anymore
if (is_not_qnan(clrTexture.r))
{
delete pcNew;
pcNew = NULL;
}
// if an ASCII effect description (HLSL?) is contained in the file,
// we can simply ignore it ...
if (iType & AI_MDL7_SKINTYPE_MATERIAL_ASCDEF)
{
VALIDATE_FILE_SIZE(szCurrent);
int32_t iMe = *((int32_t*)szCurrent);
szCurrent += sizeof(char) * iMe + sizeof(int32_t);
VALIDATE_FILE_SIZE(szCurrent);
}
// if an embedded texture has been loaded setup the corresponding
// data structures in the aiScene instance
if (pcNew && this->pScene->mNumTextures <= 999)
{
// place this as diffuse texture
char szCurrent[5];
::sprintf(szCurrent,"*%i",this->pScene->mNumTextures);
aiString szFile;
const size_t iLen = strlen((const char*)szCurrent);
size_t iLen2 = iLen+1;
iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2;
::memcpy(szFile.data,(const char*)szCurrent,iLen2);
szFile.length = iLen;
pcMatOut->AddProperty(&szFile,AI_MATKEY_TEXTURE_DIFFUSE(0));
// store the texture
aiTexture** pc = this->pScene->mTextures;
this->pScene->mTextures = new aiTexture*[this->pScene->mNumTextures+1];
for (unsigned int i = 0; i < this->pScene->mNumTextures;++i)
this->pScene->mTextures[i] = pc[i];
this->pScene->mTextures[this->pScene->mNumTextures] = pcNew;
this->pScene->mNumTextures++;
delete[] pc;
}
VALIDATE_FILE_SIZE(szCurrent);
*szCurrentOut = szCurrent;
}
// ------------------------------------------------------------------------------------------------
void MDLImporter::SkipSkinLump_3DGS_MDL7(
const unsigned char* szCurrent,
const unsigned char** szCurrentOut,
unsigned int iType,
unsigned int iWidth,
unsigned int iHeight)
{
// get the type of the skin
unsigned int iMasked = (unsigned int)(iType & 0xF);
if (0x6 == iMasked)
{
szCurrent += iWidth;
}
if (0x7 == iMasked)
{
const size_t iLen = ::strlen((const char*)szCurrent);
szCurrent += iLen+1;
}
else if (iMasked || !iType)
{
if (iMasked || !iType || (iType && iWidth && iHeight))
{
// ParseTextureColorData(..., aiTexture::pcData == 0xffffffff) will simply
// return the size of the color data in bytes in iSkip
unsigned int iSkip = 0;
aiTexture tex;
tex.pcData = reinterpret_cast<aiTexel*>(0xffffffff);
tex.mHeight = iHeight;
tex.mWidth = iWidth;
this->ParseTextureColorData(szCurrent,iMasked,&iSkip,&tex);
// skip length of texture data
szCurrent += iSkip;
}
}
// check whether a material definition is contained in the skin
if (iType & AI_MDL7_SKINTYPE_MATERIAL)
{
const MDL::Material_MDL7* pcMatIn = (const MDL::Material_MDL7*)szCurrent;
szCurrent = (unsigned char*)(pcMatIn+1);
}
// if an ASCII effect description (HLSL?) is contained in the file,
// we can simply ignore it ...
if (iType & AI_MDL7_SKINTYPE_MATERIAL_ASCDEF)
{
int32_t iMe = *((int32_t*)szCurrent);
szCurrent += sizeof(char) * iMe + sizeof(int32_t);
}
*szCurrentOut = szCurrent;
}
// ------------------------------------------------------------------------------------------------
void MDLImporter::ParseSkinLump_3DGS_MDL7(
const unsigned char* szCurrent,
const unsigned char** szCurrentOut,
std::vector<MaterialHelper*>& pcMats)
{
ai_assert(NULL != szCurrent);
ai_assert(NULL != szCurrentOut);
*szCurrentOut = szCurrent;
const MDL::Skin_MDL7* pcSkin = (const MDL::Skin_MDL7*)szCurrent;
szCurrent += 12;
// allocate an output material
MaterialHelper* pcMatOut = new MaterialHelper();
pcMats.push_back(pcMatOut);
// skip length of file name
szCurrent += AI_MDL7_MAX_TEXNAMESIZE;
this->ParseSkinLump_3DGS_MDL7(szCurrent,szCurrentOut,pcMatOut,
pcSkin->typ,pcSkin->width,pcSkin->height);
// place the name of the skin in the material
const size_t iLen = strlen(pcSkin->texture_name);
if (0 != iLen)
{
aiString szFile;
memcpy(szFile.data,pcSkin->texture_name,sizeof(pcSkin->texture_name));
szFile.length = iLen;
pcMatOut->AddProperty(&szFile,AI_MATKEY_NAME);
}
return;
}

View File

@ -465,6 +465,7 @@ aiReturn aiGetMaterialTexture(const aiMaterial* pcMat,
}; };
char szKey[256]; char szKey[256];
if (iIndex > 100)return AI_FAILURE;
// get the path to the texture // get the path to the texture
#if _MSC_VER >= 1400 #if _MSC_VER >= 1400

View File

@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp namespace Assimp
{ {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Internal material helper class. Can be used to fill an aiMaterial /** Internal material helper class. Can be used to fill an aiMaterial
structure easily. */ structure easily. */
@ -209,4 +210,4 @@ inline aiReturn MaterialHelper::AddProperty<int> (const int* pInput,
} }
#endif //!! AI_MATERIALSYSTEM_H_INC #endif //!! AI_MATERIALSYSTEM_H_INC

115
code/ParsingUtils.h 100644
View File

@ -0,0 +1,115 @@
/*
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 helper functions for text parsing */
#ifndef AI_PARSING_UTILS_H_INC
#define AI_PARSING_UTILS_H_INC
// ---------------------------------------------------------------------------------
template <class char_t>
inline bool IsSpace( const char_t in)
{
return (in == (char_t)' ' || in == (char_t)'\t');
}
// ---------------------------------------------------------------------------------
template <class char_t>
inline bool IsLineEnd( const char_t in)
{
return (in == (char_t)'\r' || in == (char_t)'\n' || in == (char_t)'\0');
}
// ---------------------------------------------------------------------------------
template <class char_t>
inline bool IsSpaceOrNewLine( const char_t in)
{
return IsSpace<char_t>(in) || IsLineEnd<char_t>(in);
}
// ---------------------------------------------------------------------------------
template <class char_t>
inline bool SkipSpaces( const char_t* in, const char_t** out)
{
while (*in == (char_t)' ' || *in == (char_t)'\t')in++;
*out = in;
return !IsLineEnd<char_t>(*in);
}
// ---------------------------------------------------------------------------------
template <class char_t>
inline bool SkipSpaces( const char_t** inout)
{
return SkipSpaces<char_t>(*inout,inout);
}
// ---------------------------------------------------------------------------------
template <class char_t>
inline bool SkipLine( const char_t* in, const char_t** out)
{
while (*in != (char_t)'\r' && *in != (char_t)'\n' && *in != (char_t)'\0')in++;
if (*in == (char_t)'\0')
{
*out = in;
return false;
}
in++;
*out = in;
return true;
}
// ---------------------------------------------------------------------------------
template <class char_t>
inline bool SkipLine( const char_t** inout)
{
return SkipLine<char_t>(*inout,inout);
}
// ---------------------------------------------------------------------------------
template <class char_t>
inline void SkipSpacesAndLineEnd( const char_t* in, const char_t** out)
{
while (*in == (char_t)' ' || *in == (char_t)'\t' ||
*in == (char_t)'\r' || *in == (char_t)'\n')in++;
*out = in;
}
// ---------------------------------------------------------------------------------
template <class char_t>
inline bool SkipSpacesAndLineEnd( const char_t** inout)
{
return SkipSpacesAndLineEnd<char_t>(*inout,inout);
}
#endif // ! AI_PARSING_UTILS_H_INC

View File

@ -120,6 +120,7 @@ void PLYImporter::InternReadFile(
this->mBuffer[1] != 'L' && this->mBuffer[1] != 'l' || this->mBuffer[1] != 'L' && this->mBuffer[1] != 'l' ||
this->mBuffer[2] != 'Y' && this->mBuffer[2] != 'y') this->mBuffer[2] != 'Y' && this->mBuffer[2] != 'y')
{ {
delete[] this->mBuffer;
throw new ImportErrorException( "Invalid .ply file: Magic number \'ply\' is no there"); throw new ImportErrorException( "Invalid .ply file: Magic number \'ply\' is no there");
} }
char* szMe = (char*)&this->mBuffer[3]; char* szMe = (char*)&this->mBuffer[3];
@ -136,6 +137,7 @@ void PLYImporter::InternReadFile(
SkipLine(szMe,(const char**)&szMe); SkipLine(szMe,(const char**)&szMe);
if(!PLY::DOM::ParseInstance(szMe,&sPlyDom, (unsigned int)fileSize)) if(!PLY::DOM::ParseInstance(szMe,&sPlyDom, (unsigned int)fileSize))
{ {
delete[] this->mBuffer;
throw new ImportErrorException( "Invalid .ply file: Unable to build DOM (#1)"); throw new ImportErrorException( "Invalid .ply file: Unable to build DOM (#1)");
} }
} }
@ -156,16 +158,19 @@ void PLYImporter::InternReadFile(
SkipLine(szMe,(const char**)&szMe); SkipLine(szMe,(const char**)&szMe);
if(!PLY::DOM::ParseInstanceBinary(szMe,&sPlyDom,bIsBE, (unsigned int)fileSize)) if(!PLY::DOM::ParseInstanceBinary(szMe,&sPlyDom,bIsBE, (unsigned int)fileSize))
{ {
delete[] this->mBuffer;
throw new ImportErrorException( "Invalid .ply file: Unable to build DOM (#2)"); throw new ImportErrorException( "Invalid .ply file: Unable to build DOM (#2)");
} }
} }
else else
{ {
delete[] this->mBuffer;
throw new ImportErrorException( "Invalid .ply file: Unknown file format"); throw new ImportErrorException( "Invalid .ply file: Unknown file format");
} }
} }
else else
{ {
delete[] this->mBuffer;
throw new ImportErrorException( "Invalid .ply file: Missing format specification"); throw new ImportErrorException( "Invalid .ply file: Missing format specification");
} }
this->pcDOM = &sPlyDom; this->pcDOM = &sPlyDom;
@ -193,6 +198,7 @@ void PLYImporter::InternReadFile(
{ {
if (avPositions.size() < 3) if (avPositions.size() < 3)
{ {
delete[] this->mBuffer;
throw new ImportErrorException( "Invalid .ply file: Not enough vertices to build " throw new ImportErrorException( "Invalid .ply file: Not enough vertices to build "
"a face list. "); "a face list. ");
} }
@ -230,6 +236,7 @@ void PLYImporter::InternReadFile(
if (avMeshes.empty()) if (avMeshes.empty())
{ {
delete[] this->mBuffer;
throw new ImportErrorException( "Invalid .ply file: Unable to extract mesh data "); throw new ImportErrorException( "Invalid .ply file: Unable to extract mesh data ");
} }

View File

@ -48,6 +48,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <list> #include <list>
#include <sstream> #include <sstream>
#include "ParsingUtils.h"
#include "../include/aiTypes.h" #include "../include/aiTypes.h"
#include "../include/aiMesh.h" #include "../include/aiMesh.h"
#include "../include/aiAnim.h" #include "../include/aiAnim.h"
@ -551,48 +553,6 @@ TYPE PLY::PropertyInstance::ConvertTo(
} }
}; };
// ---------------------------------------------------------------------------------
inline bool IsSpace( const char in)
{
return (in == ' ' || in == '\t');
}
// ---------------------------------------------------------------------------------
inline bool IsLineEnd( const char in)
{
return (in == '\r' || in == '\n' || in == '\0');
}
// ---------------------------------------------------------------------------------
inline bool IsSpaceOrNewLine( const char in)
{
return IsSpace(in) || IsLineEnd(in);
}
// ---------------------------------------------------------------------------------
inline bool SkipSpaces( const char* in, const char** out)
{
while (*in == ' ' || *in == '\t')in++;
*out = in;
return !IsLineEnd(*in);
}
// ---------------------------------------------------------------------------------
inline bool SkipLine( const char* in, const char** out)
{
while (*in != '\r' && *in != '\n' && *in != '\0')in++;
if (*in == '\0')
{
*out = in;
return false;
}
in++;
*out = in;
return true;
}
// ---------------------------------------------------------------------------------
inline void SkipSpacesAndLineEnd( const char* in, const char** out)
{
while (*in == ' ' || *in == '\t' || *in == '\r' || *in == '\n')in++;
*out = in;
}
}; };
#endif // !! include guard #endif // !! include guard

1070
code/SMDLoader.cpp 100644

File diff suppressed because it is too large Load Diff

408
code/SMDLoader.h 100644
View File

@ -0,0 +1,408 @@
/*
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 Definition of SMD importer class
//!
#ifndef AI_SMDLOADER_H_INCLUDED
#define AI_SMDLOADER_H_INCLUDED
#include "BaseImporter.h"
#include "ParsingUtils.h"
#include "../include/aiTypes.h"
#include "../include/aiTexture.h"
#include "../include/aiAnim.h"
#include "../include/aiMaterial.h"
struct aiNode;
#include <vector>
namespace Assimp {
class MaterialHelper;
namespace SMD {
// ---------------------------------------------------------------------------
/** Data structure for a vertex in a SMD file
*/
struct Vertex
{
Vertex() : iParentNode(0xffffffff)
{}
//! Vertex position, normal and texture coordinate
aiVector3D pos,nor,uv;
//! Vertex parent node
unsigned int iParentNode;
//! Links to bones: pair.first is the bone index,
//! pair.second is the vertex weight.
//! WARN: The remaining weight (to reach 1.0f) is assigned
//! to the parent node/bone
std::vector<std::pair<unsigned int, float> > aiBoneLinks;
};
// ---------------------------------------------------------------------------
/** Data structure for a face in a SMD file
*/
struct Face
{
Face() : iTexture(0x0)
{}
//! Texture index for the face
unsigned int iTexture;
//! The three vertices of the face
Vertex avVertices[3];
};
// ---------------------------------------------------------------------------
/** Data structure for a bone in a SMD file
*/
struct Bone
{
//! Default constructor
Bone() : iParent(0xffffffff), bIsUsed(false)
{
}
//! Destructor
~Bone()
{
}
//! Name of the bone
std::string mName;
//! Parent of the bone
uint32_t iParent;
//! Animation of the bone
struct Animation
{
//! Public default constructor
Animation()
{
asKeys.reserve(20);
}
//! Data structure for a matrix key
struct MatrixKey
{
//! Matrix at this time
aiMatrix4x4 matrix;
//! Absolute transformation matrix
aiMatrix4x4 matrixAbsolute;
//! Position
aiVector3D vPos;
//! Rotation (euler angles)
aiVector3D vRot;
//! Current time. may be negative, this
//! will be fixed later
double dTime;
};
//! Index of the key with the smallest time value
uint32_t iFirstTimeKey;
//! Array of matrix keys
std::vector<MatrixKey> asKeys;
} sAnim;
//! Offset matrix of the bone
aiMatrix4x4 mOffsetMatrix;
//! true if the bone is referenced by at least one mesh
bool bIsUsed;
};
}; //! namespace SMD
// ---------------------------------------------------------------------------
/** Used to load Half-life 1 and 2 SMD models
*/
class SMDImporter : public BaseImporter
{
friend class Importer;
protected:
/** Constructor to be privately used by Importer */
SMDImporter();
/** Destructor, private as well */
~SMDImporter();
public:
// -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file.
* See BaseImporter::CanRead() for details. */
bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const;
protected:
// -------------------------------------------------------------------
/** Called by Importer::GetExtensionList() for each loaded importer.
* See BaseImporter::GetExtensionList() for details
*/
void GetExtensionList(std::string& append)
{
append.append("*.smd;*.vta");
}
// -------------------------------------------------------------------
/** Imports the given file into the given scene structure.
* See BaseImporter::InternReadFile() for details
*/
void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler);
protected:
// -------------------------------------------------------------------
/** Parse the SMD file and create the output scene
*/
void ParseFile();
// -------------------------------------------------------------------
/** Parse the triangles section of the SMD file
* \param szCurrent Current position in the file. Points to the first
* data line of the section.
* \param szCurrentOut Receives a pointer to the heading line of
* the next section (or to EOF)
*/
void ParseTrianglesSection(const char* szCurrent,
const char** szCurrentOut);
// -------------------------------------------------------------------
/** Parse the vertex animation section in VTA files
* \param szCurrent Current position in the file. Points to the first
* data line of the section.
* \param szCurrentOut Receives a pointer to the heading line of
* the next section (or to EOF)
*/
void ParseVASection(const char* szCurrent,
const char** szCurrentOut);
// -------------------------------------------------------------------
/** Parse the nodes section of the SMD file
* \param szCurrent Current position in the file. Points to the first
* data line of the section.
* \param szCurrentOut Receives a pointer to the heading line of
* the next section (or to EOF)
*/
void ParseNodesSection(const char* szCurrent,
const char** szCurrentOut);
// -------------------------------------------------------------------
/** Parse the skeleton section of the SMD file
* \param szCurrent Current position in the file. Points to the first
* data line of the section.
* \param szCurrentOut Receives a pointer to the heading line of
* the next section (or to EOF)
*/
void ParseSkeletonSection(const char* szCurrent,
const char** szCurrentOut);
// -------------------------------------------------------------------
/** Parse a single triangle in the SMD file
* \param szCurrent Current position in the file. Points to the first
* data line of the section.
* \param szCurrentOut Receives the output cursor position
*/
void ParseTriangle(const char* szCurrent,
const char** szCurrentOut);
// -------------------------------------------------------------------
/** Parse a single vertex in the SMD file
* \param szCurrent Current position in the file. Points to the first
* data line of the section.
* \param szCurrentOut Receives the output cursor position
* \param vertex Vertex to be filled
*/
void ParseVertex(const char* szCurrent,
const char** szCurrentOut, SMD::Vertex& vertex,
bool bVASection = false);
// -------------------------------------------------------------------
/** Get the index of a texture. If the texture was not yet known
* it will be added to the internal texture list.
* \param filename Name of the texture
* \return Value texture index
*/
unsigned int GetTextureIndex(const std::string& filename);
// -------------------------------------------------------------------
/** Computes absolute bone transformations
* All output transformations are in worldspace.
*/
void ComputeAbsoluteBoneTransformations();
// -------------------------------------------------------------------
/** Parse a line in the skeleton section
*/
void ParseSkeletonElement(const char* szCurrent,
const char** szCurrentOut,int iTime);
// -------------------------------------------------------------------
/** Parse a line in the nodes section
*/
void ParseNodeInfo(const char* szCurrent,
const char** szCurrentOut);
// -------------------------------------------------------------------
/** Parse a floating-point value
*/
bool ParseFloat(const char* szCurrent,
const char** szCurrentOut, float& out);
// -------------------------------------------------------------------
/** Parse an unsigned integer. There may be no sign!
*/
bool ParseUnsignedInt(const char* szCurrent,
const char** szCurrentOut, uint32_t& out);
// -------------------------------------------------------------------
/** Parse a signed integer. Signs (+,-) are handled.
*/
bool ParseSignedInt(const char* szCurrent,
const char** szCurrentOut, int32_t& out);
// -------------------------------------------------------------------
/** Fix invalid time values in the file
*/
void FixTimeValues();
// -------------------------------------------------------------------
/** Add all children of a bone as subnodes to a node
* \param pcNode Parent node
* \param iParent Parent bone index
*/
void AddBoneChildren(aiNode* pcNode, uint32_t iParent);
// -------------------------------------------------------------------
/** Build output meshes/materials/nodes/animations
*/
void CreateOutputMeshes();
void CreateOutputNodes();
void CreateOutputAnimations();
void CreateOutputMaterials();
// -------------------------------------------------------------------
/** Print a log message together with the current line number
*/
void LogErrorNoThrow(const char* msg);
void LogWarning(const char* msg);
// -------------------------------------------------------------------
inline bool SkipLine( const char* in, const char** out)
{
::SkipLine(in,out);
++iLineNumber;
return true;
}
// -------------------------------------------------------------------
inline void SkipSpacesAndLineEnd( const char* in, const char** out)
{
::SkipSpacesAndLineEnd(in,out);
++iLineNumber;
}
private:
/** Buffer to hold the loaded file */
const char* mBuffer;
/** Output scene to be filled
*/
aiScene* pScene;
/** Size of the input file in bytes
*/
unsigned int iFileSize;
/** Array of textures found in the file
*/
std::vector<std::string> aszTextures;
/** Array of triangles found in the file
*/
std::vector<SMD::Face> asTriangles;
/** Array of bones found in the file
*/
std::vector<SMD::Bone> asBones;
/** Smallest frame index found in the skeleton
*/
int iSmallestFrame;
/** Length of the whole animation, in frames
*/
double dLengthOfAnim;
/** Do we have texture coordinates?
*/
bool bHasUVs;
/** Current line numer
*/
unsigned int iLineNumber;
};
}; // end of namespace Assimp
#endif // AI_SMDIMPORTER_H_INC

View File

@ -54,8 +54,8 @@ namespace Assimp
class SplitLargeMeshesProcess_Triangle; class SplitLargeMeshesProcess_Triangle;
class SplitLargeMeshesProcess_Vertex; class SplitLargeMeshesProcess_Vertex;
// NOTE: If you change these limits, don't forget to also change the // NOTE: If you change these limits, don't forget to change the
// corresponding values in the Assimp ports // corresponding values in all Assimp ports
// ********************************************************** // **********************************************************
// Java: PostProcessStep.java, // Java: PostProcessStep.java,
@ -64,10 +64,14 @@ class SplitLargeMeshesProcess_Vertex;
// ********************************************************** // **********************************************************
// default limit for vertices // default limit for vertices
#define AI_SLM_DEFAULT_MAX_VERTICES 1000000 #if (!defined AI_SLM_DEFAULT_MAX_VERTICES)
# define AI_SLM_DEFAULT_MAX_VERTICES 1000000
#endif
// default limit for triangles // default limit for triangles
#define AI_SLM_DEFAULT_MAX_TRIANGLES 1000000 #if (!defined AI_SLM_DEFAULT_MAX_TRIANGLES)
# define AI_SLM_DEFAULT_MAX_TRIANGLES 1000000
#endif
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Postprocessing filter to split large meshes into submeshes /** Postprocessing filter to split large meshes into submeshes

View File

@ -55,8 +55,7 @@ namespace Assimp
void TextureTransform::PreProcessUVTransform( void TextureTransform::PreProcessUVTransform(
Dot3DS::Texture& rcIn) Dot3DS::Texture& rcIn)
{ {
std::string s; char szTemp[512];
std::stringstream ss;
int iField; int iField;
if (rcIn.mOffsetU) if (rcIn.mOffsetU)
@ -66,10 +65,10 @@ void TextureTransform::PreProcessUVTransform(
if (aiTextureMapMode_Wrap == rcIn.mMapMode) if (aiTextureMapMode_Wrap == rcIn.mMapMode)
{ {
float fNew = rcIn.mOffsetU-(float)iField; float fNew = rcIn.mOffsetU-(float)iField;
ss << "[wrap] Found texture coordinate U offset " << rcIn.mOffsetU << ". " sprintf(szTemp,"[wrap] Found texture coordinate U offset %f. "
"This can be optimized to " << fNew; "This can be optimized to %f",rcIn.mOffsetU,fNew);
ss >> s;
DefaultLogger::get()->info(s); DefaultLogger::get()->info(szTemp);
rcIn.mOffsetU = fNew; rcIn.mOffsetU = fNew;
} }
else if (aiTextureMapMode_Mirror == rcIn.mMapMode) else if (aiTextureMapMode_Mirror == rcIn.mMapMode)
@ -77,18 +76,18 @@ void TextureTransform::PreProcessUVTransform(
if (0 != (iField % 2))iField--; if (0 != (iField % 2))iField--;
float fNew = rcIn.mOffsetU-(float)iField; float fNew = rcIn.mOffsetU-(float)iField;
ss << "[mirror] Found texture coordinate U offset " << rcIn.mOffsetU << ". " sprintf(szTemp,"[mirror] Found texture coordinate U offset %f. "
"This can be optimized to " << fNew; "This can be optimized to %f",rcIn.mOffsetU,fNew);
ss >> s;
DefaultLogger::get()->info(s); DefaultLogger::get()->info(szTemp);
rcIn.mOffsetU = fNew; rcIn.mOffsetU = fNew;
} }
else if (aiTextureMapMode_Clamp == rcIn.mMapMode) else if (aiTextureMapMode_Clamp == rcIn.mMapMode)
{ {
ss << "[clamp] Found texture coordinate U offset " << rcIn.mOffsetU << ". " sprintf(szTemp,"[clamp] Found texture coordinate U offset %f. "
"This can be clamped to 1.0f"; "This can be clamped to 1.0f",rcIn.mOffsetU);
ss >> s;
DefaultLogger::get()->info(s); DefaultLogger::get()->info(szTemp);
rcIn.mOffsetU = 1.0f; rcIn.mOffsetU = 1.0f;
} }
} }
@ -100,10 +99,10 @@ void TextureTransform::PreProcessUVTransform(
if (aiTextureMapMode_Wrap == rcIn.mMapMode) if (aiTextureMapMode_Wrap == rcIn.mMapMode)
{ {
float fNew = rcIn.mOffsetV-(float)iField; float fNew = rcIn.mOffsetV-(float)iField;
ss << "[wrap] Found texture coordinate V offset " << rcIn.mOffsetV << ". " sprintf(szTemp,"[wrap] Found texture coordinate V offset %f. "
"This can be optimized to " << fNew; "This can be optimized to %f",rcIn.mOffsetV,fNew);
ss >> s;
DefaultLogger::get()->info(s); DefaultLogger::get()->info(szTemp);
rcIn.mOffsetV = fNew; rcIn.mOffsetV = fNew;
} }
else if (aiTextureMapMode_Mirror == rcIn.mMapMode) else if (aiTextureMapMode_Mirror == rcIn.mMapMode)
@ -111,18 +110,18 @@ void TextureTransform::PreProcessUVTransform(
if (0 != (iField % 2))iField--; if (0 != (iField % 2))iField--;
float fNew = rcIn.mOffsetV-(float)iField; float fNew = rcIn.mOffsetV-(float)iField;
ss << "[mirror] Found texture coordinate V offset " << rcIn.mOffsetV << ". " sprintf(szTemp,"[mirror] Found texture coordinate V offset %f. "
"This can be optimized to " << fNew; "This can be optimized to %f",rcIn.mOffsetV,fNew);
ss >> s;
DefaultLogger::get()->info(s); DefaultLogger::get()->info(szTemp);
rcIn.mOffsetV = fNew; rcIn.mOffsetV = fNew;
} }
else if (aiTextureMapMode_Clamp == rcIn.mMapMode) else if (aiTextureMapMode_Clamp == rcIn.mMapMode)
{ {
ss << "[clamp] Found texture coordinate V offset " << rcIn.mOffsetV << ". " sprintf(szTemp,"[clamp] Found texture coordinate U offset %f. "
"This can be clamped to 1.0f"; "This can be clamped to 1.0f",rcIn.mOffsetV);
ss >> s;
DefaultLogger::get()->info(s); DefaultLogger::get()->info(szTemp);
rcIn.mOffsetV = 1.0f; rcIn.mOffsetV = 1.0f;
} }
} }
@ -132,9 +131,11 @@ void TextureTransform::PreProcessUVTransform(
if (iField = (int)(rcIn.mRotation / 3.141592654f)) if (iField = (int)(rcIn.mRotation / 3.141592654f))
{ {
float fNew = rcIn.mRotation-(float)iField*3.141592654f; float fNew = rcIn.mRotation-(float)iField*3.141592654f;
ss << "[wrap] Found texture coordinate rotation " << rcIn.mRotation << ". "
"This can be optimized to " << fNew; sprintf(szTemp,"[wrap] Found texture coordinate rotation %f. "
DefaultLogger::get()->info(s); "This can be optimized to %f",rcIn.mRotation,fNew);
DefaultLogger::get()->info(szTemp);
rcIn.mRotation = fNew; rcIn.mRotation = fNew;
} }
} }
@ -300,10 +301,16 @@ void TextureTransform::BakeScaleNOffset(
// it is more efficient this way ... // it is more efficient this way ...
if (!pcMesh->mTextureCoords[0])return; if (!pcMesh->mTextureCoords[0])return;
if (1 == pcSrc->iBakeUVTransform) if (0x1 == pcSrc->iBakeUVTransform)
{ {
char szTemp[512]; char szTemp[512];
sprintf(szTemp,"Transforming existing UV channel. Source UV: %i" int iLen;
#if _MSC_VER >= 1400
iLen = ::sprintf_s(szTemp,
#else
iLen = ::sprintf(szTemp,
#endif
"Transforming existing UV channel. Source UV: %i"
" OffsetU: %f" " OffsetU: %f"
" OffsetV: %f" " OffsetV: %f"
" ScaleU: %f" " ScaleU: %f"
@ -314,7 +321,9 @@ void TextureTransform::BakeScaleNOffset(
pcSrc->pcSingleTexture->mScaleU, pcSrc->pcSingleTexture->mScaleU,
pcSrc->pcSingleTexture->mScaleV, pcSrc->pcSingleTexture->mScaleV,
pcSrc->pcSingleTexture->mRotation); pcSrc->pcSingleTexture->mRotation);
DefaultLogger::get()->info(std::string(szTemp));
ai_assert(0 < iLen);
DefaultLogger::get()->info(std::string(szTemp,iLen));
if (!pcSrc->pcSingleTexture->mRotation) if (!pcSrc->pcSingleTexture->mRotation)
{ {
@ -349,7 +358,7 @@ void TextureTransform::BakeScaleNOffset(
} }
} }
} }
else if (2 == pcSrc->iBakeUVTransform) else if (0x2 == pcSrc->iBakeUVTransform)
{ {
// first save all texture coordinate sets // first save all texture coordinate sets
aiVector3D* apvOriginalSets[AI_MAX_NUMBER_OF_TEXTURECOORDS]; aiVector3D* apvOriginalSets[AI_MAX_NUMBER_OF_TEXTURECOORDS];
@ -367,13 +376,14 @@ void TextureTransform::BakeScaleNOffset(
// now we need to find all textures in the material // now we need to find all textures in the material
// which require scaling/offset operations // which require scaling/offset operations
std::vector<STransformVecInfo> sOps; std::vector<STransformVecInfo> sOps;
AddToList(sOps,&pcSrc->sTexDiffuse); sOps.reserve(10);
AddToList(sOps,&pcSrc->sTexSpecular); TextureTransform::AddToList(sOps,&pcSrc->sTexDiffuse);
AddToList(sOps,&pcSrc->sTexEmissive); TextureTransform::AddToList(sOps,&pcSrc->sTexSpecular);
AddToList(sOps,&pcSrc->sTexOpacity); TextureTransform::AddToList(sOps,&pcSrc->sTexEmissive);
AddToList(sOps,&pcSrc->sTexBump); TextureTransform::AddToList(sOps,&pcSrc->sTexOpacity);
AddToList(sOps,&pcSrc->sTexShininess); TextureTransform::AddToList(sOps,&pcSrc->sTexBump);
AddToList(sOps,&pcSrc->sTexAmbient); TextureTransform::AddToList(sOps,&pcSrc->sTexShininess);
TextureTransform::AddToList(sOps,&pcSrc->sTexAmbient);
// check the list and find out how many we won't be able // check the list and find out how many we won't be able
// to generate. // to generate.
@ -446,7 +456,13 @@ void TextureTransform::BakeScaleNOffset(
pcMesh->mTextureCoords[iNum] = _pvOut; pcMesh->mTextureCoords[iNum] = _pvOut;
char szTemp[512]; char szTemp[512];
sprintf(szTemp,"Generating additional UV channel. Source UV: %i" int iLen;
#if _MSC_VER >= 1400
iLen = ::sprintf_s(szTemp,
#else
iLen = ::sprintf(szTemp,
#endif
"Generating additional UV channel. Source UV: %i"
" OffsetU: %f" " OffsetU: %f"
" OffsetV: %f" " OffsetV: %f"
" ScaleU: %f" " ScaleU: %f"
@ -457,7 +473,8 @@ void TextureTransform::BakeScaleNOffset(
(**i).fScaleU, (**i).fScaleU,
(**i).fScaleV, (**i).fScaleV,
(**i).fRotation); (**i).fRotation);
DefaultLogger::get()->info(std::string(szTemp)); ai_assert(0 < iLen);
DefaultLogger::get()->info(std::string(szTemp,iLen));
const aiVector3D* pvBase = _pvBase; const aiVector3D* pvBase = _pvBase;
aiVector3D* pvOut = _pvOut; aiVector3D* pvOut = _pvOut;
@ -516,6 +533,12 @@ void TextureTransform::BakeScaleNOffset(
if (apvOriginalSets[iNum])delete[] apvOriginalSets[iNum]; if (apvOriginalSets[iNum])delete[] apvOriginalSets[iNum];
} }
} }
// setup bitflags to indicate which texture coordinate
// channels are used (this class works for 2d texture coordinates only)
unsigned int iIndex = 0;
while (pcMesh->HasTextureCoords(iIndex))pcMesh->mNumUVComponents[iIndex++] = 2;
return; return;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -342,6 +342,8 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
void ValidateDSProcess::Validate( const aiMesh* pMesh, void ValidateDSProcess::Validate( const aiMesh* pMesh,
const aiBone* pBone) const aiBone* pBone)
{ {
this->Validate(&pBone->mName);
// check whether all vertices affected by this bone are valid // check whether all vertices affected by this bone are valid
for (unsigned int i = 0; i < pBone->mNumWeights;++i) for (unsigned int i = 0; i < pBone->mNumWeights;++i)
{ {
@ -359,6 +361,8 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh,
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ValidateDSProcess::Validate( const aiAnimation* pAnimation) void ValidateDSProcess::Validate( const aiAnimation* pAnimation)
{ {
this->Validate(&pAnimation->mName);
// validate all materials // validate all materials
if (pAnimation->mNumBones) if (pAnimation->mNumBones)
{ {
@ -480,7 +484,7 @@ void ValidateDSProcess::Validate( const aiMaterial* pMaterial)
// check whether there are material keys that are obviously not legal // check whether there are material keys that are obviously not legal
for (unsigned int i = 0; i < pMaterial->mNumProperties;++i) for (unsigned int i = 0; i < pMaterial->mNumProperties;++i)
{ {
aiMaterialProperty* prop = pMaterial->mProperties[i]; const aiMaterialProperty* prop = pMaterial->mProperties[i];
if (!prop) if (!prop)
{ {
this->ReportError("aiMaterial::mProperties[%i] is NULL (aiMaterial::mNumProperties is %i)", this->ReportError("aiMaterial::mProperties[%i] is NULL (aiMaterial::mNumProperties is %i)",
@ -491,9 +495,39 @@ void ValidateDSProcess::Validate( const aiMaterial* pMaterial)
this->ReportError("aiMaterial::mProperties[%i].mDataLength or " this->ReportError("aiMaterial::mProperties[%i].mDataLength or "
"aiMaterial::mProperties[%i].mData is 0",i,i); "aiMaterial::mProperties[%i].mData is 0",i,i);
} }
// check all predefined types
if (aiPTI_String == prop->mType)
{
if (prop->mDataLength < sizeof(aiString))
{
this->ReportError("aiMaterial::mProperties[%i].mDataLength is "
"too small to contain a string (%i, needed: %i)",
i,prop->mDataLength,sizeof(aiString));
}
this->Validate((const aiString*)prop->mData);
}
else if (aiPTI_Float == prop->mType)
{
if (prop->mDataLength < sizeof(float))
{
this->ReportError("aiMaterial::mProperties[%i].mDataLength is "
"too small to contain a float (%i, needed: %i)",
i,prop->mDataLength,sizeof(float));
}
}
else if (aiPTI_Integer == prop->mType)
{
if (prop->mDataLength < sizeof(int))
{
this->ReportError("aiMaterial::mProperties[%i].mDataLength is "
"too small to contain an integer (%i, needed: %i)",
i,prop->mDataLength,sizeof(int));
}
}
// TODO: check whether there is a key with an unknown name ... // TODO: check whether there is a key with an unknown name ...
} }
// make some more specific tests
float fTemp; float fTemp;
int iShading; int iShading;
if (AI_SUCCESS == aiGetMaterialInteger( pMaterial,AI_MATKEY_SHADING_MODEL,&iShading)) if (AI_SUCCESS == aiGetMaterialInteger( pMaterial,AI_MATKEY_SHADING_MODEL,&iShading))
@ -518,7 +552,6 @@ void ValidateDSProcess::Validate( const aiMaterial* pMaterial)
}; };
} }
// check whether there are invalid texture keys // check whether there are invalid texture keys
SearchForInvalidTextures(pMaterial,"diffuse"); SearchForInvalidTextures(pMaterial,"diffuse");
SearchForInvalidTextures(pMaterial,"specular"); SearchForInvalidTextures(pMaterial,"specular");
@ -563,6 +596,8 @@ void ValidateDSProcess::Validate( const aiTexture* pTexture)
void ValidateDSProcess::Validate( const aiAnimation* pAnimation, void ValidateDSProcess::Validate( const aiAnimation* pAnimation,
const aiBoneAnim* pBoneAnim) const aiBoneAnim* pBoneAnim)
{ {
this->Validate(&pBoneAnim->mBoneName);
// check whether there is a bone with this name ... // check whether there is a bone with this name ...
unsigned int i = 0; unsigned int i = 0;
for (; i < this->mScene->mNumMeshes;++i) for (; i < this->mScene->mNumMeshes;++i)
@ -649,6 +684,8 @@ void ValidateDSProcess::Validate( const aiNode* pNode)
if (pNode != this->mScene->mRootNode && !pNode->mParent) if (pNode != this->mScene->mRootNode && !pNode->mParent)
this->ReportError("A node has no valid parent (aiNode::mParent is NULL)"); this->ReportError("A node has no valid parent (aiNode::mParent is NULL)");
this->Validate(&pNode->mName);
// validate all meshes // validate all meshes
if (pNode->mNumMeshes) if (pNode->mNumMeshes)
{ {
@ -687,3 +724,25 @@ void ValidateDSProcess::Validate( const aiNode* pNode)
} }
} }
} }
// ------------------------------------------------------------------------------------------------
void ValidateDSProcess::Validate( const aiString* pString)
{
if (pString->length > MAXLEN)
{
this->ReportError("aiString::length is too large (%i, maximum is %i)",
pString->length,MAXLEN);
}
const char* sz = pString->data;
while (true)
{
if ('\0' == *sz)
{
if (pString->length != (unsigned int)(sz-pString->data))
this->ReportError("aiString::data is invalid: the terminal zero is at a wrong offset");
break;
}
else if (sz >= &pString->data[MAXLEN])
this->ReportError("aiString::data is invalid. There is no terminal character");
++sz;
}
}

View File

@ -53,6 +53,7 @@ struct aiBoneAnim;
struct aiTexture; struct aiTexture;
struct aiMaterial; struct aiMaterial;
struct aiNode; struct aiNode;
struct aiString;
namespace Assimp namespace Assimp
{ {
@ -158,6 +159,12 @@ protected:
*/ */
void Validate( const aiNode* pNode); void Validate( const aiNode* pNode);
// -------------------------------------------------------------------
/** Validates a string
* @param pString Input string
*/
void Validate( const aiString* pString);
private: private:
aiScene* mScene; aiScene* mScene;

View File

@ -579,174 +579,188 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, const std::vector<XFile::
// texture, if there is one // texture, if there is one
if (1 == oldMat.mTextures.size()) if (1 == oldMat.mTextures.size())
{
if (oldMat.mTextures[0].length())
{ {
// if there is only one texture, assume it contains the // if there is only one texture assume it contains the diffuse color
// diffuse color aiString tex;
aiString tex; tex.Set( oldMat.mTextures[0]);
tex.Set( oldMat.mTextures[0]); mat->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE(0));
mat->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE(0));
} }
}
else else
{ {
// Otherwise ... try to search for typical strings in the // Otherwise ... try to search for typical strings in the
// texture's file name like 'bump' or 'diffuse' // texture's file name like 'bump' or 'diffuse'
unsigned int iHM = 0,iNM = 0,iDM = 0,iSM = 0,iAM = 0,iEM = 0; unsigned int iHM = 0,iNM = 0,iDM = 0,iSM = 0,iAM = 0,iEM = 0;
for( unsigned int b = 0; b < oldMat.mTextures.size(); b++) for( unsigned int b = 0; b < oldMat.mTextures.size(); b++)
{ {
std::string sz = oldMat.mTextures[b]; std::string sz = oldMat.mTextures[b];
if (!sz.length())continue;
char key[256]; char key[256];
// find the file name // find the file name
const size_t iLen = sz.length(); const size_t iLen = sz.length();
std::string::size_type s = sz.rfind('\\',iLen-1); std::string::size_type s = sz.rfind('\\',iLen-1);
if (std::string::npos == s) if (std::string::npos == s)
{ {
s = sz.rfind('/',iLen-1); s = sz.rfind('/',iLen-1);
if (std::string::npos == s)s = 0; if (std::string::npos == s)s = 0;
} }
// cut off the file extension // cut off the file extension
std::string::size_type sExt = sz.rfind('.',iLen-1); std::string::size_type sExt = sz.rfind('.',iLen-1);
if (std::string::npos != sExt) if (std::string::npos != sExt)
{ {
sz[sExt] = '\0'; sz[sExt] = '\0';
} }
// bump map // bump map
std::string::size_type s2 = sz.find("bump",s); std::string::size_type s2 = sz.find("bump",s);
if (std::string::npos == s2) if (std::string::npos == s2)
{
if (std::string::npos == (s2 = sz.find("BUMP",s)))
{ {
s2 = sz.find("BUMP",s); if (std::string::npos == (s2 = sz.find("Bump",s)))
if (std::string::npos == s2)
{ {
s2 = sz.find("Bump",s); if (std::string::npos == (s2 = sz.find("height",s)))
if (std::string::npos == s2)
{ {
s2 = sz.find("height",s); if (std::string::npos == (s2 = sz.find("HEIGHT",s)))
if (std::string::npos == s2)
{ {
s2 = sz.find("HEIGHT",s);
if (std::string::npos == s2)
{
s2 = sz.find("Height",s); s2 = sz.find("Height",s);
}
} }
} }
} }
} }
}
if (std::string::npos != s2) if (std::string::npos != s2)
{ {
sprintf(key,AI_MATKEY_TEXTURE_HEIGHT_ "[%i]",iHM++); #if _MSC_VER >= 1400
} ::sprintf_s(key,AI_MATKEY_TEXTURE_HEIGHT_ "[%i]",iHM++);
#else
::sprintf(key,AI_MATKEY_TEXTURE_HEIGHT_ "[%i]",iHM++);
#endif
}
else else
{ {
// Normal map // Normal map
std::string::size_type s2 = sz.find("normal",s); std::string::size_type s2 = sz.find("normal",s);
if (std::string::npos == s2) if (std::string::npos == s2)
{
if (std::string::npos == (s2 = sz.find("NORMAL",s)))
{ {
s2 = sz.find("NORMAL",s); if (std::string::npos == (s2 = sz.find("nm",s)))
if (std::string::npos == s2) {
{ if (std::string::npos == (s2 = sz.find("Normal",s)))
s2 = sz.find("nm",s); // not really unique
if (std::string::npos == s2)
{ {
s2 = sz.find("Normal",s);
if (std::string::npos == s2)
{
s2 = sz.find("NM",s); s2 = sz.find("NM",s);
}
} }
} }
} }
}
if (std::string::npos != s2) if (std::string::npos != s2)
{ {
sprintf(key,AI_MATKEY_TEXTURE_NORMALS_ "[%i]",iNM++); #if _MSC_VER >= 1400
} ::sprintf_s(key,AI_MATKEY_TEXTURE_NORMALS_ "[%i]",iNM++);
#else
::sprintf(key,AI_MATKEY_TEXTURE_NORMALS_ "[%i]",iNM++);
#endif
}
else else
{ {
// specular color texture (not unique, too. Could // specular color texture (not unique, too. Could
// also be the material's shininess) // also be the material's shininess)
std::string::size_type s2 = sz.find("spec",s); std::string::size_type s2 = sz.find("spec",s);
if (std::string::npos == s2) if (std::string::npos == s2)
{
if (std::string::npos == (s2 = sz.find("Spec",s)))
{ {
s2 = sz.find("Spec",s); if (std::string::npos == (sz.find("SPEC",s)))
if (std::string::npos == s2)
{ {
s2 = sz.find("SPEC",s); if (std::string::npos == (s2 = sz.find("Glanz",s)))
if (std::string::npos == s2)
{ {
s2 = sz.find("Glanz",s);
if (std::string::npos == s2)
{
s2 = sz.find("glanz",s); s2 = sz.find("glanz",s);
}
}
}
}
if (std::string::npos != s2)
{
sprintf(key,AI_MATKEY_TEXTURE_SPECULAR_ "[%i]",iSM++);
}
else
{
// ambient color texture
std::string::size_type s2 = sz.find("ambi",s);
if (std::string::npos == s2)
{
s2 = sz.find("AMBI",s);
if (std::string::npos == s2)
{
s2 = sz.find("umgebungsfarbe",s);
if (std::string::npos == s2)
{
s2 = sz.find("Ambi",s);
}
}
}
if (std::string::npos != s2)
{
sprintf(key,AI_MATKEY_TEXTURE_AMBIENT_ "[%i]",iAM++);
}
else
{
// emissive color texture
std::string::size_type s2 = sz.find("emissive",s);
if (std::string::npos == s2)
{
s2 = sz.find("EMISSIVE",s);
if (std::string::npos == s2)
{
// self illumination
s2 = sz.find("self",s);
if (std::string::npos == s2)
{
s2 = sz.find("Emissive",s);
}
}
}
if (std::string::npos != s2)
{
sprintf(key,AI_MATKEY_TEXTURE_EMISSIVE_ "[%i]",iEM++);
}
else
{
// assume it is a diffuse texture
sprintf(key,AI_MATKEY_TEXTURE_DIFFUSE_ "[%i]",iDM++);
} }
} }
} }
} }
if (std::string::npos != s2)
{
#if _MSC_VER >= 1400
::sprintf_s(key,AI_MATKEY_TEXTURE_SPECULAR_ "[%i]",iSM++);
#else
::sprintf(key,AI_MATKEY_TEXTURE_SPECULAR_ "[%i]",iSM++);
#endif
}
else
{
// ambient color texture
std::string::size_type s2 = sz.find("ambi",s);
if (std::string::npos == s2)
{
if (std::string::npos == (s2 = sz.find("AMBI",s)))
{
if (std::string::npos == (s2 = sz.find("env",s)))
{
s2 = sz.find("Ambi",s);
}
}
}
if (std::string::npos != s2)
{
#if _MSC_VER >= 1400
::sprintf_s(key,AI_MATKEY_TEXTURE_AMBIENT_ "[%i]",iAM++);
#else
::sprintf(key,AI_MATKEY_TEXTURE_AMBIENT_ "[%i]",iAM++);
#endif
}
else
{
// emissive color texture
std::string::size_type s2 = sz.find("emissive",s);
if (std::string::npos == s2)
{
s2 = sz.find("EMISSIVE",s);
if (std::string::npos == s2)
{
// self illumination
if (std::string::npos == (s2 = sz.find("self",s)))
{
s2 = sz.find("Emissive",s);
}
}
}
if (std::string::npos != s2)
{
#if _MSC_VER >= 1400
::sprintf_s(key,AI_MATKEY_TEXTURE_EMISSIVE_ "[%i]",iEM++);
#else
::sprintf(key,AI_MATKEY_TEXTURE_EMISSIVE_ "[%i]",iEM++);
#endif
}
else
{
// assume it is a diffuse texture
#if _MSC_VER >= 1400
::sprintf_s(key,AI_MATKEY_TEXTURE_DIFFUSE_ "[%i]",iDM++);
#else
::sprintf(key,AI_MATKEY_TEXTURE_DIFFUSE_ "[%i]",iDM++);
#endif
}
}
}
} }
}
aiString tex; aiString tex;
tex.Set( oldMat.mTextures[b] ); tex.Set( oldMat.mTextures[b] );
mat->AddProperty( &tex, key); mat->AddProperty( &tex, key);
}
} }
}
pScene->mMaterials[pScene->mNumMaterials] = mat; pScene->mMaterials[pScene->mNumMaterials] = mat;
mImportedMats[oldMat.mName] = pScene->mNumMaterials; mImportedMats[oldMat.mName] = pScene->mNumMaterials;
pScene->mNumMaterials++; pScene->mNumMaterials++;

View File

@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "XFileHelper.h" #include "XFileHelper.h"
#include "BaseImporter.h" #include "BaseImporter.h"
#include "fast_atof.h" #include "fast_atof.h"
#include "../include/DefaultLogger.h"
#include <boost/format.hpp> #include <boost/format.hpp>
@ -150,11 +151,11 @@ void XFileParser::ParseFile()
if( objectName == "}") if( objectName == "}")
{ {
// whatever? // whatever?
// os::Printer::log("} found in dataObject", ELL_WARNING); DefaultLogger::get()->warn("} found in dataObject");
} else } else
{ {
// unknown format // unknown format
//os::Printer::log("Unknown data object in animation of .x file", objectName.c_str(), ELL_WARNING); DefaultLogger::get()->warn("Unknown data object in animation of .x file");
ParseUnknownDataObject(); ParseUnknownDataObject();
} }
} }
@ -248,7 +249,7 @@ void XFileParser::ParseDataObjectFrame( Node* pParent)
ParseDataObjectMesh( mesh); ParseDataObjectMesh( mesh);
} else } else
{ {
// os::Printer::log("Unknown data object in frame in x file", objectName.c_str(), ELL_WARNING); DefaultLogger::get()->warn("Unknown data object in frame in x file");
ParseUnknownDataObject(); ParseUnknownDataObject();
} }
} }
@ -338,7 +339,7 @@ void XFileParser::ParseDataObjectMesh( Mesh* pMesh)
ParseDataObjectSkinWeights( pMesh); ParseDataObjectSkinWeights( pMesh);
else else
{ {
//os::Printer::log("Unknown data object in mesh in x file", objectName.c_str(), ELL_WARNING); DefaultLogger::get()->warn("Unknown data object in mesh in x file");
ParseUnknownDataObject(); ParseUnknownDataObject();
} }
} }
@ -533,7 +534,7 @@ void XFileParser::ParseDataObjectMeshMaterialList( Mesh* pMesh)
// ignore // ignore
} else } else
{ {
// os::Printer::log("Unknown data object in material list in x file", objectName.c_str(), ELL_WARNING); DefaultLogger::get()->warn("Unknown data object in material list in x file");
ParseUnknownDataObject(); ParseUnknownDataObject();
} }
} }
@ -571,7 +572,7 @@ void XFileParser::ParseDataObjectMaterial( Material* pMaterial)
pMaterial->mTextures.push_back( texname); pMaterial->mTextures.push_back( texname);
} else } else
{ {
// os::Printer::log("Unknown data object in material in .x file", objectName.c_str(), ELL_WARNING); DefaultLogger::get()->warn("Unknown data object in material in x file");
ParseUnknownDataObject(); ParseUnknownDataObject();
} }
} }
@ -608,7 +609,7 @@ void XFileParser::ParseDataObjectAnimationSet()
ParseDataObjectAnimation( anim); ParseDataObjectAnimation( anim);
else else
{ {
// os::Printer::log("Unknown data object in animation set in x file", objectName.c_str(), ELL_WARNING); DefaultLogger::get()->warn("Unknown data object in animation set in x file");
ParseUnknownDataObject(); ParseUnknownDataObject();
} }
} }
@ -644,7 +645,7 @@ void XFileParser::ParseDataObjectAnimation( Animation* pAnim)
CheckForClosingBrace(); CheckForClosingBrace();
} else } else
{ {
//os::Printer::log("Unknown data object in animation in x file", objectName.c_str(), ELL_WARNING); DefaultLogger::get()->warn("Unknown data object in animation in x file");
ParseUnknownDataObject(); ParseUnknownDataObject();
} }
} }
@ -748,6 +749,12 @@ void XFileParser::ParseDataObjectTextureFilename( std::string& pName)
readHeadOfDataObject(); readHeadOfDataObject();
GetNextTokenAsString( pName); GetNextTokenAsString( pName);
CheckForClosingBrace(); CheckForClosingBrace();
// FIX: some files (e.g. AnimationTest.x) have "" as texture file name
if (!pName.length())
{
DefaultLogger::get()->warn("Length of texture file name is zero. Skipping this texture.");
}
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -49,17 +49,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp; using namespace Assimp;
// ------------------------------------------------------------------------------------------------
MakeVerboseFormatProcess::MakeVerboseFormatProcess() MakeVerboseFormatProcess::MakeVerboseFormatProcess()
{ {
// nothing to do here // nothing to do here
} }
// ------------------------------------------------------------------------------------------------
MakeVerboseFormatProcess::~MakeVerboseFormatProcess() MakeVerboseFormatProcess::~MakeVerboseFormatProcess()
{ {
// nothing to do here // nothing to do here
} }
// ------------------------------------------------------------------- // ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data. // Executes the post processing step on the given imported data.
void MakeVerboseFormatProcess::Execute( aiScene* pScene) void MakeVerboseFormatProcess::Execute( aiScene* pScene)
{ {
@ -76,8 +76,7 @@ void MakeVerboseFormatProcess::Execute( aiScene* pScene)
else DefaultLogger::get()->debug("MakeVerboseFormatProcess. There was nothing to do."); else DefaultLogger::get()->debug("MakeVerboseFormatProcess. There was nothing to do.");
} }
// ------------------------------------------------------------------------------------------------
// -------------------------------------------------------------------
// Executes the post processing step on the given imported data. // Executes the post processing step on the given imported data.
bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh) bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh)
{ {

42
code/qnan.h 100644
View File

@ -0,0 +1,42 @@
#if (!defined AI_QNAN_H_INCLUDED)
#define AI_QNAN_H_INCLUDED
#if (!defined ASSIMP_BUILD_CPP_09)
# include <boost/static_assert.hpp>
#endif
inline bool is_qnan(const float in)
{
// _isnan() takes a double as argument and would
// require a cast. Therefore we must do it on our own ...
// Another method would be to check whether in != in.
// This should also wor since nan compares to inequal,
// even when compared with itself. However, this could
// case problems with other special floats like snan or inf
union _tagFPUNION
{
float f;
int32_t i;
} FPUNION1,FPUNION2;
// use a compile-time asertion if possible
#if (defined ASSIMP_BUILD_CPP_09)
static_assert(sizeof(float)==sizeof(int32_t),
"A float seems not to be 4 bytes on this platform");
#else
BOOST_STATIC_ASSERT(sizeof(float)==sizeof(int32_t));
#endif
FPUNION1.f = in;
FPUNION2.f = std::numeric_limits<float>::quiet_NaN();
return FPUNION1.i == FPUNION2.i;
}
inline bool is_not_qnan(const float in)
{
return !is_qnan(in);
}
#endif // !! AI_QNAN_H_INCLUDED

View File

@ -528,9 +528,9 @@ void ConvertMaterial( aiMaterial* matIn, D3DMATERIAL9* matOut )
Textures: Textures:
Textures can have various types and purposes. Sometimes ASSIMP is not able to Textures can have various types and intended purposes. Sometimes ASSIMP is not able to
determine the exact purpose of a texture. Normally it will assume diffuse as default determine the exact designated use of a texture. Normally it will assume a texture to be
purpose. Possible purposes for a texture: a diffuse color map by default. Texture types:
<b>1. Diffuse textures.</b> Diffuse textures are combined with the result of the diffuse lighting term. <b>1. Diffuse textures.</b> Diffuse textures are combined with the result of the diffuse lighting term.
<br> <br>
@ -549,10 +549,10 @@ normally grayscale images, black stands for fully transparent, white for fully o
<b>6. Height maps.</b> Height maps specify the relative height of a point on a triangle on a <b>6. Height maps.</b> Height maps specify the relative height of a point on a triangle on a
per-texel base. Normally height maps (sometimes called "Bump maps") are converted to normal per-texel base. Normally height maps (sometimes called "Bump maps") are converted to normal
maps before rendering. Height maps are normally grayscale textures. Height maps could also maps before rendering. Height maps are normally grayscale textures. Height maps could also
be used as displacement maps on a highly tesselated surface. be used as displacement maps on highly tesselated surfaces.
<br> <br>
<b>7. Normal maps.</b> Normal maps contain normal vectors for a single texel, in tangent space. <b>7. Normal maps.</b> Normal maps contain normal vectors for a single texel, in tangent space.
They are not bound to an object. However, all lighting omputations must be done in tangent space. They are not bound to an object. However, all lighting computations must be done in tangent space.
There are many resources on Normal Mapping on the internet. There are many resources on Normal Mapping on the internet.
<br> <br>
<b>8. Shininess maps</b> Shininess maps (sometimes called "Gloss" or "SpecularMap") specify <b>8. Shininess maps</b> Shininess maps (sometimes called "Gloss" or "SpecularMap") specify
@ -560,7 +560,7 @@ the shininess of a texel mapped on a surface. They are normally used together wi
to make flat surfaces look as if they were real 3d objects. to make flat surfaces look as if they were real 3d objects.
<br> <br>
Textures are generally defined by a set of parameters, including Textures are generally defined by a set of parameters including
<br> <br>
<b>1. The path to the texture.</b> This property is always set. If it is not set, a texture <b>1. The path to the texture.</b> This property is always set. If it is not set, a texture
is not existing. This can either be a valid path (beware, sometimes is not existing. This can either be a valid path (beware, sometimes
@ -585,26 +585,31 @@ else // your loading code to load from a path ...
<b>2. An UV coordinate index.</b> This is an index into the UV coordinate set list of the <b>2. An UV coordinate index.</b> This is an index into the UV coordinate set list of the
corresponding mesh. Note: Some formats don't define this, so beware, it could be that corresponding mesh. Note: Some formats don't define this, so beware, it could be that
a second diffuse texture in a mesh was originally intended to use a second UV channel although a second diffuse texture in a mesh was originally intended to use a second UV channel although
ASSIMP states it uses the first one. UV coordinate source indices are defined by the ASSIMP says it uses the first one. UV coordinate source indices are defined by the
<i>AI_MATKEY_UVWSRC_<textype>(<texindex>)</i> material property. Assume 0 as default value if <i>AI_MATKEY_UVWSRC_<textype>(<texindex>)</i> material property. Assume 0 as default value if
this property is not set. this property is not set.
<br> <br>
<b>3. A blend factor.</b> This is used if multiple textures are assigned to a slot, e.g. two <b>3. A blend factor.</b> This is used if multiple textures are assigned to a slot, e.g. two
or more textures on the diffuse channel. A texture's color value is multiplied with its or more textures on the diffuse channel. A texture's color value is multiplied with its
blend factor before it is combined with the previous color value (from the last texture) using blend factor before it is combined with the previous color value (from the last texture or the
a specific blend operation (see 4.). Blend factor are defined by the diffuse/specular/ambient/emissive base color) using
a blend operation (see 4.). Blend factor are defined by the
<i>AI_MATKEY_TEXBLEND_<textype>(<texindex>)</i> material property. Assume 1.0f as default value <i>AI_MATKEY_TEXBLEND_<textype>(<texindex>)</i> material property. Assume 1.0f as default value
if this property is not set. if this property is not set.
<br> <br>
<b>4. A blend operation.</b> This is used if multiple textures are assigned to a slot, e.g. two <b>4. A blend operation.</b> This is used if multiple textures are assigned to a slot, e.g. two
or more textures on the diffuse channel. After a texture's color value has been multiplied or more textures on the diffuse channel. After a texture's color value has been multiplied
with its blend factor, the blend operation is used to combine it with the previous color value. with its blend factor, the blend operation is used to combine it with the previous color value
(from the last texture or the diffuse/specular/ambient/emissive base color).
Blend operations are stored as integer property, however their type is aiTextureOp. Blend operations are stored as integer property, however their type is aiTextureOp.
Blend factor are defined by the <i>AI_TEXOP_BLEND_<textype>(<texindex>)</i> material property. Assume Blend factor are defined by the <i>AI_TEXOP_BLEND_<textype>(<texindex>)</i> material property. Assume
aiTextureOp_Multiply as default value if this property is not set. The blend operation for aiTextureOp_Multiply as default value if this property is not set.
the first texture in a texture slot (e.g. diffuse 0) specifies how the diffuse base color/
vertex color have to be combined with the texture color value.
<br> <br>
<b>5. Mapping modes for all axes </b> The mapping mode for an axis specifies how the rendering
system should deal with UV coordinates beyond the 0-1 range. Mapping modes are
defined by the <i>AI_MATKEY_MAPPINGMODE_<axis>_<textype>(<texindex>)</i> material property.
<axis> is either U,V or W. The data type is int, however the real type is aiTextureMapMode.
The default value is aiTextureMapMode_Wrap.
You can use the aiGetMaterialTexture() function to read all texture parameters at once (maybe You can use the aiGetMaterialTexture() function to read all texture parameters at once (maybe
if you're too lazy to read 4 or 5 values manually if there's a smart helper function if you're too lazy to read 4 or 5 values manually if there's a smart helper function
@ -612,13 +617,15 @@ doing all the work for you ...).
@code @code
if (AI_SUCCESS != aiGetMaterialTexture( if (AI_SUCCESS != aiGetMaterialTexture(
pcMat, // Material object pcMat, // aiMaterial structure
0, // first texture in the diffuse slot 0, // we want the first diffuse texture
AI_TEXTYPE_DIFFUSE, // purpose of texture is diffuse AI_TEXTYPE_DIFFUSE, // we want the first diffuse texture
&path, // receives the path of the texture &path, // receives the path of the texture
&uv, // receives the UV index of the texture &uv, // receives the UV index of the texture
&blend, // receives the blend factor of the texture &blend, // receives the blend factor of the texture
&op, // receives the blend operation of the texture &op, // receives the blend operation of the texture
&mmodes, // receives an array of three aiMappingMode's, each specifying
// the mapping mode for a particular axis. Order: UV(W)
// (you may also specify 0 for a parameter if you don't need it) // (you may also specify 0 for a parameter if you don't need it)
)) ))
{ {
@ -626,6 +633,17 @@ if (AI_SUCCESS != aiGetMaterialTexture(
} }
@endcode @endcode
<br>
As you can see, there's much undefined and subject to speculations. When implementing
ASSIMP's material system the most important point was to keep it as flexible as possible.
The first step you should do when you implement ASSIMP materials into your application is
to make a list of all material properties your rendering engine supports, too. Then I suggest
you to take a look at the remaining material properties: many of them can be simplified and replaced
with other properties, e.g. a diffuse texture blend factor can often be premultiplied
with the diffuse base color! At last a few properties you do not support will remain. Forget them.
Most models won't look worse if only small details of its material cannot be rendered as it was intended
by the artist.
@section bones Bones @section bones Bones
A mesh may have a set of bones in the form of aiBone structures.. Bones are a means to deform a mesh A mesh may have a set of bones in the form of aiBone structures.. Bones are a means to deform a mesh

View File

@ -27,7 +27,7 @@ namespace Assimp
* implementation for IOSystem that creates instances of your custom IO class. * implementation for IOSystem that creates instances of your custom IO class.
*/ */
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
class IOStream class ASSIMP_API IOStream
{ {
protected: protected:
/** Constructor protected, use IOSystem::Open() to create an instance. */ /** Constructor protected, use IOSystem::Open() to create an instance. */

View File

@ -11,6 +11,8 @@
#include <string> #include <string>
#include "aiDefines.h"
namespace Assimp namespace Assimp
{ {
@ -23,7 +25,7 @@ class IOStream;
* to the importer library. If you implement this interface, you also want to * to the importer library. If you implement this interface, you also want to
* supply a custom implementation for IOStream. * supply a custom implementation for IOStream.
*/ */
class IOSystem class ASSIMP_API IOSystem
{ {
public: public:
/** Constructor. Create an instance of your derived class and assign it to /** Constructor. Create an instance of your derived class and assign it to

View File

@ -9,7 +9,7 @@ namespace Assimp
/** @class LogStream /** @class LogStream
* @brief Abstract interface for log stream implementations. * @brief Abstract interface for log stream implementations.
*/ */
class LogStream class ASSIMP_API LogStream
{ {
protected: protected:
/** @brief Default constructor */ /** @brief Default constructor */

View File

@ -1,7 +1,48 @@
/*
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.
----------------------------------------------------------------------
*/
#ifndef AI_LOGGER_H_INC #ifndef AI_LOGGER_H_INC
#define AI_LOGGER_H_INC #define AI_LOGGER_H_INC
#include <string> #include <string>
#include "aiDefines.h"
namespace Assimp namespace Assimp
{ {
@ -12,7 +53,7 @@ class LogStream;
/** @class Logger /** @class Logger
* @brief Abstract interface for logger implementations. * @brief Abstract interface for logger implementations.
*/ */
class Logger class ASSIMP_API Logger
{ {
public: public:
/** @enum LogSeverity /** @enum LogSeverity

View File

@ -0,0 +1,97 @@
/*
---------------------------------------------------------------------------
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.
---------------------------------------------------------------------------
*/
#ifndef AI_DEFINES_H_INC
#define AI_DEFINES_H_INC
// compiler specific includes and definitions
#if (defined _MSC_VER)
// include stdint.h from the C98 standard
# include "Compiler/VisualStudio/stdint.h"
# undef ASSIMP_API
// ************************************************************
// Define ASSIMP_BUILD_DLL_EXPORT to build a DLL of the library
// ************************************************************
# if (defined ASSIMP_BUILD_DLL_EXPORT)
# define ASSIMP_API __declspec(dllexport)
// ************************************************************
// Define ASSIMP_DLL before including Assimp to use ASSIMP in
// an external DLL (otherwise a static library is used)
// ************************************************************
# elif (defined ASSIMP_DLL)
# define ASSIMP_API __declspec(dllimport)
# else
# define ASSIMP_API
# endif
#endif // (defined _MSC_VER)
#ifdef __cplusplus
# define C_STRUCT
#else
// ************************************************************
// To build the documentation, make sure ASSIMP_DOXYGEN_BUILD
// is defined by Doxygen's preprocessor. The corresponding
// entries in the DoxyFile look like this:
#if 0
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED = ASSIMP_DOXYGEN_BUILD=1
EXPAND_AS_DEFINED = C_STRUCT
SKIP_FUNCTION_MACROS = YES
#endif
// ************************************************************
# if (defined ASSIMP_DOXYGEN_BUILD)
# define C_STRUCT
# else
# define C_STRUCT struct
# endif
#endif
#endif // !! AI_DEFINES_H_INC

View File

@ -52,6 +52,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
extern "C" { extern "C" {
#endif #endif
// Default material name
#define AI_DEFAULT_MATERIAL_NAME "aiDefaultMat"
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Defines type identifiers for use within the material system. /** Defines type identifiers for use within the material system.
* *
@ -235,6 +238,18 @@ struct aiMaterialProperty
char* mData; char* mData;
}; };
#ifdef __cplusplus
} // need to end extern C block to allow template member functions
#endif
#define AI_TEXTYPE_OPACITY 0x0
#define AI_TEXTYPE_SPECULAR 0x1
#define AI_TEXTYPE_AMBIENT 0x2
#define AI_TEXTYPE_EMISSIVE 0x3
#define AI_TEXTYPE_HEIGHT 0x4
#define AI_TEXTYPE_NORMALS 0x5
#define AI_TEXTYPE_SHININESS 0x6
#define AI_TEXTYPE_DIFFUSE 0x7
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Data structure for a material /** Data structure for a material
@ -245,13 +260,67 @@ struct aiMaterialProperty
* enough for nearly all purposes. * enough for nearly all purposes.
*/ */
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
struct aiMaterial struct ASSIMP_API aiMaterial
{ {
#ifdef __cplusplus #ifdef __cplusplus
protected: protected:
aiMaterial() {} aiMaterial() {}
public: public:
#endif // __cplusplus
// -------------------------------------------------------------------
/** Retrieve an array of Type values with a specific key
* from the material
*
* @param pKey Key to search for. One of the AI_MATKEY_XXX constants.
* @param pOut Pointer to a buffer to receive the result.
* @param pMax Specifies the size of the given buffer, in Type's.
* Receives the number of values (not bytes!) read.
* NULL is a valid value for this parameter.
*/
template <typename Type>
inline aiReturn Get(const char* pKey,Type* pOut,
unsigned int* pMax);
// -------------------------------------------------------------------
/** Retrieve a Type value with a specific key
* from the material
*
* @param pKey Key to search for. One of the AI_MATKEY_XXX constants.
* @param pOut Reference to receive the output value
*/
template <typename Type>
inline aiReturn Get(const char* pKey,Type& pOut);
// -------------------------------------------------------------------
/** Helper function to get a texture from a material
*
* This function is provided just for convinience.
* @param iIndex Index of the texture to retrieve. If the index is too
* large the function fails.
* @param iTexType One of the AI_TEXTYPE constants. Specifies the type of
* the texture to retrieve (e.g. diffuse, specular, height map ...)
* @param szPath Receives the output path
* NULL is no allowed as value
* @param piUVIndex Receives the UV index of the texture.
* NULL is allowed as value.
* @param pfBlendFactor Receives the blend factor for the texture
* NULL is allowed as value.
* @param peTextureOp Receives the texture operation to perform between
* this texture and the previous texture. NULL is allowed as value.
* @param peMapMode Receives the mapping modes to be used for the texture.
* The parameter may be NULL but if it is a valid pointer it MUST
* point to an array of 3 aiTextureMapMode variables (one for each
* axis: UVW order (=XYZ)).
*/
// -------------------------------------------------------------------
inline aiReturn GetTexture(unsigned int iIndex,
unsigned int iTexType,
C_STRUCT aiString* szPath,
unsigned int* piUVIndex = NULL,
float* pfBlendFactor = NULL,
aiTextureOp* peTextureOp = NULL,
aiTextureMapMode* peMapMode = NULL);
#endif
/** List of all material properties loaded. /** List of all material properties loaded.
*/ */
@ -263,6 +332,11 @@ public:
unsigned int mNumAllocated; unsigned int mNumAllocated;
}; };
#ifdef __cplusplus
extern "C" {
#endif
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** @def AI_BUILD_KEY /** @def AI_BUILD_KEY
* Builds a material texture key with a dynamic index. * Builds a material texture key with a dynamic index.
@ -300,13 +374,27 @@ public:
* @param out Array of chars to receive the output value. It must be * @param out Array of chars to receive the output value. It must be
* sufficiently large. This will be checked via a static assertion for * sufficiently large. This will be checked via a static assertion for
* C++0x. For MSVC8 and later versions the security enhanced version of * C++0x. For MSVC8 and later versions the security enhanced version of
* sprintf() will be used. However, if your buffer is at least 512 bytes * sprintf() will be used. However, if your buffer is at least 256 bytes
* long you'll never overrun. * long you'll never overrun.
*/ */
// ---------------------------------------------------------------------------
#if _MSC_VER >= 1400 #if _MSC_VER >= 1400
// MSVC 8+. Use the sprintf_s function with security enhancements
# define AI_BUILD_KEY(base,index,out) \ # define AI_BUILD_KEY(base,index,out) \
::sprintf_s(out,"%s[%i]",base,index); ::sprintf_s(out,"%s[%i]",base,index);
#elif (defined ASSIMP_BUILD_CPP_09)
// C++09 compiler. Use a static assertion to validate the size
// of the output buffer
# define AI_BUILD_KEY(base,index,out) \
static_assert(sizeof(out) >= 180,"Output buffer is too small"); \
::sprintf(out,"%s[%i]",base,index);
#else #else
// otherwise ... simply hope the buffer is large enough :-)
# define AI_BUILD_KEY(base,index,out) \ # define AI_BUILD_KEY(base,index,out) \
::sprintf(out,"%s[%i]",base,index); ::sprintf(out,"%s[%i]",base,index);
#endif #endif
@ -416,7 +504,7 @@ public:
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** @def AI_MATKEY_TEXTURE_DIFFUSE /** @def AI_MATKEY_TEXTURE_DIFFUSE
* Defines a specified diffuse texture channel of the material * Defines a specific diffuse texture channel of the material
* <br> * <br>
* <b>Type:</b> string (aiString)<br> * <b>Type:</b> string (aiString)<br>
* <b>Default value:</b> none <br> * <b>Default value:</b> none <br>
@ -429,7 +517,7 @@ public:
#define AI_MATKEY_TEXTURE_DIFFUSE_ "$tex.file.diffuse" #define AI_MATKEY_TEXTURE_DIFFUSE_ "$tex.file.diffuse"
/** @def AI_MATKEY_TEXTURE_AMBIENT /** @def AI_MATKEY_TEXTURE_AMBIENT
* Defines a specified ambient texture channel of the material * Defines a specific ambient texture channel of the material
* <br> * <br>
* <b>Type:</b> string (aiString)<br> * <b>Type:</b> string (aiString)<br>
* <b>Default value:</b> none <br> * <b>Default value:</b> none <br>
@ -442,7 +530,7 @@ public:
#define AI_MATKEY_TEXTURE_AMBIENT_ "$tex.file.ambient" #define AI_MATKEY_TEXTURE_AMBIENT_ "$tex.file.ambient"
/** @def AI_MATKEY_TEXTURE_SPECULAR /** @def AI_MATKEY_TEXTURE_SPECULAR
* Defines a specified specular texture channel of the material * Defines a specific specular texture channel of the material
* <br> * <br>
* <b>Type:</b> string (aiString)<br> * <b>Type:</b> string (aiString)<br>
* <b>Default value:</b> none <br> * <b>Default value:</b> none <br>
@ -455,7 +543,7 @@ public:
#define AI_MATKEY_TEXTURE_SPECULAR_ "$tex.file.specular" #define AI_MATKEY_TEXTURE_SPECULAR_ "$tex.file.specular"
/** @def AI_MATKEY_TEXTURE_EMISSIVE /** @def AI_MATKEY_TEXTURE_EMISSIVE
* Defines a specified emissive texture channel of the material * Defines a specific emissive texture channel of the material
* <br> * <br>
* <b>Type:</b> string (aiString)<br> * <b>Type:</b> string (aiString)<br>
* <b>Default value:</b> none <br> * <b>Default value:</b> none <br>
@ -468,7 +556,7 @@ public:
#define AI_MATKEY_TEXTURE_EMISSIVE_ "$tex.file.emissive" #define AI_MATKEY_TEXTURE_EMISSIVE_ "$tex.file.emissive"
/** @def AI_MATKEY_TEXTURE_NORMALS /** @def AI_MATKEY_TEXTURE_NORMALS
* Defines a specified normal texture channel of the material * Defines a specific normal texture channel of the material
* <br> * <br>
* <b>Type:</b> string (aiString)<br> * <b>Type:</b> string (aiString)<br>
* <b>Default value:</b> none <br> * <b>Default value:</b> none <br>
@ -498,7 +586,7 @@ public:
#define AI_MATKEY_TEXTURE_HEIGHT_ "$tex.file.height" #define AI_MATKEY_TEXTURE_HEIGHT_ "$tex.file.height"
/** @def AI_MATKEY_TEXTURE_SHININESS /** @def AI_MATKEY_TEXTURE_SHININESS
* Defines a specified shininess texture channel of the material * Defines a specific shininess texture channel of the material
* <br> * <br>
* <b>Type:</b> string (aiString)<br> * <b>Type:</b> string (aiString)<br>
* <b>Default value:</b> none <br> * <b>Default value:</b> none <br>
@ -511,7 +599,7 @@ public:
#define AI_MATKEY_TEXTURE_SHININESS_ "$tex.file.shininess" #define AI_MATKEY_TEXTURE_SHININESS_ "$tex.file.shininess"
/** @def AI_MATKEY_TEXTURE_OPACITY /** @def AI_MATKEY_TEXTURE_OPACITY
* Defines a specified opacity texture channel of the material * Defines a specific opacity texture channel of the material
* <br> * <br>
* <b>Type:</b> string (aiString)<br> * <b>Type:</b> string (aiString)<br>
* <b>Default value:</b> none <br> * <b>Default value:</b> none <br>
@ -772,7 +860,7 @@ public:
* structure or NULL if the key has not been found. * structure or NULL if the key has not been found.
*/ */
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
aiReturn aiGetMaterialProperty(const C_STRUCT aiMaterial* pMat, ASSIMP_API aiReturn aiGetMaterialProperty(const C_STRUCT aiMaterial* pMat,
const char* pKey, const char* pKey,
const C_STRUCT aiMaterialProperty** pPropOut); const C_STRUCT aiMaterialProperty** pPropOut);
@ -788,7 +876,7 @@ aiReturn aiGetMaterialProperty(const C_STRUCT aiMaterial* pMat,
* Receives the number of values (not bytes!) read. * Receives the number of values (not bytes!) read.
*/ */
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
aiReturn aiGetMaterialFloatArray(const C_STRUCT aiMaterial* pMat, ASSIMP_API aiReturn aiGetMaterialFloatArray(const C_STRUCT aiMaterial* pMat,
const char* pKey, const char* pKey,
float* pOut, float* pOut,
unsigned int* pMax); unsigned int* pMax);
@ -817,7 +905,7 @@ inline aiReturn aiGetMaterialFloat(const C_STRUCT aiMaterial* pMat,
* Receives the number of values (not bytes!) read. * Receives the number of values (not bytes!) read.
*/ */
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
aiReturn aiGetMaterialIntegerArray(const C_STRUCT aiMaterial* pMat, ASSIMP_API aiReturn aiGetMaterialIntegerArray(const C_STRUCT aiMaterial* pMat,
const char* pKey, const char* pKey,
int* pOut, int* pOut,
unsigned int* pMax); unsigned int* pMax);
@ -844,7 +932,7 @@ inline aiReturn aiGetMaterialInteger(const C_STRUCT aiMaterial* pMat,
* @param pOut Pointer to a buffer to receive the result. * @param pOut Pointer to a buffer to receive the result.
*/ */
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
aiReturn aiGetMaterialColor(const C_STRUCT aiMaterial* pMat, ASSIMP_API aiReturn aiGetMaterialColor(const C_STRUCT aiMaterial* pMat,
const char* pKey, const char* pKey,
aiColor4D* pOut); aiColor4D* pOut);
@ -857,20 +945,11 @@ aiReturn aiGetMaterialColor(const C_STRUCT aiMaterial* pMat,
* @param pOut Pointer to a buffer to receive the result. * @param pOut Pointer to a buffer to receive the result.
*/ */
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
aiReturn aiGetMaterialString(const C_STRUCT aiMaterial* pMat, ASSIMP_API aiReturn aiGetMaterialString(const C_STRUCT aiMaterial* pMat,
const char* pKey, const char* pKey,
aiString* pOut); aiString* pOut);
#define AI_TEXTYPE_OPACITY 0x0
#define AI_TEXTYPE_SPECULAR 0x1
#define AI_TEXTYPE_AMBIENT 0x2
#define AI_TEXTYPE_EMISSIVE 0x3
#define AI_TEXTYPE_HEIGHT 0x4
#define AI_TEXTYPE_NORMALS 0x5
#define AI_TEXTYPE_SHININESS 0x6
#define AI_TEXTYPE_DIFFUSE 0x7
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Helper function to get a texture from a material /** Helper function to get a texture from a material
* *
@ -895,7 +974,7 @@ aiReturn aiGetMaterialString(const C_STRUCT aiMaterial* pMat,
*/ */
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
#ifdef __cplusplus #ifdef __cplusplus
aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* pMat, ASSIMP_API aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* pMat,
unsigned int iIndex, unsigned int iIndex,
unsigned int iTexType, unsigned int iTexType,
C_STRUCT aiString* szPath, C_STRUCT aiString* szPath,
@ -920,5 +999,4 @@ aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* pMat,
#include "aiMaterial.inl" #include "aiMaterial.inl"
#endif //!__cplusplus #endif //!__cplusplus
#endif //!!AI_MATERIAL_H_INC #endif //!!AI_MATERIAL_H_INC

View File

@ -46,46 +46,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_MATERIAL_INL_INC #ifndef AI_MATERIAL_INL_INC
#define AI_MATERIAL_INL_INC #define AI_MATERIAL_INL_INC
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** @brief A class that provides easy access to the property list of a inline aiReturn aiMaterial::GetTexture(unsigned int iIndex,
* material (aiMaterial) via template methods. You can cast an unsigned int iTexType,
* aiMaterial* to aiMaterialCPP* aiString* szPath,
* @note This extra class is necessary since template methods unsigned int* piUVIndex ,
* are not allowed within C-linkage blocks (extern "C") float* pfBlendFactor ,
*/ aiTextureOp* peTextureOp ,
class aiMaterialCPP : public aiMaterial aiTextureMapMode* peMapMode )
{ {
public: return aiGetMaterialTexture(this,iIndex,iTexType,szPath,
piUVIndex,pfBlendFactor,peTextureOp,peMapMode);
// ------------------------------------------------------------------- }
/** Retrieve an array of Type values with a specific key
* from the material
*
* @param pKey Key to search for. One of the AI_MATKEY_XXX constants.
* @param pOut Pointer to a buffer to receive the result.
* @param pMax Specifies the size of the given buffer, in Type's.
* Receives the number of values (not bytes!) read.
* NULL is a valid value for this parameter.
*/
template <typename Type>
inline aiReturn Get(const char* pKey,Type* pOut,
unsigned int* pMax);
// -------------------------------------------------------------------
/** Retrieve a Type value with a specific key
* from the material
*
* @param pKey Key to search for. One of the AI_MATKEY_XXX constants.
* @param pOut Reference to receive the output value
*/
template <typename Type>
inline aiReturn Get(const char* pKey,Type& pOut);
};
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
template <typename Type> template <typename Type>
inline aiReturn aiMaterialCPP::Get(const char* pKey,Type* pOut, inline aiReturn aiMaterial::Get(const char* pKey,Type* pOut,
unsigned int* pMax) unsigned int* pMax)
{ {
unsigned int iNum = pMax ? *pMax : 1; unsigned int iNum = pMax ? *pMax : 1;
@ -105,7 +80,7 @@ inline aiReturn aiMaterialCPP::Get(const char* pKey,Type* pOut,
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
template <typename Type> template <typename Type>
inline aiReturn aiMaterialCPP::Get(const char* pKey,Type& pOut) inline aiReturn aiMaterial::Get(const char* pKey,Type& pOut)
{ {
aiMaterialProperty* prop; aiMaterialProperty* prop;
aiReturn ret = aiGetMaterialProperty(this,pKey,&prop); aiReturn ret = aiGetMaterialProperty(this,pKey,&prop);
@ -120,39 +95,39 @@ inline aiReturn aiMaterialCPP::Get(const char* pKey,Type& pOut)
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
template <> template <>
inline aiReturn aiMaterialCPP::Get<float>(const char* pKey,float* pOut, inline aiReturn aiMaterial::Get<float>(const char* pKey,float* pOut,
unsigned int* pMax) unsigned int* pMax)
{ {
return aiGetMaterialFloatArray(this,pKey,pOut,pMax); return aiGetMaterialFloatArray(this,pKey,pOut,pMax);
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
template <> template <>
inline aiReturn aiMaterialCPP::Get<int>(const char* pKey,int* pOut, inline aiReturn aiMaterial::Get<int>(const char* pKey,int* pOut,
unsigned int* pMax) unsigned int* pMax)
{ {
return aiGetMaterialIntegerArray(this,pKey,pOut,pMax); return aiGetMaterialIntegerArray(this,pKey,pOut,pMax);
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
template <> template <>
inline aiReturn aiMaterialCPP::Get<float>(const char* pKey,float& pOut) inline aiReturn aiMaterial::Get<float>(const char* pKey,float& pOut)
{ {
return aiGetMaterialFloat(this,pKey,&pOut); return aiGetMaterialFloat(this,pKey,&pOut);
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
template <> template <>
inline aiReturn aiMaterialCPP::Get<int>(const char* pKey,int& pOut) inline aiReturn aiMaterial::Get<int>(const char* pKey,int& pOut)
{ {
return aiGetMaterialInteger(this,pKey,&pOut); return aiGetMaterialInteger(this,pKey,&pOut);
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
template <> template <>
inline aiReturn aiMaterialCPP::Get<aiColor4D>(const char* pKey,aiColor4D& pOut) inline aiReturn aiMaterial::Get<aiColor4D>(const char* pKey,aiColor4D& pOut)
{ {
return aiGetMaterialColor(this,pKey,&pOut); return aiGetMaterialColor(this,pKey,&pOut);
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
template <> template <>
inline aiReturn aiMaterialCPP::Get<aiString>(const char* pKey,aiString& pOut) inline aiReturn aiMaterial::Get<aiString>(const char* pKey,aiString& pOut)
{ {
return aiGetMaterialString(this,pKey,&pOut); return aiGetMaterialString(this,pKey,&pOut);
} }

View File

@ -9,7 +9,7 @@ extern "C" {
struct aiMatrix4x4; struct aiMatrix4x4;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Represents a column-major 3x3 matrix /** Represents a row-major 3x3 matrix
*/ */
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
struct aiMatrix3x3 struct aiMatrix3x3
@ -28,7 +28,8 @@ struct aiMatrix3x3
c1(_c1), c2(_c2), c3(_c3) c1(_c1), c2(_c2), c3(_c3)
{} {}
/** Construction from a 4x4 matrix. The remaining parts of the matrix are ignored. */ /** Construction from a 4x4 matrix. The remaining parts of the
matrix are ignored. */
explicit aiMatrix3x3( const aiMatrix4x4& pMatrix); explicit aiMatrix3x3( const aiMatrix4x4& pMatrix);
aiMatrix3x3& operator *= (const aiMatrix3x3& m); aiMatrix3x3& operator *= (const aiMatrix3x3& m);

View File

@ -50,5 +50,6 @@ inline aiMatrix3x3& aiMatrix3x3::Transpose()
} }
#endif // __cplusplus #endif // __cplusplus
#endif // AI_MATRIX3x3_INL_INC #endif // AI_MATRIX3x3_INL_INC

View File

@ -7,6 +7,7 @@ extern "C" {
#endif #endif
struct aiMatrix3x3; struct aiMatrix3x3;
struct aiQuaternion;
// Set packing to 4 // Set packing to 4
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) #if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
@ -19,7 +20,7 @@ struct aiMatrix3x3;
#endif #endif
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Represents a column-major 4x4 matrix, /** Represents a row-major 4x4 matrix,
* use this for homogenious coordinates * use this for homogenious coordinates
*/ */
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -57,6 +58,35 @@ struct aiMatrix4x4
inline bool operator== (const aiMatrix4x4 m) const; inline bool operator== (const aiMatrix4x4 m) const;
inline bool operator!= (const aiMatrix4x4 m) const; inline bool operator!= (const aiMatrix4x4 m) const;
/** \brief Decompose a trafo matrix into its original components
* \param scaling Receives the output scaling for the x,y,z axes
* \param rotation Receives the output rotation as a hamilton
* quaternion
* \param position Receives the output position for the x,y,z axes
*/
inline void Decompose (aiVector3D& scaling, aiQuaternion& rotation,
aiVector3D& position) const;
/** \brief Decompose a trafo matrix with no scaling into its
* original components
* \param rotation Receives the output rotation as a hamilton
* quaternion
* \param position Receives the output position for the x,y,z axes
*/
inline void DecomposeNoScaling (aiQuaternion& rotation,
aiVector3D& position) const;
/** \brief Creates a trafo matrix from a set of euler angles
* \param x Rotation angle for the x-axis, in radians
* \param y Rotation angle for the y-axis, in radians
* \param z Rotation angle for the z-axis, in radians
*/
inline void FromEulerAngles(float x, float y, float z);
#endif // __cplusplus #endif // __cplusplus
float a1, a2, a3, a4; float a1, a2, a3, a4;

View File

@ -11,6 +11,9 @@
#include <limits> #include <limits>
#include <math.h> #include <math.h>
#include "aiAssert.h"
#include "aiQuaternion.h"
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
inline aiMatrix4x4::aiMatrix4x4( const aiMatrix3x3& m) inline aiMatrix4x4::aiMatrix4x4( const aiMatrix3x3& m)
{ {
@ -144,6 +147,96 @@ inline bool aiMatrix4x4::operator!= (const aiMatrix4x4 m) const
{ {
return !(*this == m); return !(*this == m);
} }
// ---------------------------------------------------------------------------
inline void aiMatrix4x4::Decompose (aiVector3D& scaling, aiQuaternion& rotation,
aiVector3D& position) const
{
const aiMatrix4x4& _this = *this;
// extract translation
position.x = _this[0][3];
position.y = _this[1][3];
position.z = _this[2][3];
// extract the rows of the matrix
aiVector3D vRows[3] = {
aiVector3D(_this[0][0],_this[1][1],_this[2][0]),
aiVector3D(_this[0][1],_this[1][1],_this[2][1]),
aiVector3D(_this[0][2],_this[1][2],_this[2][2])
};
// extract the scaling factors
scaling.x = vRows[0].Length();
scaling.y = vRows[1].Length();
scaling.z = vRows[2].Length();
// and remove all scaling from the matrix
if(scaling.x)
{
vRows[0].x /= scaling.x;
vRows[0].y /= scaling.x;
vRows[0].z /= scaling.x;
}
if(scaling.y)
{
vRows[1].x /= scaling.y;
vRows[1].y /= scaling.y;
vRows[1].z /= scaling.y;
}
if(scaling.z)
{
vRows[2].x /= scaling.z;
vRows[2].y /= scaling.z;
vRows[2].z /= scaling.z;
}
// build a 3x3 rotation matrix
aiMatrix3x3 m(vRows[0].x,vRows[0].y,vRows[0].z,
vRows[1].x,vRows[1].y,vRows[1].z,
vRows[2].x,vRows[2].y,vRows[2].z);
// and generate the rotation quaternion from it
rotation = aiQuaternion(m);
}
// ---------------------------------------------------------------------------
inline void aiMatrix4x4::DecomposeNoScaling (aiQuaternion& rotation,
aiVector3D& position) const
{
const aiMatrix4x4& _this = *this;
// extract translation
position.x = _this[0][3];
position.y = _this[1][3];
position.z = _this[2][3];
// extract rotation
rotation = aiQuaternion((aiMatrix3x3)_this);
}
// ---------------------------------------------------------------------------
inline void aiMatrix4x4::FromEulerAngles(float x, float y, float z)
{
aiMatrix4x4& _this = *this;
const float A = ::cosf(x);
const float B = ::sinf(x);
const float C = ::cosf(y);
const float D = ::sinf(y);
const float E = ::cosf(z);
const float F = ::sinf(z);
const float AD = A * D;
const float BD = B * D;
_this.a1 = C * E;
_this.a2 = -C * F;
_this.a3 = D;
_this.b1 = BD * E + A * F;
_this.b2 = -BD * F + A * E;
_this.b3 = -B * C;
_this.c1 = -AD * E + B * F;
_this.c2 = AD * F + B * E;
_this.c3 = A * C;
_this.a4 = _this.b4 = _this.c4 = _this.d1 = _this.d2 = _this.d3 = 0.0f;
_this.d4 = 1.0f;
}
#endif // __cplusplus #endif // __cplusplus
#endif // AI_MATRIX4x4_INL_INC #endif // AI_MATRIX4x4_INL_INC

View File

@ -130,8 +130,10 @@ enum aiPostProcessSteps
* to a maximum value. If any vertex is affected by more than that number * to a maximum value. If any vertex is affected by more than that number
* of bones, the least important vertex weights are removed and the remaining * of bones, the least important vertex weights are removed and the remaining
* vertex weights are renormalized so that the weights still sum up to 1. * vertex weights are renormalized so that the weights still sum up to 1.
* At the moment the maximum bone count is hardcoded to 4. * The default bone weight limit is 4 (defined as AI_LMW_MAX_WEIGHTS in
* * LimitBoneWeightsProcess.h), but you can use the aiSetBoneWeightLimit
* function to supply your own limit to the post processing step.
*
* If you intend to perform the skinning in hardware, this post processing step * If you intend to perform the skinning in hardware, this post processing step
* might be of interest for you. * might be of interest for you.
*/ */
@ -156,8 +158,7 @@ enum aiPostProcessSteps
* \note The default value is AI_SLM_DEFAULT_MAX_VERTICES, defined in * \note The default value is AI_SLM_DEFAULT_MAX_VERTICES, defined in
* the internal header file SplitLargeMeshes.h * the internal header file SplitLargeMeshes.h
*/ */
aiReturn aiSetVertexSplitLimit(unsigned int pLimit); ASSIMP_API aiReturn aiSetVertexSplitLimit(unsigned int pLimit);
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \brief Set the maximum number of triangles in a mesh. /** \brief Set the maximum number of triangles in a mesh.
@ -168,7 +169,17 @@ aiReturn aiSetVertexSplitLimit(unsigned int pLimit);
* \note The default value is AI_SLM_DEFAULT_MAX_TRIANGLES, defined in * \note The default value is AI_SLM_DEFAULT_MAX_TRIANGLES, defined in
* the internal header file SplitLargeMeshes.h * the internal header file SplitLargeMeshes.h
*/ */
aiReturn aiSetTriangleSplitLimit(unsigned int pLimit); ASSIMP_API aiReturn aiSetTriangleSplitLimit(unsigned int pLimit);
// ---------------------------------------------------------------------------
/** \brief Set the maximum number of bones affecting a single vertex
*
* This is used by the aiProcess_LimitBoneWeights PostProcess-Step.
* \param pLimit Bone limit
* \note The default value is AI_LMW_MAX_WEIGHTS, defined in
* the internal header file LimitBoneWeightsProcess.h
*/
ASSIMP_API aiReturn aiSetBoneWeightLimit(unsigned int pLimit);
#ifdef __cplusplus #ifdef __cplusplus
} // end of extern "C" } // end of extern "C"

View File

@ -16,9 +16,13 @@ struct aiQuaternion
#ifdef __cplusplus #ifdef __cplusplus
aiQuaternion() : w(0.0f), x(0.0f), y(0.0f), z(0.0f) {} aiQuaternion() : w(0.0f), x(0.0f), y(0.0f), z(0.0f) {}
aiQuaternion(float _w, float _x, float _y, float _z) : w(_w), x(_x), y(_y), z(_z) {} aiQuaternion(float _w, float _x, float _y, float _z) : w(_w), x(_x), y(_y), z(_z) {}
/** Construct from rotation matrix. Result is undefined if the matrix is not orthonormal. */ /** Construct from rotation matrix. Result is undefined if the matrix is not orthonormal. */
aiQuaternion( const aiMatrix3x3& pRotMatrix); aiQuaternion( const aiMatrix3x3& pRotMatrix);
/** Construct from euler angles */
aiQuaternion( float rotx, float roty, float rotz);
/** Returns a matrix representation of the quaternion */ /** Returns a matrix representation of the quaternion */
aiMatrix3x3 GetMatrix() const; aiMatrix3x3 GetMatrix() const;
#endif // __cplusplus #endif // __cplusplus
@ -73,6 +77,24 @@ inline aiQuaternion::aiQuaternion( const aiMatrix3x3 &pRotMatrix)
} }
} }
// ---------------------------------------------------------------------------
// Construction from euler angles
inline aiQuaternion::aiQuaternion( float fPitch, float fYaw, float fRoll )
{
const float fSinPitch(sin(fPitch*0.5F));
const float fCosPitch(cos(fPitch*0.5F));
const float fSinYaw(sin(fYaw*0.5F));
const float fCosYaw(cos(fYaw*0.5F));
const float fSinRoll(sin(fRoll*0.5F));
const float fCosRoll(cos(fRoll*0.5F));
const float fCosPitchCosYaw(fCosPitch*fCosYaw);
const float fSinPitchSinYaw(fSinPitch*fSinYaw);
x = fSinRoll * fCosPitchCosYaw - fCosRoll * fSinPitchSinYaw;
y = fCosRoll * fSinPitch * fCosYaw + fSinRoll * fCosPitch * fSinYaw;
z = fCosRoll * fCosPitch * fSinYaw - fSinRoll * fSinPitch * fCosYaw;
w = fCosRoll * fCosPitchCosYaw + fSinRoll * fSinPitchSinYaw;
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Returns a matrix representation of the quaternion // Returns a matrix representation of the quaternion
inline aiMatrix3x3 aiQuaternion::GetMatrix() const inline aiMatrix3x3 aiQuaternion::GetMatrix() const
@ -91,6 +113,8 @@ inline aiMatrix3x3 aiQuaternion::GetMatrix() const
return resMatrix; return resMatrix;
} }
} // end extern "C" } // end extern "C"
#endif // __cplusplus #endif // __cplusplus

View File

@ -94,6 +94,7 @@ struct aiNode
/** Constructor */ /** Constructor */
aiNode() aiNode()
{ {
// set all members to zero by default
mParent = NULL; mParent = NULL;
mNumChildren = 0; mChildren = NULL; mNumChildren = 0; mChildren = NULL;
mNumMeshes = 0; mMeshes = NULL; mNumMeshes = 0; mMeshes = NULL;
@ -102,6 +103,7 @@ struct aiNode
/** Destructor */ /** Destructor */
~aiNode() ~aiNode()
{ {
// delete al children recursively
for( unsigned int a = 0; a < mNumChildren; a++) for( unsigned int a = 0; a < mNumChildren; a++)
delete mChildren[a]; delete mChildren[a];
delete [] mChildren; delete [] mChildren;
@ -127,6 +129,8 @@ struct aiScene
*/ */
C_STRUCT aiNode* mRootNode; C_STRUCT aiNode* mRootNode;
/** The number of meshes in the scene. */ /** The number of meshes in the scene. */
unsigned int mNumMeshes; unsigned int mNumMeshes;
@ -137,6 +141,8 @@ struct aiScene
*/ */
C_STRUCT aiMesh** mMeshes; C_STRUCT aiMesh** mMeshes;
/** The number of materials in the scene. */ /** The number of materials in the scene. */
unsigned int mNumMaterials; unsigned int mNumMaterials;
@ -147,6 +153,8 @@ struct aiScene
*/ */
C_STRUCT aiMaterial** mMaterials; C_STRUCT aiMaterial** mMaterials;
/** The number of animations in the scene. */ /** The number of animations in the scene. */
unsigned int mNumAnimations; unsigned int mNumAnimations;
@ -157,20 +165,25 @@ struct aiScene
*/ */
C_STRUCT aiAnimation** mAnimations; C_STRUCT aiAnimation** mAnimations;
/** The number of textures embedded into the file */ /** The number of textures embedded into the file */
unsigned int mNumTextures; unsigned int mNumTextures;
/** The array of embedded textures. /** The array of embedded textures.
* *
* Not many file formats embedd their textures into the file. * Not many file formats embedd their textures into the file.
* Examples include Quake's MDL format (which is also used by * An example is Quake's MDL format (which is also used by
* some GameStudio™ versions) * some GameStudio™ versions)
*/ */
C_STRUCT aiTexture** mTextures; C_STRUCT aiTexture** mTextures;
#ifdef __cplusplus #ifdef __cplusplus
//! Default constructor
aiScene() aiScene()
{ {
// set all members to zero by default
mRootNode = NULL; mRootNode = NULL;
mNumMeshes = 0; mMeshes = NULL; mNumMeshes = 0; mMeshes = NULL;
mNumMaterials = 0; mMaterials = NULL; mNumMaterials = 0; mMaterials = NULL;
@ -178,8 +191,10 @@ struct aiScene
mNumTextures = 0; mTextures = NULL; mNumTextures = 0; mTextures = NULL;
} }
//! Destructor
~aiScene() ~aiScene()
{ {
// delete all subobjects recursively
delete mRootNode; delete mRootNode;
for( unsigned int a = 0; a < mNumMeshes; a++) for( unsigned int a = 0; a < mNumMeshes; a++)
delete mMeshes[a]; delete mMeshes[a];

View File

@ -68,6 +68,21 @@ struct aiTexel
unsigned char g; unsigned char g;
unsigned char r; unsigned char r;
unsigned char a; unsigned char a;
//! Comparison operator
bool operator== (const aiTexel& other) const
{
return b == other.b && r == other.r &&
g == other.g && a == other.a;
}
//! Negative comparison operator
bool operator!= (const aiTexel& other) const
{
return b != other.b || r != other.r ||
g != other.g || a != other.a;
}
} PACK_STRUCT; } PACK_STRUCT;
// reset packing to the original value // reset packing to the original value

View File

@ -45,10 +45,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <sys/types.h> #include <sys/types.h>
#include <memory.h> #include <memory.h>
#if (defined _MSC_VER) #include "aiDefines.h"
# include "Compiler/VisualStudio/stdint.h"
#endif // (defined _MSC_VER)
// include math helper classes and their implementations
#include "aiVector3D.h" #include "aiVector3D.h"
#include "aiMatrix3x3.h" #include "aiMatrix3x3.h"
#include "aiMatrix4x4.h" #include "aiMatrix4x4.h"
@ -59,13 +58,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef __cplusplus #ifdef __cplusplus
# include <string> # include <string>
extern "C" { extern "C" {
# define C_STRUCT
#else
# if (defined ASSIMP_DOXYGEN_BUILD)
# define C_STRUCT
# else
# define C_STRUCT struct
# endif
#endif #endif
/** Maximum dimension for strings, ASSIMP strings are zero terminated */ /** Maximum dimension for strings, ASSIMP strings are zero terminated */
@ -145,14 +137,14 @@ struct aiString
inline aiString() : inline aiString() :
length(0) length(0)
{ {
// empty data[0] = '\0';
} }
//! construction from a given std::string //! construction from a given std::string
inline aiString(const aiString& rOther) : inline aiString(const aiString& rOther) :
length(rOther.length) length(rOther.length)
{ {
memcpy( data, rOther.data, rOther.length); ::memcpy( data, rOther.data, rOther.length);
this->data[this->length] = '\0'; this->data[this->length] = '\0';
} }
@ -162,7 +154,7 @@ struct aiString
if( pString.length() > MAXLEN - 1) if( pString.length() > MAXLEN - 1)
return; return;
length = pString.length(); length = pString.length();
memcpy( data, pString.c_str(), length); ::memcpy( data, pString.c_str(), length);
data[length] = 0; data[length] = 0;
} }
@ -177,7 +169,7 @@ struct aiString
bool operator!=(const aiString& other) const bool operator!=(const aiString& other) const
{ {
return (this->length != other.length || return (this->length != other.length ||
0 != strcmp(this->data,other.data)); 0 != ::strcmp(this->data,other.data));
} }
@ -194,11 +186,10 @@ struct aiString
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Standard return type for all library functions. /** Standard return type for all library functions.
* *
* To check whether a function failed or not check against * To check whether or not a function failed check against
* AI_SUCCESS. * AI_SUCCESS. The error codes are mainly used by the C-API.
*/ */
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
enum aiReturn enum aiReturn
{ {
//! Indicates that a function was successful //! Indicates that a function was successful

View File

@ -71,7 +71,8 @@ struct aiString;
* @return Pointer to the imported data or NULL if the import failed. * @return Pointer to the imported data or NULL if the import failed.
*/ */
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
const C_STRUCT aiScene* aiImportFile( const char* pFile, unsigned int pFlags); ASSIMP_API const C_STRUCT aiScene* aiImportFile( const char* pFile,
unsigned int pFlags);
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -94,8 +95,8 @@ const C_STRUCT aiScene* aiImportFile( const char* pFile, unsigned int pFlags);
* to this function. Therefore the C-API is thread-safe. * to this function. Therefore the C-API is thread-safe.
*/ */
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
const C_STRUCT aiScene* aiImportFileEx( const C_STRUCT aiFileIO* pFile); ASSIMP_API const C_STRUCT aiScene* aiImportFileEx(
const C_STRUCT aiFileIO* pFile);
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -105,7 +106,7 @@ const C_STRUCT aiScene* aiImportFileEx( const C_STRUCT aiFileIO* pFile);
* @param pScene The imported data to release. NULL is a valid value. * @param pScene The imported data to release. NULL is a valid value.
*/ */
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
void aiReleaseImport( const C_STRUCT aiScene* pScene); ASSIMP_API void aiReleaseImport( const C_STRUCT aiScene* pScene);
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -115,7 +116,7 @@ void aiReleaseImport( const C_STRUCT aiScene* pScene);
* import process. NULL if there was no error. * import process. NULL if there was no error.
*/ */
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
const char* aiGetErrorString(); ASSIMP_API const char* aiGetErrorString();
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -126,7 +127,7 @@ const char* aiGetErrorString();
* @return 1 if the extension is supported, 0 otherwise * @return 1 if the extension is supported, 0 otherwise
*/ */
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
int aiIsExtensionSupported(const char* szExtension); ASSIMP_API int aiIsExtensionSupported(const char* szExtension);
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -138,7 +139,7 @@ int aiIsExtensionSupported(const char* szExtension);
* Format of the list: "*.3ds;*.obj;*.dae". NULL is not a valid parameter. * Format of the list: "*.3ds;*.obj;*.dae". NULL is not a valid parameter.
*/ */
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
void aiGetExtensionList(C_STRUCT aiString* szOut); ASSIMP_API void aiGetExtensionList(C_STRUCT aiString* szOut);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -50,6 +50,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string> #include <string>
#include <vector> #include <vector>
#include "aiDefines.h"
struct aiScene; struct aiScene;
namespace Assimp namespace Assimp
@ -81,7 +83,7 @@ class IOSystem;
* @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 manage its own Importer instance. * threads for loading each thread should manage its own Importer instance.
*/ */
class Importer class ASSIMP_API Importer
{ {
// used internally // used internally
friend class BaseProcess; friend class BaseProcess;
@ -101,6 +103,7 @@ public:
*/ */
~Importer(); ~Importer();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Supplies a custom IO handler to the importer to use to open and /** Supplies a custom IO handler to the importer to use to open and
* access files. If you need the importer to use custion IO logic to * access files. If you need the importer to use custion IO logic to
@ -112,10 +115,31 @@ public:
* afterwards. The previously assigned handler will be deleted. * afterwards. The previously assigned handler will be deleted.
* *
* @param pIOHandler The IO handler to be used in all file accesses * @param pIOHandler The IO handler to be used in all file accesses
* of the Importer. NULL resets it to the default handler. * of the Importer. NULL resets it to the default handler.
*/ */
void SetIOHandler( IOSystem* pIOHandler); void SetIOHandler( IOSystem* pIOHandler);
// -------------------------------------------------------------------
/** Retrieves the IO handler that is currently set.
* You can use IsDefaultIOHandler() to check whether the returned
* interface is the default IO handler provided by ASSIMP. The default
* handler is active as long the application doesn't supply its own
* custom IO handler via SetIOHandler().
* @return A valid IOSystem interface
*/
IOSystem* GetIOHandler();
// -------------------------------------------------------------------
/** Checks whether a default IO handler is active
* A default handler is active as long the application doesn't
* supply its own custom IO handler via SetIOHandler().
* @return true by default
*/
bool IsDefaultIOHandler();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Reads the given file and returns its contents if successful. /** Reads the given file and returns its contents if successful.
* *
@ -127,18 +151,19 @@ public:
* GetErrorString(). * GetErrorString().
* @param pFile Path and filename to the file to be imported. * @param pFile Path and filename to the file to be imported.
* @param pFlags Optional post processing steps to be executed after * @param pFlags Optional post processing steps to be executed after
* a successful import. Provide a bitwise combination of the #aiPostProcessSteps * a successful import. Provide a bitwise combination of the
* flags. * #aiPostProcessSteps flags.
* @return A pointer to the imported data, NULL if the import failed. * @return A pointer to the imported data, NULL if the import failed.
*/ */
const aiScene* ReadFile( const std::string& pFile, unsigned int pFlags); const aiScene* ReadFile( const std::string& pFile, unsigned int pFlags);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns an error description of an error that occured in ReadFile(). /** Returns an error description of an error that occured in ReadFile().
* *
* Returns an empty string if no error occured. * Returns an empty string if no error occured.
* @return A description of the last error, an empty string if no * @return A description of the last error, an empty string if no
* error occured. * error occured.
*/ */
inline const std::string& GetErrorString() const inline const std::string& GetErrorString() const
{ return mErrorString; } { return mErrorString; }
@ -147,20 +172,20 @@ public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether a given file extension is supported by ASSIMP /** Returns whether a given file extension is supported by ASSIMP
* *
* @param szExtension Extension for which the function queries support. * @param szExtension Extension to be checked.
* Must include a leading dot '.'. Example: ".3ds", ".md3" * Must include a leading dot '.'. Example: ".3ds", ".md3"
* @return true if the extension is supported, false otherwise * @return true if the extension is supported, false otherwise
*/ */
bool IsExtensionSupported(const std::string& szExtension); bool IsExtensionSupported(const std::string& szExtension);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Get a full list of all file extensions generally supported by ASSIMP. /** Get a full list of all file extensions supported by ASSIMP.
* *
* If a file extension is contained in the list this does, of course, not * If a file extension is contained in the list this does, of course, not
* mean that ASSIMP is able to load all files with this extension. * mean that ASSIMP is able to load all files with this extension.
* @param szOut String to receive the extension list. * @param szOut String to receive the extension list.
* Format of the list: "*.3ds;*.obj;*.dae". NULL is not a valid parameter. * Format of the list: "*.3ds;*.obj;*.dae".
*/ */
void GetExtensionList(std::string& szOut); void GetExtensionList(std::string& szOut);
@ -174,12 +199,15 @@ public:
{return this->mScene;} {return this->mScene;}
private: private:
/** Empty copy constructor. */ /** Empty copy constructor. */
Importer(const Importer &other); Importer(const Importer &other);
protected: protected:
/** IO handler to use for all file accesses. */ /** IO handler to use for all file accesses. */
IOSystem* mIOHandler; IOSystem* mIOHandler;
bool mIsDefaultHandler;
/** Format-specific importer worker objects - /** Format-specific importer worker objects -
* one for each format we can read. */ * one for each format we can read. */

View File

@ -7,7 +7,7 @@
<attribute name="URI" value="/" /> <attribute name="URI" value="/" />
</containerElement> </containerElement>
</containerInfo> </containerInfo>
<setting name="jarPath" value="J:\Programmieren\ASSIMP\assimp2\port\jAssimp\assimp.jar" /> <setting name="jarPath" value="J:\Programmieren\ASSIMP\assimp\port\jAssimp\assimp.jar" />
<setting name="buildJar" value="true" /> <setting name="buildJar" value="true" />
<setting name="mainClass" value="" /> <setting name="mainClass" value="" />
</component> </component>

View File

@ -0,0 +1,11 @@
package assimp;
/**
* Created by IntelliJ IDEA.
* User: Alex
* Date: 08.06.2008
* Time: 15:31:01
* To change this template use File | Settings | File Templates.
*/
public class Bone {
}

View File

@ -0,0 +1,14 @@
package assimp;
/**
* Created by IntelliJ IDEA.
* User: Alex
* Date: 15.06.2008
* Time: 19:51:45
* To change this template use File | Settings | File Templates.
*/
public interface IOStream {
}

View File

@ -0,0 +1,73 @@
/*
---------------------------------------------------------------------------
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.
---------------------------------------------------------------------------
*/
package assimp;
import java.io.InputStream;
import java.io.FileNotFoundException;
/**
*
*/
public interface IOSystem {
/**
* Called to check whether a file is existing
*
* @param file Filename
* @return true if the file is existing and accessible
*/
boolean Exists(String file);
/**
* Open a file and return an <code> IOStream </code> interface
* to access it.
*
* @param file File name of the file to be opened
* @return A valid IOStream interface
* @throws FileNotFoundException if the file can't be accessed
*/
IOStream Open(String file) throws FileNotFoundException;
}

View File

@ -43,6 +43,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package assimp; package assimp;
import java.util.Vector; import java.util.Vector;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.File;
import java.lang.ref.Reference;
/** /**
* Main class of jAssimp. The class is a simple wrapper for the native * Main class of jAssimp. The class is a simple wrapper for the native
@ -59,6 +64,65 @@ import java.util.Vector;
*/ */
public class Importer { public class Importer {
/**
* Default implementation of <code>IOStream</code>.
* <br>
* This might become a performance bottleneck: The application
* needs to map the data read by this interface into a C-style
* array. For every single read operation! Therefore it is a good
* optimization to use the default C IOStream handler if no custom
* java handler was specified. Assuming that the Java Runtime is using
* the fXXX-family of functions internally too, the result should be
* the same. The problem is: we can't be sure we'll be able to open
* the file for reading from both Java and native code. Therefore we
* need to close our Java <code>FileReader</code> handle before
* control is given to native code.
*/
private class DefaultIOStream implements IOStream {
private FileReader reader = null;
/**
* Construction with a given path
* @param file Path to the file to be opened
* @throws FileNotFoundException If the file isn't accessible at all
*/
public DefaultIOStream(final String file) throws FileNotFoundException {
reader = new FileReader(file);
}
}
/**
* Default implementation of <code>IOSystem</code>.
*/
private class DefaultIOSystem implements IOSystem {
/**
* Called to check whether a file is existing
*
* @param file Filename
* @return true if the file is existing and accessible
*/
public boolean Exists(String file) {
File f = new File(file);
return f.exists();
}
/**
* Open a file and return an <code> IOStream </code> interface
* to access it.
*
* @param file File name of the file to be opened
* @return A valid IOStream interface
* @throws FileNotFoundException if the file can't be accessed
*/
public IOStream Open(String file) throws FileNotFoundException {
return new DefaultIOStream(file);
}
}
/** /**
* List of all postprocess steps to apply to the model * List of all postprocess steps to apply to the model
* Empty by default. * Empty by default.
@ -83,17 +147,27 @@ public class Importer {
*/ */
private String path = null; private String path = null;
/**
* I/O system to be used
*/
private IOSystem ioSystem = null;
/** /**
* Public constructor. Initialises the JNI bridge to the native * Public constructor. Initialises the JNI bridge to the native
* ASSIMP library. A native Assimp::Importer object is constructed and * ASSIMP library. A native Assimp::Importer object is constructed and
* initialized. The flag list is set to zero, a default I/O handler * initialized. The flag list is set to zero, a default I/O handler
* is constructed. * is initialized.
* *
* @param iVersion Version of the JNI interface to be used.
* @throws NativeError Thrown if the jassimp library could not be loaded * @throws NativeError Thrown if the jassimp library could not be loaded
* or if the entry point to the module wasn't found. if this exception * or if the entry point to the module wasn't found. if this exception
* is not thrown, you can assume that jAssimp is fully available. * is not thrown, you can assume that jAssimp is fully available.
*/ */
public Importer() throws NativeError { public Importer(int iVersion) throws NativeError {
// allocate a default I/O system
ioSystem = new DefaultIOSystem();
/** try to load the jassimp library. First try to load the /** try to load the jassimp library. First try to load the
* x64 version, in case of failure the x86 version * x64 version, in case of failure the x86 version
*/ */
@ -111,7 +185,7 @@ public class Importer {
// now create the native Importer class and setup our internal // now create the native Importer class and setup our internal
// data structures outside the VM. // data structures outside the VM.
try { try {
if (0xffffffffffffffffl == (this.m_iNativeHandle = _NativeInitContext())) { if (0xffffffffffffffffl == (this.m_iNativeHandle = _NativeInitContext(iVersion))) {
throw new NativeError( throw new NativeError(
"Unable to initialize the native library context." + "Unable to initialize the native library context." +
"The initialization routine has failed"); "The initialization routine has failed");
@ -125,6 +199,32 @@ public class Importer {
return; return;
} }
public Importer() throws NativeError {
this(0);
}
/**
* Get the I/O system (<code>IOSystem</code>) to be used for loading
* assets. If no custom implementation was provided via <code>setIoSystem()</code>
* a default implementation will be used. Use <code>isDefaultIoSystem()</code>
* to check this.
* @return Always a valid <code>IOSystem</code> object, never null.
*/
public IOSystem getIoSystem() {
return ioSystem;
}
/**
* Checks whether a default IO system is currently being used to load
* assets. Using the default IO system has many performance benefits,
* but it is possible to provide a custom IO system (<code>setIoSystem()</code>).
* This allows applications to add support for archives like ZIP.
* @return true if a default <code>IOSystem</code> is active,
*/
public boolean isDefaultIoSystem() {
return ioSystem instanceof DefaultIOSystem;
}
/** /**
* Add a postprocess step to the list of steps to be executed on * Add a postprocess step to the list of steps to be executed on
@ -213,6 +313,8 @@ public class Importer {
else if (step.equals(PostProcessStep.GenSmoothNormals)) flags |= 0x40; else if (step.equals(PostProcessStep.GenSmoothNormals)) flags |= 0x40;
else if (step.equals(PostProcessStep.SplitLargeMeshes)) flags |= 0x80; else if (step.equals(PostProcessStep.SplitLargeMeshes)) flags |= 0x80;
else if (step.equals(PostProcessStep.PreTransformVertices)) flags |= 0x100; else if (step.equals(PostProcessStep.PreTransformVertices)) flags |= 0x100;
else if (step.equals(PostProcessStep.LimitBoneWeights)) flags |= 0x200;
else if (step.equals(PostProcessStep.ValidateDataStructure)) flags |= 0x400;
} }
// now load the mesh // now load the mesh
@ -227,6 +329,7 @@ public class Importer {
} }
catch (NativeError exc) { catch (NativeError exc) {
// delete everything ...
this.scene = null; this.scene = null;
this.path = null; this.path = null;
throw exc; throw exc;
@ -247,9 +350,8 @@ public class Importer {
final Importer importer = (Importer) o; final Importer importer = (Importer) o;
if (m_iNativeHandle != importer.m_iNativeHandle) return false; return m_iNativeHandle == importer.m_iNativeHandle;
return true;
} }
/** /**
@ -268,7 +370,6 @@ public class Importer {
if (0xffffffff == _NativeFreeContext(this.m_iNativeHandle)) { if (0xffffffff == _NativeFreeContext(this.m_iNativeHandle)) {
throw new NativeError("Unable to destroy the native library context"); throw new NativeError("Unable to destroy the native library context");
} }
return;
} }
/** /**
@ -306,9 +407,10 @@ public class Importer {
* library functions are available, too. If they are not, an <code> * library functions are available, too. If they are not, an <code>
* UnsatisfiedLinkError</code> will be thrown during model loading. * UnsatisfiedLinkError</code> will be thrown during model loading.
* *
* @param version Version of the JNI bridge requested
* @return Unique handle for the class or 0xffffffff if an error occured * @return Unique handle for the class or 0xffffffff if an error occured
*/ */
private native int _NativeInitContext(); private native int _NativeInitContext(int version);
/** /**
* JNI bridge call. For internal use only * JNI bridge call. For internal use only

View File

@ -43,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package assimp; package assimp;
/** /**
* Class to wrap materials. Materials are represented in ASSIMP as a list of * Class to wrap materials. Materials are represented in ASSIMP as a list of
* key/value pairs, the key being a <code>String</code> and the value being * key/value pairs, the key being a <code>String</code> and the value being
@ -52,6 +53,74 @@ package assimp;
* @version 1.0 * @version 1.0
*/ */
public class Material extends Mappable { public class Material extends Mappable {
public static final String MATKEY_NAME = "$mat.name";
/**
* Specifies the blend operation to be used to combine the Nth
* diffuse texture with the (N-1)th diffuse texture (or the diffuse
* base color for the first diffuse texture)
* <br>
* <b>Type:</b> int (TextureOp)<br>
* <b>Default value:</b> 0<br>
* <b>Requires:</b> MATKEY_TEXTURE_DIFFUSE(0)<br>
*/
public static String MATKEY_TEXOP_DIFFUSE(int N) {
return "$tex.op.diffuse[" + N + "]";
}
/**
* @see MATKEY_TEXOP_DIFFUSE()
*/
public static String MATKEY_TEXOP_SPECULAR(int N) {
return "$tex.op.specular[" + N + "]";
}
/**
* @see MATKEY_TEXOP_DIFFUSE()
*/
public static String MATKEY_TEXOP_AMBIENT(int N) {
return "$tex.op.ambient[" + N + "]";
}
/**
* @see MATKEY_TEXOP_DIFFUSE()
*/
public static String MATKEY_TEXOP_EMISSIVE(int N) {
return "$tex.op.emissive[" + N + "]";
}
/**
* @see MATKEY_TEXOP_DIFFUSE()
*/
public static String MATKEY_TEXOP_NORMALS(int N) {
return "$tex.op.normals[" + N + "]";
}
/**
* @see MATKEY_TEXOP_DIFFUSE()
*/
public static String MATKEY_TEXOP_HEIGHT(int N) {
return "$tex.op.height[" + N + "]";
}
/**
* @see MATKEY_TEXOP_DIFFUSE()
*/
public static String MATKEY_TEXOP_SHININESS(int N) {
return "$tex.op.shininess[" + N + "]";
}
/**
* @see MATKEY_TEXOP_DIFFUSE()
*/
public static String MATKEY_TEXOP_OPACITY(int N) {
return "$tex.op.opacity[" + N + "]";
}
/** /**
* Construction from a given parent object and array index * Construction from a given parent object and array index
* *

View File

@ -183,29 +183,9 @@ public class Mesh extends Mappable {
assert (parent instanceof Scene); assert (parent instanceof Scene);
Scene sc = (Scene) parent; Scene sc = (Scene) parent;
if (0xffffffff == (this.m_iPresentFlags = this._NativeGetPresenceFlags( if (0xffffffff == this._NativeInitMembers(
sc.getImporter().getContext(), this.getArrayIndex()))) { sc.getImporter().getContext(), this.getArrayIndex())) {
throw new NativeError("Unable to obtain a list of vertex presence flags"); throw new NativeError("Unable to intiailise class members via JNI");
}
if (0xffffffff == (this.m_iNumVertices = this._NativeGetNumVertices(
sc.getImporter().getContext(), this.getArrayIndex()))) {
throw new NativeError("Unable to obtain the number of vertices in the mesh");
}
if (0xffffffff == (this.m_iNumFaces = this._NativeGetNumFaces(
sc.getImporter().getContext(), this.getArrayIndex()))) {
throw new NativeError("Unable to obtain the number of faces in the mesh");
}
if (0xffffffff == (this.m_iNumBones = this._NativeGetNumBones(
sc.getImporter().getContext(), this.getArrayIndex()))) {
throw new NativeError("Unable to obtain the number of bones in the mesh");
}
if (0xffffffff == (this.m_iMaterialIndex = this._NativeGetMaterialIndex(
sc.getImporter().getContext(), this.getArrayIndex()))) {
throw new NativeError("Unable to obtain the material index of the mesh");
}
if (0xffffffff == this._NativeGetNumUVComponents(
sc.getImporter().getContext(), this.getArrayIndex(), this.m_aiNumUVComponents)) {
throw new NativeError("Unable to obtain the number of UV components");
} }
} }
@ -821,18 +801,12 @@ public class Mesh extends Mappable {
/** /**
* JNI bridge function - for internal use only * JNI bridge function - for internal use only
* Retrieve the number of vertices in the mesh * Initialise class members
* *
* @param context Current importer context (imp.hashCode) * @param context Current importer context (imp.hashCode)
* @return Number of vertices in the mesh * @return Number of vertices in the mesh
*/ */
private native int _NativeGetNumVertices(long context, long index); private native int _NativeInitMembers(long context, long index);
private native int _NativeGetNumFaces(long context, long index);
private native int _NativeGetNumBones(long context, long index);
private native int _NativeGetMaterialIndex(long context, long index);
/** /**
* JNI bridge function - for internal use only * JNI bridge function - for internal use only

View File

@ -1,11 +1,223 @@
/*
---------------------------------------------------------------------------
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.
---------------------------------------------------------------------------
*/
package assimp; package assimp;
import java.util.Vector;
/** /**
* Created by IntelliJ IDEA. * A node in the imported hierarchy.
* User: Alex * <p/>
* Date: 22.05.2008 * Each node has name, a parent node (except for the root node),
* Time: 13:05:12 * a transformation relative to its parent and possibly several child nodes.
* To change this template use File | Settings | File Templates. * Simple file formats don't support hierarchical structures, for these formats
* the imported scene does consist of only a single root node with no childs.
*
* @author Aramis (Alexander Gessler)
* @version 1.0
*/ */
public class Node { public class Node {
/**
* List of all meshes of this node.
* The array contains indices into the Scene's mesh list
*/
private int[] meshIndices = null;
/**
* Local transformation matrix of the node
* Stored in row-major order.
*/
private float[] nodeTransform = null;
/**
* Name of the node
* The name might be empty (length of zero) but all nodes which
* need to be accessed afterwards by bones or anims are usually named.
*/
private String name = "";
/**
* List of all child nodes
* May be empty
*/
private Vector<Node> children = null;
private int numChildren = 0; // temporary
/**
* Parent scene
*/
private Scene parentScene = null;
/**
* Parent node or null if we're the root node of the scene
*/
private Node parent = null;
/**
* Constructs a new node and initializes it
* @param parentScene Parent scene object
* @param parentNode Parent node or null for root nodes
* @param index Unique index of the node
*/
public Node(Scene parentScene, Node parentNode, int index) {
this.parentScene = parentScene;
this.parent = parentNode;
// Initialize JNI class members, including numChildren
this._NativeInitMembers(parentScene.getImporter().getContext(),index);
// get all children of the node
for (int i = 0; i < numChildren;++i) {
this.children.add(new Node(parentScene, this, ++index));
}
}
/**
* Get a list of all meshes of this node
*
* @return Array containing indices into the Scene's mesh list
*/
int[] getMeshes() {
return meshIndices;
}
/**
* Get the local transformation matrix of the node in row-major
* order:
* <code>
* a1 a2 a3 a4 (the translational part of the matrix is stored
* b1 b2 b3 b4 in (a4|b4|c4))
* c1 c2 c3 c4
* d1 d2 d3 d4
* </code>
*
* @return Row-major transformation matrix
*/
float[] getTransformRowMajor() {
return nodeTransform;
}
/**
* Get the local transformation matrix of the node in column-major
* order:
* <code>
* a1 b1 c1 d1 (the translational part of the matrix is stored
* a2 b2 c2 d2 in (a4|b4|c4))
* a3 b3 c3 d3
* a4 b4 c4 d4
* </code>
*
* @return Column-major transformation matrix
*/
float[] getTransformColumnMajor() {
float[] transform = new float[16];
transform[0] = nodeTransform[0];
transform[1] = nodeTransform[4];
transform[2] = nodeTransform[8];
transform[3] = nodeTransform[12];
transform[4] = nodeTransform[1];
transform[5] = nodeTransform[5];
transform[6] = nodeTransform[9];
transform[7] = nodeTransform[13];
transform[8] = nodeTransform[2];
transform[9] = nodeTransform[6];
transform[10] = nodeTransform[10];
transform[11] = nodeTransform[14];
transform[12] = nodeTransform[3];
transform[13] = nodeTransform[7];
transform[15] = nodeTransform[11];
transform[16] = nodeTransform[15];
return transform;
}
private native int _NativeInitMembers(long context, int nodeIndex);
/**
* Get the name of the node.
* The name might be empty (length of zero) but all nodes which
* need to be accessed afterwards by bones or anims are usually named.
*
* @return Node name
*/
public String getName() {
return name;
}
/**
* Get the list of all child nodes of *this* node
* @return List of children. May be empty.
*/
public Vector<Node> getChildren() {
return children;
}
/**
* Get the parent node of the node
* @return Parent node
*/
public Node getParent() {
return parent;
}
/**
* Get the parent scene of the node
* @return Never null
*/
public Scene getParentScene() {
return parentScene;
}
} }

View File

@ -45,7 +45,7 @@ package assimp;
/** /**
* Enumeration class that defines postprocess steps that can be executed on a model * Enumeration class that defines postprocess steps that can be executed on a model
* after it has been loaded. All PPSteps are implemented in C++, so their performance * after it has been loaded. All PPSteps are implemented in C++, so their performance
* is awesome. Most steps are O(n * log(n)). * is awesome. Most steps are O(n * log(n)). ;-)
* *
* @author Aramis (Alexander Gessler) * @author Aramis (Alexander Gessler)
* @version 1.0 * @version 1.0
@ -62,8 +62,15 @@ public class PostProcessStep {
*/ */
public static final int DEFAULT_TRIANGLE_SPLIT_LIMIT = 1000000; public static final int DEFAULT_TRIANGLE_SPLIT_LIMIT = 1000000;
/**
* Default bone weight limit for the LimitBoneWeight process
*/
public static final int DEFAULT_BONE_WEIGHT_LIMIT = 4;
private static int s_iVertexSplitLimit = DEFAULT_VERTEX_SPLIT_LIMIT; private static int s_iVertexSplitLimit = DEFAULT_VERTEX_SPLIT_LIMIT;
private static int s_iTriangleSplitLimit = DEFAULT_TRIANGLE_SPLIT_LIMIT; private static int s_iTriangleSplitLimit = DEFAULT_TRIANGLE_SPLIT_LIMIT;
private static int s_iBoneWeightLimit = DEFAULT_BONE_WEIGHT_LIMIT;
/** /**
* Identifies and joins identical vertex data sets within all imported * Identifies and joins identical vertex data sets within all imported
@ -154,6 +161,31 @@ public class PostProcessStep {
public static final PostProcessStep PreTransformVertices = public static final PostProcessStep PreTransformVertices =
new PostProcessStep("PreTransformVertices"); new PostProcessStep("PreTransformVertices");
/**
* Limits the number of bones simultaneously affecting a single vertex
* to a maximum value. If any vertex is affected by more than that number
* of bones, the least important vertex weights are removed and the remaining
* vertex weights are renormalized so that the weights still sum up to 1.
* The default bone weight limit is 4 (DEFAULT_BONE_WEIGHT_LIMIT).
* However, you can use setBoneWeightLimit() to supply your own limit.
* If you intend to perform the skinning in hardware, this post processing step
* might be of interest for you.
*/
public static final PostProcessStep LimitBoneWeights =
new PostProcessStep("LimitBoneWeights");
/**
* Validates the aiScene data structure before it is returned.
* This makes sure that all indices are valid, all animations and
* bones are linked correctly, all material are correct and so on ...
* This is primarily intended for our internal debugging stuff,
* however, it could be of interest for applications like editors
* where stability is more important than loading performance.
*/
public static final PostProcessStep ValidateDataStructure =
new PostProcessStep("ValidateDataStructure");
/** /**
* Set the vertex split limit for the "SplitLargeMeshes" process * Set the vertex split limit for the "SplitLargeMeshes" process
@ -191,6 +223,22 @@ public class PostProcessStep {
return limit; return limit;
} }
/**
* Set the bone weight limit for the "LimitBoneWeights" process
* If a mesh exceeds this limit it will be splitted
*
* @param limit new bone weight limit. Pass 0xffffffff to disable it.
* @return Old bone weight limit
*/
public static synchronized int setSetBoneWeightLimit(int limit) {
if (s_iBoneWeightLimit != limit) {
// send to the JNI bridge ...
s_iBoneWeightLimit = limit;
_NativeSetBoneWeightLimit(limit);
}
return limit;
}
/** /**
* JNI bridge call. For internal use only * JNI bridge call. For internal use only
* *
@ -205,6 +253,13 @@ public class PostProcessStep {
*/ */
private native static void _NativeSetTriangleSplitLimit(int limit); private native static void _NativeSetTriangleSplitLimit(int limit);
/**
* JNI bridge call. For internal use only
*
* @param limit New bone weight limit
*/
private native static void _NativeSetBoneWeightLimit(int limit);
private final String myName; // for debug only private final String myName; // for debug only

View File

@ -0,0 +1,116 @@
/*
---------------------------------------------------------------------------
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.
---------------------------------------------------------------------------
*/
package assimp;
/**
* Defines all shading models supported by the library
* <p/>
* NOTE: The list of shading modes has been taken from Blender3D.
* See Blender3D documentation for more information. The API does
* not distinguish between "specular" and "diffuse" shaders (thus the
* specular term for diffuse shading models like Oren-Nayar remains
* undefined)
*/
public class ShadingMode {
/**
* Flat shading. Shading is done on per-face base,
* diffuse only.
*/
int Flat = 0x1;
/**
* Diffuse gouraud shading. Shading on per-vertex base
*/
int Gouraud = 0x2;
/**
* Diffuse/Specular Phong-Shading
* <p/>
* Shading is applied on per-pixel base. This is the
* slowest algorithm, but generates the best results.
*/
int Phong = 0x3;
/**
* Diffuse/Specular Phong-Blinn-Shading
* <p/>
* Shading is applied on per-pixel base. This is a little
* bit faster than phong and in some cases even
* more realistic
*/
int Blinn = 0x4;
/**
* Toon-Shading per pixel
* <p/>
* Shading is applied on per-pixel base. The output looks
* like a comic. Often combined with edge detection.
*/
int Toon = 0x5;
/**
* OrenNayar-Shading per pixel
* <p/>
* Extension to standard lambertian shading, taking the
* roughness of the material into account
*/
int OrenNayar = 0x6;
/**
* Minnaert-Shading per pixel
* <p/>
* Extension to standard lambertian shading, taking the
* "darkness" of the material into account
*/
int Minnaert = 0x7;
/**
* CookTorrance-Shading per pixel
*/
int CookTorrance = 0x8;
/**
* No shading at all
*/
int NoShading = 0x8;
}

View File

@ -0,0 +1,52 @@
/*
---------------------------------------------------------------------------
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.
---------------------------------------------------------------------------
*/
package assimp;
/**
* Created by IntelliJ IDEA.
* User: Alex
* Date: 08.06.2008
* Time: 17:27:11
* To change this template use File | Settings | File Templates.
*/
public class TextureMapMode {
}

View File

@ -0,0 +1,71 @@
/*
---------------------------------------------------------------------------
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.
---------------------------------------------------------------------------
*/
package assimp;
public class TextureOp {
private TextureOp() {}
/** T = T1 * T2
*/
public static int Add = 0x0;
/** T = T1 * T2
*/
public static int Multiply = 0x1;
/** T = T1 - T2
*/
public static int Subtract = 0x2;
/** T = T1 / T2
*/
public static int Divide = 0x3;
/** T = (T1 + T2) - (T1 * T2)
*/
public static int SmoothAdd = 0x4;
/** T = T1 + (T2-0.5)
*/
public static int SignedAdd = 0x5;
}

BIN
test/HMP/planar.hmp 100644

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,15 @@
version 1
nodes
0 "TriangleTest0" -1
end
skeleton
time 0
0 0.0 0.0 0.0 0.0 0.0 0.0
end
triangles
none.quak
0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0
0 1.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0
0 1.0 1.0 0.0 1.0 1.0 1.0 1.0 1.0
end

View File

@ -137,7 +137,6 @@ int CMaterialManager::SetDefaultTexture(IDirect3DTexture9** p_ppiOut)
bool CMaterialManager::TryLongerPath(char* szTemp,aiString* p_szString) bool CMaterialManager::TryLongerPath(char* szTemp,aiString* p_szString)
{ {
char szTempB[MAX_PATH]; char szTempB[MAX_PATH];
strcpy(szTempB,szTemp); strcpy(szTempB,szTemp);
// go to the beginning of the file name // go to the beginning of the file name
@ -146,7 +145,9 @@ bool CMaterialManager::TryLongerPath(char* szTemp,aiString* p_szString)
char* szFile2 = szTemp + (szFile - szTempB)+1; char* szFile2 = szTemp + (szFile - szTempB)+1;
szFile++; szFile++;
char* szExt = strrchr(szFile,'.')+1; char* szExt = strrchr(szFile,'.');
if (!szExt)return false;
szExt++;
*szFile = 0; *szFile = 0;
strcat(szTempB,"*.*"); strcat(szTempB,"*.*");
@ -163,9 +164,10 @@ bool CMaterialManager::TryLongerPath(char* szTemp,aiString* p_szString)
{ {
if (!(strcmp(info.cFileName, ".") == 0 || strcmp(info.cFileName, "..") == 0)) if (!(strcmp(info.cFileName, ".") == 0 || strcmp(info.cFileName, "..") == 0))
{ {
char* szExtFound = strrchr(info.cFileName, '.')+1; char* szExtFound = strrchr(info.cFileName, '.');
if ((char*)0x1 != szExtFound) if (szExtFound)
{ {
++szExtFound;
if (0 == ASSIMP_stricmp(szExtFound,szExt)) if (0 == ASSIMP_stricmp(szExtFound,szExt))
{ {
const unsigned int iSizeFound = (const unsigned int) ( const unsigned int iSizeFound = (const unsigned int) (

View File

@ -49,7 +49,7 @@
<option name="MAXIMUM_HEAP_SIZE" value="128" /> <option name="MAXIMUM_HEAP_SIZE" value="128" />
</component> </component>
<component name="JavadocGenerationManager"> <component name="JavadocGenerationManager">
<option name="OUTPUT_DIRECTORY" value="J:/Programmieren/ASSIMP/assimp2/doc/javadoc" /> <option name="OUTPUT_DIRECTORY" value="J:/Programmieren/ASSIMP/assimp/doc/javadoc" />
<option name="OPTION_SCOPE" value="package" /> <option name="OPTION_SCOPE" value="package" />
<option name="OPTION_HIERARCHY" value="true" /> <option name="OPTION_HIERARCHY" value="true" />
<option name="OPTION_NAVIGATOR" value="true" /> <option name="OPTION_NAVIGATOR" value="true" />
@ -178,7 +178,7 @@
</component> </component>
<component name="ProjectModuleManager"> <component name="ProjectModuleManager">
<modules> <modules>
<module fileurl="file://J:/Programmieren/ASSIMP/assimp2/port/jAssimp/assimp.iml" filepath="J:/Programmieren/ASSIMP/assimp2/port/jAssimp/assimp.iml" /> <module fileurl="file://J:/Programmieren/ASSIMP/ASSIMP/port/jAssimp/assimp.iml" filepath="J:/Programmieren/ASSIMP/ASSIMP/port/jAssimp/assimp.iml" />
</modules> </modules>
</component> </component>
<component name="ProjectRootManager" version="2" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" /> <component name="ProjectRootManager" version="2" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" />

View File

@ -48,7 +48,7 @@
RuntimeLibrary="1" RuntimeLibrary="1"
EnableFunctionLevelLinking="true" EnableFunctionLevelLinking="true"
WarningLevel="3" WarningLevel="3"
Detect64BitPortabilityProblems="true" Detect64BitPortabilityProblems="false"
DebugInformationFormat="4" DebugInformationFormat="4"
/> />
<Tool <Tool
@ -174,6 +174,7 @@
BufferSecurityCheck="false" BufferSecurityCheck="false"
EnableEnhancedInstructionSet="2" EnableEnhancedInstructionSet="2"
WarningLevel="3" WarningLevel="3"
Detect64BitPortabilityProblems="false"
/> />
<Tool <Tool
Name="VCManagedResourceCompilerTool" Name="VCManagedResourceCompilerTool"
@ -294,11 +295,12 @@
EnableIntrinsicFunctions="true" EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1" FavorSizeOrSpeed="1"
AdditionalIncludeDirectories="" AdditionalIncludeDirectories=""
PreprocessorDefinitions="NDEBUG, _SCL_SECURE_NO_WARNINGS, _CRT_SECURE_NO_WARNINGS,WIN32" PreprocessorDefinitions="NDEBUG;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32;ASSIMP_BUILD_DLL_EXPORT"
StringPooling="true" StringPooling="true"
BufferSecurityCheck="false" BufferSecurityCheck="false"
EnableEnhancedInstructionSet="2" EnableEnhancedInstructionSet="2"
WarningLevel="3" WarningLevel="3"
Detect64BitPortabilityProblems="false"
/> />
<Tool <Tool
Name="VCManagedResourceCompilerTool" Name="VCManagedResourceCompilerTool"
@ -367,7 +369,7 @@
EnableIntrinsicFunctions="true" EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1" FavorSizeOrSpeed="1"
AdditionalIncludeDirectories="" AdditionalIncludeDirectories=""
PreprocessorDefinitions="NDEBUG, _SCL_SECURE_NO_WARNINGS, _CRT_SECURE_NO_WARNINGS,WIN32" PreprocessorDefinitions="NDEBUG;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32;ASSIMP_BUILD_DLL_EXPORT"
StringPooling="true" StringPooling="true"
BufferSecurityCheck="false" BufferSecurityCheck="false"
EnableEnhancedInstructionSet="2" EnableEnhancedInstructionSet="2"
@ -437,12 +439,13 @@
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
Optimization="0" Optimization="0"
AdditionalIncludeDirectories="" AdditionalIncludeDirectories=""
PreprocessorDefinitions="DEBUG, _SCL_SECURE_NO_WARNINGS, _CRT_SECURE_NO_WARNINGS,WIN32" PreprocessorDefinitions="DEBUG;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32;ASSIMP_BUILD_DLL_EXPORT"
BasicRuntimeChecks="3" BasicRuntimeChecks="3"
SmallerTypeCheck="true" SmallerTypeCheck="true"
RuntimeLibrary="1" RuntimeLibrary="1"
EnableFunctionLevelLinking="true" EnableFunctionLevelLinking="true"
WarningLevel="3" WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="4" DebugInformationFormat="4"
/> />
<Tool <Tool
@ -509,7 +512,7 @@
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
Optimization="0" Optimization="0"
AdditionalIncludeDirectories="" AdditionalIncludeDirectories=""
PreprocessorDefinitions="DEBUG, _SCL_SECURE_NO_WARNINGS, _CRT_SECURE_NO_WARNINGS,WIN32" PreprocessorDefinitions="DEBUG;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32;ASSIMP_BUILD_DLL_EXPORT"
BasicRuntimeChecks="3" BasicRuntimeChecks="3"
SmallerTypeCheck="true" SmallerTypeCheck="true"
RuntimeLibrary="1" RuntimeLibrary="1"
@ -584,11 +587,12 @@
EnableIntrinsicFunctions="true" EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1" FavorSizeOrSpeed="1"
AdditionalIncludeDirectories="&quot;$(JAVA_HOME)\include&quot;;&quot;$(JAVA_HOME)\include\win32&quot;" AdditionalIncludeDirectories="&quot;$(JAVA_HOME)\include&quot;;&quot;$(JAVA_HOME)\include\win32&quot;"
PreprocessorDefinitions="NDEBUG;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32;ASSIMP_JNI_EXPORT" PreprocessorDefinitions="NDEBUG;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32;ASSIMP_JNI_EXPORT;ASSIMP_BUILD_DLL_EXPORT"
StringPooling="true" StringPooling="true"
BufferSecurityCheck="false" BufferSecurityCheck="false"
EnableEnhancedInstructionSet="2" EnableEnhancedInstructionSet="2"
WarningLevel="3" WarningLevel="3"
Detect64BitPortabilityProblems="false"
/> />
<Tool <Tool
Name="VCManagedResourceCompilerTool" Name="VCManagedResourceCompilerTool"
@ -658,7 +662,7 @@
EnableIntrinsicFunctions="true" EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1" FavorSizeOrSpeed="1"
AdditionalIncludeDirectories="&quot;$(JAVA_HOME)\include&quot;;&quot;$(JAVA_HOME)\include\win32&quot;" AdditionalIncludeDirectories="&quot;$(JAVA_HOME)\include&quot;;&quot;$(JAVA_HOME)\include\win32&quot;"
PreprocessorDefinitions="NDEBUG;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32;ASSIMP_JNI_EXPORT" PreprocessorDefinitions="NDEBUG;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32;ASSIMP_JNI_EXPORT;ASSIMP_BUILD_DLL_EXPORT"
StringPooling="true" StringPooling="true"
BufferSecurityCheck="false" BufferSecurityCheck="false"
EnableEnhancedInstructionSet="2" EnableEnhancedInstructionSet="2"
@ -729,12 +733,13 @@
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
Optimization="0" Optimization="0"
AdditionalIncludeDirectories="&quot;$(JAVA_HOME)\include&quot;;&quot;$(JAVA_HOME)\include\win32&quot;" AdditionalIncludeDirectories="&quot;$(JAVA_HOME)\include&quot;;&quot;$(JAVA_HOME)\include\win32&quot;"
PreprocessorDefinitions="DEBUG;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32;ASSIMP_JNI_EXPORT" PreprocessorDefinitions="DEBUG;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32;ASSIMP_JNI_EXPORT;ASSIMP_BUILD_DLL_EXPORT"
BasicRuntimeChecks="3" BasicRuntimeChecks="3"
SmallerTypeCheck="true" SmallerTypeCheck="true"
RuntimeLibrary="1" RuntimeLibrary="1"
EnableFunctionLevelLinking="true" EnableFunctionLevelLinking="true"
WarningLevel="3" WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="4" DebugInformationFormat="4"
/> />
<Tool <Tool
@ -802,7 +807,7 @@
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
Optimization="0" Optimization="0"
AdditionalIncludeDirectories="&quot;$(JAVA_HOME)\include&quot;;&quot;$(JAVA_HOME)\include\win32&quot;" AdditionalIncludeDirectories="&quot;$(JAVA_HOME)\include&quot;;&quot;$(JAVA_HOME)\include\win32&quot;"
PreprocessorDefinitions="DEBUG;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32;ASSIMP_JNI_EXPORT" PreprocessorDefinitions="DEBUG;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32;ASSIMP_JNI_EXPORT;ASSIMP_BUILD_DLL_EXPORT"
BasicRuntimeChecks="3" BasicRuntimeChecks="3"
SmallerTypeCheck="true" SmallerTypeCheck="true"
RuntimeLibrary="1" RuntimeLibrary="1"
@ -865,6 +870,10 @@
RelativePath="..\..\include\aiAssert.h" RelativePath="..\..\include\aiAssert.h"
> >
</File> </File>
<File
RelativePath="..\..\include\aiDefines.h"
>
</File>
<File <File
RelativePath="..\..\include\aiFileIO.h" RelativePath="..\..\include\aiFileIO.h"
> >
@ -1021,10 +1030,18 @@
RelativePath="..\..\code\MaterialSystem.h" RelativePath="..\..\code\MaterialSystem.h"
> >
</File> </File>
<File
RelativePath="..\..\code\ParsingUtils.h"
>
</File>
<File <File
RelativePath="..\..\code\PretransformVertices.h" RelativePath="..\..\code\PretransformVertices.h"
> >
</File> </File>
<File
RelativePath="..\..\code\qnan.h"
>
</File>
<File <File
RelativePath="..\..\code\SpatialSort.h" RelativePath="..\..\code\SpatialSort.h"
> >
@ -1217,39 +1234,39 @@
Name="jAssimp" Name="jAssimp"
> >
<File <File
RelativePath="..\..\code\jAssimp\assimp_Importer.h" RelativePath="..\..\port\jAssimp\jni_bridge\assimp_Importer.h"
> >
</File> </File>
<File <File
RelativePath="..\..\code\jAssimp\assimp_Material.h" RelativePath="..\..\port\jAssimp\jni_bridge\assimp_Material.h"
> >
</File> </File>
<File <File
RelativePath="..\..\code\jAssimp\assimp_Mesh.h" RelativePath="..\..\port\jAssimp\jni_bridge\jAssimp\assimp_Mesh.h"
> >
</File> </File>
<File <File
RelativePath="..\..\code\jAssimp\assimp_Node.h" RelativePath="..\..\port\jAssimp\jni_bridge\jAssimp\assimp_Node.h"
> >
</File> </File>
<File <File
RelativePath="..\..\code\jAssimp\assimp_PostProcessStep.h" RelativePath="..\..\port\jAssimp\jni_bridge\assimp_PostProcessStep.h"
> >
</File> </File>
<File <File
RelativePath="..\..\code\jAssimp\assimp_Scene.h" RelativePath="..\..\port\jAssimp\jni_bridge\assimp_Scene.h"
> >
</File> </File>
<File <File
RelativePath="..\..\code\jAssimp\assimp_Texture.h" RelativePath="..\..\port\jAssimp\jni_bridge\assimp_Texture.h"
> >
</File> </File>
<File <File
RelativePath="..\..\code\jAssimp\JNIEnvironment.h" RelativePath="..\..\port\jAssimp\jni_bridge\JNIEnvironment.h"
> >
</File> </File>
<File <File
RelativePath="..\..\code\jAssimp\JNILogger.h" RelativePath="..\..\port\jAssimp\jni_bridge\JNILogger.h"
> >
</File> </File>
</Filter> </Filter>
@ -1261,6 +1278,22 @@
> >
</File> </File>
</Filter> </Filter>
<Filter
Name="HMPLoader"
>
<File
RelativePath="..\..\code\HMPLoader.h"
>
</File>
</Filter>
<Filter
Name="SMDLoader"
>
<File
RelativePath="..\..\code\SMDLoader.h"
>
</File>
</Filter>
</Filter> </Filter>
<Filter <Filter
Name="sources" Name="sources"
@ -1436,6 +1469,10 @@
RelativePath="..\..\code\MDLLoader.cpp" RelativePath="..\..\code\MDLLoader.cpp"
> >
</File> </File>
<File
RelativePath="..\..\code\MDLMaterialLoader.cpp"
>
</File>
</Filter> </Filter>
<Filter <Filter
Name="ASELoader" Name="ASELoader"
@ -1461,15 +1498,15 @@
Name="jAssimp" Name="jAssimp"
> >
<File <File
RelativePath="..\..\code\jAssimp\JNICalls.cpp" RelativePath="..\..\port\jAssimp\jni_bridge\JNICalls.cpp"
> >
</File> </File>
<File <File
RelativePath="..\..\code\jAssimp\JNIEnvironment.cpp" RelativePath="..\..\port\jAssimp\jni_bridge\JNIEnvironment.cpp"
> >
</File> </File>
<File <File
RelativePath="..\..\code\jAssimp\JNILogger.cpp" RelativePath="..\..\port\jAssimp\jni_bridge\JNILogger.cpp"
> >
</File> </File>
</Filter> </Filter>
@ -1481,6 +1518,22 @@
> >
</File> </File>
</Filter> </Filter>
<Filter
Name="HMPLoader"
>
<File
RelativePath="..\..\code\HMPLoader.cpp"
>
</File>
</Filter>
<Filter
Name="SMDLoader"
>
<File
RelativePath="..\..\code\SMDLoader.cpp"
>
</File>
</Filter>
</Filter> </Filter>
<Filter <Filter
Name="doc" Name="doc"