Added first working version of a MDC loader; no further features like compressed frames tested at the moment. Added config options for keyframe loading, this has been tested with MDL7 only (atm). Some refactoring, a few files are much cleaner and smaller now. RemoveRedundantMats step does now remove unreferenced materials.
git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@103 67173fc5-114c-0410-ac8e-9d2fd5bffc1fpull/1/head
parent
5ef187c1d0
commit
6f49c4518c
|
@ -59,6 +59,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
using namespace Assimp;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define sprintf sprintf_s
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Dot3DSImporter::ReplaceDefaultMaterial()
|
||||
|
@ -113,8 +116,7 @@ void Dot3DSImporter::ReplaceDefaultMaterial()
|
|||
{
|
||||
(*a) = iIndex;
|
||||
++iCnt;
|
||||
DefaultLogger::get()->warn("Material index overflow in 3DS file. Assigning "
|
||||
"default material ...");
|
||||
DefaultLogger::get()->warn("Material index overflow in 3DS file. Using default material");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -157,58 +159,36 @@ void Dot3DSImporter::CheckIndices(Dot3DS::Mesh* sMesh)
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
void Dot3DSImporter::MakeUnique(Dot3DS::Mesh* sMesh)
|
||||
{
|
||||
std::vector<aiVector3D> vNew;
|
||||
vNew.resize(sMesh->mFaces.size() * 3);
|
||||
|
||||
std::vector<aiVector2D> vNew2;
|
||||
|
||||
// TODO: Remove this step. By maintaining a small LUT it
|
||||
// would be possible to do this directly in the parsing step
|
||||
unsigned int iBase = 0;
|
||||
|
||||
if (0 != sMesh->mTexCoords.size())
|
||||
std::vector<aiVector3D> vNew;
|
||||
std::vector<aiVector2D> vNew2;
|
||||
|
||||
vNew.resize(sMesh->mFaces.size() * 3);
|
||||
if (sMesh->mTexCoords.size())vNew2.resize(sMesh->mFaces.size() * 3);
|
||||
|
||||
for (unsigned int i = 0; i < sMesh->mFaces.size();++i)
|
||||
{
|
||||
vNew2.resize(sMesh->mFaces.size() * 3);
|
||||
for (unsigned int i = 0; i < sMesh->mFaces.size();++i)
|
||||
uint32_t iTemp1,iTemp2;
|
||||
|
||||
// positions
|
||||
vNew[iBase] = sMesh->mPositions[sMesh->mFaces[i].mIndices[2]];
|
||||
iTemp1 = iBase++;
|
||||
vNew[iBase] = sMesh->mPositions[sMesh->mFaces[i].mIndices[1]];
|
||||
iTemp2 = iBase++;
|
||||
vNew[iBase] = sMesh->mPositions[sMesh->mFaces[i].mIndices[0]];
|
||||
|
||||
// texture coordinates
|
||||
if (sMesh->mTexCoords.size())
|
||||
{
|
||||
uint32_t iTemp1,iTemp2;
|
||||
|
||||
// position and texture coordinates
|
||||
vNew[iBase] = sMesh->mPositions[sMesh->mFaces[i].mIndices[2]];
|
||||
vNew2[iBase] = sMesh->mTexCoords[sMesh->mFaces[i].mIndices[2]];
|
||||
iTemp1 = iBase++;
|
||||
|
||||
vNew[iBase] = sMesh->mPositions[sMesh->mFaces[i].mIndices[1]];
|
||||
vNew2[iBase] = sMesh->mTexCoords[sMesh->mFaces[i].mIndices[1]];
|
||||
iTemp2 = iBase++;
|
||||
|
||||
vNew[iBase] = sMesh->mPositions[sMesh->mFaces[i].mIndices[0]];
|
||||
vNew2[iBase] = sMesh->mTexCoords[sMesh->mFaces[i].mIndices[0]];
|
||||
sMesh->mFaces[i].mIndices[2] = iBase++;
|
||||
|
||||
sMesh->mFaces[i].mIndices[0] = iTemp1;
|
||||
sMesh->mFaces[i].mIndices[1] = iTemp2;
|
||||
vNew2[iTemp1] = sMesh->mTexCoords[sMesh->mFaces[i].mIndices[2]];
|
||||
vNew2[iTemp2] = sMesh->mTexCoords[sMesh->mFaces[i].mIndices[1]];
|
||||
vNew2[iBase] = sMesh->mTexCoords[sMesh->mFaces[i].mIndices[0]];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 0; i < sMesh->mFaces.size();++i)
|
||||
{
|
||||
uint32_t iTemp1,iTemp2;
|
||||
|
||||
// position only
|
||||
vNew[iBase] = sMesh->mPositions[sMesh->mFaces[i].mIndices[2]];
|
||||
iTemp1 = iBase++;
|
||||
|
||||
vNew[iBase] = sMesh->mPositions[sMesh->mFaces[i].mIndices[1]];
|
||||
iTemp2 = iBase++;
|
||||
|
||||
vNew[iBase] = sMesh->mPositions[sMesh->mFaces[i].mIndices[0]];
|
||||
sMesh->mFaces[i].mIndices[2] = iBase++;
|
||||
|
||||
sMesh->mFaces[i].mIndices[0] = iTemp1;
|
||||
sMesh->mFaces[i].mIndices[1] = iTemp2;
|
||||
}
|
||||
sMesh->mFaces[i].mIndices[2] = iBase++;
|
||||
sMesh->mFaces[i].mIndices[0] = iTemp1;
|
||||
sMesh->mFaces[i].mIndices[1] = iTemp2;
|
||||
}
|
||||
sMesh->mPositions = vNew;
|
||||
sMesh->mTexCoords = vNew2;
|
||||
|
@ -400,7 +380,7 @@ void Dot3DSImporter::ConvertMaterial(Dot3DS::Material& oldMat,
|
|||
}
|
||||
|
||||
// store the name of the material itself, too
|
||||
if( oldMat.mName.length() > 0)
|
||||
if( oldMat.mName.length())
|
||||
{
|
||||
aiString tex;
|
||||
tex.Set( oldMat.mName);
|
||||
|
@ -430,14 +410,19 @@ void Dot3DSImporter::ConvertMeshes(aiScene* pcOut)
|
|||
a != (*i).mFaceMaterials.end();++a,++iNum)
|
||||
{
|
||||
// check range
|
||||
// FIX: shouldn't be necessary anymore, has been moved to ReplaceDefaultMaterial()
|
||||
#if 0
|
||||
if ((*a) >= this->mScene->mMaterials.size())
|
||||
{
|
||||
DefaultLogger::get()->error("3DS face material index is out of range");
|
||||
|
||||
// use the last material instead
|
||||
// TODO: assign the default material index
|
||||
aiSplit[this->mScene->mMaterials.size()-1].push_back(iNum);
|
||||
}
|
||||
else aiSplit[*a].push_back(iNum);
|
||||
else
|
||||
#endif
|
||||
aiSplit[*a].push_back(iNum);
|
||||
}
|
||||
// now generate submeshes
|
||||
bool bFirst = true;
|
||||
|
@ -455,14 +440,14 @@ void Dot3DSImporter::ConvertMeshes(aiScene* pcOut)
|
|||
avOutMeshes.push_back(p_pcOut);
|
||||
|
||||
// convert vertices
|
||||
p_pcOut->mNumVertices = (unsigned int)aiSplit[p].size()*3;
|
||||
p_pcOut->mNumFaces = (unsigned int)aiSplit[p].size();
|
||||
p_pcOut->mNumVertices = p_pcOut->mNumFaces*3;
|
||||
|
||||
// allocate enough storage for faces
|
||||
p_pcOut->mFaces = new aiFace[p_pcOut->mNumFaces];
|
||||
iFaceCnt += p_pcOut->mNumFaces;
|
||||
|
||||
if (p_pcOut->mNumVertices != 0)
|
||||
if (p_pcOut->mNumVertices)
|
||||
{
|
||||
p_pcOut->mVertices = new aiVector3D[p_pcOut->mNumVertices];
|
||||
p_pcOut->mNormals = new aiVector3D[p_pcOut->mNumVertices];
|
||||
|
@ -489,7 +474,7 @@ void Dot3DSImporter::ConvertMeshes(aiScene* pcOut)
|
|||
}
|
||||
}
|
||||
// convert texture coordinates
|
||||
if ((*i).mTexCoords.size() != 0)
|
||||
if ((*i).mTexCoords.size())
|
||||
{
|
||||
p_pcOut->mTextureCoords[0] = new aiVector3D[p_pcOut->mNumVertices];
|
||||
|
||||
|
@ -525,17 +510,13 @@ void Dot3DSImporter::ConvertMeshes(aiScene* pcOut)
|
|||
pcOut->mMeshes[a] = avOutMeshes[a];
|
||||
}
|
||||
|
||||
if (0 == iFaceCnt)
|
||||
{
|
||||
if (!iFaceCnt)
|
||||
throw new ImportErrorException("No faces loaded. The mesh is empty");
|
||||
}
|
||||
|
||||
// for each material in the scene we need to setup the UV source
|
||||
// set for each texture
|
||||
for (unsigned int a = 0; a < pcOut->mNumMaterials;++a)
|
||||
{
|
||||
TextureTransform::SetupMatUVSrc( pcOut->mMaterials[a], &this->mScene->mMaterials[a] );
|
||||
}
|
||||
return;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -551,7 +532,9 @@ void Dot3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,Dot3DS::Node*
|
|||
const Dot3DS::Mesh* pcMesh = (const Dot3DS::Mesh*)pcSOut->mMeshes[a]->mColors[0];
|
||||
ai_assert(NULL != pcMesh);
|
||||
|
||||
if (0 == ASSIMP_stricmp(pcIn->mName.c_str(),pcMesh->mName.c_str()))
|
||||
// do case independent comparisons here, just for safety
|
||||
if (pcIn->mName.length() == pcMesh->mName.length() &&
|
||||
!ASSIMP_stricmp(pcIn->mName.c_str(),pcMesh->mName.c_str()))
|
||||
{
|
||||
iArray.push_back(a);
|
||||
}
|
||||
|
@ -560,7 +543,8 @@ void Dot3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,Dot3DS::Node*
|
|||
{
|
||||
aiMatrix4x4& mTrafo = ((Dot3DS::Mesh*)pcSOut->mMeshes[iArray[0]]->mColors[0])->mMat;
|
||||
aiMatrix4x4 mInv = mTrafo;
|
||||
mInv.Inverse();
|
||||
if (!this->configSkipPivot)
|
||||
mInv.Inverse();
|
||||
|
||||
pcOut->mName.Set(pcIn->mName);
|
||||
pcOut->mNumMeshes = (unsigned int)iArray.size();
|
||||
|
@ -575,7 +559,7 @@ void Dot3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,Dot3DS::Node*
|
|||
const aiVector3D* const pvEnd = mesh->mVertices+mesh->mNumVertices;
|
||||
aiVector3D* pvCurrent = mesh->mVertices;
|
||||
|
||||
if(pivot.x || pivot.y || pivot.z)
|
||||
if(pivot.x || pivot.y || pivot.z && !this->configSkipPivot)
|
||||
{
|
||||
while (pvCurrent != pvEnd)
|
||||
{
|
||||
|
@ -593,18 +577,12 @@ void Dot3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,Dot3DS::Node*
|
|||
while (pvCurrent != pvEnd)
|
||||
{
|
||||
std::swap( pvCurrent->y, pvCurrent->z );
|
||||
//pvCurrent->y *= -1.0f;
|
||||
++pvCurrent;
|
||||
}
|
||||
}
|
||||
pcOut->mMeshes[i] = iIndex;
|
||||
}
|
||||
}
|
||||
/*else
|
||||
{
|
||||
DefaultLogger::get()->warn("A node that is not a dummy does not "
|
||||
"reference a valid mesh.");
|
||||
}*/
|
||||
}
|
||||
pcOut->mTransformation = aiMatrix4x4();
|
||||
pcOut->mNumChildren = (unsigned int)pcIn->mChildren.size();
|
||||
|
@ -636,8 +614,7 @@ void Dot3DSImporter::GenerateNodeGraph(aiScene* pcOut)
|
|||
//
|
||||
unsigned int iCnt = 0;
|
||||
|
||||
DefaultLogger::get()->warn("No hierarchy information has been "
|
||||
"found in the file. A flat hierarchy tree is built ...");
|
||||
DefaultLogger::get()->warn("No hierarchy information has been found in the file. ");
|
||||
|
||||
pcOut->mRootNode->mNumChildren = pcOut->mNumMeshes;
|
||||
pcOut->mRootNode->mChildren = new aiNode* [ pcOut->mNumMeshes ];
|
||||
|
@ -654,11 +631,7 @@ void Dot3DSImporter::GenerateNodeGraph(aiScene* pcOut)
|
|||
|
||||
char szBuffer[128];
|
||||
int iLen;
|
||||
#if _MSC_VER >= 1400
|
||||
iLen = sprintf_s(szBuffer,"UNNAMED_%i",i);
|
||||
#else
|
||||
iLen = sprintf(szBuffer,"UNNAMED_%i",i);
|
||||
#endif
|
||||
ai_assert(0 < iLen);
|
||||
::memcpy(pcNode->mName.data,szBuffer,iLen);
|
||||
pcNode->mName.data[iLen] = '\0';
|
||||
|
|
|
@ -120,8 +120,8 @@ public:
|
|||
enum
|
||||
{
|
||||
|
||||
// **************************************************************
|
||||
// Base chunks which can be found everywhere in the file
|
||||
// ********************************************************************
|
||||
// Basic chunks which can be found everywhere in the file
|
||||
CHUNK_VERSION = 0x0002,
|
||||
CHUNK_RGBF = 0x0010, // float4 R; float4 G; float4 B
|
||||
CHUNK_RGBB = 0x0011, // int1 R; int1 G; int B
|
||||
|
@ -132,7 +132,7 @@ public:
|
|||
|
||||
CHUNK_PERCENTW = 0x0030, // int2 percentage
|
||||
CHUNK_PERCENTF = 0x0031, // float4 percentage
|
||||
// **************************************************************
|
||||
// ********************************************************************
|
||||
|
||||
// Unknown and ignored. Possibly a chunk used by PROJ (
|
||||
// Discreet 3DS max Project File)?
|
||||
|
@ -162,7 +162,7 @@ public:
|
|||
CHUNK_BIT_MAP = 0x1100,
|
||||
CHUNK_BIT_MAP_EXISTS = 0x1101,
|
||||
|
||||
// **************************************************************
|
||||
// ********************************************************************
|
||||
// Viewport related stuff. Ignored
|
||||
CHUNK_DEFAULT_VIEW = 0x3000,
|
||||
CHUNK_VIEW_TOP = 0x3010,
|
||||
|
@ -173,7 +173,7 @@ public:
|
|||
CHUNK_VIEW_BACK = 0x3060,
|
||||
CHUNK_VIEW_USER = 0x3070,
|
||||
CHUNK_VIEW_CAMERA = 0x3080,
|
||||
// **************************************************************
|
||||
// ********************************************************************
|
||||
|
||||
// Mesh chunks
|
||||
CHUNK_OBJBLOCK = 0x4000,
|
||||
|
@ -196,7 +196,7 @@ public:
|
|||
// to the root node's transformation matrix
|
||||
CHUNK_MASTER_SCALE = 0x0100,
|
||||
|
||||
// **************************************************************
|
||||
// ********************************************************************
|
||||
// Material chunks
|
||||
CHUNK_MAT_MATERIAL = 0xAFFF,
|
||||
|
||||
|
@ -280,7 +280,7 @@ public:
|
|||
|
||||
// Specifies whether a materail requires two-sided rendering
|
||||
CHUNK_MAT_TWO_SIDE = 0xA081,
|
||||
// **************************************************************
|
||||
// ********************************************************************
|
||||
|
||||
// Main keyframer chunk. Contains translation/rotation/scaling data
|
||||
CHUNK_KEYFRAMER = 0xB000,
|
||||
|
@ -293,7 +293,7 @@ public:
|
|||
CHUNK_TRACKROTATE = 0xB021,
|
||||
CHUNK_TRACKSCALE = 0xB022,
|
||||
|
||||
// **************************************************************
|
||||
// ********************************************************************
|
||||
// Keyframes for various other stuff in the file
|
||||
// Ignored
|
||||
CHUNK_AMBIENTKEY = 0xB001,
|
||||
|
@ -308,7 +308,7 @@ public:
|
|||
CHUNK_TRACKLIGTGT = 0xB006,
|
||||
CHUNK_TRACKSPOTL = 0xB007,
|
||||
CHUNK_FRAMES = 0xB008
|
||||
// **************************************************************
|
||||
// ********************************************************************
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "../include/aiMesh.h"
|
||||
#include "../include/aiScene.h"
|
||||
#include "../include/aiAssert.h"
|
||||
#include "../include/assimp.hpp"
|
||||
|
||||
// boost headers
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
@ -99,6 +100,12 @@ bool Dot3DSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) co
|
|||
return false;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Setup configuration properties
|
||||
void Dot3DSImporter::SetupProperties(const Importer* pImp)
|
||||
{
|
||||
this->configSkipPivot = pImp->GetProperty(AI_CONFIG_IMPORT_3DS_IGNORE_PIVOT,0) ? true : false;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Imports the given file into the given scene structure.
|
||||
void Dot3DSImporter::InternReadFile(
|
||||
const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
|
||||
|
@ -144,48 +151,46 @@ void Dot3DSImporter::InternReadFile(
|
|||
try
|
||||
{
|
||||
this->ParseMainChunk(iRemaining);
|
||||
|
||||
// Generate an unique set of vertices/indices for
|
||||
// all meshes contained in the file
|
||||
for (std::vector<Dot3DS::Mesh>::iterator
|
||||
i = this->mScene->mMeshes.begin();
|
||||
i != this->mScene->mMeshes.end();++i)
|
||||
{
|
||||
// TODO: see function body
|
||||
this->CheckIndices(&(*i));
|
||||
this->MakeUnique(&(*i));
|
||||
|
||||
// first generate normals for the mesh
|
||||
this->GenNormals(&(*i));
|
||||
}
|
||||
|
||||
// Apply scaling and offsets to all texture coordinates
|
||||
TextureTransform::ApplyScaleNOffset(this->mScene->mMaterials);
|
||||
|
||||
// Replace all occurences of the default material with a valid material.
|
||||
// Generate it if no material containing DEFAULT in its name has been
|
||||
// found in the file
|
||||
this->ReplaceDefaultMaterial();
|
||||
|
||||
// Convert the scene from our internal representation to an aiScene object
|
||||
this->ConvertScene(pScene);
|
||||
|
||||
// Generate the node graph for the scene. This is a little bit
|
||||
// tricky since we'll need to split some meshes into submeshes
|
||||
this->GenerateNodeGraph(pScene);
|
||||
|
||||
// Now apply a master scaling factor to the scene
|
||||
this->ApplyMasterScale(pScene);
|
||||
|
||||
}
|
||||
catch ( ImportErrorException* ex)
|
||||
{
|
||||
delete[] this->mBuffer;
|
||||
delete[] this->mBuffer;AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
|
||||
throw ex;
|
||||
};
|
||||
|
||||
// Generate an unique set of vertices/indices for
|
||||
// all meshes contained in the file
|
||||
for (std::vector<Dot3DS::Mesh>::iterator
|
||||
i = this->mScene->mMeshes.begin();
|
||||
i != this->mScene->mMeshes.end();++i)
|
||||
{
|
||||
// TODO: see function body
|
||||
this->CheckIndices(&(*i));
|
||||
this->MakeUnique(&(*i));
|
||||
|
||||
// first generate normals for the mesh
|
||||
this->GenNormals(&(*i));
|
||||
}
|
||||
|
||||
// Apply scaling and offsets to all texture coordinates
|
||||
TextureTransform::ApplyScaleNOffset(this->mScene->mMaterials);
|
||||
|
||||
// Replace all occurences of the default material with a valid material.
|
||||
// Generate it if no material containing DEFAULT in its name has been
|
||||
// found in the file
|
||||
this->ReplaceDefaultMaterial();
|
||||
|
||||
// Convert the scene from our internal representation to an aiScene object
|
||||
this->ConvertScene(pScene);
|
||||
|
||||
// Generate the node graph for the scene. This is a little bit
|
||||
// tricky since we'll need to split some meshes into submeshes
|
||||
this->GenerateNodeGraph(pScene);
|
||||
|
||||
// Now apply a master scaling factor to the scene
|
||||
this->ApplyMasterScale(pScene);
|
||||
|
||||
delete[] this->mBuffer;
|
||||
delete this->mScene;
|
||||
return;
|
||||
delete[] this->mBuffer;AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Dot3DSImporter::ApplyMasterScale(aiScene* pScene)
|
||||
|
|
|
@ -43,8 +43,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef AI_3DSIMPORTER_H_INC
|
||||
#define AI_3DSIMPORTER_H_INC
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "BaseImporter.h"
|
||||
#include "../include/aiTypes.h"
|
||||
|
||||
|
@ -73,11 +71,19 @@ protected:
|
|||
~Dot3DSImporter();
|
||||
|
||||
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;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Called prior to ReadFile().
|
||||
* The function is a request to the importer to update its configuration
|
||||
* basing on the Importer's configuration property list.
|
||||
*/
|
||||
void SetupProperties(const Importer* pImp);
|
||||
|
||||
protected:
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
@ -233,6 +239,10 @@ protected:
|
|||
|
||||
|
||||
protected:
|
||||
|
||||
/** Configuration option: skip pivot chunks */
|
||||
bool configSkipPivot;
|
||||
|
||||
/** Buffer to hold the loaded file */
|
||||
unsigned char* mBuffer;
|
||||
|
||||
|
|
|
@ -109,14 +109,11 @@ void ASEImporter::InternReadFile(
|
|||
|
||||
// Check whether we can read from the file
|
||||
if( file.get() == NULL)
|
||||
{
|
||||
throw new ImportErrorException( "Failed to open ASE file " + pFile + ".");
|
||||
}
|
||||
|
||||
size_t fileSize = file->FileSize();
|
||||
std::string::size_type pos = pFile.find_last_of('.');
|
||||
std::string extension = pFile.substr( pos);
|
||||
this->mIsAsk = (extension[3] == 'k' || extension[3] == 'K');
|
||||
|
||||
// allocate storage and copy the contents of the file to a memory buffer
|
||||
// (terminate it with zero)
|
||||
|
@ -144,11 +141,7 @@ void ASEImporter::InternReadFile(
|
|||
{
|
||||
if ((*i).bSkip)continue;
|
||||
|
||||
// transform all vertices into worldspace
|
||||
// world2obj transform is specified in the
|
||||
// transformation matrix of a scenegraph node
|
||||
this->TransformVertices(*i);
|
||||
|
||||
// now we need to create proper meshes from the import we need to
|
||||
// split them by materials, build valid vertex/face lists ...
|
||||
this->BuildUniqueRepresentation(*i);
|
||||
|
@ -215,7 +208,7 @@ void ASEImporter::GenerateDefaultMaterial()
|
|||
this->mParser->m_vMaterials.push_back ( ASE::Material() );
|
||||
ASE::Material& mat = this->mParser->m_vMaterials.back();
|
||||
|
||||
mat.mDiffuse = aiColor3D(0.6f,0.6f,0.6f);
|
||||
mat.mDiffuse = aiColor3D(0.6f,0.6f,0.6f);
|
||||
mat.mSpecular = aiColor3D(1.0f,1.0f,1.0f);
|
||||
mat.mAmbient = aiColor3D(0.05f,0.05f,0.05f);
|
||||
mat.mShading = Dot3DSFile::Gouraud;
|
||||
|
@ -449,21 +442,6 @@ void ASEImporter::BuildNodes()
|
|||
std::string* szMyName = (std::string*)pcScene->mMeshes[*i]->mColors[1];
|
||||
if (!szMyName)continue;
|
||||
|
||||
#if 0 // moved to the scope above
|
||||
for (std::vector<unsigned int>::iterator
|
||||
a = i+1;
|
||||
a != aiList.end();++a)
|
||||
{
|
||||
std::string* szMyName2 = (std::string*)pcScene->mMeshes[*i]->mColors[1];
|
||||
if (!szMyName)continue;
|
||||
if (0 == ASSIMP_stricmp(szMyName2->c_str(),szMyName->c_str()))
|
||||
{
|
||||
a = aiList.erase(a);
|
||||
if (a == aiList.end())break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
DefaultLogger::get()->info("Generating dummy node: " + szMyName[1] + ". "
|
||||
"This node is not defined in the ASE file, but referenced as "
|
||||
"parent node.");
|
||||
|
@ -604,19 +582,6 @@ void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh)
|
|||
|
||||
for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
|
||||
mesh.amTexCoords[c] = amTexCoords[c];
|
||||
|
||||
// now need to transform all vertices with the inverse of their
|
||||
// transformation matrix ...
|
||||
//aiMatrix4x4 mInverse = mesh.mTransform;
|
||||
//mInverse.Inverse();
|
||||
|
||||
//for (std::vector<aiVector3D>::iterator
|
||||
// i = mesh.mPositions.begin();
|
||||
// i != mesh.mPositions.end();++i)
|
||||
//{
|
||||
// (*i) = mInverse * (*i);
|
||||
//}
|
||||
|
||||
return;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -1066,7 +1031,7 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMesh
|
|||
pc->mName.Set(mesh.mBones[jfkennedy].mName);
|
||||
pc->mNumWeights = (unsigned int)avBonesOut[jfkennedy].size();
|
||||
pc->mWeights = new aiVertexWeight[pc->mNumWeights];
|
||||
memcpy(pc->mWeights,&avBonesOut[jfkennedy][0],
|
||||
::memcpy(pc->mWeights,&avBonesOut[jfkennedy][0],
|
||||
sizeof(aiVertexWeight) * pc->mNumWeights);
|
||||
++pcBone;
|
||||
}
|
||||
|
@ -1246,9 +1211,8 @@ void ASEImporter::GenerateNormals(ASE::Mesh& mesh)
|
|||
aiVector3D pDelta2 = *pV3 - *pV1;
|
||||
aiVector3D vNor = pDelta1 ^ pDelta2;
|
||||
|
||||
mesh.mNormals[face.mIndices[0]] = vNor;
|
||||
mesh.mNormals[face.mIndices[1]] = vNor;
|
||||
mesh.mNormals[face.mIndices[2]] = vNor;
|
||||
for (unsigned int i = 0; i < 3;++i)
|
||||
mesh.mNormals[face.mIndices[i]] = vNor;
|
||||
}
|
||||
|
||||
// calculate the position bounds so we have a reliable epsilon to
|
||||
|
@ -1287,15 +1251,13 @@ void ASEImporter::GenerateNormals(ASE::Mesh& mesh)
|
|||
posEpsilon,poResult);
|
||||
|
||||
aiVector3D vNormals;
|
||||
float fDiv = 0.0f;
|
||||
for (std::vector<unsigned int>::const_iterator
|
||||
a = poResult.begin();
|
||||
a != poResult.end();++a)
|
||||
{
|
||||
vNormals += mesh.mNormals[(*a)];
|
||||
fDiv += 1.0f;
|
||||
}
|
||||
vNormals /= fDiv;
|
||||
vNormals.Normalize();
|
||||
avNormals[(*i).mIndices[c]] = vNormals;
|
||||
poResult.clear();
|
||||
}
|
||||
|
|
|
@ -114,8 +114,6 @@ protected:
|
|||
* \param mesh Mesh to work on
|
||||
*/
|
||||
void TransformVertices(ASE::Mesh& mesh);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Create one-material-per-mesh meshes ;-)
|
||||
* \param mesh Mesh to work with
|
||||
* \param Receives the list of all created meshes
|
||||
|
@ -168,9 +166,6 @@ protected:
|
|||
/** Buffer to hold the loaded file */
|
||||
unsigned char* mBuffer;
|
||||
|
||||
/** true if this is an .ask file */
|
||||
bool mIsAsk;
|
||||
|
||||
/** Scene to be filled */
|
||||
aiScene* pcScene;
|
||||
};
|
||||
|
|
|
@ -794,6 +794,7 @@ void Parser::ParseLV1GeometryObjectBlock(ASE::Mesh& mesh)
|
|||
{
|
||||
this->m_szFile+=9;
|
||||
this->ParseLV2NodeTransformBlock(mesh);continue;
|
||||
//mesh.mTransform.Transpose();
|
||||
}
|
||||
// mesh data
|
||||
if (0 == strncmp(this->m_szFile,"*MESH" ,5) &&
|
||||
|
|
|
@ -56,6 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "../include/aiPostProcess.h"
|
||||
#include "../include/aiMesh.h"
|
||||
#include "../include/aiScene.h"
|
||||
#include "../include/assimp.hpp"
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
|
@ -80,6 +81,16 @@ bool CalcTangentsProcess::IsActive( unsigned int pFlags) const
|
|||
return (pFlags & aiProcess_CalcTangentSpace) != 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
void CalcTangentsProcess::SetupProperties(const Importer* pImp)
|
||||
{
|
||||
// get the current value of the property
|
||||
this->configMaxAngle = pImp->GetProperty(AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE,45000) / 1000.0f;
|
||||
this->configMaxAngle = std::max(std::min(this->configMaxAngle,180.0f),0.0f);
|
||||
this->configMaxAngle *= 0.0174532925f;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
void CalcTangentsProcess::Execute( aiScene* pScene)
|
||||
|
@ -213,7 +224,6 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh)
|
|||
vertexFinder.FindPositions( origPos, posEpsilon, verticesFound);
|
||||
|
||||
// look among them for other vertices sharing the same normal and a close-enough tangent/bitangent
|
||||
static const float MAX_DIFF_ANGLE = 0.701f;
|
||||
for( unsigned int b = 0; b < verticesFound.size(); b++)
|
||||
{
|
||||
unsigned int idx = verticesFound[b];
|
||||
|
@ -221,9 +231,9 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh)
|
|||
continue;
|
||||
if( meshNorm[idx] * origNorm < angleEpsilon)
|
||||
continue;
|
||||
if( meshTang[idx] * origTang < MAX_DIFF_ANGLE)
|
||||
if( acosf( meshTang[idx] * origTang) > this->configMaxAngle)
|
||||
continue;
|
||||
if( meshBitang[idx] * origBitang < MAX_DIFF_ANGLE)
|
||||
if( acosf( meshBitang[idx] * origBitang) > this->configMaxAngle)
|
||||
continue;
|
||||
|
||||
// it's similar enough -> add it to the smoothing group
|
||||
|
|
|
@ -70,26 +70,39 @@ protected:
|
|||
|
||||
public:
|
||||
// -------------------------------------------------------------------
|
||||
/** Returns whether the processing step is present in the given flag field.
|
||||
* @param pFlags The processing flags the importer was called with. A bitwise
|
||||
* combination of #aiPostProcessSteps.
|
||||
* @return true if the process is present in this flag fields, false if not.
|
||||
/** Returns whether the processing step is present in the given flag.
|
||||
* @param pFlags The processing flags the importer was called with.
|
||||
* A bitwise combination of #aiPostProcessSteps.
|
||||
* @return true if the process is present in this flag fields,
|
||||
* false if not.
|
||||
*/
|
||||
bool IsActive( unsigned int pFlags) const;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Called prior to ExecuteOnScene().
|
||||
* The function is a request to the process to update its configuration
|
||||
* basing on the Importer's configuration property list.
|
||||
*/
|
||||
void SetupProperties(const Importer* pImp);
|
||||
|
||||
protected:
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Calculates tangents and bitangents for a specific mesh.
|
||||
* @param pMesh The mesh to process.
|
||||
*/
|
||||
bool ProcessMesh( aiMesh* pMesh);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Executes the post processing step on the given imported data.
|
||||
* At the moment a process is not supposed to fail.
|
||||
* @param pScene The imported data to work at.
|
||||
*/
|
||||
void Execute( aiScene* pScene);
|
||||
|
||||
protected:
|
||||
// -------------------------------------------------------------------
|
||||
/** Calculates tangents and bitangents for the given mesh
|
||||
* @param pMesh The mesh to process.
|
||||
*/
|
||||
bool ProcessMesh( aiMesh* pMesh);
|
||||
private:
|
||||
|
||||
/** Configuration option: maximum smoothing angle, in radians*/
|
||||
float configMaxAngle;
|
||||
};
|
||||
|
||||
} // end of namespace Assimp
|
||||
|
|
|
@ -48,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "../include/aiPostProcess.h"
|
||||
#include "../include/aiMesh.h"
|
||||
#include "../include/aiScene.h"
|
||||
#include "../include/assimp.hpp"
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
|
@ -70,7 +71,15 @@ bool GenVertexNormalsProcess::IsActive( unsigned int pFlags) const
|
|||
{
|
||||
return (pFlags & aiProcess_GenSmoothNormals) != 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
void GenVertexNormalsProcess::SetupProperties(const Importer* pImp)
|
||||
{
|
||||
// get the current value of the property
|
||||
this->configMaxAngle = pImp->GetProperty(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE,180000) / 1000.0f;
|
||||
this->configMaxAngle = std::max(std::min(this->configMaxAngle,180.0f),0.0f);
|
||||
this->configMaxAngle *= 0.0174532925f;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
void GenVertexNormalsProcess::Execute( aiScene* pScene)
|
||||
|
@ -111,14 +120,10 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh)
|
|||
aiVector3D pDelta1 = *pV2 - *pV1;
|
||||
aiVector3D pDelta2 = *pV3 - *pV1;
|
||||
aiVector3D vNor = pDelta1 ^ pDelta2;
|
||||
|
||||
/*if (face.mIndices[1] > face.mIndices[2])
|
||||
vNor *= -1.0f;*/
|
||||
vNor.Normalize();
|
||||
|
||||
for (unsigned int i = 0;i < face.mNumIndices;++i)
|
||||
{
|
||||
pMesh->mNormals[face.mIndices[i]] = vNor;
|
||||
}
|
||||
}
|
||||
|
||||
// calculate the position bounds so we have a reliable epsilon to
|
||||
|
@ -135,10 +140,14 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh)
|
|||
}
|
||||
|
||||
const float posEpsilon = (maxVec - minVec).Length() * 1e-5f;
|
||||
|
||||
// set up a SpatialSort to quickly find all vertices close to a given position
|
||||
SpatialSort vertexFinder( pMesh->mVertices, pMesh->mNumVertices, sizeof( aiVector3D));
|
||||
std::vector<unsigned int> verticesFound;
|
||||
|
||||
const float fLimit = (AI_MESH_SMOOTHING_ANGLE_NOT_SET == pMesh->mMaxSmoothingAngle
|
||||
? this->configMaxAngle : pMesh->mMaxSmoothingAngle);
|
||||
|
||||
aiVector3D* pcNew = new aiVector3D[pMesh->mNumVertices];
|
||||
for (unsigned int i = 0; i < pMesh->mNumVertices;++i)
|
||||
{
|
||||
|
@ -148,12 +157,19 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh)
|
|||
vertexFinder.FindPositions( posThis, posEpsilon, verticesFound);
|
||||
|
||||
aiVector3D pcNor;
|
||||
unsigned int div = 0;
|
||||
for (unsigned int a = 0; a < verticesFound.size(); ++a)
|
||||
{
|
||||
unsigned int vidx = verticesFound[a];
|
||||
|
||||
// check whether the angle between the two normals is not too large
|
||||
if (acosf(pMesh->mNormals[vidx] * pMesh->mNormals[i]) > fLimit)
|
||||
continue;
|
||||
|
||||
pcNor += pMesh->mNormals[vidx];
|
||||
++div;
|
||||
}
|
||||
pcNor /= (float) verticesFound.size();
|
||||
pcNor.Normalize();
|
||||
pcNew[i] = pcNor;
|
||||
}
|
||||
delete[] pMesh->mNormals;
|
||||
|
|
|
@ -38,7 +38,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file Defines a post processing step to compute vertex normals for all loaded vertizes */
|
||||
/** @file Defines a post processing step to compute vertex normals
|
||||
for all loaded vertizes */
|
||||
#ifndef AI_GENVERTEXNORMALPROCESS_H_INC
|
||||
#define AI_GENVERTEXNORMALPROCESS_H_INC
|
||||
|
||||
|
@ -48,7 +49,7 @@ class GenNormalsTest;
|
|||
namespace Assimp {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** The GenFaceNormalsProcess computes vertex normals for all vertizes of all meshes
|
||||
/** The GenFaceNormalsProcess computes vertex normals for all vertizes
|
||||
*/
|
||||
class ASSIMP_API GenVertexNormalsProcess : public BaseProcess
|
||||
{
|
||||
|
@ -64,13 +65,21 @@ protected:
|
|||
|
||||
public:
|
||||
// -------------------------------------------------------------------
|
||||
/** Returns whether the processing step is present in the given flag field.
|
||||
* @param pFlags The processing flags the importer was called with. A bitwise
|
||||
* combination of #aiPostProcessSteps.
|
||||
* @return true if the process is present in this flag fields, false if not.
|
||||
/** Returns whether the processing step is present in the given flag.
|
||||
* @param pFlags The processing flags the importer was called with.
|
||||
* A bitwise combination of #aiPostProcessSteps.
|
||||
* @return true if the process is present in this flag fields,
|
||||
* false if not.
|
||||
*/
|
||||
bool IsActive( unsigned int pFlags) const;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Called prior to ExecuteOnScene().
|
||||
* The function is a request to the process to update its configuration
|
||||
* basing on the Importer's configuration property list.
|
||||
*/
|
||||
void SetupProperties(const Importer* pImp);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Executes the post processing step on the given imported data.
|
||||
* At the moment a process is not supposed to fail.
|
||||
|
@ -78,9 +87,19 @@ public:
|
|||
*/
|
||||
void Execute( aiScene* pScene);
|
||||
|
||||
protected:
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Computes normals for a specific mesh
|
||||
* @param pcMesh Mesh
|
||||
* @return true if vertex normals have been computed
|
||||
*/
|
||||
bool GenMeshVertexNormals (aiMesh* pcMesh);
|
||||
|
||||
private:
|
||||
bool GenMeshVertexNormals (aiMesh* pcMesh);
|
||||
|
||||
/** Configuration option: maximum smoothing angle, in radians*/
|
||||
float configMaxAngle;
|
||||
};
|
||||
|
||||
}; // end of namespace Assimp
|
||||
|
|
|
@ -93,10 +93,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#if (!defined AI_BUILD_NO_MDR_IMPORTER)
|
||||
# include "MDRLoader.h"
|
||||
#endif
|
||||
#endif
|
||||
#if (!defined AI_BUILD_NO_MDC_IMPORTER)
|
||||
# include "MDCLoader.h"
|
||||
#endif
|
||||
#endif
|
||||
#if (!defined AI_BUILD_NO_MD5_IMPORTER)
|
||||
# include "MD5Loader.h"
|
||||
#endif
|
||||
|
@ -202,10 +202,10 @@ Importer::Importer() :
|
|||
#if (!defined AI_BUILD_NO_MDR_IMPORTER)
|
||||
mImporter.push_back( new MDRImporter());
|
||||
#endif
|
||||
#endif
|
||||
#if (!defined AI_BUILD_NO_MDC_IMPORTER)
|
||||
mImporter.push_back( new MDCImporter());
|
||||
#endif
|
||||
#endif
|
||||
#if (!defined AI_BUILD_NO_MD5_IMPORTER)
|
||||
mImporter.push_back( new MD5Importer());
|
||||
#endif
|
||||
|
|
|
@ -88,11 +88,7 @@ void LimitBoneWeightsProcess::Execute( aiScene* pScene)
|
|||
void LimitBoneWeightsProcess::SetupProperties(const Importer* pImp)
|
||||
{
|
||||
// get the current value of the property
|
||||
if(0xffffffff == (this->mMaxWeights = pImp->GetProperty(
|
||||
AI_CONFIG_PP_LBW_MAX_WEIGHTS,0xffffffff)))
|
||||
{
|
||||
this->mMaxWeights = AI_LMW_MAX_WEIGHTS;
|
||||
}
|
||||
this->mMaxWeights = pImp->GetProperty(AI_CONFIG_PP_LBW_MAX_WEIGHTS,AI_LMW_MAX_WEIGHTS);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -83,10 +83,11 @@ protected:
|
|||
|
||||
public:
|
||||
// -------------------------------------------------------------------
|
||||
/** Returns whether the processing step is present in the given flag field.
|
||||
* @param pFlags The processing flags the importer was called with. A bitwise
|
||||
* combination of #aiPostProcessSteps.
|
||||
* @return true if the process is present in this flag fields, false if not.
|
||||
/** Returns whether the processing step is present in the given flag.
|
||||
* @param pFlags The processing flags the importer was called with.
|
||||
* A bitwise combination of #aiPostProcessSteps.
|
||||
* @return true if the process is present in this flag fields,
|
||||
* false if not.
|
||||
*/
|
||||
bool IsActive( unsigned int pFlags) const;
|
||||
|
||||
|
@ -95,7 +96,7 @@ public:
|
|||
* The function is a request to the process to update its configuration
|
||||
* basing on the Importer's configuration property list.
|
||||
*/
|
||||
virtual void SetupProperties(const Importer* pImp);
|
||||
void SetupProperties(const Importer* pImp);
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
@ -169,7 +169,7 @@ void MD2Importer::ValidateHeader( )
|
|||
if (this->m_pcHeader->numVertices > AI_MD2_MAX_VERTS)
|
||||
DefaultLogger::get()->warn("The model contains more vertices than Quake 2 supports");
|
||||
|
||||
if (this->m_pcHeader->numFrames >= this->configFrameID )
|
||||
if (this->m_pcHeader->numFrames <= this->configFrameID )
|
||||
throw new ImportErrorException("The requested frame is not existing the file");
|
||||
|
||||
}
|
||||
|
|
|
@ -93,28 +93,26 @@ bool MD3Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
|
|||
void MD3Importer::ValidateHeaderOffsets()
|
||||
{
|
||||
// check magic number
|
||||
if (this->m_pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_BE &&
|
||||
this->m_pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_LE)
|
||||
if (pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_BE &&
|
||||
pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_LE)
|
||||
throw new ImportErrorException( "Invalid MD3 file: Magic bytes not found");
|
||||
|
||||
// check file format version
|
||||
if (this->m_pcHeader->VERSION > 15)
|
||||
if (pcHeader->VERSION > 15)
|
||||
DefaultLogger::get()->warn( "Unsupported MD3 file version. Continuing happily ...");
|
||||
|
||||
// check some values whether they are valid
|
||||
if (!this->m_pcHeader->NUM_FRAMES)
|
||||
throw new ImportErrorException( "Invalid MD3 file: NUM_FRAMES is 0");
|
||||
if (!this->m_pcHeader->NUM_SURFACES)
|
||||
if (!pcHeader->NUM_SURFACES)
|
||||
throw new ImportErrorException( "Invalid md3 file: NUM_SURFACES is 0");
|
||||
|
||||
if (this->m_pcHeader->OFS_FRAMES >= this->fileSize ||
|
||||
this->m_pcHeader->OFS_SURFACES >= this->fileSize ||
|
||||
this->m_pcHeader->OFS_EOF > this->fileSize)
|
||||
if (pcHeader->OFS_FRAMES >= fileSize ||
|
||||
pcHeader->OFS_SURFACES >= fileSize ||
|
||||
pcHeader->OFS_EOF > fileSize)
|
||||
{
|
||||
throw new ImportErrorException("Invalid MD3 header: some offsets are outside the file");
|
||||
}
|
||||
|
||||
if (this->m_pcHeader->NUM_FRAMES >= this->configFrameID )
|
||||
if (pcHeader->NUM_FRAMES <= this->configFrameID )
|
||||
throw new ImportErrorException("The requested frame is not existing the file");
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -123,10 +121,10 @@ 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)
|
||||
if (pcSurf->OFS_TRIANGLES + ofs + pcSurf->NUM_TRIANGLES * sizeof(MD3::Triangle) > fileSize ||
|
||||
pcSurf->OFS_SHADERS + ofs + pcSurf->NUM_SHADER * sizeof(MD3::Shader) > fileSize ||
|
||||
pcSurf->OFS_ST + ofs + pcSurf->NUM_VERTICES * sizeof(MD3::TexCoord) > fileSize ||
|
||||
pcSurf->OFS_XYZNORMAL + ofs + pcSurf->NUM_VERTICES * sizeof(MD3::Vertex) > fileSize)
|
||||
{
|
||||
throw new ImportErrorException("Invalid MD3 surface header: some offsets are outside the file");
|
||||
}
|
||||
|
@ -170,310 +168,279 @@ void MD3Importer::InternReadFile(
|
|||
throw new ImportErrorException( "MD3 File is too small.");
|
||||
|
||||
// allocate storage and copy the contents of the file to a memory buffer
|
||||
this->mBuffer = new unsigned char[fileSize];
|
||||
file->Read( (void*)mBuffer, 1, fileSize);
|
||||
std::vector<unsigned char> mBuffer2 (fileSize);
|
||||
file->Read( &mBuffer2[0], 1, fileSize);
|
||||
mBuffer = &mBuffer2[0];
|
||||
|
||||
try
|
||||
pcHeader = (BE_NCONST MD3::Header*)mBuffer;
|
||||
|
||||
#ifdef AI_BUILD_BIG_ENDIAN
|
||||
|
||||
ByteSwap::Swap4(&pcHeader->VERSION);
|
||||
ByteSwap::Swap4(&pcHeader->FLAGS);
|
||||
ByteSwap::Swap4(&pcHeader->IDENT);
|
||||
ByteSwap::Swap4(&pcHeader->NUM_FRAMES);
|
||||
ByteSwap::Swap4(&pcHeader->NUM_SKINS);
|
||||
ByteSwap::Swap4(&pcHeader->NUM_SURFACES);
|
||||
ByteSwap::Swap4(&pcHeader->NUM_TAGS);
|
||||
ByteSwap::Swap4(&pcHeader->OFS_EOF);
|
||||
ByteSwap::Swap4(&pcHeader->OFS_FRAMES);
|
||||
ByteSwap::Swap4(&pcHeader->OFS_SURFACES);
|
||||
ByteSwap::Swap4(&pcHeader->OFS_TAGS);
|
||||
|
||||
#endif
|
||||
|
||||
// validate the header
|
||||
this->ValidateHeaderOffsets();
|
||||
|
||||
// now navigate to the list of surfaces
|
||||
const MD3::Surface* pcSurfaces = (const MD3::Surface*)(mBuffer + pcHeader->OFS_SURFACES);
|
||||
|
||||
// allocate output storage
|
||||
pScene->mNumMeshes = pcHeader->NUM_SURFACES;
|
||||
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
|
||||
|
||||
pScene->mNumMaterials = pcHeader->NUM_SURFACES;
|
||||
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 = pcHeader->NUM_SURFACES;
|
||||
unsigned int iNumMaterials = 0;
|
||||
unsigned int iDefaultMatIndex = 0xFFFFFFFF;
|
||||
while (iNum-- > 0)
|
||||
{
|
||||
|
||||
this->m_pcHeader = (const MD3::Header*)this->mBuffer;
|
||||
|
||||
#ifdef AI_BUILD_BIG_ENDIAN
|
||||
|
||||
ByteSwap::Swap4(&m_pcHeader->VERSION);
|
||||
ByteSwap::Swap4(&m_pcHeader->FLAGS);
|
||||
ByteSwap::Swap4(&m_pcHeader->IDENT);
|
||||
ByteSwap::Swap4(&m_pcHeader->NUM_FRAMES);
|
||||
ByteSwap::Swap4(&m_pcHeader->NUM_SKINS);
|
||||
ByteSwap::Swap4(&m_pcHeader->NUM_SURFACES);
|
||||
ByteSwap::Swap4(&m_pcHeader->NUM_TAGS);
|
||||
ByteSwap::Swap4(&m_pcHeader->OFS_EOF);
|
||||
ByteSwap::Swap4(&m_pcHeader->OFS_FRAMES);
|
||||
ByteSwap::Swap4(&m_pcHeader->OFS_SURFACES);
|
||||
ByteSwap::Swap4(&m_pcHeader->OFS_TAGS);
|
||||
ByteSwap::Swap4(pcSurfaces->FLAGS);
|
||||
ByteSwap::Swap4(pcSurfaces->IDENT);
|
||||
ByteSwap::Swap4(pcSurfaces->NUM_FRAMES);
|
||||
ByteSwap::Swap4(pcSurfaces->NUM_SHADER);
|
||||
ByteSwap::Swap4(pcSurfaces->NUM_TRIANGLES);
|
||||
ByteSwap::Swap4(pcSurfaces->NUM_VERTICES);
|
||||
ByteSwap::Swap4(pcSurfaces->OFS_END);
|
||||
ByteSwap::Swap4(pcSurfaces->OFS_SHADERS);
|
||||
ByteSwap::Swap4(pcSurfaces->OFS_ST);
|
||||
ByteSwap::Swap4(pcSurfaces->OFS_TRIANGLES);
|
||||
ByteSwap::Swap4(pcSurfaces->OFS_XYZNORMAL);
|
||||
|
||||
#endif
|
||||
|
||||
// validate the header
|
||||
this->ValidateHeaderOffsets();
|
||||
// validate the surface
|
||||
this->ValidateSurfaceHeaderOffsets(pcSurfaces);
|
||||
|
||||
// now navigate to the list of surfaces
|
||||
const MD3::Surface* pcSurfaces = (const MD3::Surface*)
|
||||
(this->mBuffer + this->m_pcHeader->OFS_SURFACES);
|
||||
// navigate to the vertex list of the surface
|
||||
const MD3::Vertex* pcVertices = (const MD3::Vertex*)
|
||||
(((uint8_t*)pcSurfaces) + pcSurfaces->OFS_XYZNORMAL);
|
||||
|
||||
// allocate output storage
|
||||
pScene->mNumMeshes = this->m_pcHeader->NUM_SURFACES;
|
||||
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
|
||||
// navigate to the triangle list of the surface
|
||||
const MD3::Triangle* pcTriangles = (const MD3::Triangle*)
|
||||
(((uint8_t*)pcSurfaces) + pcSurfaces->OFS_TRIANGLES);
|
||||
|
||||
pScene->mNumMaterials = this->m_pcHeader->NUM_SURFACES;
|
||||
pScene->mMaterials = new aiMaterial*[pScene->mNumMeshes];
|
||||
// navigate to the texture coordinate list of the surface
|
||||
const MD3::TexCoord* pcUVs = (const MD3::TexCoord*)
|
||||
(((uint8_t*)pcSurfaces) + pcSurfaces->OFS_ST);
|
||||
|
||||
// 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*));
|
||||
// navigate to the shader list of the surface
|
||||
const MD3::Shader* pcShaders = (const MD3::Shader*)
|
||||
(((uint8_t*)pcSurfaces) + pcSurfaces->OFS_SHADERS);
|
||||
|
||||
unsigned int iNum = this->m_pcHeader->NUM_SURFACES;
|
||||
unsigned int iNumMaterials = 0;
|
||||
unsigned int iDefaultMatIndex = 0xFFFFFFFF;
|
||||
while (iNum-- > 0)
|
||||
// if the submesh is empty ignore it
|
||||
if (0 == pcSurfaces->NUM_VERTICES || 0 == pcSurfaces->NUM_TRIANGLES)
|
||||
{
|
||||
pcSurfaces = (const MD3::Surface*)(((uint8_t*)pcSurfaces) + pcSurfaces->OFS_END);
|
||||
pScene->mNumMeshes--;
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef AI_BUILD_BIG_ENDIAN
|
||||
|
||||
ByteSwap::Swap4(pcSurfaces->FLAGS);
|
||||
ByteSwap::Swap4(pcSurfaces->IDENT);
|
||||
ByteSwap::Swap4(pcSurfaces->NUM_FRAMES);
|
||||
ByteSwap::Swap4(pcSurfaces->NUM_SHADER);
|
||||
ByteSwap::Swap4(pcSurfaces->NUM_TRIANGLES);
|
||||
ByteSwap::Swap4(pcSurfaces->NUM_VERTICES);
|
||||
ByteSwap::Swap4(pcSurfaces->OFS_END);
|
||||
ByteSwap::Swap4(pcSurfaces->OFS_SHADERS);
|
||||
ByteSwap::Swap4(pcSurfaces->OFS_ST);
|
||||
ByteSwap::Swap4(pcSurfaces->OFS_TRIANGLES);
|
||||
ByteSwap::Swap4(pcSurfaces->OFS_XYZNORMAL);
|
||||
for (uint32_t i = 0; i < pcSurfaces->NUM_VERTICES;++i)
|
||||
{
|
||||
ByteSwap::Swap2( & pcVertices[i].NORMAL );
|
||||
ByteSwap::Swap2( & pcVertices[i].X );
|
||||
ByteSwap::Swap2( & pcVertices[i].Y );
|
||||
ByteSwap::Swap2( & pcVertices[i].Z );
|
||||
|
||||
ByteSwap::Swap4( & pcUVs[i].U );
|
||||
ByteSwap::Swap4( & pcUVs[i].U );
|
||||
}
|
||||
for (uint32_t i = 0; i < pcSurfaces->NUM_TRIANGLES;++i)
|
||||
{
|
||||
ByteSwap::Swap4(pcTriangles[i].INDEXES[0]);
|
||||
ByteSwap::Swap4(pcTriangles[i].INDEXES[1]);
|
||||
ByteSwap::Swap4(pcTriangles[i].INDEXES[2]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// validate the surface
|
||||
this->ValidateSurfaceHeaderOffsets(pcSurfaces);
|
||||
// allocate the output mesh
|
||||
pScene->mMeshes[iNum] = new aiMesh();
|
||||
aiMesh* pcMesh = pScene->mMeshes[iNum];
|
||||
|
||||
// navigate to the vertex list of the surface
|
||||
const MD3::Vertex* pcVertices = (const MD3::Vertex*)
|
||||
(((uint8_t*)pcSurfaces) + pcSurfaces->OFS_XYZNORMAL);
|
||||
pcMesh->mNumVertices = pcSurfaces->NUM_TRIANGLES*3;
|
||||
pcMesh->mNumFaces = pcSurfaces->NUM_TRIANGLES;
|
||||
pcMesh->mFaces = new aiFace[pcSurfaces->NUM_TRIANGLES];
|
||||
pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
|
||||
pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
|
||||
pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
|
||||
pcMesh->mNumUVComponents[0] = 2;
|
||||
|
||||
// navigate to the triangle list of the surface
|
||||
const MD3::Triangle* pcTriangles = (const MD3::Triangle*)
|
||||
(((uint8_t*)pcSurfaces) + pcSurfaces->OFS_TRIANGLES);
|
||||
// fill in all triangles
|
||||
unsigned int iCurrent = 0;
|
||||
for (unsigned int i = 0; i < (unsigned int)pcSurfaces->NUM_TRIANGLES;++i)
|
||||
{
|
||||
pcMesh->mFaces[i].mIndices = new unsigned int[3];
|
||||
pcMesh->mFaces[i].mNumIndices = 3;
|
||||
|
||||
// navigate to the texture coordinate list of the surface
|
||||
const MD3::TexCoord* pcUVs = (const MD3::TexCoord*)
|
||||
(((uint8_t*)pcSurfaces) + pcSurfaces->OFS_ST);
|
||||
|
||||
// navigate to the shader list of the surface
|
||||
const MD3::Shader* pcShaders = (const MD3::Shader*)
|
||||
(((uint8_t*)pcSurfaces) + pcSurfaces->OFS_SHADERS);
|
||||
|
||||
// if the submesh is empty ignore it
|
||||
if (0 == pcSurfaces->NUM_VERTICES || 0 == pcSurfaces->NUM_TRIANGLES)
|
||||
unsigned int iTemp = iCurrent;
|
||||
for (unsigned int c = 0; c < 3;++c,++iCurrent)
|
||||
{
|
||||
pcSurfaces = (const MD3::Surface*)(((uint8_t*)pcSurfaces) + pcSurfaces->OFS_END);
|
||||
pScene->mNumMeshes--;
|
||||
continue;
|
||||
// read vertices
|
||||
pcMesh->mVertices[iCurrent].x = pcVertices[ pcTriangles->INDEXES[c]].X;
|
||||
pcMesh->mVertices[iCurrent].y = pcVertices[ pcTriangles->INDEXES[c]].Y*-1.0f;
|
||||
pcMesh->mVertices[iCurrent].z = pcVertices[ pcTriangles->INDEXES[c]].Z;
|
||||
|
||||
// convert the normal vector to uncompressed float3 format
|
||||
LatLngNormalToVec3(pcVertices[pcTriangles->INDEXES[c]].NORMAL,
|
||||
(float*)&pcMesh->mNormals[iCurrent]);
|
||||
|
||||
pcMesh->mNormals[iCurrent].y *= -1.0f;
|
||||
|
||||
// read texture coordinates
|
||||
pcMesh->mTextureCoords[0][iCurrent].x = pcUVs[ pcTriangles->INDEXES[c]].U;
|
||||
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[1] = iTemp+1;
|
||||
pcMesh->mFaces[i].mIndices[2] = iTemp+0;
|
||||
pcTriangles++;
|
||||
}
|
||||
|
||||
#ifdef AI_BUILD_BIG_ENDIAN
|
||||
// get the first shader (= texture?) assigned to the surface
|
||||
if (pcSurfaces->NUM_SHADER)
|
||||
{
|
||||
// make a relative path.
|
||||
// if the MD3's internal path itself and the given path are using
|
||||
// the same directory remove it
|
||||
const char* szEndDir1 = ::strrchr((const char*)pcHeader->NAME,'\\');
|
||||
if (!szEndDir1)szEndDir1 = ::strrchr((const char*)pcHeader->NAME,'/');
|
||||
|
||||
for (uint32_t i = 0; i < pcSurfaces->NUM_VERTICES;++i)
|
||||
const char* szEndDir2 = ::strrchr((const char*)pcShaders->NAME,'\\');
|
||||
if (!szEndDir2)szEndDir2 = ::strrchr((const char*)pcShaders->NAME,'/');
|
||||
|
||||
if (szEndDir1 && szEndDir2)
|
||||
{
|
||||
ByteSwap::Swap2( & pcVertices[i].NORMAL );
|
||||
ByteSwap::Swap2( & pcVertices[i].X );
|
||||
ByteSwap::Swap2( & pcVertices[i].Y );
|
||||
ByteSwap::Swap2( & pcVertices[i].Z );
|
||||
// both of them are valid
|
||||
const unsigned int iLen1 = (unsigned int)(szEndDir1 - (const char*)pcHeader->NAME);
|
||||
const unsigned int iLen2 = std::min (iLen1, (unsigned int)(szEndDir2 - (const char*)pcShaders->NAME) );
|
||||
|
||||
ByteSwap::Swap4( & pcUVs[i].U );
|
||||
ByteSwap::Swap4( & pcUVs[i].U );
|
||||
}
|
||||
for (uint32_t i = 0; i < pcSurfaces->NUM_TRIANGLES;++i)
|
||||
{
|
||||
ByteSwap::Swap4(pcTriangles[i].INDEXES[0]);
|
||||
ByteSwap::Swap4(pcTriangles[i].INDEXES[1]);
|
||||
ByteSwap::Swap4(pcTriangles[i].INDEXES[2]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// allocate the output mesh
|
||||
pScene->mMeshes[iNum] = new aiMesh();
|
||||
aiMesh* pcMesh = pScene->mMeshes[iNum];
|
||||
|
||||
pcMesh->mNumVertices = pcSurfaces->NUM_TRIANGLES*3;
|
||||
pcMesh->mNumFaces = pcSurfaces->NUM_TRIANGLES;
|
||||
pcMesh->mFaces = new aiFace[pcSurfaces->NUM_TRIANGLES];
|
||||
pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
|
||||
pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
|
||||
pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
|
||||
pcMesh->mNumUVComponents[0] = 2;
|
||||
|
||||
// fill in all triangles
|
||||
unsigned int iCurrent = 0;
|
||||
for (unsigned int i = 0; i < (unsigned int)pcSurfaces->NUM_TRIANGLES;++i)
|
||||
{
|
||||
pcMesh->mFaces[i].mIndices = new unsigned int[3];
|
||||
pcMesh->mFaces[i].mNumIndices = 3;
|
||||
|
||||
unsigned int iTemp = iCurrent;
|
||||
for (unsigned int c = 0; c < 3;++c,++iCurrent)
|
||||
bool bSuccess = true;
|
||||
for (unsigned int a = 0; a < iLen2;++a)
|
||||
{
|
||||
// read vertices
|
||||
pcMesh->mVertices[iCurrent].x = pcVertices[ pcTriangles->INDEXES[c]].X;
|
||||
pcMesh->mVertices[iCurrent].y = pcVertices[ pcTriangles->INDEXES[c]].Y*-1.0f;
|
||||
pcMesh->mVertices[iCurrent].z = pcVertices[ pcTriangles->INDEXES[c]].Z;
|
||||
|
||||
// convert the normal vector to uncompressed float3 format
|
||||
LatLngNormalToVec3(pcVertices[pcTriangles->INDEXES[c]].NORMAL,
|
||||
(float*)&pcMesh->mNormals[iCurrent]);
|
||||
|
||||
pcMesh->mNormals[iCurrent].y *= -1.0f;
|
||||
|
||||
// read texture coordinates
|
||||
pcMesh->mTextureCoords[0][iCurrent].x = pcUVs[ pcTriangles->INDEXES[c]].U;
|
||||
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[1] = iTemp+1;
|
||||
pcMesh->mFaces[i].mIndices[2] = iTemp+0;
|
||||
pcTriangles++;
|
||||
}
|
||||
|
||||
// get the first shader (= texture?) assigned to the surface
|
||||
if (0 != pcSurfaces->NUM_SHADER)
|
||||
{
|
||||
// make a relative path.
|
||||
// if the MD3's internal path itself and the given path are using
|
||||
// the same directory remove it
|
||||
const char* 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,'\\');
|
||||
if (!szEndDir2)szEndDir2 = ::strrchr((const char*)pcShaders->NAME,'/');
|
||||
|
||||
if (szEndDir1 && szEndDir2)
|
||||
{
|
||||
// both of them are valid
|
||||
const unsigned int iLen1 = (unsigned int)(szEndDir1 - (const char*)this->m_pcHeader->NAME);
|
||||
const unsigned int iLen2 = std::min (iLen1, (unsigned int)(szEndDir2 - (const char*)pcShaders->NAME) );
|
||||
|
||||
bool bSuccess = true;
|
||||
for (unsigned int a = 0; a < iLen2;++a)
|
||||
char sz = ::tolower ( pcShaders->NAME[a] );
|
||||
char sz2 = ::tolower ( pcHeader->NAME[a] );
|
||||
if (sz != sz2)
|
||||
{
|
||||
char sz = ::tolower ( pcShaders->NAME[a] );
|
||||
char sz2 = ::tolower ( this->m_pcHeader->NAME[a] );
|
||||
if (sz != sz2)
|
||||
{
|
||||
bSuccess = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bSuccess)
|
||||
{
|
||||
// use the file name only
|
||||
szEndDir2++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// use the full path
|
||||
szEndDir2 = (const char*)pcShaders->NAME;
|
||||
bSuccess = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// now try to find out whether we have this shader already
|
||||
bool bHave = false;
|
||||
for (unsigned int p = 0; p < iNumMaterials;++p)
|
||||
if (bSuccess)
|
||||
{
|
||||
if (iDefaultMatIndex == p)continue;
|
||||
|
||||
aiString szOut;
|
||||
if(AI_SUCCESS == aiGetMaterialString ( (aiMaterial*)pScene->mMaterials[p],
|
||||
AI_MATKEY_TEXTURE_DIFFUSE(0),&szOut))
|
||||
{
|
||||
if (0 == ASSIMP_stricmp(szOut.data,szEndDir2))
|
||||
{
|
||||
// equal. reuse this material (texture)
|
||||
bHave = true;
|
||||
pcMesh->mMaterialIndex = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!bHave)
|
||||
{
|
||||
MaterialHelper* pcHelper = new MaterialHelper();
|
||||
|
||||
if (szEndDir2)
|
||||
{
|
||||
if (szEndDir2[0])
|
||||
{
|
||||
aiString szString;
|
||||
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));
|
||||
}
|
||||
else
|
||||
{
|
||||
DefaultLogger::get()->warn("Texture file name has zero length. "
|
||||
"It will be skipped.");
|
||||
}
|
||||
}
|
||||
|
||||
int iMode = (int)aiShadingMode_Gouraud;
|
||||
pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
|
||||
|
||||
// add a small ambient color value - Quake 3 seems to have one
|
||||
aiColor3D clr;
|
||||
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);
|
||||
|
||||
pScene->mMaterials[iNumMaterials] = (aiMaterial*)pcHelper;
|
||||
iDefaultMatIndex = pcMesh->mMaterialIndex = iNumMaterials++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (0xFFFFFFFF != iDefaultMatIndex)
|
||||
{
|
||||
pcMesh->mMaterialIndex = iDefaultMatIndex;
|
||||
// use the file name only
|
||||
szEndDir2++;
|
||||
}
|
||||
else
|
||||
{
|
||||
MaterialHelper* pcHelper = new MaterialHelper();
|
||||
|
||||
// fill in a default material
|
||||
int iMode = (int)aiShadingMode_Gouraud;
|
||||
pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
|
||||
|
||||
aiColor3D clr;
|
||||
clr.b = clr.g = clr.r = 0.6f;
|
||||
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);
|
||||
|
||||
pScene->mMaterials[iNumMaterials] = (aiMaterial*)pcHelper;
|
||||
iDefaultMatIndex = pcMesh->mMaterialIndex = iNumMaterials++;
|
||||
// use the full path
|
||||
szEndDir2 = (const char*)pcShaders->NAME;
|
||||
}
|
||||
}
|
||||
// go to the next surface
|
||||
pcSurfaces = (const MD3::Surface*)(((unsigned char*)pcSurfaces) + pcSurfaces->OFS_END);
|
||||
MaterialHelper* pcHelper = new MaterialHelper();
|
||||
|
||||
if (szEndDir2)
|
||||
{
|
||||
if (szEndDir2[0])
|
||||
{
|
||||
aiString szString;
|
||||
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));
|
||||
}
|
||||
else
|
||||
{
|
||||
DefaultLogger::get()->warn("Texture file name has zero length. "
|
||||
"It will be skipped.");
|
||||
}
|
||||
}
|
||||
|
||||
int iMode = (int)aiShadingMode_Gouraud;
|
||||
pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
|
||||
|
||||
// add a small ambient color value - Quake 3 seems to have one
|
||||
aiColor3D clr;
|
||||
clr.b = clr.g = clr.r = 0.05f;
|
||||
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
|
||||
|
||||
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);
|
||||
|
||||
aiString szName;
|
||||
szName.Set(AI_DEFAULT_MATERIAL_NAME);
|
||||
pcHelper->AddProperty(&szName,AI_MATKEY_NAME);
|
||||
|
||||
pScene->mMaterials[iNumMaterials] = (aiMaterial*)pcHelper;
|
||||
pcMesh->mMaterialIndex = iNumMaterials++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (0xFFFFFFFF != iDefaultMatIndex)
|
||||
{
|
||||
pcMesh->mMaterialIndex = iDefaultMatIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
MaterialHelper* pcHelper = new MaterialHelper();
|
||||
|
||||
if (0 == pScene->mNumMeshes)
|
||||
throw new ImportErrorException( "Invalid md3 file: File contains no valid mesh");
|
||||
pScene->mNumMaterials = iNumMaterials;
|
||||
// fill in a default material
|
||||
int iMode = (int)aiShadingMode_Gouraud;
|
||||
pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
|
||||
|
||||
// now we need to generate an empty node graph
|
||||
pScene->mRootNode = new aiNode();
|
||||
pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
|
||||
pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
|
||||
aiColor3D clr;
|
||||
clr.b = clr.g = clr.r = 0.6f;
|
||||
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
|
||||
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
|
||||
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
||||
pScene->mRootNode->mMeshes[i] = i;
|
||||
clr.b = clr.g = clr.r = 0.05f;
|
||||
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
|
||||
|
||||
pScene->mMaterials[iNumMaterials] = (aiMaterial*)pcHelper;
|
||||
iDefaultMatIndex = pcMesh->mMaterialIndex = iNumMaterials++;
|
||||
}
|
||||
}
|
||||
// go to the next surface
|
||||
pcSurfaces = (const MD3::Surface*)(((unsigned char*)pcSurfaces) + pcSurfaces->OFS_END);
|
||||
}
|
||||
catch (ImportErrorException* ex)
|
||||
{
|
||||
delete[] this->mBuffer; AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
|
||||
throw ex;
|
||||
}
|
||||
delete[] this->mBuffer; AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
|
||||
|
||||
if (!pScene->mNumMeshes)
|
||||
throw new ImportErrorException( "Invalid MD3 file: File contains no valid mesh");
|
||||
pScene->mNumMaterials = iNumMaterials;
|
||||
|
||||
// now we need to generate an empty node graph
|
||||
pScene->mRootNode = new aiNode();
|
||||
pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
|
||||
pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
|
||||
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
||||
pScene->mRootNode->mMeshes[i] = i;
|
||||
}
|
|
@ -42,17 +42,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef AI_MD3LOADER_H_INCLUDED
|
||||
#define AI_MD3LOADER_H_INCLUDED
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "BaseImporter.h"
|
||||
#include "ByteSwap.h"
|
||||
|
||||
#include "../include/aiTypes.h"
|
||||
|
||||
struct aiNode;
|
||||
|
||||
#include "MD3FileData.h"
|
||||
namespace Assimp
|
||||
{
|
||||
namespace Assimp {
|
||||
class MaterialHelper;
|
||||
|
||||
using namespace MD3;
|
||||
|
@ -117,10 +115,10 @@ protected:
|
|||
unsigned int configFrameID;
|
||||
|
||||
/** Header of the MD3 file */
|
||||
const MD3::Header* m_pcHeader;
|
||||
BE_NCONST MD3::Header* pcHeader;
|
||||
|
||||
/** Buffer to hold the loaded file */
|
||||
const unsigned char* mBuffer;
|
||||
/** File buffer */
|
||||
BE_NCONST unsigned char* mBuffer;
|
||||
|
||||
/** Size of the file, in bytes */
|
||||
unsigned int fileSize;
|
||||
|
|
|
@ -53,14 +53,7 @@ http://themdcfile.planetwolfenstein.gamespy.com/MDC_File_Format.pdf
|
|||
#include "../include/aiMesh.h"
|
||||
#include "../include/aiAnim.h"
|
||||
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
||||
# pragma pack(push,1)
|
||||
# define PACK_STRUCT
|
||||
#elif defined( __GNUC__ )
|
||||
# define PACK_STRUCT __attribute__((packed))
|
||||
#else
|
||||
# error Compiler not supported
|
||||
#endif
|
||||
#include "./Compiler/pushpack1.h"
|
||||
|
||||
|
||||
namespace Assimp {
|
||||
|
@ -188,11 +181,7 @@ struct Shader
|
|||
|
||||
} PACK_STRUCT;
|
||||
|
||||
// reset packing to the original value
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
||||
# pragma pack( pop )
|
||||
#endif
|
||||
#undef PACK_STRUCT
|
||||
#include "./Compiler/poppack1.h"
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
@ -0,0 +1,476 @@
|
|||
/*
|
||||
---------------------------------------------------------------------------
|
||||
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 MDC importer class */
|
||||
|
||||
// internal headers
|
||||
#include "MDCLoader.h"
|
||||
#include "MD3FileData.h"
|
||||
#include "MaterialSystem.h"
|
||||
#include "StringComparison.h"
|
||||
#include "MDCNormalTable.h" // shouldn't be included by other units
|
||||
#include "ByteSwap.h"
|
||||
|
||||
// public ASSIMP headers
|
||||
#include "../include/IOStream.h"
|
||||
#include "../include/IOSystem.h"
|
||||
#include "../include/aiMesh.h"
|
||||
#include "../include/aiScene.h"
|
||||
#include "../include/aiAssert.h"
|
||||
#include "../include/DefaultLogger.h"
|
||||
#include "../include/assimp.hpp"
|
||||
|
||||
// boost headers
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
using namespace Assimp;
|
||||
using namespace Assimp::MDC;
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void MDC::BuildVertex(const Frame& frame,
|
||||
const BaseVertex& bvert,
|
||||
const CompressedVertex& cvert,
|
||||
aiVector3D& vXYZOut,
|
||||
aiVector3D& vNorOut)
|
||||
{
|
||||
// compute the position
|
||||
const float xd = (cvert.xd - AI_MDC_CVERT_BIAS) * AI_MDC_DELTA_SCALING;
|
||||
const float yd = (cvert.yd - AI_MDC_CVERT_BIAS) * AI_MDC_DELTA_SCALING;
|
||||
const float zd = (cvert.zd - AI_MDC_CVERT_BIAS) * AI_MDC_DELTA_SCALING;
|
||||
vXYZOut.x = frame.localOrigin.x + AI_MDC_BASE_SCALING * (bvert.x + xd);
|
||||
vXYZOut.y = frame.localOrigin.y + AI_MDC_BASE_SCALING * (bvert.y + yd);
|
||||
vXYZOut.z = frame.localOrigin.z + AI_MDC_BASE_SCALING * (bvert.z + zd);
|
||||
|
||||
// compute the normal vector .. ehm ... lookup it in the table :-)
|
||||
vNorOut.x = mdcNormals[cvert.nd][0];
|
||||
vNorOut.y = mdcNormals[cvert.nd][1];
|
||||
vNorOut.z = mdcNormals[cvert.nd][2];
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
MDCImporter::MDCImporter()
|
||||
{
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Destructor, private as well
|
||||
MDCImporter::~MDCImporter()
|
||||
{
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns whether the class can handle the format of the given file.
|
||||
bool MDCImporter::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] != 'M' && extension[1] != 'm')return false;
|
||||
if( extension[2] != 'D' && extension[2] != 'd')return false;
|
||||
if( extension[3] != 'C' && extension[3] != 'c')return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Validate the header of the given MDC file
|
||||
void MDCImporter::ValidateHeader()
|
||||
{
|
||||
AI_SWAP4( this->pcHeader->ulVersion );
|
||||
AI_SWAP4( this->pcHeader->ulFlags );
|
||||
AI_SWAP4( this->pcHeader->ulNumFrames );
|
||||
AI_SWAP4( this->pcHeader->ulNumTags );
|
||||
AI_SWAP4( this->pcHeader->ulNumSurfaces );
|
||||
AI_SWAP4( this->pcHeader->ulNumSkins );
|
||||
AI_SWAP4( this->pcHeader->ulOffsetBorderFrames );
|
||||
|
||||
if (pcHeader->ulIdent != AI_MDC_MAGIC_NUMBER_BE &&
|
||||
pcHeader->ulIdent != AI_MDC_MAGIC_NUMBER_LE)
|
||||
{
|
||||
char szBuffer[5];
|
||||
szBuffer[0] = ((char*)&pcHeader->ulIdent)[0];
|
||||
szBuffer[1] = ((char*)&pcHeader->ulIdent)[1];
|
||||
szBuffer[2] = ((char*)&pcHeader->ulIdent)[2];
|
||||
szBuffer[3] = ((char*)&pcHeader->ulIdent)[3];
|
||||
szBuffer[4] = '\0';
|
||||
|
||||
throw new ImportErrorException("Invalid MDC magic word: should be IDPC, the "
|
||||
"magic word found is " + std::string( szBuffer ));
|
||||
}
|
||||
|
||||
if (pcHeader->ulVersion != AI_MDC_VERSION)
|
||||
DefaultLogger::get()->warn("Unsupported MDC file version (2 (AI_MDC_VERSION) was expected)");
|
||||
|
||||
if (pcHeader->ulOffsetBorderFrames + pcHeader->ulNumFrames * sizeof(MDC::Frame) > this->fileSize ||
|
||||
pcHeader->ulOffsetSurfaces + pcHeader->ulNumSurfaces * sizeof(MDC::Surface) > this->fileSize)
|
||||
{
|
||||
throw new ImportErrorException("Some of the offset values in the MDC header are invalid "
|
||||
"and point to something behind the file.");
|
||||
}
|
||||
|
||||
if (this->configFrameID >= this->pcHeader->ulNumFrames)
|
||||
throw new ImportErrorException("The requested frame is not available");
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Validate the header of a given MDC file surface
|
||||
void MDCImporter::ValidateSurfaceHeader(BE_NCONST MDC::Surface* pcSurf)
|
||||
{
|
||||
AI_SWAP4(pcSurf->ulFlags);
|
||||
AI_SWAP4(pcSurf->ulNumCompFrames);
|
||||
AI_SWAP4(pcSurf->ulNumBaseFrames);
|
||||
AI_SWAP4(pcSurf->ulNumShaders);
|
||||
AI_SWAP4(pcSurf->ulNumVertices);
|
||||
AI_SWAP4(pcSurf->ulNumTriangles);
|
||||
AI_SWAP4(pcSurf->ulOffsetTriangles);
|
||||
AI_SWAP4(pcSurf->ulOffsetTexCoords);
|
||||
AI_SWAP4(pcSurf->ulOffsetBaseVerts);
|
||||
AI_SWAP4(pcSurf->ulOffsetCompVerts);
|
||||
AI_SWAP4(pcSurf->ulOffsetFrameBaseFrames);
|
||||
AI_SWAP4(pcSurf->ulOffsetFrameCompFrames);
|
||||
AI_SWAP4(pcSurf->ulOffsetEnd);
|
||||
|
||||
const unsigned int iMax = this->fileSize - (unsigned int)((int8_t*)pcSurf-(int8_t*)pcHeader);
|
||||
|
||||
if (pcSurf->ulOffsetBaseVerts + pcSurf->ulNumVertices * sizeof(MDC::BaseVertex) > iMax ||
|
||||
(pcSurf->ulNumCompFrames && pcSurf->ulOffsetCompVerts + pcSurf->ulNumVertices * sizeof(MDC::CompressedVertex) > iMax) ||
|
||||
pcSurf->ulOffsetTriangles + pcSurf->ulNumTriangles * sizeof(MDC::Triangle) > iMax ||
|
||||
pcSurf->ulOffsetTexCoords + pcSurf->ulNumVertices * sizeof(MDC::TexturCoord) > iMax ||
|
||||
pcSurf->ulOffsetShaders + pcSurf->ulNumShaders * sizeof(MDC::Shader) > iMax ||
|
||||
pcSurf->ulOffsetFrameBaseFrames + pcSurf->ulNumBaseFrames * 2 > iMax ||
|
||||
(pcSurf->ulNumCompFrames && pcSurf->ulOffsetFrameCompFrames + pcSurf->ulNumCompFrames * 2 > iMax))
|
||||
{
|
||||
throw new ImportErrorException("Some of the offset values in the MDC surface header "
|
||||
"are invalid and point somewhere behind the file.");
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Setup configuration properties
|
||||
void MDCImporter::SetupProperties(const Importer* pImp)
|
||||
{
|
||||
// The AI_CONFIG_IMPORT_MDC_KEYFRAME option overrides the
|
||||
// AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
|
||||
if(0xffffffff == (this->configFrameID = pImp->GetProperty(
|
||||
AI_CONFIG_IMPORT_MDC_KEYFRAME,0xffffffff)))
|
||||
{
|
||||
this->configFrameID = pImp->GetProperty(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Imports the given file into the given scene structure.
|
||||
void MDCImporter::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 MDC file " + pFile + ".");
|
||||
|
||||
// check whether the mdc file is large enough to contain the file header
|
||||
fileSize = (unsigned int)file->FileSize();
|
||||
if( fileSize < sizeof(MDC::Header))
|
||||
throw new ImportErrorException( "MDC File is too small.");
|
||||
|
||||
std::vector<unsigned char> mBuffer2(fileSize);
|
||||
file->Read( &mBuffer2[0], 1, fileSize);
|
||||
mBuffer = &mBuffer2[0];
|
||||
|
||||
// validate the file header
|
||||
this->pcHeader = (BE_NCONST MDC::Header*)this->mBuffer;
|
||||
this->ValidateHeader();
|
||||
|
||||
std::vector<std::string> aszShaders;
|
||||
|
||||
// get a pointer to the frame we want to read
|
||||
BE_NCONST MDC::Frame* pcFrame = (BE_NCONST MDC::Frame*)(this->mBuffer+
|
||||
this->pcHeader->ulOffsetBorderFrames);
|
||||
|
||||
// no need to swap the other members, we won't need them
|
||||
pcFrame += configFrameID;
|
||||
AI_SWAP4( pcFrame->localOrigin[0] );
|
||||
AI_SWAP4( pcFrame->localOrigin[1] );
|
||||
AI_SWAP4( pcFrame->localOrigin[2] );
|
||||
|
||||
// get the number of valid surfaces
|
||||
BE_NCONST MDC::Surface* pcSurface, *pcSurface2;
|
||||
pcSurface = pcSurface2 = (BE_NCONST MDC::Surface*)(mBuffer + pcHeader->ulOffsetSurfaces);
|
||||
unsigned int iNumShaders = 0;
|
||||
for (unsigned int i = 0; i < pcHeader->ulNumSurfaces;++i)
|
||||
{
|
||||
// validate the surface header
|
||||
this->ValidateSurfaceHeader(pcSurface2);
|
||||
|
||||
if (pcSurface2->ulNumVertices && pcSurface2->ulNumTriangles)++pScene->mNumMeshes;
|
||||
iNumShaders += pcSurface2->ulNumShaders;
|
||||
pcSurface2 = (const MDC::Surface*)((int8_t*)pcSurface2 + pcSurface2->ulOffsetEnd);
|
||||
}
|
||||
aszShaders.reserve(iNumShaders);
|
||||
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
|
||||
|
||||
// necessary that we don't crash if an exception occurs
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
||||
pScene->mMeshes[i] = NULL;
|
||||
|
||||
// now read all surfaces
|
||||
unsigned int iDefaultMatIndex = 0xffffffff;
|
||||
for (unsigned int i = 0, iNum = 0; i < pcHeader->ulNumSurfaces;++i)
|
||||
{
|
||||
if (!pcSurface->ulNumVertices || !pcSurface->ulNumTriangles)continue;
|
||||
aiMesh* pcMesh = pScene->mMeshes[iNum++] = new aiMesh();
|
||||
|
||||
pcMesh->mNumFaces = pcSurface->ulNumTriangles;
|
||||
pcMesh->mNumVertices = pcMesh->mNumFaces * 3;
|
||||
|
||||
// store the name of the surface for use as node name.
|
||||
// FIX: make sure there is a 0 termination
|
||||
const_cast<char&>(pcSurface->ucName[AI_MDC_MAXQPATH-1]) = '\0';
|
||||
pcMesh->mTextureCoords[3] = (aiVector3D*)pcSurface->ucName;
|
||||
|
||||
// go to the first shader in the file. ignore the others.
|
||||
if (pcSurface->ulNumShaders)
|
||||
{
|
||||
const MDC::Shader* pcShader = (const MDC::Shader*)((int8_t*)pcSurface + pcSurface->ulOffsetShaders);
|
||||
pcMesh->mMaterialIndex = (unsigned int)aszShaders.size();
|
||||
|
||||
// create a new shader
|
||||
aszShaders.push_back(std::string( pcShader->ucName, std::min(
|
||||
::strlen(pcShader->ucName),sizeof(pcShader->ucName)) ));
|
||||
}
|
||||
// need to create a default material
|
||||
else if (0xffffffff == iDefaultMatIndex)
|
||||
{
|
||||
pcMesh->mMaterialIndex = iDefaultMatIndex = (unsigned int)aszShaders.size();
|
||||
aszShaders.push_back(std::string());
|
||||
}
|
||||
// otherwise assign a reference to the default material
|
||||
else pcMesh->mMaterialIndex = iDefaultMatIndex;
|
||||
|
||||
// allocate output storage for the mesh
|
||||
aiVector3D* pcVertCur = pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
|
||||
aiVector3D* pcNorCur = pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
|
||||
aiVector3D* pcUVCur = pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
|
||||
aiFace* pcFaceCur = pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
|
||||
|
||||
// create all vertices/faces
|
||||
BE_NCONST MDC::Triangle* pcTriangle = (BE_NCONST MDC::Triangle*)
|
||||
((int8_t*)pcSurface+pcSurface->ulOffsetTriangles);
|
||||
|
||||
BE_NCONST MDC::TexturCoord* const pcUVs = (BE_NCONST MDC::TexturCoord*)
|
||||
((int8_t*)pcSurface+pcSurface->ulOffsetTexCoords);
|
||||
|
||||
// get a pointer to the uncompressed vertices
|
||||
int16_t iOfs = *((int16_t*) ((int8_t*) pcSurface +
|
||||
pcSurface->ulOffsetFrameBaseFrames) + this->configFrameID);
|
||||
|
||||
AI_SWAP2(iOfs);
|
||||
|
||||
BE_NCONST MDC::BaseVertex* const pcVerts = (BE_NCONST MDC::BaseVertex*)
|
||||
((int8_t*)pcSurface+pcSurface->ulOffsetBaseVerts) +
|
||||
((int)iOfs * pcSurface->ulNumVertices * 4);
|
||||
|
||||
// do the main swapping stuff ...
|
||||
#if (defined AI_BUILD_BIG_ENDIAN)
|
||||
|
||||
// swap all triangles
|
||||
for (unsigned int i = 0; i < pcSurface->ulNumTriangles;++i)
|
||||
{
|
||||
AI_SWAP4( pcTriangle[i].aiIndices[0] );
|
||||
AI_SWAP4( pcTriangle[i].aiIndices[1] );
|
||||
AI_SWAP4( pcTriangle[i].aiIndices[2] );
|
||||
}
|
||||
|
||||
// swap all vertices
|
||||
for (unsigned int i = 0; i < pcSurface->ulNumVertices*pcSurface->ulNumBaseFrames;++i)
|
||||
{
|
||||
AI_SWAP2( pcVerts->normal );
|
||||
AI_SWAP2( pcVerts->x );
|
||||
AI_SWAP2( pcVerts->y );
|
||||
AI_SWAP2( pcVerts->z );
|
||||
}
|
||||
|
||||
// swap all texture coordinates
|
||||
for (unsigned int i = 0; i < pcSurface->ulNumVertices;++i)
|
||||
{
|
||||
AI_SWAP4( pcUVs->v );
|
||||
AI_SWAP4( pcUVs->v );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
const MDC::CompressedVertex* pcCVerts;
|
||||
int16_t* mdcCompVert = NULL;
|
||||
|
||||
// access compressed frames for large frame numbers, but never for the first
|
||||
if( this->configFrameID && pcSurface->ulNumCompFrames > 0 )
|
||||
{
|
||||
mdcCompVert = (int16_t*) ((int8_t*)pcSurface+pcSurface->ulOffsetFrameCompFrames) + this->configFrameID;
|
||||
AI_SWAP2P(mdcCompVert);
|
||||
if( *mdcCompVert >= 0 )
|
||||
{
|
||||
pcCVerts = (const MDC::CompressedVertex*)((int8_t*)pcSurface +
|
||||
pcSurface->ulOffsetCompVerts) + *mdcCompVert * pcSurface->ulNumVertices;
|
||||
}
|
||||
else mdcCompVert = NULL;
|
||||
}
|
||||
|
||||
// copy all faces
|
||||
for (unsigned int iFace = 0; iFace < pcSurface->ulNumTriangles;++iFace,
|
||||
++pcTriangle,++pcFaceCur)
|
||||
{
|
||||
const unsigned int iOutIndex = iFace*3;
|
||||
pcFaceCur->mNumIndices = 3;
|
||||
pcFaceCur->mIndices = new unsigned int[3];
|
||||
|
||||
for (unsigned int iIndex = 0; iIndex < 3;++iIndex,
|
||||
++pcVertCur,++pcUVCur,++pcNorCur)
|
||||
{
|
||||
uint32_t quak = pcTriangle->aiIndices[iIndex];
|
||||
if (quak >= pcSurface->ulNumVertices)
|
||||
{
|
||||
DefaultLogger::get()->error("MDC vertex index is out of range");
|
||||
quak = pcSurface->ulNumVertices-1;
|
||||
}
|
||||
|
||||
// compressed vertices?
|
||||
if (mdcCompVert)
|
||||
{
|
||||
MDC::BuildVertex(*pcFrame,pcVerts[quak],pcCVerts[quak],
|
||||
*pcVertCur,*pcNorCur);
|
||||
}
|
||||
else
|
||||
{
|
||||
// copy position
|
||||
pcVertCur->x = pcVerts[quak].x * AI_MDC_BASE_SCALING;
|
||||
pcVertCur->y = pcVerts[quak].y * AI_MDC_BASE_SCALING;
|
||||
pcVertCur->z = pcVerts[quak].z * AI_MDC_BASE_SCALING;
|
||||
|
||||
// copy normals
|
||||
MD3::LatLngNormalToVec3( pcVerts[quak].normal, &pcNorCur->x );
|
||||
|
||||
// copy texture coordinates
|
||||
pcUVCur->x = pcUVs[quak].u;
|
||||
pcUVCur->y = 1.0f-pcUVs[quak].v; // DX to OGL
|
||||
}
|
||||
pcVertCur->x += pcFrame->localOrigin[0] ;
|
||||
pcVertCur->y += pcFrame->localOrigin[1] ;
|
||||
pcVertCur->z += pcFrame->localOrigin[2] ;
|
||||
}
|
||||
|
||||
// swap the face order - DX to OGL
|
||||
pcFaceCur->mIndices[0] = iOutIndex + 2;
|
||||
pcFaceCur->mIndices[1] = iOutIndex + 1;
|
||||
pcFaceCur->mIndices[2] = iOutIndex + 0;
|
||||
}
|
||||
|
||||
pcSurface = (BE_NCONST MDC::Surface*)((int8_t*)pcSurface + pcSurface->ulOffsetEnd);
|
||||
}
|
||||
|
||||
// create a flat node graph with a root node and one child for each surface
|
||||
if (!pScene->mNumMeshes)
|
||||
throw new ImportErrorException( "Invalid MDC file: File contains no valid mesh");
|
||||
else if (1 == pScene->mNumMeshes)
|
||||
{
|
||||
pScene->mRootNode = new aiNode();
|
||||
pScene->mRootNode->mName.Set(std::string((const char*)pScene->mMeshes[0]->mTextureCoords[3]));
|
||||
pScene->mRootNode->mNumMeshes = 1;
|
||||
pScene->mRootNode->mMeshes = new unsigned int[1];
|
||||
pScene->mRootNode->mMeshes[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
pScene->mRootNode = new aiNode();
|
||||
pScene->mRootNode->mNumChildren = pScene->mNumMeshes;
|
||||
pScene->mRootNode->mChildren = new aiNode*[pScene->mNumMeshes];
|
||||
pScene->mRootNode->mName.Set("<root>");
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
||||
{
|
||||
aiNode* pcNode = pScene->mRootNode->mChildren[i] = new aiNode();
|
||||
pcNode->mParent = pScene->mRootNode;
|
||||
pcNode->mName.Set(std::string((const char*)pScene->mMeshes[i]->mTextureCoords[3]));
|
||||
pcNode->mNumMeshes = 1;
|
||||
pcNode->mMeshes = new unsigned int[1];
|
||||
pcNode->mMeshes[0] = i;
|
||||
}
|
||||
}
|
||||
|
||||
// make sure we invalidate the pointer to the mesh name
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
||||
pScene->mMeshes[i]->mTextureCoords[3] = NULL;
|
||||
|
||||
// create materials
|
||||
pScene->mNumMaterials = aszShaders.size();
|
||||
pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
|
||||
for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
|
||||
{
|
||||
MaterialHelper* pcMat = new MaterialHelper();
|
||||
pScene->mMaterials[i] = pcMat;
|
||||
|
||||
const std::string& name = aszShaders[i];
|
||||
|
||||
int iMode = (int)aiShadingMode_Gouraud;
|
||||
pcMat->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
|
||||
|
||||
// add a small ambient color value - RtCW seems to have one
|
||||
aiColor3D clr;
|
||||
clr.b = clr.g = clr.r = 0.05f;
|
||||
pcMat->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
|
||||
|
||||
if (name.length())clr.b = clr.g = clr.r = 1.0f;
|
||||
else clr.b = clr.g = clr.r = 0.6f;
|
||||
|
||||
pcMat->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
|
||||
pcMat->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
|
||||
|
||||
if (name.length())
|
||||
{
|
||||
aiString path;
|
||||
path.Set(name);
|
||||
pcMat->AddProperty(&path,AI_MATKEY_TEXTURE_DIFFUSE(0));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
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 the MDC importer class. */
|
||||
#ifndef AI_MDCLOADER_H_INCLUDED
|
||||
#define AI_MDCLOADER_H_INCLUDED
|
||||
|
||||
#include "../include/aiTypes.h"
|
||||
|
||||
#include "BaseImporter.h"
|
||||
#include "MDCFileData.h"
|
||||
#include "ByteSwap.h"
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
using namespace MDC;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Used to load MDC files
|
||||
*/
|
||||
class MDCImporter : public BaseImporter
|
||||
{
|
||||
friend class Importer;
|
||||
|
||||
protected:
|
||||
/** Constructor to be privately used by Importer */
|
||||
MDCImporter();
|
||||
|
||||
/** Destructor, private as well */
|
||||
~MDCImporter();
|
||||
|
||||
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;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Called prior to ReadFile().
|
||||
* The function is a request to the importer to update its configuration
|
||||
* basing on the Importer's configuration property list.
|
||||
*/
|
||||
void SetupProperties(const Importer* pImp);
|
||||
|
||||
protected:
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Called by Importer::GetExtensionList() for each loaded importer.
|
||||
* See BaseImporter::GetExtensionList() for details
|
||||
*/
|
||||
void GetExtensionList(std::string& append)
|
||||
{
|
||||
append.append("*.mdc");
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** 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:
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Validate the header of the file
|
||||
*/
|
||||
void ValidateHeader();
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Validate the header of a MDC surface
|
||||
*/
|
||||
void ValidateSurfaceHeader(BE_NCONST MDC::Surface* pcSurf);
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
/** Configuration option: frame to be loaded */
|
||||
unsigned int configFrameID;
|
||||
|
||||
/** Header of the MDC file */
|
||||
BE_NCONST MDC::Header* pcHeader;
|
||||
|
||||
/** Buffer to hold the loaded file */
|
||||
unsigned char* mBuffer;
|
||||
|
||||
/** size of the file, in bytes */
|
||||
unsigned int fileSize;
|
||||
};
|
||||
|
||||
} // end of namespace Assimp
|
||||
|
||||
#endif // AI_3DSIMPORTER_H_INC
|
|
@ -0,0 +1,299 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
|
||||
PicoModel Library
|
||||
|
||||
Copyright (c) 2002, Randy Reddig & seaw0lf
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use 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 names of the copyright holders nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
#if (!defined MDC_NORMAL_TABLE_INCLUDED)
|
||||
#define MDC_NORMAL_TABLE_INCLUDED
|
||||
|
||||
/* mdc decoding normal table */
|
||||
float mdcNormals[ 256 ][ 3 ] =
|
||||
{
|
||||
{ 1.000000f, 0.000000f, 0.000000f },
|
||||
{ 0.980785f, 0.195090f, 0.000000f },
|
||||
{ 0.923880f, 0.382683f, 0.000000f },
|
||||
{ 0.831470f, 0.555570f, 0.000000f },
|
||||
{ 0.707107f, 0.707107f, 0.000000f },
|
||||
{ 0.555570f, 0.831470f, 0.000000f },
|
||||
{ 0.382683f, 0.923880f, 0.000000f },
|
||||
{ 0.195090f, 0.980785f, 0.000000f },
|
||||
{ -0.000000f, 1.000000f, 0.000000f },
|
||||
{ -0.195090f, 0.980785f, 0.000000f },
|
||||
{ -0.382683f, 0.923880f, 0.000000f },
|
||||
{ -0.555570f, 0.831470f, 0.000000f },
|
||||
{ -0.707107f, 0.707107f, 0.000000f },
|
||||
{ -0.831470f, 0.555570f, 0.000000f },
|
||||
{ -0.923880f, 0.382683f, 0.000000f },
|
||||
{ -0.980785f, 0.195090f, 0.000000f },
|
||||
{ -1.000000f, -0.000000f, 0.000000f },
|
||||
{ -0.980785f, -0.195090f, 0.000000f },
|
||||
{ -0.923880f, -0.382683f, 0.000000f },
|
||||
{ -0.831470f, -0.555570f, 0.000000f },
|
||||
{ -0.707107f, -0.707107f, 0.000000f },
|
||||
{ -0.555570f, -0.831469f, 0.000000f },
|
||||
{ -0.382684f, -0.923880f, 0.000000f },
|
||||
{ -0.195090f, -0.980785f, 0.000000f },
|
||||
{ 0.000000f, -1.000000f, 0.000000f },
|
||||
{ 0.195090f, -0.980785f, 0.000000f },
|
||||
{ 0.382684f, -0.923879f, 0.000000f },
|
||||
{ 0.555570f, -0.831470f, 0.000000f },
|
||||
{ 0.707107f, -0.707107f, 0.000000f },
|
||||
{ 0.831470f, -0.555570f, 0.000000f },
|
||||
{ 0.923880f, -0.382683f, 0.000000f },
|
||||
{ 0.980785f, -0.195090f, 0.000000f },
|
||||
{ 0.980785f, 0.000000f, -0.195090f },
|
||||
{ 0.956195f, 0.218245f, -0.195090f },
|
||||
{ 0.883657f, 0.425547f, -0.195090f },
|
||||
{ 0.766809f, 0.611510f, -0.195090f },
|
||||
{ 0.611510f, 0.766809f, -0.195090f },
|
||||
{ 0.425547f, 0.883657f, -0.195090f },
|
||||
{ 0.218245f, 0.956195f, -0.195090f },
|
||||
{ -0.000000f, 0.980785f, -0.195090f },
|
||||
{ -0.218245f, 0.956195f, -0.195090f },
|
||||
{ -0.425547f, 0.883657f, -0.195090f },
|
||||
{ -0.611510f, 0.766809f, -0.195090f },
|
||||
{ -0.766809f, 0.611510f, -0.195090f },
|
||||
{ -0.883657f, 0.425547f, -0.195090f },
|
||||
{ -0.956195f, 0.218245f, -0.195090f },
|
||||
{ -0.980785f, -0.000000f, -0.195090f },
|
||||
{ -0.956195f, -0.218245f, -0.195090f },
|
||||
{ -0.883657f, -0.425547f, -0.195090f },
|
||||
{ -0.766809f, -0.611510f, -0.195090f },
|
||||
{ -0.611510f, -0.766809f, -0.195090f },
|
||||
{ -0.425547f, -0.883657f, -0.195090f },
|
||||
{ -0.218245f, -0.956195f, -0.195090f },
|
||||
{ 0.000000f, -0.980785f, -0.195090f },
|
||||
{ 0.218245f, -0.956195f, -0.195090f },
|
||||
{ 0.425547f, -0.883657f, -0.195090f },
|
||||
{ 0.611510f, -0.766809f, -0.195090f },
|
||||
{ 0.766809f, -0.611510f, -0.195090f },
|
||||
{ 0.883657f, -0.425547f, -0.195090f },
|
||||
{ 0.956195f, -0.218245f, -0.195090f },
|
||||
{ 0.923880f, 0.000000f, -0.382683f },
|
||||
{ 0.892399f, 0.239118f, -0.382683f },
|
||||
{ 0.800103f, 0.461940f, -0.382683f },
|
||||
{ 0.653281f, 0.653281f, -0.382683f },
|
||||
{ 0.461940f, 0.800103f, -0.382683f },
|
||||
{ 0.239118f, 0.892399f, -0.382683f },
|
||||
{ -0.000000f, 0.923880f, -0.382683f },
|
||||
{ -0.239118f, 0.892399f, -0.382683f },
|
||||
{ -0.461940f, 0.800103f, -0.382683f },
|
||||
{ -0.653281f, 0.653281f, -0.382683f },
|
||||
{ -0.800103f, 0.461940f, -0.382683f },
|
||||
{ -0.892399f, 0.239118f, -0.382683f },
|
||||
{ -0.923880f, -0.000000f, -0.382683f },
|
||||
{ -0.892399f, -0.239118f, -0.382683f },
|
||||
{ -0.800103f, -0.461940f, -0.382683f },
|
||||
{ -0.653282f, -0.653281f, -0.382683f },
|
||||
{ -0.461940f, -0.800103f, -0.382683f },
|
||||
{ -0.239118f, -0.892399f, -0.382683f },
|
||||
{ 0.000000f, -0.923880f, -0.382683f },
|
||||
{ 0.239118f, -0.892399f, -0.382683f },
|
||||
{ 0.461940f, -0.800103f, -0.382683f },
|
||||
{ 0.653281f, -0.653282f, -0.382683f },
|
||||
{ 0.800103f, -0.461940f, -0.382683f },
|
||||
{ 0.892399f, -0.239117f, -0.382683f },
|
||||
{ 0.831470f, 0.000000f, -0.555570f },
|
||||
{ 0.790775f, 0.256938f, -0.555570f },
|
||||
{ 0.672673f, 0.488726f, -0.555570f },
|
||||
{ 0.488726f, 0.672673f, -0.555570f },
|
||||
{ 0.256938f, 0.790775f, -0.555570f },
|
||||
{ -0.000000f, 0.831470f, -0.555570f },
|
||||
{ -0.256938f, 0.790775f, -0.555570f },
|
||||
{ -0.488726f, 0.672673f, -0.555570f },
|
||||
{ -0.672673f, 0.488726f, -0.555570f },
|
||||
{ -0.790775f, 0.256938f, -0.555570f },
|
||||
{ -0.831470f, -0.000000f, -0.555570f },
|
||||
{ -0.790775f, -0.256938f, -0.555570f },
|
||||
{ -0.672673f, -0.488726f, -0.555570f },
|
||||
{ -0.488725f, -0.672673f, -0.555570f },
|
||||
{ -0.256938f, -0.790775f, -0.555570f },
|
||||
{ 0.000000f, -0.831470f, -0.555570f },
|
||||
{ 0.256938f, -0.790775f, -0.555570f },
|
||||
{ 0.488725f, -0.672673f, -0.555570f },
|
||||
{ 0.672673f, -0.488726f, -0.555570f },
|
||||
{ 0.790775f, -0.256938f, -0.555570f },
|
||||
{ 0.707107f, 0.000000f, -0.707107f },
|
||||
{ 0.653281f, 0.270598f, -0.707107f },
|
||||
{ 0.500000f, 0.500000f, -0.707107f },
|
||||
{ 0.270598f, 0.653281f, -0.707107f },
|
||||
{ -0.000000f, 0.707107f, -0.707107f },
|
||||
{ -0.270598f, 0.653282f, -0.707107f },
|
||||
{ -0.500000f, 0.500000f, -0.707107f },
|
||||
{ -0.653281f, 0.270598f, -0.707107f },
|
||||
{ -0.707107f, -0.000000f, -0.707107f },
|
||||
{ -0.653281f, -0.270598f, -0.707107f },
|
||||
{ -0.500000f, -0.500000f, -0.707107f },
|
||||
{ -0.270598f, -0.653281f, -0.707107f },
|
||||
{ 0.000000f, -0.707107f, -0.707107f },
|
||||
{ 0.270598f, -0.653281f, -0.707107f },
|
||||
{ 0.500000f, -0.500000f, -0.707107f },
|
||||
{ 0.653282f, -0.270598f, -0.707107f },
|
||||
{ 0.555570f, 0.000000f, -0.831470f },
|
||||
{ 0.481138f, 0.277785f, -0.831470f },
|
||||
{ 0.277785f, 0.481138f, -0.831470f },
|
||||
{ -0.000000f, 0.555570f, -0.831470f },
|
||||
{ -0.277785f, 0.481138f, -0.831470f },
|
||||
{ -0.481138f, 0.277785f, -0.831470f },
|
||||
{ -0.555570f, -0.000000f, -0.831470f },
|
||||
{ -0.481138f, -0.277785f, -0.831470f },
|
||||
{ -0.277785f, -0.481138f, -0.831470f },
|
||||
{ 0.000000f, -0.555570f, -0.831470f },
|
||||
{ 0.277785f, -0.481138f, -0.831470f },
|
||||
{ 0.481138f, -0.277785f, -0.831470f },
|
||||
{ 0.382683f, 0.000000f, -0.923880f },
|
||||
{ 0.270598f, 0.270598f, -0.923880f },
|
||||
{ -0.000000f, 0.382683f, -0.923880f },
|
||||
{ -0.270598f, 0.270598f, -0.923880f },
|
||||
{ -0.382683f, -0.000000f, -0.923880f },
|
||||
{ -0.270598f, -0.270598f, -0.923880f },
|
||||
{ 0.000000f, -0.382683f, -0.923880f },
|
||||
{ 0.270598f, -0.270598f, -0.923880f },
|
||||
{ 0.195090f, 0.000000f, -0.980785f },
|
||||
{ -0.000000f, 0.195090f, -0.980785f },
|
||||
{ -0.195090f, -0.000000f, -0.980785f },
|
||||
{ 0.000000f, -0.195090f, -0.980785f },
|
||||
{ 0.980785f, 0.000000f, 0.195090f },
|
||||
{ 0.956195f, 0.218245f, 0.195090f },
|
||||
{ 0.883657f, 0.425547f, 0.195090f },
|
||||
{ 0.766809f, 0.611510f, 0.195090f },
|
||||
{ 0.611510f, 0.766809f, 0.195090f },
|
||||
{ 0.425547f, 0.883657f, 0.195090f },
|
||||
{ 0.218245f, 0.956195f, 0.195090f },
|
||||
{ -0.000000f, 0.980785f, 0.195090f },
|
||||
{ -0.218245f, 0.956195f, 0.195090f },
|
||||
{ -0.425547f, 0.883657f, 0.195090f },
|
||||
{ -0.611510f, 0.766809f, 0.195090f },
|
||||
{ -0.766809f, 0.611510f, 0.195090f },
|
||||
{ -0.883657f, 0.425547f, 0.195090f },
|
||||
{ -0.956195f, 0.218245f, 0.195090f },
|
||||
{ -0.980785f, -0.000000f, 0.195090f },
|
||||
{ -0.956195f, -0.218245f, 0.195090f },
|
||||
{ -0.883657f, -0.425547f, 0.195090f },
|
||||
{ -0.766809f, -0.611510f, 0.195090f },
|
||||
{ -0.611510f, -0.766809f, 0.195090f },
|
||||
{ -0.425547f, -0.883657f, 0.195090f },
|
||||
{ -0.218245f, -0.956195f, 0.195090f },
|
||||
{ 0.000000f, -0.980785f, 0.195090f },
|
||||
{ 0.218245f, -0.956195f, 0.195090f },
|
||||
{ 0.425547f, -0.883657f, 0.195090f },
|
||||
{ 0.611510f, -0.766809f, 0.195090f },
|
||||
{ 0.766809f, -0.611510f, 0.195090f },
|
||||
{ 0.883657f, -0.425547f, 0.195090f },
|
||||
{ 0.956195f, -0.218245f, 0.195090f },
|
||||
{ 0.923880f, 0.000000f, 0.382683f },
|
||||
{ 0.892399f, 0.239118f, 0.382683f },
|
||||
{ 0.800103f, 0.461940f, 0.382683f },
|
||||
{ 0.653281f, 0.653281f, 0.382683f },
|
||||
{ 0.461940f, 0.800103f, 0.382683f },
|
||||
{ 0.239118f, 0.892399f, 0.382683f },
|
||||
{ -0.000000f, 0.923880f, 0.382683f },
|
||||
{ -0.239118f, 0.892399f, 0.382683f },
|
||||
{ -0.461940f, 0.800103f, 0.382683f },
|
||||
{ -0.653281f, 0.653281f, 0.382683f },
|
||||
{ -0.800103f, 0.461940f, 0.382683f },
|
||||
{ -0.892399f, 0.239118f, 0.382683f },
|
||||
{ -0.923880f, -0.000000f, 0.382683f },
|
||||
{ -0.892399f, -0.239118f, 0.382683f },
|
||||
{ -0.800103f, -0.461940f, 0.382683f },
|
||||
{ -0.653282f, -0.653281f, 0.382683f },
|
||||
{ -0.461940f, -0.800103f, 0.382683f },
|
||||
{ -0.239118f, -0.892399f, 0.382683f },
|
||||
{ 0.000000f, -0.923880f, 0.382683f },
|
||||
{ 0.239118f, -0.892399f, 0.382683f },
|
||||
{ 0.461940f, -0.800103f, 0.382683f },
|
||||
{ 0.653281f, -0.653282f, 0.382683f },
|
||||
{ 0.800103f, -0.461940f, 0.382683f },
|
||||
{ 0.892399f, -0.239117f, 0.382683f },
|
||||
{ 0.831470f, 0.000000f, 0.555570f },
|
||||
{ 0.790775f, 0.256938f, 0.555570f },
|
||||
{ 0.672673f, 0.488726f, 0.555570f },
|
||||
{ 0.488726f, 0.672673f, 0.555570f },
|
||||
{ 0.256938f, 0.790775f, 0.555570f },
|
||||
{ -0.000000f, 0.831470f, 0.555570f },
|
||||
{ -0.256938f, 0.790775f, 0.555570f },
|
||||
{ -0.488726f, 0.672673f, 0.555570f },
|
||||
{ -0.672673f, 0.488726f, 0.555570f },
|
||||
{ -0.790775f, 0.256938f, 0.555570f },
|
||||
{ -0.831470f, -0.000000f, 0.555570f },
|
||||
{ -0.790775f, -0.256938f, 0.555570f },
|
||||
{ -0.672673f, -0.488726f, 0.555570f },
|
||||
{ -0.488725f, -0.672673f, 0.555570f },
|
||||
{ -0.256938f, -0.790775f, 0.555570f },
|
||||
{ 0.000000f, -0.831470f, 0.555570f },
|
||||
{ 0.256938f, -0.790775f, 0.555570f },
|
||||
{ 0.488725f, -0.672673f, 0.555570f },
|
||||
{ 0.672673f, -0.488726f, 0.555570f },
|
||||
{ 0.790775f, -0.256938f, 0.555570f },
|
||||
{ 0.707107f, 0.000000f, 0.707107f },
|
||||
{ 0.653281f, 0.270598f, 0.707107f },
|
||||
{ 0.500000f, 0.500000f, 0.707107f },
|
||||
{ 0.270598f, 0.653281f, 0.707107f },
|
||||
{ -0.000000f, 0.707107f, 0.707107f },
|
||||
{ -0.270598f, 0.653282f, 0.707107f },
|
||||
{ -0.500000f, 0.500000f, 0.707107f },
|
||||
{ -0.653281f, 0.270598f, 0.707107f },
|
||||
{ -0.707107f, -0.000000f, 0.707107f },
|
||||
{ -0.653281f, -0.270598f, 0.707107f },
|
||||
{ -0.500000f, -0.500000f, 0.707107f },
|
||||
{ -0.270598f, -0.653281f, 0.707107f },
|
||||
{ 0.000000f, -0.707107f, 0.707107f },
|
||||
{ 0.270598f, -0.653281f, 0.707107f },
|
||||
{ 0.500000f, -0.500000f, 0.707107f },
|
||||
{ 0.653282f, -0.270598f, 0.707107f },
|
||||
{ 0.555570f, 0.000000f, 0.831470f },
|
||||
{ 0.481138f, 0.277785f, 0.831470f },
|
||||
{ 0.277785f, 0.481138f, 0.831470f },
|
||||
{ -0.000000f, 0.555570f, 0.831470f },
|
||||
{ -0.277785f, 0.481138f, 0.831470f },
|
||||
{ -0.481138f, 0.277785f, 0.831470f },
|
||||
{ -0.555570f, -0.000000f, 0.831470f },
|
||||
{ -0.481138f, -0.277785f, 0.831470f },
|
||||
{ -0.277785f, -0.481138f, 0.831470f },
|
||||
{ 0.000000f, -0.555570f, 0.831470f },
|
||||
{ 0.277785f, -0.481138f, 0.831470f },
|
||||
{ 0.481138f, -0.277785f, 0.831470f },
|
||||
{ 0.382683f, 0.000000f, 0.923880f },
|
||||
{ 0.270598f, 0.270598f, 0.923880f },
|
||||
{ -0.000000f, 0.382683f, 0.923880f },
|
||||
{ -0.270598f, 0.270598f, 0.923880f },
|
||||
{ -0.382683f, -0.000000f, 0.923880f },
|
||||
{ -0.270598f, -0.270598f, 0.923880f },
|
||||
{ 0.000000f, -0.382683f, 0.923880f },
|
||||
{ 0.270598f, -0.270598f, 0.923880f },
|
||||
{ 0.195090f, 0.000000f, 0.980785f },
|
||||
{ -0.000000f, 0.195090f, 0.980785f },
|
||||
{ -0.195090f, -0.000000f, 0.980785f },
|
||||
{ 0.000000f, -0.195090f, 0.980785f }
|
||||
};
|
||||
|
||||
#endif // !! MDC_NORMAL_TABLE_INCLUDED
|
|
@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "MDLDefaultColorMap.h"
|
||||
#include "MD2FileData.h"
|
||||
#include "qnan.h"
|
||||
#include "ByteSwap.h"
|
||||
|
||||
// public ASSIMP headers
|
||||
#include "../include/DefaultLogger.h"
|
||||
|
@ -62,8 +63,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
using namespace Assimp;
|
||||
|
||||
extern float g_avNormals[162][3];
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// macros used by the MDL7 loader
|
||||
|
@ -81,7 +80,6 @@ extern float g_avNormals[162][3];
|
|||
_AI_MDL7_ACCESS(_data,_index,_limit,MDL::Vertex_MDL7)
|
||||
#endif
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
MDLImporter::MDLImporter()
|
||||
|
@ -116,36 +114,34 @@ bool MDLImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
|
|||
return true;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Setup configuration properties
|
||||
void MDLImporter::SetupProperties(const Importer* pImp)
|
||||
{
|
||||
// The AI_CONFIG_IMPORT_MDL_KEYFRAME option overrides the
|
||||
// AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
|
||||
if(0xffffffff == (this->configFrameID = pImp->GetProperty(
|
||||
AI_CONFIG_IMPORT_MDL_KEYFRAME,0xffffffff)))
|
||||
{
|
||||
this->configFrameID = pImp->GetProperty(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Imports the given file into the given scene structure.
|
||||
void MDLImporter::InternReadFile(
|
||||
const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
|
||||
void MDLImporter::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 MDL file " + pFile + ".");
|
||||
}
|
||||
|
||||
// The AI_CONFIG_IMPORT_MDL_KEYFRAME option overrides the
|
||||
// AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
|
||||
#if 0
|
||||
if(0xffffffff == (this->configFrameID = this->mImporter->GetProperty(
|
||||
AI_CONFIG_IMPORT_MDL_KEYFRAME,0xffffffff)))
|
||||
{
|
||||
this->configFrameID = this->mImporter->GetProperty(
|
||||
AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
|
||||
}
|
||||
#endif
|
||||
|
||||
// this should work for all other types of MDL files, too ...
|
||||
// the quake header is one of the smallest, afaik
|
||||
this->iFileSize = (unsigned int)file->FileSize();
|
||||
if( this->iFileSize < sizeof(MDL::Header))
|
||||
{
|
||||
throw new ImportErrorException( "MDL File is too small.");
|
||||
}
|
||||
|
||||
// allocate storage and copy the contents of the file to a memory buffer
|
||||
this->pScene = pScene;
|
||||
|
@ -162,89 +158,93 @@ void MDLImporter::InternReadFile(
|
|||
// determine the file subtype and call the appropriate member function
|
||||
try {
|
||||
|
||||
// Original Quake1 format
|
||||
if (AI_MDL_MAGIC_NUMBER_BE == iMagicWord ||
|
||||
AI_MDL_MAGIC_NUMBER_LE == iMagicWord)
|
||||
{
|
||||
DefaultLogger::get()->debug("MDL subtype: Quake 1, magic word is IDPO");
|
||||
this->iGSFileVersion = 0;
|
||||
this->InternReadFile_Quake1();
|
||||
}
|
||||
// GameStudio A<old> MDL2 format - used by some test models that come with 3DGS
|
||||
else if (AI_MDL_MAGIC_NUMBER_BE_GS3 == iMagicWord ||
|
||||
AI_MDL_MAGIC_NUMBER_LE_GS3 == iMagicWord)
|
||||
{
|
||||
DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A2, magic word is MDL2");
|
||||
this->iGSFileVersion = 2;
|
||||
this->InternReadFile_Quake1();
|
||||
}
|
||||
// GameStudio A4 MDL3 format
|
||||
else if (AI_MDL_MAGIC_NUMBER_BE_GS4 == iMagicWord ||
|
||||
AI_MDL_MAGIC_NUMBER_LE_GS4 == iMagicWord)
|
||||
{
|
||||
DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A4, magic word is MDL3");
|
||||
this->iGSFileVersion = 3;
|
||||
this->InternReadFile_3DGS_MDL345();
|
||||
}
|
||||
// GameStudio A5+ MDL4 format
|
||||
else if (AI_MDL_MAGIC_NUMBER_BE_GS5a == iMagicWord ||
|
||||
AI_MDL_MAGIC_NUMBER_LE_GS5a == iMagicWord)
|
||||
{
|
||||
DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A4, magic word is MDL4");
|
||||
this->iGSFileVersion = 4;
|
||||
this->InternReadFile_3DGS_MDL345();
|
||||
}
|
||||
// GameStudio A5+ MDL5 format
|
||||
else if (AI_MDL_MAGIC_NUMBER_BE_GS5b == iMagicWord ||
|
||||
AI_MDL_MAGIC_NUMBER_LE_GS5b == iMagicWord)
|
||||
{
|
||||
DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A5, magic word is MDL5");
|
||||
this->iGSFileVersion = 5;
|
||||
this->InternReadFile_3DGS_MDL345();
|
||||
}
|
||||
// GameStudio A6+ MDL6 format (not sure whether it is really existing ... )
|
||||
else if (AI_MDL_MAGIC_NUMBER_BE_GS6 == iMagicWord ||
|
||||
AI_MDL_MAGIC_NUMBER_LE_GS6 == iMagicWord)
|
||||
{
|
||||
DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A6, magic word is MDL6");
|
||||
this->iGSFileVersion = 6;
|
||||
this->InternReadFile_3DGS_MDL345();
|
||||
}
|
||||
// GameStudio A7 MDL7 format
|
||||
else if (AI_MDL_MAGIC_NUMBER_BE_GS7 == iMagicWord ||
|
||||
AI_MDL_MAGIC_NUMBER_LE_GS7 == iMagicWord)
|
||||
{
|
||||
DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A7, magic word is MDL7");
|
||||
this->iGSFileVersion = 7;
|
||||
this->InternReadFile_3DGS_MDL7();
|
||||
}
|
||||
// IDST/IDSQ Format (CS:S/HL², etc ...)
|
||||
else if (AI_MDL_MAGIC_NUMBER_BE_HL2a == iMagicWord ||
|
||||
AI_MDL_MAGIC_NUMBER_LE_HL2a == iMagicWord ||
|
||||
AI_MDL_MAGIC_NUMBER_BE_HL2b == iMagicWord ||
|
||||
AI_MDL_MAGIC_NUMBER_LE_HL2b == iMagicWord)
|
||||
{
|
||||
DefaultLogger::get()->debug("MDL subtype: CS:S\\HL², magic word is IDST/IDSQ");
|
||||
this->iGSFileVersion = 0;
|
||||
this->InternReadFile_HL2();
|
||||
}
|
||||
else
|
||||
{
|
||||
// print the magic word to the logger
|
||||
char szBuffer[5];
|
||||
szBuffer[0] = ((char*)&iMagicWord)[0];
|
||||
szBuffer[1] = ((char*)&iMagicWord)[1];
|
||||
szBuffer[2] = ((char*)&iMagicWord)[2];
|
||||
szBuffer[3] = ((char*)&iMagicWord)[3];
|
||||
szBuffer[4] = '\0';
|
||||
// Original Quake1 format
|
||||
if (AI_MDL_MAGIC_NUMBER_BE == iMagicWord ||
|
||||
AI_MDL_MAGIC_NUMBER_LE == iMagicWord)
|
||||
{
|
||||
DefaultLogger::get()->debug("MDL subtype: Quake 1, magic word is IDPO");
|
||||
this->iGSFileVersion = 0;
|
||||
this->InternReadFile_Quake1();
|
||||
}
|
||||
// GameStudio A<old> MDL2 format - used by some test models that come with 3DGS
|
||||
else if (AI_MDL_MAGIC_NUMBER_BE_GS3 == iMagicWord ||
|
||||
AI_MDL_MAGIC_NUMBER_LE_GS3 == iMagicWord)
|
||||
{
|
||||
DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A2, magic word is MDL2");
|
||||
this->iGSFileVersion = 2;
|
||||
this->InternReadFile_Quake1();
|
||||
}
|
||||
// GameStudio A4 MDL3 format
|
||||
else if (AI_MDL_MAGIC_NUMBER_BE_GS4 == iMagicWord ||
|
||||
AI_MDL_MAGIC_NUMBER_LE_GS4 == iMagicWord)
|
||||
{
|
||||
DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A4, magic word is MDL3");
|
||||
this->iGSFileVersion = 3;
|
||||
this->InternReadFile_3DGS_MDL345();
|
||||
}
|
||||
// GameStudio A5+ MDL4 format
|
||||
else if (AI_MDL_MAGIC_NUMBER_BE_GS5a == iMagicWord ||
|
||||
AI_MDL_MAGIC_NUMBER_LE_GS5a == iMagicWord)
|
||||
{
|
||||
DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A4, magic word is MDL4");
|
||||
this->iGSFileVersion = 4;
|
||||
this->InternReadFile_3DGS_MDL345();
|
||||
}
|
||||
// GameStudio A5+ MDL5 format
|
||||
else if (AI_MDL_MAGIC_NUMBER_BE_GS5b == iMagicWord ||
|
||||
AI_MDL_MAGIC_NUMBER_LE_GS5b == iMagicWord)
|
||||
{
|
||||
DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A5, magic word is MDL5");
|
||||
this->iGSFileVersion = 5;
|
||||
this->InternReadFile_3DGS_MDL345();
|
||||
}
|
||||
// GameStudio A6+ MDL6 format (not sure whether it is really existing ... )
|
||||
else if (AI_MDL_MAGIC_NUMBER_BE_GS6 == iMagicWord ||
|
||||
AI_MDL_MAGIC_NUMBER_LE_GS6 == iMagicWord)
|
||||
{
|
||||
DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A6, magic word is MDL6");
|
||||
this->iGSFileVersion = 6;
|
||||
this->InternReadFile_3DGS_MDL345();
|
||||
}
|
||||
// GameStudio A7 MDL7 format
|
||||
else if (AI_MDL_MAGIC_NUMBER_BE_GS7 == iMagicWord ||
|
||||
AI_MDL_MAGIC_NUMBER_LE_GS7 == iMagicWord)
|
||||
{
|
||||
DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A7, magic word is MDL7");
|
||||
this->iGSFileVersion = 7;
|
||||
this->InternReadFile_3DGS_MDL7();
|
||||
}
|
||||
// IDST/IDSQ Format (CS:S/HL², etc ...)
|
||||
else if (AI_MDL_MAGIC_NUMBER_BE_HL2a == iMagicWord ||
|
||||
AI_MDL_MAGIC_NUMBER_LE_HL2a == iMagicWord ||
|
||||
AI_MDL_MAGIC_NUMBER_BE_HL2b == iMagicWord ||
|
||||
AI_MDL_MAGIC_NUMBER_LE_HL2b == iMagicWord)
|
||||
{
|
||||
DefaultLogger::get()->debug("MDL subtype: CS:S\\HL², magic word is IDST/IDSQ");
|
||||
this->iGSFileVersion = 0;
|
||||
this->InternReadFile_HL2();
|
||||
}
|
||||
else
|
||||
{
|
||||
// print the magic word to the logger
|
||||
char szBuffer[5];
|
||||
szBuffer[0] = ((char*)&iMagicWord)[0];
|
||||
szBuffer[1] = ((char*)&iMagicWord)[1];
|
||||
szBuffer[2] = ((char*)&iMagicWord)[2];
|
||||
szBuffer[3] = ((char*)&iMagicWord)[3];
|
||||
szBuffer[4] = '\0';
|
||||
|
||||
// we're definitely unable to load this file
|
||||
throw new ImportErrorException( "Unknown MDL subformat " + pFile +
|
||||
". Magic word (" + szBuffer + ") is not known");
|
||||
}
|
||||
// we're definitely unable to load this file
|
||||
throw new ImportErrorException( "Unknown MDL subformat " + pFile +
|
||||
". Magic word (" + szBuffer + ") is not known");
|
||||
}
|
||||
|
||||
} catch (ImportErrorException* ex) {
|
||||
}
|
||||
catch (ImportErrorException* ex) {
|
||||
delete[] this->mBuffer;
|
||||
AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
|
||||
AI_DEBUG_INVALIDATE_PTR(this->pIOHandler);
|
||||
AI_DEBUG_INVALIDATE_PTR(this->pScene);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
|
@ -253,7 +253,6 @@ void MDLImporter::InternReadFile(
|
|||
AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
|
||||
AI_DEBUG_INVALIDATE_PTR(this->pIOHandler);
|
||||
AI_DEBUG_INVALIDATE_PTR(this->pScene);
|
||||
return;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void MDLImporter::SizeCheck(const void* szPos)
|
||||
|
@ -279,12 +278,7 @@ void MDLImporter::SizeCheck(const void* szPos, const char* szFile, unsigned int
|
|||
if (szFilePtr)++szFilePtr;
|
||||
|
||||
char szBuffer[1024];
|
||||
#if _MSC_VER >= 1400
|
||||
::sprintf_s(szBuffer,
|
||||
#else
|
||||
::sprintf(szBuffer,
|
||||
#endif
|
||||
"Invalid MDL file. The file is too small "
|
||||
::sprintf(szBuffer,"Invalid MDL file. The file is too small "
|
||||
"or contains invalid data (File: %s Line: %i)",szFilePtr,iLine);
|
||||
|
||||
throw new ImportErrorException(szBuffer);
|
||||
|
@ -295,56 +289,67 @@ void MDLImporter::ValidateHeader_Quake1(const MDL::Header* pcHeader)
|
|||
{
|
||||
// some values may not be NULL
|
||||
if (!pcHeader->num_frames)
|
||||
{
|
||||
throw new ImportErrorException( "[Quake 1 MDL] There are no frames in the file");
|
||||
}
|
||||
|
||||
if (!pcHeader->num_verts)
|
||||
{
|
||||
throw new ImportErrorException( "[Quake 1 MDL] There are no vertices in the file");
|
||||
}
|
||||
|
||||
if (!pcHeader->num_tris)
|
||||
{
|
||||
throw new ImportErrorException( "[Quake 1 MDL] There are no triangles in the file");
|
||||
}
|
||||
|
||||
// check whether the maxima are exceeded ...however, this applies for Quake 1 MDLs only
|
||||
if (!this->iGSFileVersion)
|
||||
{
|
||||
if (pcHeader->num_verts > AI_MDL_MAX_VERTS)
|
||||
{
|
||||
DefaultLogger::get()->warn("Quake 1 MDL model has more than AI_MDL_MAX_VERTS vertices");
|
||||
}
|
||||
|
||||
if (pcHeader->num_tris > AI_MDL_MAX_TRIANGLES)
|
||||
{
|
||||
DefaultLogger::get()->warn("Quake 1 MDL model has more than AI_MDL_MAX_TRIANGLES triangles");
|
||||
}
|
||||
|
||||
if (pcHeader->num_frames > AI_MDL_MAX_FRAMES)
|
||||
{
|
||||
DefaultLogger::get()->warn("Quake 1 MDL model has more than AI_MDL_MAX_FRAMES frames");
|
||||
}
|
||||
|
||||
// (this does not apply for 3DGS MDLs)
|
||||
if (!this->iGSFileVersion && pcHeader->version != AI_MDL_VERSION)
|
||||
{
|
||||
DefaultLogger::get()->warn("Quake 1 MDL model has an unknown version: AI_MDL_VERSION (=6) is "
|
||||
"the expected file format version");
|
||||
}
|
||||
|
||||
if (pcHeader->num_skins)
|
||||
{
|
||||
if(!pcHeader->skinwidth || !pcHeader->skinheight)
|
||||
{
|
||||
DefaultLogger::get()->warn("Skin width or height are 0. Division through "
|
||||
"zero would occur ...");
|
||||
}
|
||||
}
|
||||
if(pcHeader->num_skins && (!pcHeader->skinwidth || !pcHeader->skinheight))
|
||||
DefaultLogger::get()->warn("Skin width or height are 0");
|
||||
}
|
||||
}
|
||||
#ifdef AI_BUILD_BIG_ENDIAN
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void FlipQuakeHeader(BE_NCONST MDL::Header* pcHeader)
|
||||
{
|
||||
ByteSwap::Swap4(& pcHeader->ident);
|
||||
ByteSwap::Swap4(& pcHeader->version);
|
||||
ByteSwap::Swap4(& pcHeader->boundingradius);
|
||||
ByteSwap::Swap4(& pcHeader->flags);
|
||||
ByteSwap::Swap4(& pcHeader->num_frames);
|
||||
ByteSwap::Swap4(& pcHeader->num_skins);
|
||||
ByteSwap::Swap4(& pcHeader->num_tris);
|
||||
ByteSwap::Swap4(& pcHeader->num_verts);
|
||||
for (unsigned int i = 0; i < 3;++i)
|
||||
{
|
||||
ByteSwap::Swap4(& pcHeader->scale[i]);
|
||||
ByteSwap::Swap4(& pcHeader->translate[i]);
|
||||
}
|
||||
ByteSwap::Swap4(& pcHeader->size);
|
||||
ByteSwap::Swap4(& pcHeader->skinheight);
|
||||
ByteSwap::Swap4(& pcHeader->skin);
|
||||
}
|
||||
#endif
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void MDLImporter::InternReadFile_Quake1( )
|
||||
{
|
||||
ai_assert(NULL != pScene);
|
||||
|
||||
const MDL::Header* pcHeader = (const MDL::Header*)this->mBuffer;
|
||||
BE_NCONST MDL::Header* pcHeader = (BE_NCONST MDL::Header*)this->mBuffer;
|
||||
|
||||
#ifdef AI_BUILD_BIG_ENDIAN
|
||||
FlipQuakeHeader(pcHeader);
|
||||
#endif
|
||||
|
||||
ValidateHeader_Quake1(pcHeader);
|
||||
|
||||
// current cursor position in the file
|
||||
|
@ -353,13 +358,16 @@ void MDLImporter::InternReadFile_Quake1( )
|
|||
// need to read all textures
|
||||
for (unsigned int i = 0; i < (unsigned int)pcHeader->num_skins;++i)
|
||||
{
|
||||
union{const MDL::Skin* pcSkin;const MDL::GroupSkin* pcGroupSkin;};
|
||||
pcSkin = (const MDL::Skin*)szCurrent;
|
||||
union{BE_NCONST MDL::Skin* pcSkin;BE_NCONST MDL::GroupSkin* pcGroupSkin;};
|
||||
pcSkin = (BE_NCONST MDL::Skin*)szCurrent;
|
||||
|
||||
AI_SWAP4( pcSkin->group );
|
||||
|
||||
// Quake 1 groupskins
|
||||
if (1 == pcSkin->group)
|
||||
{
|
||||
AI_SWAP4( pcGroupSkin->nb );
|
||||
|
||||
// need to skip multiple images
|
||||
const unsigned int iNumImages = (unsigned int)pcGroupSkin->nb;
|
||||
szCurrent += sizeof(uint32_t) * 2;
|
||||
|
@ -413,6 +421,25 @@ void MDLImporter::InternReadFile_Quake1( )
|
|||
|
||||
VALIDATE_FILE_SIZE((const unsigned char*)(pcVertices + pcHeader->num_verts));
|
||||
|
||||
#ifdef AI_BUILD_BIG_ENDIAN
|
||||
|
||||
for (unsigned int i = 0; i<pcHeader->num_verts;++i)
|
||||
{
|
||||
AI_SWAP4( pcTexCoords[i].onseam );
|
||||
AI_SWAP4( pcTexCoords[i].s );
|
||||
AI_SWAP4( pcTexCoords[i].t );
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i<pcHeader->num_tris;++i)
|
||||
{
|
||||
AI_SWAP4( pcTriangles[i].facesfront);
|
||||
AI_SWAP4( pcTriangles[i].vertex[0]);
|
||||
AI_SWAP4( pcTriangles[i].vertex[1]);
|
||||
AI_SWAP4( pcTriangles[i].vertex[2]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// setup materials
|
||||
this->SetupMaterialProperties_3DGS_MDL5_Quake1();
|
||||
|
||||
|
@ -453,7 +480,6 @@ void MDLImporter::InternReadFile_Quake1( )
|
|||
if (iIndex >= (unsigned int)pcHeader->num_verts)
|
||||
{
|
||||
iIndex = pcHeader->num_verts-1;
|
||||
|
||||
DefaultLogger::get()->warn("Index overflow in Q1-MDL vertex list.");
|
||||
}
|
||||
|
||||
|
@ -461,16 +487,16 @@ void MDLImporter::InternReadFile_Quake1( )
|
|||
vec.x = (float)pcVertices[iIndex].v[0] * pcHeader->scale[0];
|
||||
vec.x += pcHeader->translate[0];
|
||||
|
||||
// (flip z and y component)
|
||||
vec.z = (float)pcVertices[iIndex].v[1] * pcHeader->scale[1];
|
||||
vec.z += pcHeader->translate[1];
|
||||
vec.y = (float)pcVertices[iIndex].v[1] * pcHeader->scale[1];
|
||||
vec.y += pcHeader->translate[1];
|
||||
vec.y *= -1.0f;
|
||||
|
||||
vec.y = (float)pcVertices[iIndex].v[2] * pcHeader->scale[2];
|
||||
vec.y += pcHeader->translate[2];
|
||||
vec.z = (float)pcVertices[iIndex].v[2] * pcHeader->scale[2];
|
||||
vec.z += pcHeader->translate[2];
|
||||
|
||||
// read the normal vector from the precalculated normal table
|
||||
MD2::LookupNormalIndex(pcVertices[iIndex].normalIndex,pcMesh->mNormals[iCurrent]);
|
||||
std::swap ( pcMesh->mNormals[iCurrent].y,pcMesh->mNormals[iCurrent].z );
|
||||
pcMesh->mNormals[iCurrent].y *= -1.0f;
|
||||
|
||||
// read texture coordinates
|
||||
float s = (float)pcTexCoords[iIndex].s;
|
||||
|
@ -546,6 +572,9 @@ void MDLImporter::InternReadFile_3DGS_MDL345( )
|
|||
|
||||
// the header of MDL 3/4/5 is nearly identical to the original Quake1 header
|
||||
const MDL::Header* pcHeader = (const MDL::Header*)this->mBuffer;
|
||||
#ifdef AI_BUILD_BIG_ENDIAN
|
||||
FlipQuakeHeader(pcHeader);
|
||||
#endif
|
||||
this->ValidateHeader_Quake1(pcHeader);
|
||||
|
||||
// current cursor position in the file
|
||||
|
@ -584,6 +613,26 @@ void MDLImporter::InternReadFile_3DGS_MDL345( )
|
|||
const MDL::Triangle_MDL3* pcTriangles = (const MDL::Triangle_MDL3*)szCurrent;
|
||||
szCurrent += sizeof(MDL::Triangle_MDL3) * pcHeader->num_tris;
|
||||
|
||||
#ifdef AI_BUILD_BIG_ENDIAN
|
||||
|
||||
for (unsigned int i = 0; i<pcHeader->synctype;++i)
|
||||
{
|
||||
AI_SWAP2( pcTexCoords[i].u );
|
||||
AI_SWAP2( pcTexCoords[i].v );
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i<pcHeader->num_tris;++i)
|
||||
{
|
||||
AI_SWAP4( pcTriangles[i].index_xyz[0]);
|
||||
AI_SWAP4( pcTriangles[i].index_xyz[1]);
|
||||
AI_SWAP4( pcTriangles[i].index_xyz[2]);
|
||||
AI_SWAP4( pcTriangles[i].index_uv[0]);
|
||||
AI_SWAP4( pcTriangles[i].index_uv[1]);
|
||||
AI_SWAP4( pcTriangles[i].index_uv[2]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
VALIDATE_FILE_SIZE(szCurrent);
|
||||
|
||||
// setup materials
|
||||
|
@ -620,15 +669,15 @@ void MDLImporter::InternReadFile_3DGS_MDL345( )
|
|||
const MDL::Frame* pcFrames = (const MDL::Frame*)szCurrent;
|
||||
|
||||
// byte packed vertices
|
||||
// BIG TODO: these two snippets are nearly totally identical ...
|
||||
// ***********************************************************************
|
||||
if (0 == pcFrames->type || 3 >= this->iGSFileVersion)
|
||||
{
|
||||
const MDL::SimpleFrame* pcFirstFrame =
|
||||
(const MDL::SimpleFrame*)(szCurrent + sizeof(uint32_t));
|
||||
const MDL::SimpleFrame* pcFirstFrame = (const MDL::SimpleFrame*)(szCurrent + sizeof(uint32_t));
|
||||
|
||||
// get a pointer to the vertices
|
||||
const MDL::Vertex* pcVertices = (const MDL::Vertex*) (
|
||||
(pcFirstFrame->name) + sizeof(pcFirstFrame->name));
|
||||
const MDL::Vertex* pcVertices = (const MDL::Vertex*) ((pcFirstFrame->name)
|
||||
+ sizeof(pcFirstFrame->name));
|
||||
|
||||
VALIDATE_FILE_SIZE(pcVertices + pcHeader->num_verts);
|
||||
|
||||
|
@ -654,16 +703,16 @@ void MDLImporter::InternReadFile_3DGS_MDL345( )
|
|||
vec.x = (float)pcVertices[iIndex].v[0] * pcHeader->scale[0];
|
||||
vec.x += pcHeader->translate[0];
|
||||
|
||||
// (flip z and y component)
|
||||
vec.z = (float)pcVertices[iIndex].v[1] * pcHeader->scale[1];
|
||||
vec.z += pcHeader->translate[1];
|
||||
vec.y = (float)pcVertices[iIndex].v[1] * pcHeader->scale[1];
|
||||
vec.y += pcHeader->translate[1];
|
||||
vec.y *= -1.0f;
|
||||
|
||||
vec.y = (float)pcVertices[iIndex].v[2] * pcHeader->scale[2];
|
||||
vec.y += pcHeader->translate[2];
|
||||
vec.z = (float)pcVertices[iIndex].v[2] * pcHeader->scale[2];
|
||||
vec.z += pcHeader->translate[2];
|
||||
|
||||
// read the normal vector from the precalculated normal table
|
||||
MD2::LookupNormalIndex(pcVertices[iIndex].normalIndex,pcMesh->mNormals[iCurrent]);
|
||||
std::swap ( pcMesh->mNormals[iCurrent].y,pcMesh->mNormals[iCurrent].z );
|
||||
pcMesh->mNormals[iCurrent].y *= -1.0f;
|
||||
|
||||
// read texture coordinates
|
||||
if (pcHeader->synctype)
|
||||
|
@ -684,12 +733,11 @@ void MDLImporter::InternReadFile_3DGS_MDL345( )
|
|||
else
|
||||
{
|
||||
// now get a pointer to the first frame in the file
|
||||
const MDL::SimpleFrame_MDLn_SP* pcFirstFrame =
|
||||
(const MDL::SimpleFrame_MDLn_SP*) (szCurrent + sizeof(uint32_t));
|
||||
const MDL::SimpleFrame_MDLn_SP* pcFirstFrame = (const MDL::SimpleFrame_MDLn_SP*) (szCurrent + sizeof(uint32_t));
|
||||
|
||||
// get a pointer to the vertices
|
||||
const MDL::Vertex_MDL4* pcVertices = (const MDL::Vertex_MDL4*)
|
||||
((pcFirstFrame->name) + sizeof(pcFirstFrame->name));
|
||||
const MDL::Vertex_MDL4* pcVertices = (const MDL::Vertex_MDL4*) ((pcFirstFrame->name) +
|
||||
sizeof(pcFirstFrame->name));
|
||||
|
||||
VALIDATE_FILE_SIZE(pcVertices + pcHeader->num_verts);
|
||||
|
||||
|
@ -715,16 +763,16 @@ void MDLImporter::InternReadFile_3DGS_MDL345( )
|
|||
vec.x = (float)pcVertices[iIndex].v[0] * pcHeader->scale[0];
|
||||
vec.x += pcHeader->translate[0];
|
||||
|
||||
// (flip z and y component)
|
||||
vec.z = (float)pcVertices[iIndex].v[1] * pcHeader->scale[1];
|
||||
vec.z += pcHeader->translate[1];
|
||||
vec.y = (float)pcVertices[iIndex].v[1] * pcHeader->scale[1];
|
||||
vec.y += pcHeader->translate[1];
|
||||
vec.y *= -1.0f;
|
||||
|
||||
vec.y = (float)pcVertices[iIndex].v[2] * pcHeader->scale[2];
|
||||
vec.y += pcHeader->translate[2];
|
||||
vec.z = (float)pcVertices[iIndex].v[2] * pcHeader->scale[2];
|
||||
vec.z += pcHeader->translate[2];
|
||||
|
||||
// read the normal vector from the precalculated normal table
|
||||
MD2::LookupNormalIndex(pcVertices[iIndex].normalIndex,pcMesh->mNormals[iCurrent]);
|
||||
std::swap ( pcMesh->mNormals[iCurrent].y,pcMesh->mNormals[iCurrent].z );
|
||||
pcMesh->mNormals[iCurrent].y *= -1.0f;
|
||||
|
||||
// read texture coordinates
|
||||
if (pcHeader->synctype)
|
||||
|
@ -920,14 +968,9 @@ void MDLImporter::CalcAbsBoneMatrices_3DGS_MDL7(const MDL::Bone_MDL7* pcBones,
|
|||
|
||||
if (AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE == pcHeader->bone_stc_size)
|
||||
{
|
||||
// no real name for our poor bone :-(
|
||||
# if (_MSC_VER >= 1400)
|
||||
pcOutBone->mName.length = ::sprintf_s(pcOutBone->mName.data,
|
||||
MAXLEN,"UnnamedBone_%i",iBone);
|
||||
# else
|
||||
pcOutBone->mName.length = ::sprintf(pcOutBone->mName.data,
|
||||
"UnnamedBone_%i",iBone);
|
||||
# endif
|
||||
// no real name for our poor bone is specified :-(
|
||||
pcOutBone->mName.length = ::sprintf(pcOutBone->mName.data,
|
||||
"UnnamedBone_%i",iBone);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1012,17 +1055,15 @@ void MDLImporter::ReadFaces_3DGS_MDL7(
|
|||
// write the output face index
|
||||
groupData.pcFaces[iTriangle].mIndices[2-c] = iOutIndex;
|
||||
|
||||
// swap z and y axis
|
||||
aiVector3D& vPosition = groupData.vPositions[ iOutIndex ];
|
||||
vPosition.x = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .x;
|
||||
vPosition.z = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .y;
|
||||
vPosition.y = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .z;
|
||||
vPosition.y = -1.0f*_AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .y;
|
||||
vPosition.z = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .z;
|
||||
|
||||
// if we have bones, save the index
|
||||
if (!groupData.aiBones.empty())
|
||||
{
|
||||
groupData.aiBones[iOutIndex] = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size).vertindex;
|
||||
}
|
||||
groupData.aiBones[iOutIndex] = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,
|
||||
iIndex,pcHeader->mainvertex_stc_size).vertindex;
|
||||
|
||||
// now read the normal vector
|
||||
if (AI_MDL7_FRAMEVERTEX030305_STCSIZE <= pcHeader->mainvertex_stc_size)
|
||||
|
@ -1030,8 +1071,8 @@ void MDLImporter::ReadFaces_3DGS_MDL7(
|
|||
// read the full normal vector
|
||||
aiVector3D& vNormal = groupData.vNormals[ iOutIndex ];
|
||||
vNormal.x = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[0];
|
||||
vNormal.z = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[1];
|
||||
vNormal.y = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[2];
|
||||
vNormal.y = -1.0f*_AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[1];
|
||||
vNormal.z = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[2];
|
||||
}
|
||||
else if (AI_MDL7_FRAMEVERTEX120503_STCSIZE <= pcHeader->mainvertex_stc_size)
|
||||
{
|
||||
|
@ -1039,8 +1080,7 @@ void MDLImporter::ReadFaces_3DGS_MDL7(
|
|||
aiVector3D& vNormal = groupData.vNormals[ iOutIndex ];
|
||||
MD2::LookupNormalIndex(_AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,
|
||||
pcHeader->mainvertex_stc_size) .norm162index,vNormal);
|
||||
|
||||
std::swap(groupData.vNormals[iOutIndex].z,groupData.vNormals[iOutIndex].y);
|
||||
vNormal.y *= -1.0f;
|
||||
}
|
||||
// validate and process the first uv coordinate set
|
||||
// *************************************************************
|
||||
|
@ -1063,9 +1103,7 @@ void MDLImporter::ReadFaces_3DGS_MDL7(
|
|||
}
|
||||
// assign the material index, but only if it is existing
|
||||
if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV_WITH_MATINDEX)
|
||||
{
|
||||
groupData.pcFaces[iTriangle].iMatIndex[0] = pcGroupTris->skinsets[0].material;
|
||||
}
|
||||
}
|
||||
// validate and process the second uv coordinate set
|
||||
// *************************************************************
|
||||
|
@ -1090,14 +1128,11 @@ void MDLImporter::ReadFaces_3DGS_MDL7(
|
|||
// coordinate set ... wastes memory and loading time
|
||||
if (0 != iIndex && (u != groupData.vTextureCoords1[ iOutIndex ].x ||
|
||||
v != groupData.vTextureCoords1[ iOutIndex ].y ) )
|
||||
{
|
||||
groupData.bNeed2UV = true;
|
||||
}
|
||||
|
||||
// if the material differs, we need a second skin, too
|
||||
if (pcGroupTris->skinsets[ 1 ].material != pcGroupTris->skinsets[ 0 ].material)
|
||||
{
|
||||
groupData.bNeed2UV = true;
|
||||
}
|
||||
}
|
||||
// assign the material index
|
||||
groupData.pcFaces[ iTriangle ].iMatIndex[ 1 ] = pcGroupTris->skinsets[ 1 ].material;
|
||||
|
@ -1144,9 +1179,7 @@ bool MDLImporter::ProcessFrames_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInf
|
|||
// our output frame?
|
||||
if (configFrameID == iFrame)
|
||||
{
|
||||
const MDL::Vertex_MDL7* pcFrameVertices = (const MDL::Vertex_MDL7*)
|
||||
(szCurrent + pcHeader->framevertex_stc_size);
|
||||
|
||||
const MDL::Vertex_MDL7* pcFrameVertices = (const MDL::Vertex_MDL7*)(szCurrent+pcHeader->frame_stc_size);
|
||||
for (unsigned int qq = 0; qq < frame.pcFrame->vertices_count;++qq)
|
||||
{
|
||||
// I assume this are simple replacements for normal
|
||||
|
@ -1157,37 +1190,33 @@ bool MDLImporter::ProcessFrames_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInf
|
|||
|
||||
if (iIndex >= groupInfo.pcGroup->numverts)
|
||||
{
|
||||
DefaultLogger::get()->warn("Invalid vertex index in frame vertex section. "
|
||||
"Skipping this frame vertex");
|
||||
DefaultLogger::get()->warn("Invalid vertex index in frame vertex section");
|
||||
continue;
|
||||
}
|
||||
|
||||
aiVector3D vPosition,vNormal;
|
||||
|
||||
vPosition.x = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .x;
|
||||
vPosition.z = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .y;
|
||||
vPosition.y = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .z;
|
||||
vPosition.y = -1.0f*_AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .y;
|
||||
vPosition.z = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .z;
|
||||
|
||||
// now read the normal vector
|
||||
if (AI_MDL7_FRAMEVERTEX030305_STCSIZE <= pcHeader->mainvertex_stc_size)
|
||||
{
|
||||
// read the full normal vector
|
||||
vNormal.x = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .norm[0];
|
||||
vNormal.z = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .norm[1];
|
||||
vNormal.y = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .norm[2];
|
||||
vNormal.y = -1.0f* _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .norm[1];
|
||||
vNormal.z = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .norm[2];
|
||||
}
|
||||
else if (AI_MDL7_FRAMEVERTEX120503_STCSIZE <= pcHeader->mainvertex_stc_size)
|
||||
{
|
||||
// read the normal vector from Quake2's smart table
|
||||
MD2::LookupNormalIndex(_AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,
|
||||
pcHeader->framevertex_stc_size) .norm162index,vNormal);
|
||||
|
||||
std::swap(vNormal.z,vNormal.y);
|
||||
vNormal.y *= -1.0f;
|
||||
}
|
||||
|
||||
// FIXME: O(n^2) at the moment ...
|
||||
// shouldn't be too worse, frame vertices aren't required more
|
||||
// than once a century ...
|
||||
const MDL::Triangle_MDL7* pcGroupTris = groupInfo.pcGroupTris;
|
||||
unsigned int iOutIndex = 0;
|
||||
for (unsigned int iTriangle = 0; iTriangle < (unsigned int)groupInfo.pcGroup->numtris; ++iTriangle)
|
||||
|
@ -1204,16 +1233,13 @@ bool MDLImporter::ProcessFrames_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInf
|
|||
}
|
||||
}
|
||||
// get the next triangle in the list
|
||||
pcGroupTris = (const MDL::Triangle_MDL7*)((const char*)pcGroupTris +
|
||||
pcHeader->triangle_stc_size);
|
||||
pcGroupTris = (const MDL::Triangle_MDL7*)((const char*)
|
||||
pcGroupTris + pcHeader->triangle_stc_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
// parse bone trafo matrix keys (only if there are bones ...)
|
||||
if (shared.apcOutBones)
|
||||
{
|
||||
this->ParseBoneTrafoKeys_3DGS_MDL7(groupInfo,frame,shared);
|
||||
}
|
||||
if (shared.apcOutBones)this->ParseBoneTrafoKeys_3DGS_MDL7(groupInfo,frame,shared);
|
||||
szCurrent += iAdd;
|
||||
}
|
||||
*szCurrentOut = szCurrent;
|
||||
|
@ -1371,7 +1397,6 @@ void MDLImporter::InternReadFile_3DGS_MDL7( )
|
|||
// load all bones (they are shared by all groups, so
|
||||
// we'll need to add them to all groups/meshes later)
|
||||
// apcBonesOut is a list of all bones or NULL if they could not been loaded
|
||||
// TODO (aramis): Make apcBonesOut an MDL::IntBone_MDL7*
|
||||
szCurrent += pcHeader->bones_num * pcHeader->bone_stc_size;
|
||||
sharedData.apcOutBones = this->LoadBones_3DGS_MDL7();
|
||||
|
||||
|
@ -1493,19 +1518,13 @@ void MDLImporter::InternReadFile_3DGS_MDL7( )
|
|||
if (!splittedGroupData.aiSplit[qq]->empty())
|
||||
sharedData.abNeedMaterials[qq] = true;
|
||||
}
|
||||
|
||||
// now generate output meshes
|
||||
this->GenerateOutputMeshes_3DGS_MDL7(groupData,
|
||||
splittedGroupData);
|
||||
}
|
||||
else DefaultLogger::get()->warn("[3DGS MDL7] Mesh group consists of 0 "
|
||||
"vertices or faces. It will be skipped.");
|
||||
|
||||
// process all frames
|
||||
if(!ProcessFrames_3DGS_MDL7(groupInfo,groupData, sharedData,szCurrent,&szCurrent))
|
||||
{
|
||||
break;
|
||||
}
|
||||
// process all frames and generate output meshes
|
||||
this->ProcessFrames_3DGS_MDL7(groupInfo,groupData, sharedData,szCurrent,&szCurrent);
|
||||
this->GenerateOutputMeshes_3DGS_MDL7(groupData,splittedGroupData);
|
||||
}
|
||||
|
||||
// generate a nodegraph and subnodes for each group
|
||||
|
@ -1545,16 +1564,9 @@ void MDLImporter::InternReadFile_3DGS_MDL7( )
|
|||
|
||||
// setup the name of the node
|
||||
char* const szBuffer = &aszGroupNameBuffer[i*AI_MDL7_MAX_GROUPNAMESIZE];
|
||||
if ('\0' == *szBuffer)
|
||||
{
|
||||
#if _MSC_VER >= 1400
|
||||
::sprintf_s(szBuffer,AI_MDL7_MAX_GROUPNAMESIZE,"Group_%i",p);
|
||||
#else
|
||||
::sprintf(szBuffer,"Group_%i",p);
|
||||
#endif
|
||||
}
|
||||
if ('\0' == *szBuffer)pcNode->mName.length = ::sprintf(szBuffer,"Group_%i",p);
|
||||
else pcNode->mName.length = ::strlen(szBuffer);
|
||||
::strcpy(pcNode->mName.data,szBuffer);
|
||||
pcNode->mName.length = ::strlen(szBuffer);
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
@ -1566,10 +1578,9 @@ void MDLImporter::InternReadFile_3DGS_MDL7( )
|
|||
this->pScene->mRootNode = pcOldRoot->mChildren[0];
|
||||
pcOldRoot->mChildren[0] = NULL;
|
||||
delete pcOldRoot;
|
||||
|
||||
this->pScene->mRootNode->mParent = NULL;
|
||||
}
|
||||
else this->pScene->mRootNode->mName.Set("mesh_root");
|
||||
else this->pScene->mRootNode->mName.Set("<mesh_root>");
|
||||
|
||||
delete[] avOutList;
|
||||
delete[] aszGroupNameBuffer;
|
||||
|
@ -1578,8 +1589,6 @@ void MDLImporter::InternReadFile_3DGS_MDL7( )
|
|||
|
||||
// build a final material list.
|
||||
this->CopyMaterials_3DGS_MDL7(sharedData);
|
||||
|
||||
// handle materials that are just referencing another material correctly
|
||||
this->HandleMaterialReferences_3DGS_MDL7();
|
||||
|
||||
// generate output bone animations and add all bones to the scenegraph
|
||||
|
@ -1590,7 +1599,7 @@ void MDLImporter::InternReadFile_3DGS_MDL7( )
|
|||
aiNode* const pc = this->pScene->mRootNode->mChildren[
|
||||
this->pScene->mRootNode->mNumChildren-1] = new aiNode();
|
||||
|
||||
pc->mName.Set("skeleton_root");
|
||||
pc->mName.Set("<skeleton_root>");
|
||||
|
||||
// add bones to the nodegraph
|
||||
this->AddBonesToNodeGraph_3DGS_MDL7((const Assimp::MDL::IntBone_MDL7 **)
|
||||
|
@ -1604,64 +1613,15 @@ void MDLImporter::InternReadFile_3DGS_MDL7( )
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
void MDLImporter::CopyMaterials_3DGS_MDL7(MDL::IntSharedData_MDL7 &shared)
|
||||
{
|
||||
unsigned int iNewNumMaterials = 0;
|
||||
unsigned int p = 0;
|
||||
for (;p < shared.pcMats.size();++p)
|
||||
if (shared.abNeedMaterials[p])++iNewNumMaterials;
|
||||
|
||||
this->pScene->mMaterials = new aiMaterial*[iNewNumMaterials];
|
||||
if ((unsigned int)shared.pcMats.size() == iNewNumMaterials)
|
||||
{
|
||||
this->pScene->mNumMaterials = (unsigned int)shared.pcMats.size();
|
||||
for (unsigned int i = 0; i < this->pScene->mNumMaterials;++i)
|
||||
this->pScene->mMaterials[i] = shared.pcMats[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
p = 0;
|
||||
const unsigned int iMSB = 0x1u << (sizeof (unsigned int)*8-1);
|
||||
for (unsigned int i = 0; i < (unsigned int)shared.pcMats.size();++i)
|
||||
{
|
||||
if (!shared.abNeedMaterials[i])
|
||||
{
|
||||
// destruction is done by the destructor of sh
|
||||
delete shared.pcMats[i];
|
||||
AI_DEBUG_INVALIDATE_PTR(shared.pcMats[i]);
|
||||
continue;
|
||||
}
|
||||
this->pScene->mMaterials[p] = shared.pcMats[i];
|
||||
|
||||
if (p != i)
|
||||
{
|
||||
// replace the material index and MSB in all material
|
||||
// indices that have been replaced to make sure they won't be
|
||||
// replaced again (this won't work if there are more than
|
||||
// 2^31 materials in the model - but this shouldn't care :-)).
|
||||
for (unsigned int qq = 0; qq < this->pScene->mNumMeshes;++qq)
|
||||
{
|
||||
aiMesh* const pcMesh = this->pScene->mMeshes[qq];
|
||||
if (i == pcMesh->mMaterialIndex)
|
||||
{
|
||||
pcMesh->mMaterialIndex = p | iMSB;
|
||||
}
|
||||
}
|
||||
}
|
||||
++p;
|
||||
}
|
||||
this->pScene->mNumMaterials = iNewNumMaterials;
|
||||
|
||||
// Remove the MSB from all material indices
|
||||
for (unsigned int qq = 0; qq < this->pScene->mNumMeshes;++qq)
|
||||
{
|
||||
this->pScene->mMeshes[qq]->mMaterialIndex &= ~iMSB;
|
||||
}
|
||||
}
|
||||
this->pScene->mNumMaterials = (unsigned int)shared.pcMats.size();
|
||||
this->pScene->mMaterials = new aiMaterial*[this->pScene->mNumMaterials];
|
||||
for (unsigned int i = 0; i < this->pScene->mNumMaterials;++i)
|
||||
this->pScene->mMaterials[i] = shared.pcMats[i];
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void MDLImporter::HandleMaterialReferences_3DGS_MDL7()
|
||||
{
|
||||
// search for referrer materials
|
||||
// (there is no test file but Conitec's docs say it is supported ... :cry: )
|
||||
for (unsigned int i = 0; i < this->pScene->mNumMaterials;++i)
|
||||
{
|
||||
int iIndex = 0;
|
||||
|
@ -1672,9 +1632,7 @@ void MDLImporter::HandleMaterialReferences_3DGS_MDL7()
|
|||
{
|
||||
aiMesh* const pcMesh = this->pScene->mMeshes[a];
|
||||
if (i == pcMesh->mMaterialIndex)
|
||||
{
|
||||
pcMesh->mMaterialIndex = iIndex;
|
||||
}
|
||||
}
|
||||
// collapse the rest of the array
|
||||
delete this->pScene->mMaterials[i];
|
||||
|
@ -1731,8 +1689,7 @@ void MDLImporter::ParseBoneTrafoKeys_3DGS_MDL7(
|
|||
else
|
||||
{
|
||||
DefaultLogger::get()->warn("Found animation keyframes "
|
||||
"in a group that is not the first. They will be igored, "
|
||||
"the format specification says this should not occur");
|
||||
"in a group that is not the first. They will be igored");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1802,7 +1759,7 @@ void MDLImporter::BuildOutputAnims_3DGS_MDL7(
|
|||
aiBoneAnim* const pcBoneAnim = pcAnim->mBones[iCnt++] = new aiBoneAnim();
|
||||
pcBoneAnim->mBoneName = aiString( intBone->mName );
|
||||
|
||||
// allocate enough storahe for all keys
|
||||
// allocate enough storage for all keys
|
||||
pcBoneAnim->mNumPositionKeys = (unsigned int)intBone->pkeyPositions.size();
|
||||
pcBoneAnim->mNumScalingKeys = (unsigned int)intBone->pkeyPositions.size();
|
||||
pcBoneAnim->mNumRotationKeys = (unsigned int)intBone->pkeyPositions.size();
|
||||
|
|
|
@ -87,6 +87,14 @@ public:
|
|||
* See BaseImporter::CanRead() for details. */
|
||||
bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Called prior to ReadFile().
|
||||
* The function is a request to the importer to update its configuration
|
||||
* basing on the Importer's configuration property list.
|
||||
*/
|
||||
void SetupProperties(const Importer* pImp);
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
|
|
|
@ -88,6 +88,10 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
|
|||
unsigned int* aiMappingTable = new unsigned int[pScene->mNumMaterials];
|
||||
unsigned int iNewNum = 0;
|
||||
|
||||
std::vector<bool> abReferenced(pScene->mNumMaterials,false);
|
||||
for (unsigned int i = 0;i < pScene->mNumMeshes;++i)
|
||||
abReferenced[pScene->mMeshes[i]->mMaterialIndex] = true;
|
||||
|
||||
// iterate through all materials and calculate a hash for them
|
||||
// store all hashes in a list and so a quick search whether
|
||||
// we do already have a specific hash. This allows us to
|
||||
|
@ -96,6 +100,9 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
|
|||
aiHashes = new uint32_t[pScene->mNumMaterials];
|
||||
for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
|
||||
{
|
||||
// if the material is not referenced ... remove it
|
||||
if (!abReferenced[i])continue;
|
||||
|
||||
uint32_t me = aiHashes[i] = ((MaterialHelper*)pScene->mMaterials[i])->ComputeHash();
|
||||
for (unsigned int a = 0; a < i;++a)
|
||||
{
|
||||
|
@ -120,6 +127,9 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
|
|||
::memset(ppcMaterials,0,sizeof(void*)*iNewNum);
|
||||
for (unsigned int p = 0; p < pScene->mNumMaterials;++p)
|
||||
{
|
||||
// if the material is not referenced ... remove it
|
||||
if (!abReferenced[p])continue;
|
||||
|
||||
// generate new names for all modified materials
|
||||
const unsigned int idx = aiMappingTable[p];
|
||||
if (ppcMaterials[idx])
|
||||
|
|
|
@ -101,12 +101,8 @@ void SplitLargeMeshesProcess_Triangle::Execute( aiScene* pScene)
|
|||
// Setup properties
|
||||
void SplitLargeMeshesProcess_Triangle::SetupProperties( const Importer* pImp)
|
||||
{
|
||||
// get the current value of the split property
|
||||
if(0xcdcdcdcd == (this->LIMIT = pImp->GetProperty(
|
||||
AI_CONFIG_PP_SLM_TRIANGLE_LIMIT,0xcdcdcdcd)))
|
||||
{
|
||||
this->LIMIT = AI_SLM_DEFAULT_MAX_TRIANGLES;
|
||||
}
|
||||
// get the current value of the split property
|
||||
this->LIMIT = pImp->GetProperty(AI_CONFIG_PP_SLM_TRIANGLE_LIMIT,AI_SLM_DEFAULT_MAX_TRIANGLES);
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Update a node after some meshes have been split
|
||||
|
@ -291,15 +287,11 @@ void SplitLargeMeshesProcess_Triangle::SplitMesh(
|
|||
|
||||
// copy positions
|
||||
if (pMesh->mVertices != NULL)
|
||||
{
|
||||
pcMesh->mVertices[iIndexOut] = pMesh->mVertices[iIndex];
|
||||
}
|
||||
|
||||
// copy normals
|
||||
if (pMesh->HasNormals())
|
||||
{
|
||||
pcMesh->mNormals[iIndexOut] = pMesh->mNormals[iIndex];
|
||||
}
|
||||
|
||||
// copy tangents/bitangents
|
||||
if (pMesh->HasTangentsAndBitangents())
|
||||
|
@ -312,17 +304,13 @@ void SplitLargeMeshesProcess_Triangle::SplitMesh(
|
|||
for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
|
||||
{
|
||||
if (pMesh->HasTextureCoords( c))
|
||||
{
|
||||
pcMesh->mTextureCoords[c][iIndexOut] = pMesh->mTextureCoords[c][iIndex];
|
||||
}
|
||||
}
|
||||
// vertex colors
|
||||
for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c)
|
||||
{
|
||||
if (pMesh->HasVertexColors( c))
|
||||
{
|
||||
pcMesh->mColors[c][iIndexOut] = pMesh->mColors[c][iIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -386,12 +374,7 @@ void SplitLargeMeshesProcess_Vertex::Execute( aiScene* pScene)
|
|||
// Setup properties
|
||||
void SplitLargeMeshesProcess_Vertex::SetupProperties( const Importer* pImp)
|
||||
{
|
||||
// get the current value of the split property
|
||||
if(0xcdcdcdcd == (this->LIMIT = pImp->GetProperty(
|
||||
AI_CONFIG_PP_SLM_VERTEX_LIMIT,0xcdcdcdcd)))
|
||||
{
|
||||
this->LIMIT = AI_SLM_DEFAULT_MAX_VERTICES;
|
||||
}
|
||||
this->LIMIT = pImp->GetProperty(AI_CONFIG_PP_SLM_VERTEX_LIMIT,AI_SLM_DEFAULT_MAX_VERTICES);
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
|
@ -455,9 +438,15 @@ void SplitLargeMeshesProcess_Vertex::SplitMesh(
|
|||
}
|
||||
|
||||
// clear the temporary helper array
|
||||
if (0 != iBase)
|
||||
if (iBase)
|
||||
{
|
||||
memset(&avWasCopied[0],0xFF,pMesh->mNumVertices * sizeof(unsigned int));
|
||||
// we can't use memset here we unsigned int needn' be 32 bits
|
||||
for (std::vector<unsigned int>::iterator
|
||||
iter = avWasCopied.begin(),end = avWasCopied.end();
|
||||
iter != end;++iter)
|
||||
{
|
||||
(*iter) = 0xffffffff;
|
||||
}
|
||||
}
|
||||
|
||||
// output vectors
|
||||
|
|
|
@ -710,10 +710,10 @@ __break_out:
|
|||
}
|
||||
if (pBoneAnim->mPositionKeys[i].mTime <= dLast)
|
||||
{
|
||||
this->ReportError("aiBoneAnim::mPositionKeys[%i].mTime (%.5f) is larger "
|
||||
this->ReportWarning("aiBoneAnim::mPositionKeys[%i].mTime (%.5f) is smaller "
|
||||
"than aiAnimation::mPositionKeys[%i] (which is %.5f)",i,
|
||||
(float)pBoneAnim->mPositionKeys[i].mTime,
|
||||
i, (float)dLast);
|
||||
i-1, (float)dLast);
|
||||
}
|
||||
dLast = pBoneAnim->mPositionKeys[i].mTime;
|
||||
}
|
||||
|
@ -738,10 +738,10 @@ __break_out:
|
|||
}
|
||||
if (pBoneAnim->mRotationKeys[i].mTime <= dLast)
|
||||
{
|
||||
this->ReportError("aiBoneAnim::mRotationKeys[%i].mTime (%.5f) is larger "
|
||||
this->ReportWarning("aiBoneAnim::mRotationKeys[%i].mTime (%.5f) is smaller "
|
||||
"than aiAnimation::mRotationKeys[%i] (which is %.5f)",i,
|
||||
(float)pBoneAnim->mRotationKeys[i].mTime,
|
||||
i, (float)dLast);
|
||||
i-1, (float)dLast);
|
||||
}
|
||||
dLast = pBoneAnim->mRotationKeys[i].mTime;
|
||||
}
|
||||
|
@ -766,10 +766,10 @@ __break_out:
|
|||
}
|
||||
if (pBoneAnim->mScalingKeys[i].mTime <= dLast)
|
||||
{
|
||||
this->ReportError("aiBoneAnim::mScalingKeys[%i].mTime (%.5f) is larger "
|
||||
this->ReportWarning("aiBoneAnim::mScalingKeys[%i].mTime (%.5f) is smaller "
|
||||
"than aiAnimation::mScalingKeys[%i] (which is %.5f)",i,
|
||||
(float)pBoneAnim->mScalingKeys[i].mTime,
|
||||
i, (float)dLast);
|
||||
i-1, (float)dLast);
|
||||
}
|
||||
dLast = pBoneAnim->mScalingKeys[i].mTime;
|
||||
}
|
||||
|
|
|
@ -105,6 +105,27 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
*/
|
||||
#define AI_CONFIG_IMPORT_3DS_IGNORE_PIVOT "imp.3ds.nopivot"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Specifies the maximum angle that may be between two vertex tangents
|
||||
* that their tangents and bitangents are smoothed.
|
||||
*
|
||||
* This applies to the CalcTangentSpace-Step. The angle is specified
|
||||
* in degrees * 1000, so 180000 is PI. The default value is
|
||||
* 45 degrees. The maximum value is 180000.
|
||||
*/
|
||||
#define AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE "pp.ct.max_smoothing"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Specifies the maximum angle that may be between two face normals
|
||||
* at the same vertex position that their are smoothed.
|
||||
*
|
||||
* This applies to the GenSmoothNormals-Step. The angle is specified
|
||||
* in degrees * 1000, so 180000 is PI. The default value is
|
||||
* 180 degrees (all vertex normals are smoothed). The maximum value is 180000
|
||||
* \note This can be manually overriden by loaders via #aiMesh::mMaxSmoothingAngle;
|
||||
*/
|
||||
#define AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE "pp.gsn.max_smoothing"
|
||||
|
||||
|
||||
#define AI_CONFIG_PP_OG_MAX_DEPTH "pp.og.max_depth"
|
||||
#define AI_CONFIG_PP_OG_MIN_TRIS_PER_NODE "pp.og.min_tris"
|
||||
|
|
|
@ -248,6 +248,8 @@ struct aiBone
|
|||
|
||||
#endif // !! AI_MAX_NUMBER_OF_TEXTURECOORDS
|
||||
|
||||
#define AI_MESH_SMOOTHING_ANGLE_NOT_SET (10e10f)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** A mesh represents a geometry or model with a single material.
|
||||
*
|
||||
|
@ -358,8 +360,9 @@ struct aiMesh
|
|||
* If the angle between two vertex normals is larger,
|
||||
* the vertex normals should not be smoothed. The GenVertexNormals-Step
|
||||
* takes care of this value. The angle is specified in radians.
|
||||
* It is 2PI if the source file didn't contain any additional
|
||||
* information related to the calculation of vertex normals.
|
||||
* It is set to AI_MESH_SMOOTHING_ANGLE_NOT_SET if the source file didn't
|
||||
* contain any additional information related to the calculation of
|
||||
* vertex normals.
|
||||
*/
|
||||
float mMaxSmoothingAngle;
|
||||
|
||||
|
@ -381,7 +384,7 @@ struct aiMesh
|
|||
mColors[a] = NULL;
|
||||
mNumBones = 0; mBones = NULL;
|
||||
mMaterialIndex = 0;
|
||||
mMaxSmoothingAngle = (float)AI_MATH_TWO_PI;
|
||||
mMaxSmoothingAngle = AI_MESH_SMOOTHING_ANGLE_NOT_SET;
|
||||
}
|
||||
|
||||
//! Deletes all storage allocated for the mesh
|
||||
|
|
Binary file not shown.
|
@ -38,21 +38,22 @@ IDI_SMALL ICON "small.ico"
|
|||
// Dialog
|
||||
//
|
||||
|
||||
IDD_ABOUTBOX DIALOGEX 22, 17, 283, 170
|
||||
IDD_ABOUTBOX DIALOGEX 22, 17, 283, 169
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "About ASSIMP"
|
||||
CAPTION "About Open Asset Import Library"
|
||||
FONT 10, "MS Shell Dlg", 400, 0, 0x0
|
||||
BEGIN
|
||||
LTEXT "ASSIMP is the free, OpenSource ASSet IMPort Library",IDC_STATIC,42,12,204,12
|
||||
LTEXT "Developed by members of the german game development community www.zfx.info",IDC_STATIC,42,30,204,24
|
||||
LTEXT "Thomas Schulze \t\taka <Schrompf> ",IDC_STATIC,42,66,192,8
|
||||
LTEXT "Kim Kulling \t\t\taka <Sir Kimmi> ",IDC_STATIC,42,78,186,8
|
||||
LTEXT "Rainer Schmidt \t\t\taka <Guru>",IDC_STATIC,42,90,180,8
|
||||
LTEXT "Alexander Gessler\t\taka <Aramis>",IDC_STATIC,42,102,186,8
|
||||
LTEXT "Open Asset Import Library (Assimp)",IDC_STATIC,77,13,121,12
|
||||
LTEXT "A free C/C++ library for game && graphics developers. Developed by members of the german game development community www.zfx.info",IDC_STATIC,47,26,204,24
|
||||
LTEXT "Thomas Schulze \t\taka <Schrompf> ",IDC_STATIC,55,80,192,8
|
||||
LTEXT "Kim Kulling \t\t\taka <Kimmi> ",IDC_STATIC,55,92,186,8
|
||||
LTEXT "Rainer Schmidt \t\t\taka <Guru>",IDC_STATIC,55,104,180,8
|
||||
LTEXT "Alexander Gessler\t\taka <Aramis>",IDC_STATIC,55,68,186,8
|
||||
CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,60,282,1
|
||||
LTEXT "http://zfxce.svn.sourceforge.net/viewvc/zfxce/trunk/ASSIMP",IDC_STATIC,42,120,198,8
|
||||
DEFPUSHBUTTON "Love this library",IDOK,199,148,67,14
|
||||
CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,138,281,1
|
||||
LTEXT "assimp.sourceforge.net",IDC_STATIC,7,137,78,8
|
||||
DEFPUSHBUTTON "Love this library",IDOK,200,128,67,14
|
||||
CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,148,283,1
|
||||
CONTROL 130,IDC_STATIC,"Static",SS_BITMAP,0,149,514,20
|
||||
END
|
||||
|
||||
IDD_DIALOGMAIN DIALOGEX 0, 0, 594, 384
|
||||
|
@ -233,6 +234,7 @@ GUIDELINES DESIGNINFO
|
|||
BEGIN
|
||||
IDD_ABOUTBOX, DIALOG
|
||||
BEGIN
|
||||
TOPMARGIN, 1
|
||||
BOTTOMMARGIN, 158
|
||||
END
|
||||
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 141 KiB |
Binary file not shown.
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 106 KiB |
|
@ -582,6 +582,10 @@
|
|||
RelativePath="..\..\include\aiAssert.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\aiConfig.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\aiDefines.h"
|
||||
>
|
||||
|
@ -674,6 +678,10 @@
|
|||
RelativePath="..\..\include\LogStream.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\NullLogger.h"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="Compiler"
|
||||
>
|
||||
|
@ -965,10 +973,6 @@
|
|||
<Filter
|
||||
Name="Logger"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\code\DefaultLogger.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\code\FileLogStream.h"
|
||||
>
|
||||
|
@ -1030,6 +1034,30 @@
|
|||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="MDC"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\code\MDCFileData.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\code\MDCLoader.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\code\MDCNormalTable.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="MDR"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\code\MDRFileData.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="sources"
|
||||
|
@ -1302,6 +1330,14 @@
|
|||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="MDC"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\code\MDCLoader.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="doc"
|
||||
|
|
Loading…
Reference in New Issue