- Major update to the viewer. A little bit buggy now, but I'll fix that

- 2/3 of the viewer code are no wrapped in helper classes
- ByteSwap.h header added 
- Bugfix in the 3DS loader: Texture blend mode was read incorrectly
- Bugfix in the X-Loader. Assets with specular_exp == 0 use gouraud lighting now
- Added new helper functions to MaterialHelper 
- Added aiMaterialGetTexture() function to allow easy access to all properties of a texture

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@16 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
This commit is contained in:
aramis_acg
2008-05-13 23:26:52 +00:00
parent 7144737824
commit 2eb6fca408
60 changed files with 7502 additions and 2613 deletions
+3 -3
View File
@@ -380,7 +380,7 @@ struct Material
{
static int iCnt = 0;
std::stringstream ss(mName);
ss << "%%_UNNAMED_" << iCnt++ << "_%%";
ss << "$$_UNNAMED_" << iCnt++ << "_$$";
}
//! Name of the material
@@ -433,7 +433,7 @@ struct Mesh
{
static int iCnt = 0;
std::stringstream ss(mName);
ss << "%%_UNNAMED_" << iCnt++ << "_%%";
ss << "$$_UNNAMED_" << iCnt++ << "_$$";
}
//! Name of the mesh
@@ -468,7 +468,7 @@ struct Node
{
static int iCnt = 0;
std::stringstream ss(mName);
ss << "%%_UNNAMED_" << iCnt++ << "_%%";
ss << "$$_UNNAMED_" << iCnt++ << "_$$";
mHierarchyPos = 0;
mHierarchyIndex = 0;
+1 -1
View File
@@ -1213,7 +1213,7 @@ void Dot3DSImporter::ParseTextureChunk(int* piRemaining,Dot3DS::Texture* pcOut)
break;
// manually parse the blend factor
case Dot3DSFile::CHUNK_PERCENTW:
pcOut->mTextureBlend = (float)(*((short*)this->mCurrent)) / (float)0xFFFF;
pcOut->mTextureBlend = (float)(*((short*)this->mCurrent)) / (float)100;
break;
case Dot3DSFile::CHUNK_MAT_MAP_USCALE:
+1 -1
View File
@@ -60,7 +60,7 @@ class BaseProcess
{
friend class Importer;
protected:
public:
/** Constructor to be privately used by Importer */
BaseProcess();
+128
View File
@@ -0,0 +1,128 @@
/*
Free 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 Helper class tp perform various byte oder swappings
(e.g. little to big endian) */
#ifndef AI_BYTESWAP_H_INC
#define AI_BYTESWAP_H_INC
#include "..\include\aiAssert.h"
namespace Assimp
{
// ---------------------------------------------------------------------------
/** \brief Defines some useful byte order swap routines.
*
* This can e.g. be used for the conversion from and to littel and big endian.
* This is required by some loaders since some model formats
*/
class ByteSwap
{
ByteSwap() {}
public:
//! Swap the byte oder of 2 byte of data
//! \param szOut Buffer to be swapped
static inline void Swap2(char* szOut)
{
ai_assert(NULL != szOut);
std::swap(szOut[0],szOut[1]);
}
//! Swap the byte oder of 4 byte of data
//! \param szOut Buffer to be swapped
static inline void Swap4(char* szOut)
{
ai_assert(NULL != szOut);
std::swap(szOut[0],szOut[3]);
std::swap(szOut[1],szOut[2]);
}
//! Swap the byte oder of 8 byte of data
//! \param szOut Buffer to be swapped
static inline void Swap8(char* szOut)
{
ai_assert(NULL != szOut);
std::swap(szOut[0],szOut[7]);
std::swap(szOut[1],szOut[6]);
std::swap(szOut[2],szOut[5]);
std::swap(szOut[3],szOut[4]);
}
//! Swap a single precision float
//! \param fOut Float value to be swapped
static inline void Swap(float* fOut)
{
Swap4((char*)fOut);
}
//! Swap a double precision float
//! \param fOut Double value to be swapped
static inline void Swap(double* fOut)
{
Swap8((char*)fOut);
}
//! Swap a 16 bit integer
//! \param fOut Integer to be swapped
static inline void Swap(int16_t* fOut)
{
Swap2((char*)fOut);
}
//! Swap a 32 bit integer
//! \param fOut Integer to be swapped
static inline void Swap(int32_t* fOut)
{
Swap4((char*)fOut);
}
//! Swap a 64 bit integer
//! \param fOut Integer to be swapped
static inline void Swap(int64_t* fOut)
{
Swap8((char*)fOut);
}
};
};
#endif //!! AI_BYTESWAP_H_INC
+5
View File
@@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <vector>
#include <assert.h>
#include "DefaultLogger.h"
#include "CalcTangentsProcess.h"
#include "SpatialSort.h"
#include "../include/aiPostProcess.h"
@@ -78,8 +79,12 @@ bool CalcTangentsProcess::IsActive( unsigned int pFlags) const
// Executes the post processing step on the given imported data.
void CalcTangentsProcess::Execute( aiScene* pScene)
{
DefaultLogger::get()->debug("CalcTangentsProcess begin");
for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
ProcessMesh( pScene->mMeshes[a]);
DefaultLogger::get()->debug("CalcTangentsProcess finished");
}
// ------------------------------------------------------------------------------------------------
+5 -4
View File
@@ -39,7 +39,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** @file Defines a post processing step to calculate tangents and bitangents on all imported meshes.*/
/** @file Defines a post processing step to calculate tangents and
bitangents on all imported meshes.*/
#ifndef AI_CALCTANGENTSPROCESS_H_INC
#define AI_CALCTANGENTSPROCESS_H_INC
@@ -53,14 +54,14 @@ namespace Assimp
// ---------------------------------------------------------------------------
/** The CalcTangentsProcess calculates the tangent and bitangent for any vertex
* of all meshes. It is expected to be run before the JoinVerticesProcess runs
* because the joining of vertices also considers tangents and bitangents for uniqueness.
* because the joining of vertices also considers tangents and bitangents for
* uniqueness.
*/
class CalcTangentsProcess : public BaseProcess
{
friend class Importer;
protected:
public:
/** Constructor to be privately used by Importer */
CalcTangentsProcess();
+7
View File
@@ -2,6 +2,7 @@
* to a left-handed coordinate system.
*/
#include "ConvertToLHProcess.h"
#include "DefaultLogger.h"
#include "../include/aiPostProcess.h"
#include "../include/aiMesh.h"
#include "../include/aiAnim.h"
@@ -46,7 +47,12 @@ void ConvertToLHProcess::Execute( aiScene* pScene)
{
// Check for an existent root node to proceed
if (NULL == pScene->mRootNode)
{
DefaultLogger::get()->error("ConvertToLHProcess fails, there is no root node");
return;
}
DefaultLogger::get()->debug("ConvertToLHProcess begin");
// transform the root node of the scene, the other nodes will follow then
ConvertToDX( pScene->mRootNode->mTransformation);
@@ -66,6 +72,7 @@ void ConvertToLHProcess::Execute( aiScene* pScene)
ProcessAnimation( boneAnim);
}
}
DefaultLogger::get()->debug("ConvertToLHProcess finished");
}
// ------------------------------------------------------------------------------------------------
+42 -1
View File
@@ -1,3 +1,44 @@
/*
---------------------------------------------------------------------------
Free 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.
---------------------------------------------------------------------------
*/
#include "DefaultLogger.h"
#include "aiAssert.h"
#include "DefaultIOSystem.h"
@@ -142,11 +183,11 @@ void DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity )
DefaultLogger::DefaultLogger( const std::string &name, LogSeverity severity ) :
m_Severity( severity )
{
m_Streams.push_back( new Win32DebugLogStream() );
if (name.empty())
return;
m_Streams.push_back( new FileLogStream( name ) );
m_Streams.push_back( new Win32DebugLogStream() );
}
// ---------------------------------------------------------------------------
+40
View File
@@ -1,3 +1,43 @@
/*
Free 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.
----------------------------------------------------------------------
*/
#include "Logger.h"
#include <vector>
+23 -13
View File
@@ -43,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* normals for all imported faces.
*/
#include "GenFaceNormalsProcess.h"
#include "DefaultLogger.h"
#include "../include/aiPostProcess.h"
#include "../include/aiMesh.h"
#include "../include/aiScene.h"
@@ -71,23 +72,35 @@ bool GenFaceNormalsProcess::IsActive( unsigned int pFlags) const
// Executes the post processing step on the given imported data.
void GenFaceNormalsProcess::Execute( aiScene* pScene)
{
DefaultLogger::get()->debug("GenFaceNormalsProcess begin");
bool bHas = false;
for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
this->GenMeshFaceNormals( pScene->mMeshes[a]);
{
if(this->GenMeshFaceNormals( pScene->mMeshes[a]))
bHas = true;
}
if (bHas)
{
DefaultLogger::get()->info("GenFaceNormalsProcess finished. "
"Face normals have been calculated");
}
else DefaultLogger::get()->debug("GenFaceNormalsProcess finished. "
"There was nothing to do");
}
// -------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh)
bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh)
{
if (NULL != pMesh->mNormals)return;
if (NULL != pMesh->mNormals)return false;
pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
{
const aiFace& face = pMesh->mFaces[a];
// assume it is a triangle
aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[2]];
@@ -95,14 +108,11 @@ void GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh)
aiVector3D pDelta1 = *pV2 - *pV1;
aiVector3D pDelta2 = *pV3 - *pV1;
aiVector3D vNor = pDelta1 ^ pDelta2;
// NOTE: Never normalize here. Causes problems ...
//float fLength = vNor.Length();
//if (0.0f != fLength)vNor /= fLength;
pMesh->mNormals[face.mIndices[0]] = vNor;
pMesh->mNormals[face.mIndices[1]] = vNor;
pMesh->mNormals[face.mIndices[2]] = vNor;
for (unsigned int i = 0;i < face.mNumIndices;++i)
{
pMesh->mNormals[face.mIndices[i]] = vNor;
}
}
return;
return true;
}
+2 -2
View File
@@ -55,7 +55,7 @@ class GenFaceNormalsProcess : public BaseProcess
{
friend class Importer;
protected:
public:
/** Constructor to be privately used by Importer */
GenFaceNormalsProcess();
@@ -80,7 +80,7 @@ public:
private:
void GenMeshFaceNormals (aiMesh* pcMesh);
bool GenMeshFaceNormals (aiMesh* pcMesh);
};
} // end of namespace Assimp
+23 -10
View File
@@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "GenVertexNormalsProcess.h"
#include "SpatialSort.h"
#include "DefaultLogger.h"
#include "../include/aiPostProcess.h"
#include "../include/aiMesh.h"
#include "../include/aiScene.h"
@@ -72,22 +73,35 @@ bool GenVertexNormalsProcess::IsActive( unsigned int pFlags) const
// Executes the post processing step on the given imported data.
void GenVertexNormalsProcess::Execute( aiScene* pScene)
{
DefaultLogger::get()->debug("GenVertexNormalsProcess begin");
bool bHas = false;
for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
this->GenMeshVertexNormals( pScene->mMeshes[a]);
{
if(this->GenMeshVertexNormals( pScene->mMeshes[a]))
bHas = true;
}
if (bHas)
{
DefaultLogger::get()->info("GenVertexNormalsProcess finished. "
"Vertex normals have been calculated");
}
else DefaultLogger::get()->debug("GenVertexNormalsProcess finished. "
"There was nothing to do");
}
// -------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh)
bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh)
{
if (NULL != pMesh->mNormals)return;
if (NULL != pMesh->mNormals)return false;
pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
{
const aiFace& face = pMesh->mFaces[a];
// assume it is a triangle
aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[2]];
@@ -95,12 +109,11 @@ void GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh)
aiVector3D pDelta1 = *pV2 - *pV1;
aiVector3D pDelta2 = *pV3 - *pV1;
aiVector3D vNor = pDelta1 ^ pDelta2;
float fLength = vNor.Length();
if (0.0f != fLength)vNor /= fLength;
pMesh->mNormals[face.mIndices[0]] = vNor;
pMesh->mNormals[face.mIndices[1]] = vNor;
pMesh->mNormals[face.mIndices[2]] = vNor;
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
@@ -141,5 +154,5 @@ void GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh)
delete pMesh->mNormals;
pMesh->mNormals = pcNew;
return;
return true;
}
+31 -31
View File
@@ -47,41 +47,41 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp
{
// ---------------------------------------------------------------------------
/** The GenFaceNormalsProcess computes vertex normals for all vertizes of all meshes
// ---------------------------------------------------------------------------
/** The GenFaceNormalsProcess computes vertex normals for all vertizes of all meshes
*/
class GenVertexNormalsProcess : public BaseProcess
{
friend class Importer;
public:
/** Constructor to be privately used by Importer */
GenVertexNormalsProcess();
/** Destructor, private as well */
~GenVertexNormalsProcess();
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.
*/
class GenVertexNormalsProcess : public BaseProcess
{
friend class Importer;
bool IsActive( unsigned int pFlags) const;
protected:
/** Constructor to be privately used by Importer */
GenVertexNormalsProcess();
/** Destructor, private as well */
~GenVertexNormalsProcess();
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.
*/
bool IsActive( unsigned int pFlags) const;
// -------------------------------------------------------------------
/** 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);
// -------------------------------------------------------------------
/** 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);
private:
void GenMeshVertexNormals (aiMesh* pcMesh);
};
private:
bool GenMeshVertexNormals (aiMesh* pcMesh);
};
} // end of namespace Assimp
}; // end of namespace Assimp
#endif // !!AI_GENVERTEXNORMALPROCESS_H_INC
+7
View File
@@ -86,6 +86,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "GenVertexNormalsProcess.h"
#include "KillNormalsProcess.h"
#include "SplitLargeMeshes.h"
#include "DefaultLogger.h"
using namespace Assimp;
@@ -96,6 +97,10 @@ Importer::Importer() :
mScene(NULL),
mErrorString("")
{
// construct a new logger
/*DefaultLogger::create( "test.log", DefaultLogger::VERBOSE );
DefaultLogger::get()->info("Start logging");*/
// allocate a default IO handler
mIOHandler = new DefaultIOSystem;
@@ -181,6 +186,7 @@ const aiScene* Importer::ReadFile( const std::string& pFile, unsigned int pFlags
if( !mIOHandler->Exists( pFile))
{
mErrorString = "Unable to open file \"" + pFile + "\".";
DefaultLogger::get()->error(mErrorString);
return NULL;
}
@@ -199,6 +205,7 @@ const aiScene* Importer::ReadFile( const std::string& pFile, unsigned int pFlags
if( !imp)
{
mErrorString = "No suitable reader found for the file format of file \"" + pFile + "\".";
DefaultLogger::get()->error(mErrorString);
return NULL;
}
+14 -2
View File
@@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assert.h>
#include "JoinVerticesProcess.h"
#include "SpatialSort.h"
#include "DefaultLogger.h"
#include "../include/aiPostProcess.h"
#include "../include/aiMesh.h"
#include "../include/aiScene.h"
@@ -78,13 +79,21 @@ bool JoinVerticesProcess::IsActive( unsigned int pFlags) const
// Executes the post processing step on the given imported data.
void JoinVerticesProcess::Execute( aiScene* pScene)
{
DefaultLogger::get()->debug("JoinVerticesProcess begin");
bool bHas = false;
for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
ProcessMesh( pScene->mMeshes[a]);
{
if( this->ProcessMesh( pScene->mMeshes[a]))
bHas = true;
}
if (bHas)DefaultLogger::get()->info("JoinVerticesProcess finished. Found vertices to join");
else DefaultLogger::get()->debug("JoinVerticesProcess finished. There was nothing to do.");
}
// ------------------------------------------------------------------------------------------------
// Unites identical vertices in the given mesh
void JoinVerticesProcess::ProcessMesh( aiMesh* pMesh)
bool JoinVerticesProcess::ProcessMesh( aiMesh* pMesh)
{
// helper structure to hold all the data a single vertex can possibly have
typedef struct Vertex vertex;
@@ -100,6 +109,8 @@ void JoinVerticesProcess::ProcessMesh( aiMesh* pMesh)
std::vector<Vertex> uniqueVertices;
uniqueVertices.reserve( pMesh->mNumVertices);
unsigned int iOldVerts = pMesh->mNumVertices;
// For each vertex the index of the vertex it was replaced by.
std::vector<unsigned int> replaceIndex( pMesh->mNumVertices, 0xffffffff);
// for each vertex whether it was replaced by an existing unique vertex (true) or a new vertex was created for it (false)
@@ -300,4 +311,5 @@ void JoinVerticesProcess::ProcessMesh( aiMesh* pMesh)
bone->mWeights = new aiVertexWeight[bone->mNumWeights];
memcpy( bone->mWeights, &newWeights[0], bone->mNumWeights * sizeof( aiVertexWeight));
}
return (iOldVerts != pMesh->mNumVertices);
}
+14 -6
View File
@@ -38,9 +38,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file Defines a post processing step to join identical vertices on all imported meshes.*/
/** @file Defines a post processing step to join identical vertices
on all imported meshes.*/
#ifndef AI_JOINVERTICESPROCESS_H_INC
#define AI_CALCTANGENTSPROCESS_H_INC
#define AI_JOINVERTICESPROCESS_H_INC
#include "BaseProcess.h"
#include "../include/aiTypes.h"
@@ -62,7 +63,7 @@ class JoinVerticesProcess : public BaseProcess
{
friend class Importer;
protected:
public:
/** Constructor to be privately used by Importer */
JoinVerticesProcess();
@@ -90,12 +91,19 @@ protected:
/** Unites identical vertices in the given mesh.
* @param pMesh The mesh to process.
*/
void ProcessMesh( aiMesh* pMesh);
bool ProcessMesh( aiMesh* pMesh);
/** Little helper function to calculate the quadratic difference of two colours. */
// -------------------------------------------------------------------
/** Little helper function to calculate the quadratic difference
* of two colours.
* @param pColor1 First color
* @param pColor2 second color
* @return Quadratic color difference
*/
float GetColorDifference( const aiColor4D& pColor1, const aiColor4D& pColor2) const
{
aiColor4D c( pColor1.r - pColor2.r, pColor1.g - pColor2.g, pColor1.b - pColor2.b, pColor1.a - pColor2.a);
aiColor4D c( pColor1.r - pColor2.r, pColor1.g - pColor2.g,
pColor1.b - pColor2.b, pColor1.a - pColor2.a);
return c.r*c.r + c.g*c.g + c.b*c.b + c.a*c.a;
}
};
+14 -3
View File
@@ -41,6 +41,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Implementation of the post processing step tokill mesh normals
*/
#include "KillNormalsProcess.h"
#include "DefaultLogger.h"
#include "../include/aiPostProcess.h"
#include "../include/aiMesh.h"
#include "../include/aiScene.h"
@@ -69,15 +70,25 @@ bool KillNormalsProcess::IsActive( unsigned int pFlags) const
// Executes the post processing step on the given imported data.
void KillNormalsProcess::Execute( aiScene* pScene)
{
DefaultLogger::get()->debug("KillNormalsProcess begin");
bool bHas = false;
for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
this->KillMeshNormals( pScene->mMeshes[a]);
{
if( this->KillMeshNormals( pScene->mMeshes[a]))
bHas = true;
}
if (bHas)DefaultLogger::get()->info("KillNormalsProcess finished. Found normals to kill");
else DefaultLogger::get()->debug("KillNormalsProcess finished. There was nothing to do.");
}
// -------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void KillNormalsProcess::KillMeshNormals(aiMesh* pMesh)
bool KillNormalsProcess::KillMeshNormals(aiMesh* pMesh)
{
if (!pMesh->mNormals)return false;
delete[] pMesh->mNormals;
pMesh->mNormals = NULL;
return;
return true;
}
+31 -32
View File
@@ -47,41 +47,40 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp
{
// ---------------------------------------------------------------------------
/** KillNormalsProcess: Class to kill all normals loaded
// ---------------------------------------------------------------------------
/** KillNormalsProcess: Class to kill all normals loaded
*/
class KillNormalsProcess : public BaseProcess
{
friend class Importer;
protected:
/** Constructor to be privately used by Importer */
KillNormalsProcess();
/** Destructor, private as well */
~KillNormalsProcess();
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.
*/
class KillNormalsProcess : public BaseProcess
{
friend class Importer;
bool IsActive( unsigned int pFlags) const;
protected:
/** Constructor to be privately used by Importer */
KillNormalsProcess();
/** Destructor, private as well */
~KillNormalsProcess();
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.
*/
bool IsActive( unsigned int pFlags) const;
// -------------------------------------------------------------------
/** 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);
// -------------------------------------------------------------------
/** 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);
private:
void KillMeshNormals (aiMesh* pcMesh);
};
} // end of namespace Assimp
private:
bool KillMeshNormals (aiMesh* pcMesh);
};
}; // end of namespace Assimp
#endif // !!AI_KILLNORMALPROCESS_H_INC
+87
View File
@@ -95,6 +95,12 @@ namespace MDL
#define AI_MDL_MAGIC_NUMBER_BE_GS7 'MDL7'
#define AI_MDL_MAGIC_NUMBER_LE_GS7 '7LDM'
// magic bytes used in Half Life 2 MDL models
#define AI_MDL_MAGIC_NUMBER_BE_HL2a 'IDST'
#define AI_MDL_MAGIC_NUMBER_LE_HL2a 'TSDI'
#define AI_MDL_MAGIC_NUMBER_BE_HL2b 'IDSQ'
#define AI_MDL_MAGIC_NUMBER_LE_HL2b 'QSDI'
// common limitations for Quake1 meshes. The loader does not check them,
// but models should not exceed these limits.
#if (!defined AI_MDL_VERSION)
@@ -210,6 +216,87 @@ struct Header_MDL7
uint16_t frame_stc_size;
} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \struct Header_HL2
* \brief Data structure for the HL2 main header
*/
// ---------------------------------------------------------------------------
struct Header_HL2
{
//! magic number: "IDST"/"IDSQ"
char ident[4];
//! Version number
int32_t version;
//! Original file name in pak ?
char name[64];
//! Length of file name/length of file?
int32_t length;
//! For viewer, ignored
aiVector3D eyeposition;
aiVector3D min;
aiVector3D max;
//! AABB of the model
aiVector3D bbmin;
aiVector3D bbmax;
// File flags
int32_t flags;
//! NUmber of bones contained in the file
int32_t numbones;
int32_t boneindex;
//! Number of bone controllers for bone animation
int32_t numbonecontrollers;
int32_t bonecontrollerindex;
//! More bounding boxes ...
int32_t numhitboxes;
int32_t hitboxindex;
//! Animation sequences in the file
int32_t numseq;
int32_t seqindex;
//! Loaded sequences. Ignored
int32_t numseqgroups;
int32_t seqgroupindex;
//! Raw texture data
int32_t numtextures;
int32_t textureindex;
int32_t texturedataindex;
//! Number of skins (=textures?)
int32_t numskinref;
int32_t numskinfamilies;
int32_t skinindex;
//! Number of parts
int32_t numbodyparts;
int32_t bodypartindex;
//! attachable points for gameplay and physics
int32_t numattachments;
int32_t attachmentindex;
//! Table of sound effects associated with the model
int32_t soundtable;
int32_t soundindex;
int32_t soundgroups;
int32_t soundgroupindex;
//! Number of animation transitions
int32_t numtransitions;
int32_t transitionindex;
} PACK_STRUCT;
#define AI_MDL7_MAX_BONENAMESIZE 20
// ---------------------------------------------------------------------------
+76 -26
View File
@@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "MaterialSystem.h"
#include "MDLLoader.h"
#include "MDLDefaultColorMap.h"
#include "DefaultLogger.h"
#include "../include/IOStream.h"
#include "../include/IOSystem.h"
@@ -640,7 +641,8 @@ void MDLImporter::InternReadFile_Quake1( )
if (iIndex >= (unsigned int)this->m_pcHeader->num_verts)
{
iIndex = this->m_pcHeader->num_verts-1;
// LOG
DefaultLogger::get()->warn("Index overflow in Q1-MDL vertex list.");
}
aiVector3D& vec = pcMesh->mVertices[iCurrent];
@@ -809,7 +811,7 @@ void MDLImporter::InternReadFile_GameStudio( )
if (iIndex >= (unsigned int)this->m_pcHeader->num_verts)
{
iIndex = this->m_pcHeader->num_verts-1;
// LOG
DefaultLogger::get()->warn("Index overflow in MDL3/4/5/6 vertex list");
}
aiVector3D& vec = vPositions[iCurrent];
@@ -838,7 +840,7 @@ void MDLImporter::InternReadFile_GameStudio( )
if (iIndex >= (unsigned int)this->m_pcHeader->synctype)
{
iIndex = this->m_pcHeader->synctype-1;
// LOG
DefaultLogger::get()->warn("Index overflow in MDL3/4/5/6 UV coord list");
}
float s = (float)pcTexCoords[iIndex].u;
@@ -886,7 +888,7 @@ void MDLImporter::InternReadFile_GameStudio( )
if (iIndex >= (unsigned int)this->m_pcHeader->num_verts)
{
iIndex = this->m_pcHeader->num_verts-1;
// LOG
DefaultLogger::get()->warn("Index overflow in MDL3/4/5/6 vertex list");
}
aiVector3D& vec = vPositions[iCurrent];
@@ -914,7 +916,7 @@ void MDLImporter::InternReadFile_GameStudio( )
if (iIndex >= (unsigned int) this->m_pcHeader->synctype)
{
iIndex = this->m_pcHeader->synctype-1;
// LOG
DefaultLogger::get()->warn("Index overflow in MDL3/4/5/6 UV coord list");
}
float s = (float)pcTexCoords[iIndex].u;
@@ -1029,7 +1031,8 @@ void MDLImporter::ParseSkinLump_GameStudioA7(
// ***** EMBEDDED DDS FILE *****
if (1 != pcSkin->height)
{
// LOG
DefaultLogger::get()->warn("Found a reference to an embedded DDS texture, "
"but texture height is not equal to 1, which is not supported by MED");
}
pcNew = new aiTexture();
@@ -1048,7 +1051,8 @@ void MDLImporter::ParseSkinLump_GameStudioA7(
// ***** REFERENCE TO EXTERNAL FILE FILE *****
if (1 != pcSkin->height)
{
// LOG
DefaultLogger::get()->warn("Found a reference to an external texture, "
"but texture height is not equal to 1, which is not supported by MED");
}
aiString szFile;
@@ -1058,29 +1062,52 @@ void MDLImporter::ParseSkinLump_GameStudioA7(
memcpy(szFile.data,(const char*)szCurrent,iLen2);
szFile.length = iLen;
szCurrent += iLen2;
// place this as diffuse texture
pcMatOut->AddProperty<aiString>(&szFile,1,AI_MATKEY_TEXTURE_DIFFUSE(0));
pcMatOut->AddProperty(&szFile,AI_MATKEY_TEXTURE_DIFFUSE(0));
}
else if (0 != iMasked)
else if (0 != iMasked || 0 == pcSkin->typ)
{
// ***** STANDARD COLOR TEXTURE *****
pcNew = new aiTexture();
if (0 == pcSkin->height || 0 == pcSkin->width)
{
// LOG
DefaultLogger::get()->warn("Found embedded texture, but its width "
"an height are both 0. Is this a joke?");
// generate an empty chess pattern
pcNew->mWidth = pcNew->mHeight = 8;
pcNew->pcData = new aiTexel[64];
for (unsigned int x = 0; x < 8;++x)
{
for (unsigned int y = 0; y < 8;++y)
{
bool bSet = false;
if (0 == x % 2 && 0 != y % 2 ||
0 != x % 2 && 0 == y % 2)bSet = true;
aiTexel* pc = &pcNew->pcData[y * 8 + x];
if (bSet)pc->r = pc->b = pc->g = 0xFF;
else pc->r = pc->b = pc->g = 0;
pc->a = 0xFF;
}
}
}
else
{
// it is a standard color texture. Fill in width and height
// and call the same function we used for loading MDL5 files
// it is a standard color texture. Fill in width and height
// and call the same function we used for loading MDL5 files
pcNew->mWidth = pcSkin->width;
pcNew->mHeight = pcSkin->height;
pcNew = new aiTexture();
pcNew->mWidth = pcSkin->width;
pcNew->mHeight = pcSkin->height;
unsigned int iSkip = 0;
this->ParseTextureColorData(szCurrent,iMasked,&iSkip,pcNew);
unsigned int iSkip = 0;
this->ParseTextureColorData(szCurrent,iMasked,&iSkip,pcNew);
// skip length of texture data
szCurrent += iSkip;
// skip length of texture data
szCurrent += iSkip;
}
}
// check whether a material definition is contained in the skin
@@ -1169,6 +1196,17 @@ void MDLImporter::ParseSkinLump_GameStudioA7(
delete[] pc;
}
// place the name of the skin in the material
const size_t iLen = strlen(pcSkin->texture_name);
if (0 != iLen)
{
aiString szFile;
memcpy(szFile.data,pcSkin->texture_name,sizeof(pcSkin->texture_name));
szFile.length = iLen;
pcMatOut->AddProperty(&szFile,AI_MATKEY_NAME);
}
*szCurrentOut = szCurrent;
return;
}
@@ -1243,7 +1281,8 @@ void MDLImporter::InternReadFile_GameStudioA7( )
if (1 != pcGroup->typ)
{
// Not a triangle-based mesh
// LOGWRITE("[3DGS MDL7] Mesh group is no basing in triangles. Continuing happily");
DefaultLogger::get()->warn("[3DGS MDL7] Mesh group is not basing on"
"triangles. Continuing happily");
}
// read all skins
@@ -1315,6 +1354,8 @@ void MDLImporter::InternReadFile_GameStudioA7( )
{
// LOG
iIndex = pcGroup->numverts-1;
DefaultLogger::get()->warn("Index overflow in MDL7 vertex list");
}
unsigned int iOutIndex = iTriangle * 3 + c;
@@ -1439,7 +1480,10 @@ void MDLImporter::InternReadFile_GameStudioA7( )
// use the last material instead
aiSplit[iNumMaterials-1]->push_back(iFace);
// LOG
// sometimes MED writes -1, but normally only if there is only
// one skin assigned. No warning in this case
if(0xFFFFFFFF != pcFaces[iFace].iMatIndex[0])
DefaultLogger::get()->warn("Index overflow in MDL7 material list [#0]");
}
else aiSplit[pcFaces[iFace].iMatIndex[0]]->push_back(iFace);
}
@@ -1464,13 +1508,19 @@ void MDLImporter::InternReadFile_GameStudioA7( )
if (iMatIndex >= iNumMaterials)
{
iMatIndex = iNumMaterials-1;
// LOG
// sometimes MED writes -1, but normally only if there is only
// one skin assigned. No warning in this case
if(0xFFFFFFFF != iMatIndex)
DefaultLogger::get()->warn("Index overflow in MDL7 material list [#1]");
}
unsigned int iMatIndex2 = pcFaces[iFace].iMatIndex[1];
if (iMatIndex2 >= iNumMaterials)
{
iMatIndex2 = iNumMaterials-1;
// LOG
// sometimes MED writes -1, but normally only if there is only
// one skin assigned. No warning in this case
if(0xFFFFFFFF != iMatIndex2)
DefaultLogger::get()->warn("Index overflow in MDL7 material list [#2]");
}
// do a slow O(log(n)*n) seach in the list ...
@@ -1563,7 +1613,7 @@ void MDLImporter::InternReadFile_GameStudioA7( )
if (((unsigned int)szCurrent - (unsigned int)pcHeader) + iAdd > (unsigned int)pcHeader->data_size)
{
// LOG
DefaultLogger::get()->warn("Index overflow in frame area. Ignoring frames");
// don't parse more groups if we can't even read one
goto __BREAK_OUT;
}
+58
View File
@@ -232,6 +232,34 @@ aiReturn aiGetMaterialString(const aiMaterial* pMat,
return AI_FAILURE;
}
// ------------------------------------------------------------------------------------------------
aiReturn MaterialHelper::RemoveProperty (const char* pKey)
{
ai_assert(NULL != pKey);
for (unsigned int i = 0; i < this->mNumProperties;++i)
{
if (NULL != this->mProperties[i])
{
if (0 == ASSIMP_stricmp( this->mProperties[i]->mKey->data, pKey ))
{
// delete this entry
delete[] this->mProperties[i]->mData;
delete this->mProperties[i];
// collapse the array behind --.
--this->mNumProperties;
for (unsigned int a = i; a < this->mNumProperties;++a)
{
this->mProperties[a] = this->mProperties[a+1];
}
return AI_SUCCESS;
}
}
}
return AI_FAILURE;
}
// ------------------------------------------------------------------------------------------------
aiReturn MaterialHelper::AddBinaryProperty (const void* pInput,
const unsigned int pSizeInBytes,
const char* pKey,
@@ -241,6 +269,23 @@ aiReturn MaterialHelper::AddBinaryProperty (const void* pInput,
ai_assert (pKey != NULL);
ai_assert (0 != pSizeInBytes);
// first search the list whether there is already an entry
// with this name.
unsigned int iOutIndex = 0xFFFFFFFF;
for (unsigned int i = 0; i < this->mNumProperties;++i)
{
if (NULL != this->mProperties[i])
{
if (0 == ASSIMP_stricmp( this->mProperties[i]->mKey->data, pKey ))
{
// delete this entry
delete[] this->mProperties[i]->mData;
delete this->mProperties[i];
iOutIndex = i;
}
}
}
aiMaterialProperty* pcNew = new aiMaterialProperty();
// fill this
@@ -255,6 +300,12 @@ aiReturn MaterialHelper::AddBinaryProperty (const void* pInput,
ai_assert ( MAXLEN > pcNew->mKey->length);
strcpy( pcNew->mKey->data, pKey );
if (0xFFFFFFFF != iOutIndex)
{
this->mProperties[iOutIndex] = pcNew;
return AI_SUCCESS;
}
// resize the array ... allocate
// storage for 5 other properties
if (this->mNumProperties == this->mNumAllocated)
@@ -373,6 +424,12 @@ aiReturn aiGetMaterialTexture(const aiMaterial* pcMat,
szBlendBase = AI_MATKEY_TEXBLEND_SHININESS_;
szOpBase = AI_MATKEY_TEXOP_SHININESS_;
break;
case AI_TEXTYPE_OPACITY:
szPathBase = AI_MATKEY_TEXTURE_OPACITY_;
szUVBase = AI_MATKEY_UVWSRC_OPACITY_;
szBlendBase = AI_MATKEY_TEXBLEND_OPACITY_;
szOpBase = AI_MATKEY_TEXOP_OPACITY_;
break;
default: return AI_FAILURE;
};
@@ -404,6 +461,7 @@ aiReturn aiGetMaterialTexture(const aiMaterial* pcMat,
*pfBlendFactor = fBlend;
}
// get the texture operation of the texture
if (peTextureOp)
{
+21
View File
@@ -60,6 +60,11 @@ namespace Assimp
// ---------------------------------------------------------------------------
inline int ASSIMP_stricmp(const char *s1, const char *s2)
{
#if (defined _MSC_VER)
return _stricmp(s1,s2);
#else
const char *a1, *a2;
a1 = s1;
a2 = s2;
@@ -74,6 +79,7 @@ inline int ASSIMP_stricmp(const char *s1, const char *s2)
++a1;
++a2;
}
#endif
}
// ---------------------------------------------------------------------------
@@ -90,6 +96,11 @@ inline int ASSIMP_stricmp(const char *s1, const char *s2)
// ---------------------------------------------------------------------------
inline int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n)
{
#if (defined _MSC_VER)
return _strnicmp(s1,s2,n);
#else
const char *a1, *a2;
a1 = s1;
a2 = s2;
@@ -109,6 +120,7 @@ inline int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n)
++a2;
++p;
}
#endif
}
@@ -159,6 +171,15 @@ public:
const unsigned int pNumValues,
const char* pKey);
// -------------------------------------------------------------------
/** Remove a given key from the list
* The function fails if the key isn't found
*
* \param pKey Key/Usage to be deleted
*/
aiReturn RemoveProperty (const char* pKey);
// -------------------------------------------------------------------
/** Copy the property list of a material
* \param pcDest Destination material
-4
View File
@@ -26,8 +26,6 @@ ObjFileImporter::ObjFileImporter() :
m_pRootObject(NULL),
m_strAbsPath("\\")
{
DefaultLogger::create( "test.log", DefaultLogger::VERBOSE );
DefaultLogger::get()->info("Start logging");
}
// ------------------------------------------------------------------------------------------------
@@ -40,8 +38,6 @@ ObjFileImporter::~ObjFileImporter()
delete m_pRootObject;
m_pRootObject = NULL;
}
DefaultLogger::kill();
}
// ------------------------------------------------------------------------------------------------
+5 -3
View File
@@ -108,7 +108,9 @@ void PLYImporter::InternReadFile(
// allocate storage and copy the contents of the file to a memory buffer
// (terminate it with zero)
this->mBuffer = new unsigned char[fileSize+1];
// FIX: Allocate an extra buffer of 12.5% to be sure we won't crash
// if an overrun occurs.
this->mBuffer = new unsigned char[fileSize+1 + (fileSize>>3)];
file->Read( (void*)mBuffer, 1, fileSize);
this->mBuffer[fileSize] = '\0';
@@ -131,7 +133,7 @@ void PLYImporter::InternReadFile(
{
szMe += 6;
SkipLine(szMe,(const char**)&szMe);
if(!PLY::DOM::ParseInstance(szMe,&sPlyDom))
if(!PLY::DOM::ParseInstance(szMe,&sPlyDom, fileSize))
{
throw new ImportErrorException( "Invalid .ply file: Unable to build DOM (#1)");
}
@@ -151,7 +153,7 @@ void PLYImporter::InternReadFile(
// skip the line, parse the rest of the header and build the DOM
SkipLine(szMe,(const char**)&szMe);
if(!PLY::DOM::ParseInstanceBinary(szMe,&sPlyDom,bIsBE))
if(!PLY::DOM::ParseInstanceBinary(szMe,&sPlyDom,bIsBE, fileSize))
{
throw new ImportErrorException( "Invalid .ply file: Unable to build DOM (#2)");
}
+271 -59
View File
@@ -44,6 +44,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "PLYLoader.h"
#include "MaterialSystem.h"
#include "fast_atof.h"
#include "DefaultLogger.h"
#include "ByteSwap.h"
#include "../include/IOStream.h"
#include "../include/IOSystem.h"
@@ -55,9 +57,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
void ValidateOut(const char* szCur, const char* szMax)
{
if (szCur > szMax)
{
throw new ImportErrorException("Buffer overflow. PLY file contains invalid indices");
}
return;
}
// ------------------------------------------------------------------------------------------------
PLY::EDataType PLY::Property::ParseDataType(const char* p_szIn,const char** p_szOut)
{
ai_assert(NULL != p_szIn);
ai_assert(NULL != p_szOut);
const char* szMax = *p_szOut;
PLY::EDataType eOut = PLY::EDT_INVALID;
if (0 == ASSIMP_strincmp(p_szIn,"char",4) ||
@@ -134,12 +150,22 @@ PLY::EDataType PLY::Property::ParseDataType(const char* p_szIn,const char** p_sz
{
eOut = PLY::EDT_INVALID;
}
if (PLY::EDT_INVALID == eOut)
{
DefaultLogger::get()->info("Found unknown data type in PLY file. This is OK");
}
*p_szOut = p_szIn;
ValidateOut(p_szIn,szMax);
return eOut;
}
// ------------------------------------------------------------------------------------------------
PLY::ESemantic PLY::Property::ParseSemantic(const char* p_szIn,const char** p_szOut)
{
ai_assert(NULL != p_szIn);
ai_assert(NULL != p_szOut);
const char* szMax = *p_szOut;
PLY::ESemantic eOut = PLY::EST_INVALID;
if (0 == ASSIMP_strincmp(p_szIn,"red",3))
{
@@ -298,6 +324,8 @@ PLY::ESemantic PLY::Property::ParseSemantic(const char* p_szIn,const char** p_sz
}
else
{
DefaultLogger::get()->info("Found unknown property in file. This is ok");
// ... find the next space or new line
while (*p_szIn != ' ' && *p_szIn != '\t' &&
*p_szIn != '\r' && *p_szIn != '\0' && *p_szIn != '\n')p_szIn++;
@@ -307,6 +335,7 @@ PLY::ESemantic PLY::Property::ParseSemantic(const char* p_szIn,const char** p_sz
{
eOut = PLY::EST_INVALID;
}
ValidateOut(p_szIn,szMax);
*p_szOut = p_szIn;
return eOut;
}
@@ -315,9 +344,13 @@ bool PLY::Property::ParseProperty (const char* p_szIn,
const char** p_szOut,
PLY::Property* pOut)
{
ai_assert(NULL != p_szIn);
ai_assert(NULL != p_szOut);
// Forms supported:
// "property float x"
// "property list uchar int vertex_index"
const char* szMax = *p_szOut;
*p_szOut = p_szIn;
// skip leading spaces
@@ -339,46 +372,56 @@ bool PLY::Property::ParseProperty (const char* p_szIn,
// seems to be a list.
p_szIn += 5;
if(EDT_INVALID == (pOut->eFirstType = PLY::Property::ParseDataType(p_szIn, &p_szIn)))
const char* szPass = szMax;
if(EDT_INVALID == (pOut->eFirstType = PLY::Property::ParseDataType(p_szIn, &szPass)))
{
// unable to parse list size data type
SkipLine(p_szIn,&p_szIn);
*p_szOut = p_szIn;
return false;
}
p_szIn = szPass;
if (!SkipSpaces(p_szIn,&p_szIn))return false;
if(EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(p_szIn, &p_szIn)))
szPass = szMax;
if(EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(p_szIn, &szPass)))
{
// unable to parse list data type
SkipLine(p_szIn,&p_szIn);
*p_szOut = p_szIn;
return false;
}
p_szIn = szPass;
}
else
{
if(EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(p_szIn, &p_szIn)))
const char* szPass = szMax;
if(EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(p_szIn, &szPass)))
{
// unable to parse data type. Skip the property
SkipLine(p_szIn,&p_szIn);
*p_szOut = p_szIn;
return false;
}
p_szIn = szPass;
}
if (!SkipSpaces(p_szIn,&p_szIn))return false;
const char* szCur = p_szIn;
pOut->Semantic = PLY::Property::ParseSemantic(p_szIn, &p_szIn);
const char* szPass = szMax;
pOut->Semantic = PLY::Property::ParseSemantic(p_szIn, &szPass);
p_szIn = szPass;
if (PLY::EST_INVALID == pOut->Semantic)
{
// store the name of the semantic
uintptr_t iDiff = (uintptr_t)p_szIn - (uintptr_t)szCur;
DefaultLogger::get()->info("Found unknown semantic in PLY file. This is OK");
pOut->szName = std::string(szCur,iDiff);
}
SkipSpacesAndLineEnd(p_szIn,&p_szIn);
ValidateOut(p_szIn,szMax);
*p_szOut = p_szIn;
return true;
}
@@ -386,6 +429,11 @@ bool PLY::Property::ParseProperty (const char* p_szIn,
PLY::EElementSemantic PLY::Element::ParseSemantic(const char* p_szIn,
const char** p_szOut)
{
ai_assert(NULL != p_szIn);
ai_assert(NULL != p_szOut);
const char* szMax = *p_szOut;
PLY::EElementSemantic eOut = PLY::EEST_INVALID;
if (0 == ASSIMP_strincmp(p_szIn,"vertex",6))
{
@@ -425,6 +473,7 @@ PLY::EElementSemantic PLY::Element::ParseSemantic(const char* p_szIn,
{
eOut = PLY::EEST_INVALID;
}
ValidateOut(p_szIn,szMax);
*p_szOut = p_szIn;
return eOut;
}
@@ -433,7 +482,12 @@ bool PLY::Element::ParseElement (const char* p_szIn,
const char** p_szOut,
PLY::Element* pOut)
{
ai_assert(NULL != p_szIn);
ai_assert(NULL != p_szOut);
ai_assert(NULL != pOut);
// Example format: "element vertex 8"
const char* szMax = *p_szOut;
*p_szOut = p_szIn;
// skip leading spaces
@@ -451,7 +505,9 @@ bool PLY::Element::ParseElement (const char* p_szIn,
// parse the semantic of the element
const char* szCur = p_szIn;
pOut->eSemantic = PLY::Element::ParseSemantic(p_szIn,&p_szIn);
const char* szPass = szMax;
pOut->eSemantic = PLY::Element::ParseSemantic(p_szIn,&szPass);
p_szIn = szPass;
if (PLY::EEST_INVALID == pOut->eSemantic)
{
@@ -476,11 +532,15 @@ bool PLY::Element::ParseElement (const char* p_szIn,
PLY::DOM::SkipComments(p_szIn,&p_szIn);
PLY::Property* prop = new PLY::Property();
if(!PLY::Property::ParseProperty(p_szIn,&p_szIn,prop))break;
const char* szPass = szMax;
if(!PLY::Property::ParseProperty(p_szIn,&szPass,prop))break;
p_szIn = szPass;
// add the property to the property list
pOut->alProperties.push_back(prop);
}
ValidateOut(p_szIn,szMax);
*p_szOut = p_szIn;
return true;
}
@@ -488,6 +548,10 @@ bool PLY::Element::ParseElement (const char* p_szIn,
bool PLY::DOM::SkipComments (const char* p_szIn,
const char** p_szOut)
{
ai_assert(NULL != p_szIn);
ai_assert(NULL != p_szOut);
const char* szMax = *p_szOut;
*p_szOut = p_szIn;
// skip spaces
@@ -503,12 +567,20 @@ bool PLY::DOM::SkipComments (const char* p_szIn,
*p_szOut = p_szIn;
return true;
}
ValidateOut(p_szIn,szMax);
*p_szOut = p_szIn;
return false;
}
// ------------------------------------------------------------------------------------------------
bool PLY::DOM::ParseHeader (const char* p_szIn,const char** p_szOut)
{
ai_assert(NULL != p_szIn);
ai_assert(NULL != p_szOut);
DefaultLogger::get()->debug("PLY::DOM::ParseHeader() begin");
// after ply and format line
const char* szMax = *p_szOut;
*p_szOut = p_szIn;
// parse all elements
@@ -518,8 +590,11 @@ bool PLY::DOM::ParseHeader (const char* p_szIn,const char** p_szOut)
PLY::DOM::SkipComments(p_szIn,&p_szIn);
PLY::Element* out = new PLY::Element();
if(PLY::Element::ParseElement(p_szIn,&p_szIn,out))
const char* szPass = szMax;
if(PLY::Element::ParseElement(p_szIn,&szPass,out))
{
p_szIn = szPass;
// add the element to the list of elements
this->alElements.push_back(out);
}
@@ -532,7 +607,10 @@ bool PLY::DOM::ParseHeader (const char* p_szIn,const char** p_szOut)
// ignore unknown header elements
}
SkipSpacesAndLineEnd(p_szIn,&p_szIn);
ValidateOut(p_szIn,szMax);
*p_szOut = p_szIn;
DefaultLogger::get()->debug("PLY::DOM::ParseHeader() succeeded");
return true;
}
// ------------------------------------------------------------------------------------------------
@@ -540,6 +618,14 @@ bool PLY::DOM::ParseElementInstanceLists (
const char* p_szIn,
const char** p_szOut)
{
ai_assert(NULL != p_szIn);
ai_assert(NULL != p_szOut);
DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() begin");
const char* szMax = *p_szOut;
*p_szOut = p_szIn;
this->alElementData.resize(this->alElements.size());
std::vector<PLY::Element*>::const_iterator i = this->alElements.begin();
@@ -549,8 +635,15 @@ bool PLY::DOM::ParseElementInstanceLists (
for (;i != this->alElements.end();++i,++a)
{
*a = new PLY::ElementInstanceList((*i)); // reserve enough storage
PLY::ElementInstanceList::ParseInstanceList(p_szIn,&p_szIn,(*i),(*a));
const char* szPass = szMax;
PLY::ElementInstanceList::ParseInstanceList(p_szIn,&szPass,(*i),(*a));
p_szIn = szPass;
}
DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() succeeded");
ValidateOut(p_szIn,szMax);
*p_szOut = p_szIn;
return true;
}
// ------------------------------------------------------------------------------------------------
@@ -559,6 +652,14 @@ bool PLY::DOM::ParseElementInstanceListsBinary (
const char** p_szOut,
bool p_bBE)
{
ai_assert(NULL != p_szIn);
ai_assert(NULL != p_szOut);
DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() begin");
const char* szMax = *p_szOut;
*p_szOut = p_szIn;
this->alElementData.resize(this->alElements.size());
std::vector<PLY::Element*>::const_iterator i = this->alElements.begin();
@@ -568,40 +669,80 @@ bool PLY::DOM::ParseElementInstanceListsBinary (
for (;i != this->alElements.end();++i,++a)
{
*a = new PLY::ElementInstanceList((*i)); // reserve enough storage
PLY::ElementInstanceList::ParseInstanceListBinary(p_szIn,&p_szIn,(*i),(*a),p_bBE);
const char* szPass = szMax;
PLY::ElementInstanceList::ParseInstanceListBinary(p_szIn,&szPass,(*i),(*a),p_bBE);
p_szIn = szPass;
}
DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() succeeded");
ValidateOut(p_szIn,szMax);
*p_szOut = p_szIn;
return true;
}
// ------------------------------------------------------------------------------------------------
bool PLY::DOM::ParseInstanceBinary (const char* p_szIn,DOM* p_pcOut,bool p_bBE)
bool PLY::DOM::ParseInstanceBinary (const char* p_szIn,DOM* p_pcOut,bool p_bBE,unsigned int iSize)
{
if(!p_pcOut->ParseHeader(p_szIn,&p_szIn))
ai_assert(NULL != p_szIn);
ai_assert(NULL != p_pcOut);
DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() begin");
const char* szMax = p_szIn + iSize;
const char* szPass = szMax;
if(!p_pcOut->ParseHeader(p_szIn,&szPass))
{
DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure");
return false;
}
if(!p_pcOut->ParseElementInstanceListsBinary(p_szIn,&p_szIn,p_bBE))
p_szIn = szPass;
szPass = szMax;
if(!p_pcOut->ParseElementInstanceListsBinary(p_szIn,&szPass,p_bBE))
{
DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure");
return false;
}
DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() succeeded");
return true;
}
// ------------------------------------------------------------------------------------------------
bool PLY::DOM::ParseInstance (const char* p_szIn,DOM* p_pcOut)
bool PLY::DOM::ParseInstance (const char* p_szIn,DOM* p_pcOut,unsigned int iSize)
{
if(!p_pcOut->ParseHeader(p_szIn,&p_szIn))
ai_assert(NULL != p_szIn);
ai_assert(NULL != p_pcOut);
DefaultLogger::get()->debug("PLY::DOM::ParseInstance() begin");
const char* szMax = p_szIn + iSize;
const char* szPass = szMax;
if(!p_pcOut->ParseHeader(p_szIn,&szPass))
{
DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure");
return false;
}
if(!p_pcOut->ParseElementInstanceLists(p_szIn,&p_szIn))
p_szIn = szPass;
szPass = szMax;
if(!p_pcOut->ParseElementInstanceLists(p_szIn,&szPass))
{
DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure");
return false;
}
DefaultLogger::get()->debug("PLY::DOM::ParseInstance() succeeded");
return true;
}
// ------------------------------------------------------------------------------------------------
bool PLY::ElementInstanceList::ParseInstanceList (const char* p_szIn,const char** p_szOut,
const PLY::Element* pcElement, PLY::ElementInstanceList* p_pcOut)
bool PLY::ElementInstanceList::ParseInstanceList (
const char* p_szIn,
const char** p_szOut,
const PLY::Element* pcElement,
PLY::ElementInstanceList* p_pcOut)
{
ai_assert(NULL != p_szIn);
ai_assert(NULL != p_szOut);
ai_assert(NULL != pcElement);
ai_assert(NULL != p_pcOut);
const char* szMax = *p_szOut;
if (EEST_INVALID == pcElement->eSemantic)
{
// if the element has an unknown semantic we can skip all lines
@@ -621,11 +762,15 @@ bool PLY::ElementInstanceList::ParseInstanceList (const char* p_szIn,const char*
PLY::DOM::SkipComments(p_szIn,&p_szIn);
PLY::ElementInstance* out = new PLY::ElementInstance();
PLY::ElementInstance::ParseInstance(p_szIn, &p_szIn,pcElement, out);
const char* szPass = szMax;
PLY::ElementInstance::ParseInstance(p_szIn, &szPass,pcElement, out);
p_szIn = szPass;
// add it to the list
p_pcOut->alInstances[i] = out;
}
}
ValidateOut(p_szIn,szMax);
*p_szOut = p_szIn;
return true;
}
@@ -637,6 +782,14 @@ bool PLY::ElementInstanceList::ParseInstanceListBinary (
PLY::ElementInstanceList* p_pcOut,
bool p_bBE /* = false */)
{
ai_assert(NULL != p_szIn);
ai_assert(NULL != p_szOut);
ai_assert(NULL != pcElement);
ai_assert(NULL != p_pcOut);
const char* szMax = *p_szOut;
*p_szOut = p_szIn;
// we can add special handling code for unknown element semantics since
// we can't skip it as a whole block (we don't know its exact size
// due to the fact that lists could be contained in the property list
@@ -644,10 +797,13 @@ bool PLY::ElementInstanceList::ParseInstanceListBinary (
for (unsigned int i = 0; i < pcElement->NumOccur;++i)
{
PLY::ElementInstance* out = new PLY::ElementInstance();
const char* szPass = szMax;
PLY::ElementInstance::ParseInstanceBinary(p_szIn, &p_szIn,pcElement, out, p_bBE);
p_szIn = szPass;
// add it to the list
p_pcOut->alInstances[i] = out;
}
ValidateOut(p_szIn,szMax);
*p_szOut = p_szIn;
return true;
}
@@ -658,25 +814,38 @@ bool PLY::ElementInstance::ParseInstance (
const PLY::Element* pcElement,
PLY::ElementInstance* p_pcOut)
{
ai_assert(NULL != p_szIn);
ai_assert(NULL != p_szOut);
ai_assert(NULL != pcElement);
ai_assert(NULL != p_pcOut);
if (!SkipSpaces(p_szIn, &p_szIn))return false;
// allocate enough storage
p_pcOut->alProperties.resize(pcElement->alProperties.size());
const char* szMax = *p_szOut;
*p_szOut = p_szIn;
std::vector<PLY::PropertyInstance>::iterator i = p_pcOut->alProperties.begin();
std::vector<PLY::Property*>::const_iterator a = pcElement->alProperties.begin();
for (;i != p_pcOut->alProperties.end();++i,++a)
{
if(!(PLY::PropertyInstance::ParseInstance(p_szIn, &p_szIn,(*a),&(*i))))
const char* szPass = szMax;
if(!(PLY::PropertyInstance::ParseInstance(p_szIn, &szPass,(*a),&(*i))))
{
DefaultLogger::get()->warn("Unable to parse property instance. "
"Skipping this element instance");
// skip the rest of the instance
SkipLine(p_szIn, &p_szIn);
PLY::PropertyInstance::ValueUnion v = PLY::PropertyInstance::DefaultValue((*a)->eType);
(*i).avList.push_back(v);
}
p_szIn = szPass;
}
ValidateOut(p_szIn,szMax);
*p_szOut = p_szIn;
return true;
}
@@ -688,20 +857,33 @@ bool PLY::ElementInstance::ParseInstanceBinary (
PLY::ElementInstance* p_pcOut,
bool p_bBE /* = false */)
{
ai_assert(NULL != p_szIn);
ai_assert(NULL != p_szOut);
ai_assert(NULL != pcElement);
ai_assert(NULL != p_pcOut);
const char* szMax = *p_szOut;
*p_szOut = p_szIn;
// allocate enough storage
p_pcOut->alProperties.resize(pcElement->alProperties.size());
*p_szOut = p_szIn;
std::vector<PLY::PropertyInstance>::iterator i = p_pcOut->alProperties.begin();
std::vector<PLY::Property*>::const_iterator a = pcElement->alProperties.begin();
for (;i != p_pcOut->alProperties.end();++i,++a)
{
if(!(PLY::PropertyInstance::ParseInstance(p_szIn, &p_szIn,(*a),&(*i))))
const char* szPass = szMax;
if(!(PLY::PropertyInstance::ParseInstanceBinary(p_szIn, &szPass,(*a),&(*i),p_bBE)))
{
DefaultLogger::get()->warn("Unable to parse binary property instance. "
"Skipping this element instance");
PLY::PropertyInstance::ValueUnion v = PLY::PropertyInstance::DefaultValue((*a)->eType);
(*i).avList.push_back(v);
}
p_szIn = szPass;
}
ValidateOut(p_szIn,szMax);
*p_szOut = p_szIn;
return true;
}
@@ -709,6 +891,12 @@ bool PLY::ElementInstance::ParseInstanceBinary (
bool PLY::PropertyInstance::ParseInstance (const char* p_szIn,const char** p_szOut,
const PLY::Property* prop, PLY::PropertyInstance* p_pcOut)
{
ai_assert(NULL != p_szIn);
ai_assert(NULL != p_szOut);
ai_assert(NULL != prop);
ai_assert(NULL != p_pcOut);
const char* szMax = *p_szOut;
*p_szOut = p_szIn;
// skip spaces at the beginning
@@ -718,7 +906,10 @@ bool PLY::PropertyInstance::ParseInstance (const char* p_szIn,const char** p_szO
{
// parse the number of elements in the list
PLY::PropertyInstance::ValueUnion v;
PLY::PropertyInstance::ParseValue(p_szIn, &p_szIn,prop->eFirstType,&v);
const char* szPass = szMax;
PLY::PropertyInstance::ParseValue(p_szIn, &szPass,prop->eFirstType,&v);
p_szIn = szPass;
// convert to unsigned int
unsigned int iNum = PLY::PropertyInstance::ConvertTo<unsigned int>(v,prop->eFirstType);
@@ -728,7 +919,9 @@ bool PLY::PropertyInstance::ParseInstance (const char* p_szIn,const char** p_szO
{
if (!SkipSpaces(p_szIn, &p_szIn))return false;
PLY::PropertyInstance::ParseValue(p_szIn, &p_szIn,prop->eType,&v);
const char* szPass = szMax;
PLY::PropertyInstance::ParseValue(p_szIn, &szPass,prop->eType,&v);
p_szIn = szPass;
p_pcOut->avList.push_back(v);
}
}
@@ -736,10 +929,14 @@ bool PLY::PropertyInstance::ParseInstance (const char* p_szIn,const char** p_szO
{
// parse the property
PLY::PropertyInstance::ValueUnion v;
PLY::PropertyInstance::ParseValue(p_szIn, &p_szIn,prop->eType,&v);
const char* szPass = szMax;
PLY::PropertyInstance::ParseValue(p_szIn, &szPass,prop->eType,&v);
p_szIn = szPass;
p_pcOut->avList.push_back(v);
}
SkipSpacesAndLineEnd(p_szIn, &p_szIn);
ValidateOut(p_szIn,szMax);
*p_szOut = p_szIn;
return true;
}
@@ -747,13 +944,21 @@ bool PLY::PropertyInstance::ParseInstance (const char* p_szIn,const char** p_szO
bool PLY::PropertyInstance::ParseInstanceBinary (const char* p_szIn,const char** p_szOut,
const PLY::Property* prop, PLY::PropertyInstance* p_pcOut,bool p_bBE)
{
ai_assert(NULL != p_szIn);
ai_assert(NULL != p_szOut);
ai_assert(NULL != prop);
ai_assert(NULL != p_pcOut);
const char* szMax = *p_szOut;
*p_szOut = p_szIn;
if (prop->bIsList)
{
// parse the number of elements in the list
PLY::PropertyInstance::ValueUnion v;
PLY::PropertyInstance::ParseValueBinary(p_szIn, &p_szIn,prop->eFirstType,&v,p_bBE);
const char* szPass = szMax;
PLY::PropertyInstance::ParseValueBinary(p_szIn, &szPass,prop->eFirstType,&v,p_bBE);
p_szIn = szPass;
// convert to unsigned int
unsigned int iNum = PLY::PropertyInstance::ConvertTo<unsigned int>(v,prop->eFirstType);
@@ -761,7 +966,9 @@ bool PLY::PropertyInstance::ParseInstanceBinary (const char* p_szIn,const char**
// parse all list elements
for (unsigned int i = 0; i < iNum;++i)
{
PLY::PropertyInstance::ParseValueBinary(p_szIn, &p_szIn,prop->eType,&v,p_bBE);
const char* szPass = szMax;
PLY::PropertyInstance::ParseValueBinary(p_szIn, &szPass,prop->eType,&v,p_bBE);
p_szIn = szPass;
p_pcOut->avList.push_back(v);
}
}
@@ -769,9 +976,12 @@ bool PLY::PropertyInstance::ParseInstanceBinary (const char* p_szIn,const char**
{
// parse the property
PLY::PropertyInstance::ValueUnion v;
PLY::PropertyInstance::ParseValueBinary(p_szIn, &p_szIn,prop->eType,&v,p_bBE);
const char* szPass = szMax;
PLY::PropertyInstance::ParseValueBinary(p_szIn, &szPass,prop->eType,&v,p_bBE);
p_szIn = szPass;
p_pcOut->avList.push_back(v);
}
ValidateOut(p_szIn,szMax);
*p_szOut = p_szIn;
return true;
}
@@ -798,6 +1008,11 @@ PLY::PropertyInstance::ValueUnion PLY::PropertyInstance::DefaultValue(
bool PLY::PropertyInstance::ParseValue(const char* p_szIn,const char** p_szOut,
PLY::EDataType eType,PLY::PropertyInstance::ValueUnion* out)
{
ai_assert(NULL != p_szIn);
ai_assert(NULL != p_szOut);
ai_assert(NULL != out);
const char* szMax = *p_szOut;
*p_szOut = p_szIn;
switch (eType)
@@ -846,13 +1061,23 @@ bool PLY::PropertyInstance::ParseValue(const char* p_szIn,const char** p_szOut,
default:
return false;
}
ValidateOut(p_szIn,szMax);
*p_szOut = p_szIn;
return true;
}
// ------------------------------------------------------------------------------------------------
bool PLY::PropertyInstance::ParseValueBinary(const char* p_szIn,const char** p_szOut,
PLY::EDataType eType,PLY::PropertyInstance::ValueUnion* out, bool p_bBE)
bool PLY::PropertyInstance::ParseValueBinary(
const char* p_szIn,
const char** p_szOut,
PLY::EDataType eType,
PLY::PropertyInstance::ValueUnion* out,
bool p_bBE)
{
ai_assert(NULL != p_szIn);
ai_assert(NULL != p_szOut);
ai_assert(NULL != out);
const char* szMax = *p_szOut;
*p_szOut = p_szIn;
switch (eType)
@@ -863,8 +1088,7 @@ bool PLY::PropertyInstance::ParseValueBinary(const char* p_szIn,const char** p_s
if (p_bBE)
{
std::swap(((unsigned char*)(&out->iUInt))[0],((unsigned char*)(&out->iUInt))[3]);
std::swap(((unsigned char*)(&out->iUInt))[1],((unsigned char*)(&out->iUInt))[2]);
ByteSwap::Swap((int32_t*)&out->iUInt);
}
break;
@@ -873,7 +1097,7 @@ bool PLY::PropertyInstance::ParseValueBinary(const char* p_szIn,const char** p_s
uint16_t i = *((uint16_t*)p_szIn);
if (p_bBE)
{
std::swap(((unsigned char*)(&i))[0],((unsigned char*)(&i))[1]);
ByteSwap::Swap((int16_t*)&i);
}
out->iUInt = (uint32_t)i;
p_szIn += 2;
@@ -884,7 +1108,7 @@ bool PLY::PropertyInstance::ParseValueBinary(const char* p_szIn,const char** p_s
{
uint8_t i = *((uint8_t*)p_szIn);
out->iUInt = (uint32_t)i;
p_szIn += 2;
p_szIn ++;
break;
}
@@ -894,8 +1118,7 @@ bool PLY::PropertyInstance::ParseValueBinary(const char* p_szIn,const char** p_s
if (p_bBE)
{
std::swap(((unsigned char*)(&out->iInt))[0],((unsigned char*)(&out->iInt))[3]);
std::swap(((unsigned char*)(&out->iInt))[1],((unsigned char*)(&out->iInt))[2]);
ByteSwap::Swap((int32_t*)&out->iInt);
}
break;
@@ -904,7 +1127,7 @@ bool PLY::PropertyInstance::ParseValueBinary(const char* p_szIn,const char** p_s
int16_t i = *((int16_t*)p_szIn);
if (p_bBE)
{
std::swap(((unsigned char*)(&i))[0],((unsigned char*)(&i))[1]);
ByteSwap::Swap((int16_t*)&i);
}
out->iInt = (int32_t)i;
p_szIn += 2;
@@ -913,46 +1136,35 @@ bool PLY::PropertyInstance::ParseValueBinary(const char* p_szIn,const char** p_s
case EDT_Char:
out->iInt = (int32_t)*((int8_t*)p_szIn);
p_szIn += 1;
p_szIn ++;
break;
case EDT_Float:
{
int32_t* pf = (int32_t*)p_szIn;
if (p_bBE)
{
union {char szArray[4]; float fValue; } _X;
_X.szArray[0] = ((unsigned char*)p_szIn)[3];
_X.szArray[1] = ((unsigned char*)p_szIn)[2];
_X.szArray[2] = ((unsigned char*)p_szIn)[1];
_X.szArray[3] = ((unsigned char*)p_szIn)[0];
out->fFloat = _X.fValue;
ByteSwap::Swap((int32_t*)&pf);
}
else out->fFloat = *((float*)p_szIn);
p_szIn += 4;
out->fFloat = *((float*)&pf);
break;
}
case EDT_Double:
{
int64_t* pf = (int64_t*)p_szIn;
if (p_bBE)
{
union {char szArray[8]; double fValue; } _X;
_X.szArray[0] = ((unsigned char*)p_szIn)[7];
_X.szArray[1] = ((unsigned char*)p_szIn)[6];
_X.szArray[2] = ((unsigned char*)p_szIn)[5];
_X.szArray[3] = ((unsigned char*)p_szIn)[4];
_X.szArray[4] = ((unsigned char*)p_szIn)[3];
_X.szArray[5] = ((unsigned char*)p_szIn)[2];
_X.szArray[6] = ((unsigned char*)p_szIn)[1];
_X.szArray[7] = ((unsigned char*)p_szIn)[0];
out->fDouble = _X.fValue;
ByteSwap::Swap((int64_t*)&pf);
}
else out->fDouble = *((double*)p_szIn);
p_szIn += 8;
out->fDouble = *((double*)&pf);
break;
}
default:
return false;
}
ValidateOut(p_szIn,szMax);
*p_szOut = p_szIn;
return true;
}
+3 -3
View File
@@ -411,7 +411,7 @@ public:
ElementInstanceList (const Element* pc)
{
// reserve enough storage to speedup the process
alInstances.reserve(pc->NumOccur);
alInstances.resize(pc->NumOccur);
}
//! Destructor. Dallocates all storage
@@ -479,9 +479,9 @@ public:
//! Parse the DOM for a PLY file. The input string is assumed
//! to be terminated with zero
static bool ParseInstance (const char* p_szIn,DOM* p_pcOut);
static bool ParseInstance (const char* p_szIn,DOM* p_pcOut, unsigned int iLen);
static bool ParseInstanceBinary (const char* p_szIn,
DOM* p_pcOut,bool p_bBE);
DOM* p_pcOut,bool p_bBE, unsigned int iLen);
//! Skip all comment lines after this
static bool SkipComments (const char* p_szIn,const char** p_szOut);
+14 -2
View File
@@ -42,6 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Implementation of the SplitLargeMeshes postprocessing step
*/
#include "SplitLargeMeshes.h"
#include "DefaultLogger.h"
#include "../include/aiPostProcess.h"
#include "../include/aiMesh.h"
#include "../include/aiScene.h"
@@ -63,6 +64,7 @@ aiReturn aiSetVertexSplitLimit(unsigned int pLimit)
}
SplitLargeMeshesProcess_Vertex::LIMIT = pLimit;
//DefaultLogger::get()->debug("aiSetVertexSplitLimit() - vertex split limit was changed");
return AI_SUCCESS;
}
// ------------------------------------------------------------------------------------------------
@@ -75,6 +77,7 @@ aiReturn aiSetTriangleSplitLimit(unsigned int pLimit)
}
SplitLargeMeshesProcess_Triangle::LIMIT = pLimit;
//DefaultLogger::get()->debug("aiSetTriangleSplitLimit() - triangle split limit was changed");
return AI_SUCCESS;
}
}; //! extern "C"
@@ -99,6 +102,7 @@ bool SplitLargeMeshesProcess_Triangle::IsActive( unsigned int pFlags) const
// Executes the post processing step on the given imported data.
void SplitLargeMeshesProcess_Triangle::Execute( aiScene* pScene)
{
DefaultLogger::get()->debug("SplitLargeMeshesProcess_Triangle begin");
std::vector<std::pair<aiMesh*, unsigned int> > avList;
for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
@@ -116,7 +120,9 @@ void SplitLargeMeshesProcess_Triangle::Execute( aiScene* pScene)
// now we need to update all nodes
this->UpdateNode(pScene->mRootNode,avList);
DefaultLogger::get()->info("SplitLargeMeshesProcess_Triangle finished. Meshes have been splitted");
}
else DefaultLogger::get()->debug("SplitLargeMeshesProcess_Triangle finished. There was nothing to do");
return;
}
// ------------------------------------------------------------------------------------------------
@@ -160,8 +166,10 @@ void SplitLargeMeshesProcess_Triangle::SplitMesh(
aiMesh* pMesh,
std::vector<std::pair<aiMesh*, unsigned int> >& avList)
{
if (pMesh->mNumFaces > LIMIT)
if (pMesh->mNumFaces > SplitLargeMeshesProcess_Triangle::LIMIT)
{
DefaultLogger::get()->info("Mesh exceeds the triangle limit. It will be split ...");
// we need to split this mesh into sub meshes
// determine the size of a submesh
const unsigned int iSubMeshes = (pMesh->mNumFaces / LIMIT) + 1;
@@ -318,6 +326,7 @@ void SplitLargeMeshesProcess_Vertex::Execute( aiScene* pScene)
{
std::vector<std::pair<aiMesh*, unsigned int> > avList;
DefaultLogger::get()->debug("SplitLargeMeshesProcess_Vertex begin");
for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
this->SplitMesh(a, pScene->mMeshes[a],avList);
@@ -333,7 +342,9 @@ void SplitLargeMeshesProcess_Vertex::Execute( aiScene* pScene)
// now we need to update all nodes
SplitLargeMeshesProcess_Triangle::UpdateNode(pScene->mRootNode,avList);
DefaultLogger::get()->info("SplitLargeMeshesProcess_Vertex finished. Meshes have been splitted");
}
else DefaultLogger::get()->debug("SplitLargeMeshesProcess_Vertex finished. There was nothing to do");
return;
}
// ------------------------------------------------------------------------------------------------
@@ -510,7 +521,8 @@ void SplitLargeMeshesProcess_Vertex::SplitMesh(
// now delete the old mesh data
delete pMesh;
return;
}
else avList.push_back(std::pair<aiMesh*, unsigned int>(pMesh,a));
avList.push_back(std::pair<aiMesh*, unsigned int>(pMesh,a));
return;
}
+26 -3
View File
@@ -4,6 +4,7 @@
#include <vector>
#include <assert.h>
#include "TriangulateProcess.h"
#include "DefaultLogger.h"
#include "../include/aiPostProcess.h"
#include "../include/aiMesh.h"
#include "../include/aiScene.h"
@@ -35,14 +36,33 @@ bool TriangulateProcess::IsActive( unsigned int pFlags) const
// Executes the post processing step on the given imported data.
void TriangulateProcess::Execute( aiScene* pScene)
{
DefaultLogger::get()->debug("TriangulateProcess begin");
bool bHas = false;
for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
TriangulateMesh( pScene->mMeshes[a]);
{
if( TriangulateMesh( pScene->mMeshes[a]))
bHas = true;
}
if (bHas)DefaultLogger::get()->info("TriangulateProcess finished. Found polygons to triangulate");
else DefaultLogger::get()->debug("TriangulateProcess finished. There was nothing to do.");
}
// ------------------------------------------------------------------------------------------------
// Triangulates the given mesh.
void TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
{
// check whether we will need to do something ...
for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
{
const aiFace& face = pMesh->mFaces[a];
if( face.mNumIndices != 3)
{
break;
}
return false;
}
std::vector<aiFace> newFaces;
newFaces.reserve( pMesh->mNumFaces*2);
for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
@@ -57,7 +77,8 @@ void TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
nface.mNumIndices = face.mNumIndices;
nface.mIndices = new unsigned int[nface.mNumIndices];
memcpy( nface.mIndices, face.mIndices, nface.mNumIndices * sizeof( unsigned int));
} else
}
else
{
assert( face.mNumIndices > 3);
for( unsigned int b = 0; b < face.mNumIndices - 2; b++)
@@ -80,4 +101,6 @@ void TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
pMesh->mFaces = new aiFace[pMesh->mNumFaces];
for( unsigned int a = 0; a < newFaces.size(); a++)
pMesh->mFaces[a] = newFaces[a];
return true;
}
+1 -1
View File
@@ -88,7 +88,7 @@ protected:
/** Triangulates the given mesh.
* @param pMesh The mesh to triangulate.
*/
void TriangulateMesh( aiMesh* pMesh);
bool TriangulateMesh( aiMesh* pMesh);
};
} // end of namespace Assimp
+6 -1
View File
@@ -561,8 +561,13 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, const std::vector<XFile::
aiString name;
name.Set( oldMat.mName);
mat->AddProperty( &name, AI_MATKEY_NAME);
// Shading model: hardcoded to PHONG, there is no such information in an XFile
int shadeMode = (int) aiShadingMode_Phong;
// FIX (aramis): If the specular exponent is 0, use gouraud shading. This is a bugfix
// for some models in the SDK (e.g. good old tiny.x)
int shadeMode = (int)oldMat.mSpecularExponent == 0.0f
? aiShadingMode_Gouraud : aiShadingMode_Phong;
mat->AddProperty<int>( &shadeMode, 1, AI_MATKEY_SHADING_MODEL);
// material colours
mat->AddProperty( &oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE);