Added validation step, added helper macro AI_BUILD_KEY to the material system.
git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@59 67173fc5-114c-0410-ac8e-9d2fd5bffc1fpull/1/head
parent
d6fc5de7d5
commit
758e092449
|
@ -43,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "3DSLoader.h"
|
||||
#include "MaterialSystem.h"
|
||||
#include "TextureTransform.h"
|
||||
#include "StringComparison.h"
|
||||
|
||||
#include "../include/DefaultLogger.h"
|
||||
#include "../include/IOStream.h"
|
||||
|
@ -114,7 +115,7 @@ void Dot3DSImporter::ReplaceDefaultMaterial()
|
|||
}
|
||||
}
|
||||
}
|
||||
if (0 != iCnt && iIndex == this->mScene->mMaterials.size())
|
||||
if (iCnt && iIndex == this->mScene->mMaterials.size())
|
||||
{
|
||||
// we need to create our own default material
|
||||
Dot3DS::Material sMat;
|
||||
|
@ -184,12 +185,6 @@ void Dot3DSImporter::MakeUnique(Dot3DS::Mesh* sMesh)
|
|||
|
||||
sMesh->mFaces[i].mIndices[0] = iTemp1;
|
||||
sMesh->mFaces[i].mIndices[1] = iTemp2;
|
||||
|
||||
// handle the face order ...
|
||||
/*if (iTemp1 > iTemp2)
|
||||
{
|
||||
sMesh->mFaces[i].bFlipped = true;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -210,12 +205,6 @@ void Dot3DSImporter::MakeUnique(Dot3DS::Mesh* sMesh)
|
|||
|
||||
sMesh->mFaces[i].mIndices[0] = iTemp1;
|
||||
sMesh->mFaces[i].mIndices[1] = iTemp2;
|
||||
|
||||
// handle the face order ...
|
||||
/*if (iTemp1 > iTemp2)
|
||||
{
|
||||
sMesh->mFaces[i].bFlipped = true;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
sMesh->mPositions = vNew;
|
||||
|
|
|
@ -43,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "3DSLoader.h"
|
||||
#include "MaterialSystem.h"
|
||||
#include "TextureTransform.h"
|
||||
#include "StringComparison.h"
|
||||
|
||||
#include "../include/DefaultLogger.h"
|
||||
#include "../include/IOStream.h"
|
||||
|
|
|
@ -43,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "ASELoader.h"
|
||||
#include "3DSSpatialSort.h"
|
||||
#include "MaterialSystem.h"
|
||||
#include "StringComparison.h"
|
||||
#include "TextureTransform.h"
|
||||
#include "fast_atof.h"
|
||||
|
||||
|
@ -58,8 +59,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
using namespace Assimp;
|
||||
using namespace Assimp::ASE;
|
||||
|
||||
#define LOGOUT_WARN(x) DefaultLogger::get()->warn(x);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
ASEImporter::ASEImporter()
|
||||
|
@ -619,7 +618,7 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMesh
|
|||
if (mesh.iMaterialIndex >= this->mParser->m_vMaterials.size())
|
||||
{
|
||||
mesh.iMaterialIndex = (unsigned int)this->mParser->m_vMaterials.size()-1;
|
||||
LOGOUT_WARN("Material index is out of range");
|
||||
DefaultLogger::get()->warn("Material index is out of range");
|
||||
}
|
||||
|
||||
|
||||
|
@ -640,7 +639,7 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMesh
|
|||
// check range
|
||||
if (mesh.mFaces[i].iMaterial >= vSubMaterials.size())
|
||||
{
|
||||
LOGOUT_WARN("Submaterial index is out of range");
|
||||
DefaultLogger::get()->warn("Submaterial index is out of range");
|
||||
|
||||
// use the last material instead
|
||||
aiSplit[vSubMaterials.size()-1].push_back(i);
|
||||
|
|
|
@ -81,10 +81,14 @@ Parser::Parser (const char* szFile)
|
|||
void Parser::LogWarning(const char* szWarn)
|
||||
{
|
||||
ai_assert(NULL != szWarn);
|
||||
ai_assert(strlen(szWarn) < 950);
|
||||
|
||||
char szTemp[1024];
|
||||
sprintf(szTemp,"Line %i: %s",this->iLineNumber/2 /* fixme */,szWarn);
|
||||
#if _MSC_VER >= 1400
|
||||
sprintf_s(szTemp,"Line %i: %s",this->iLineNumber,szWarn);
|
||||
#else
|
||||
ai_assert(strlen(szWarn) < 950);
|
||||
sprintf(szTemp,"Line %i: %s",this->iLineNumber,szWarn);
|
||||
#endif
|
||||
|
||||
// output the warning to the logger ...
|
||||
DefaultLogger::get()->warn(szTemp);
|
||||
|
@ -93,10 +97,14 @@ void Parser::LogWarning(const char* szWarn)
|
|||
void Parser::LogInfo(const char* szWarn)
|
||||
{
|
||||
ai_assert(NULL != szWarn);
|
||||
ai_assert(strlen(szWarn) < 950);
|
||||
|
||||
char szTemp[1024];
|
||||
sprintf(szTemp,"Line %i: %s",this->iLineNumber/2 /* fixme */,szWarn);
|
||||
#if _MSC_VER >= 1400
|
||||
sprintf_s(szTemp,"Line %i: %s",this->iLineNumber,szWarn);
|
||||
#else
|
||||
ai_assert(strlen(szWarn) < 950);
|
||||
sprintf(szTemp,"Line %i: %s",this->iLineNumber,szWarn);
|
||||
#endif
|
||||
|
||||
// output the information to the logger ...
|
||||
DefaultLogger::get()->info(szTemp);
|
||||
|
@ -105,10 +113,14 @@ void Parser::LogInfo(const char* szWarn)
|
|||
void Parser::LogError(const char* szWarn)
|
||||
{
|
||||
ai_assert(NULL != szWarn);
|
||||
ai_assert(strlen(szWarn) < 950);
|
||||
|
||||
char szTemp[1024];
|
||||
sprintf(szTemp,"Line %i: %s",this->iLineNumber/2 /* fixme */,szWarn);
|
||||
#if _MSC_VER >= 1400
|
||||
sprintf_s(szTemp,"Line %i: %s",this->iLineNumber,szWarn);
|
||||
#else
|
||||
ai_assert(strlen(szWarn) < 950);
|
||||
sprintf(szTemp,"Line %i: %s",this->iLineNumber,szWarn);
|
||||
#endif
|
||||
|
||||
// throw an exception
|
||||
throw new ImportErrorException(szTemp);
|
||||
|
@ -118,8 +130,12 @@ bool Parser::SkipToNextToken()
|
|||
{
|
||||
while (true)
|
||||
{
|
||||
if ('*' == *this->m_szFile || '}' == *this->m_szFile || '{' == *this->m_szFile)return true;
|
||||
if ('\0' == *this->m_szFile)return false;
|
||||
char me = *this->m_szFile;
|
||||
|
||||
// increase the line number counter if necessary
|
||||
if (IsLineEnd(me))++this->iLineNumber;
|
||||
else if ('*' == me || '}' == me || '{' == me)return true;
|
||||
else if ('\0' == me)return false;
|
||||
|
||||
++this->m_szFile;
|
||||
}
|
||||
|
@ -670,21 +686,33 @@ void Parser::ParseLV3MapBlock(Texture& map)
|
|||
bool Parser::ParseString(std::string& out,const char* szName)
|
||||
{
|
||||
char szBuffer[1024];
|
||||
|
||||
#if (!defined _MSC_VER) || ( _MSC_VER < 1400)
|
||||
ai_assert(strlen(szName) < 750);
|
||||
#endif
|
||||
|
||||
// NOTE: The name could also be the texture in some cases
|
||||
// be prepared that this might occur ...
|
||||
if (!SkipSpaces(this->m_szFile,&this->m_szFile))
|
||||
{
|
||||
#if _MSC_VER >= 1400
|
||||
sprintf_s(szBuffer,"Unable to parse %s block: Unexpected EOL",szName);
|
||||
#else
|
||||
sprintf(szBuffer,"Unable to parse %s block: Unexpected EOL",szName);
|
||||
#endif
|
||||
this->LogWarning(szBuffer);
|
||||
return false;
|
||||
}
|
||||
// there must be "
|
||||
if ('\"' != *this->m_szFile)
|
||||
{
|
||||
#if _MSC_VER >= 1400
|
||||
sprintf_s(szBuffer,"Unable to parse %s block: String is expected "
|
||||
"to be enclosed in double quotation marks",szName);
|
||||
#else
|
||||
sprintf(szBuffer,"Unable to parse %s block: String is expected "
|
||||
"to be enclosed in double quotation marks",szName);
|
||||
#endif
|
||||
this->LogWarning(szBuffer);
|
||||
return false;
|
||||
}
|
||||
|
@ -695,9 +723,15 @@ bool Parser::ParseString(std::string& out,const char* szName)
|
|||
if ('\"' == *sz)break;
|
||||
else if ('\0' == sz)
|
||||
{
|
||||
#if _MSC_VER >= 1400
|
||||
sprintf_s(szBuffer,"Unable to parse %s block: String is expected to be "
|
||||
"enclosed in double quotation marks but EOF was reached before a closing "
|
||||
"quotation mark was found",szName);
|
||||
#else
|
||||
sprintf(szBuffer,"Unable to parse %s block: String is expected to be "
|
||||
"enclosed in double quotation marks but EOF was reached before a closing "
|
||||
"quotation mark was found",szName);
|
||||
#endif
|
||||
this->LogWarning(szBuffer);
|
||||
return false;
|
||||
}
|
||||
|
@ -968,6 +1002,7 @@ void Parser::ParseLV2MeshBlock(ASE::Mesh& mesh)
|
|||
this->LogWarning("Found *MESH_ANIMATION element in ASE/ASK file. "
|
||||
"Keyframe animation is not supported by Assimp, this element "
|
||||
"will be ignored");
|
||||
//this->SkipSection();
|
||||
continue;
|
||||
}
|
||||
// mesh animation keyframe. Not supported
|
||||
|
@ -1538,6 +1573,7 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh)
|
|||
{
|
||||
BLUBB("Unable to parse *MESH_NORMALS Element: Unexpected EOL [#1]")
|
||||
}
|
||||
else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
|
||||
this->m_szFile++;
|
||||
}
|
||||
return;
|
||||
|
|
|
@ -41,9 +41,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
/** @file Implementation of the few default functions of the base importer class */
|
||||
#include "BaseImporter.h"
|
||||
#include "BaseProcess.h"
|
||||
|
||||
#include "../include/DefaultLogger.h"
|
||||
#include "../include/aiScene.h"
|
||||
#include "../include/aiAssert.h"
|
||||
#include "../include/assimp.hpp"
|
||||
using namespace Assimp;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -88,3 +91,28 @@ aiScene* BaseImporter::ReadFile( const std::string& pFile, IOSystem* pIOHandler)
|
|||
// return what we gathered from the import.
|
||||
return scene;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BaseProcess::ExecuteOnScene( Importer* pImp)
|
||||
{
|
||||
ai_assert(NULL != pImp && NULL != pImp->mScene);
|
||||
|
||||
// catch exceptions thrown inside the PostProcess-Step
|
||||
try
|
||||
{
|
||||
this->Execute(pImp->mScene);
|
||||
|
||||
} catch( ImportErrorException* exception)
|
||||
{
|
||||
// extract error description
|
||||
pImp->mErrorString = exception->GetErrorText();
|
||||
|
||||
DefaultLogger::get()->error(pImp->mErrorString);
|
||||
|
||||
delete exception;
|
||||
|
||||
// and kill the partially imported data
|
||||
delete pImp->mScene;
|
||||
pImp->mScene = NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,7 +78,16 @@ public:
|
|||
|
||||
// -------------------------------------------------------------------
|
||||
/** Executes the post processing step on the given imported data.
|
||||
* At the moment a process is not supposed to fail.
|
||||
* The function deletes the scene if the postprocess step fails (
|
||||
* the object pointer will be set to NULL).
|
||||
* @param pImp Importer instance (pImp->mScene must be valid)
|
||||
*/
|
||||
void ExecuteOnScene( Importer* pImp);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Executes the post processing step on the given imported data.
|
||||
* A process should throw an ImportErrorException* if it fails.
|
||||
* This method must be implemented by deriving classes.
|
||||
* @param pScene The imported data to work at.
|
||||
*/
|
||||
virtual void Execute( aiScene* pScene) = 0;
|
||||
|
|
|
@ -47,6 +47,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "../include/aiAssert.h"
|
||||
#include "../include/aiScene.h"
|
||||
#include "../include/aiPostProcess.h"
|
||||
#include "../include/DefaultLogger.h"
|
||||
|
||||
#include "BaseImporter.h"
|
||||
#include "BaseProcess.h"
|
||||
#include "DefaultIOStream.h"
|
||||
|
@ -90,7 +92,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "SplitLargeMeshes.h"
|
||||
#include "PretransformVertices.h"
|
||||
#include "LimitBoneWeightsProcess.h"
|
||||
#include "../include/DefaultLogger.h"
|
||||
#include "ValidateDataStructure.h"
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
|
@ -134,6 +136,7 @@ Importer::Importer() :
|
|||
#endif
|
||||
|
||||
// add an instance of each post processing step here in the order of sequence it is executed
|
||||
mPostProcessingSteps.push_back( new ValidateDSProcess());
|
||||
mPostProcessingSteps.push_back( new TriangulateProcess());
|
||||
mPostProcessingSteps.push_back( new PretransformVertices());
|
||||
mPostProcessingSteps.push_back( new SplitLargeMeshesProcess_Triangle());
|
||||
|
@ -237,10 +240,7 @@ const aiScene* Importer::ReadFile( const std::string& pFile, unsigned int pFlags
|
|||
|
||||
// dispatch the reading to the worker class for this format
|
||||
mScene = imp->ReadFile( pFile, mIOHandler);
|
||||
// if failed, extract the error string
|
||||
if( !mScene)
|
||||
mErrorString = imp->GetErrorText();
|
||||
|
||||
|
||||
// if successful, apply all active post processing steps to the imported data
|
||||
if( mScene)
|
||||
{
|
||||
|
@ -248,10 +248,19 @@ const aiScene* Importer::ReadFile( const std::string& pFile, unsigned int pFlags
|
|||
{
|
||||
BaseProcess* process = mPostProcessingSteps[a];
|
||||
if( process->IsActive( pFlags))
|
||||
process->Execute( mScene);
|
||||
{
|
||||
process->ExecuteOnScene( this );
|
||||
}
|
||||
if( !mScene)break; // error string has already been set ...
|
||||
}
|
||||
}
|
||||
|
||||
// if failed, extract the error string
|
||||
else if( !mScene)
|
||||
{
|
||||
mErrorString = imp->GetErrorText();
|
||||
}
|
||||
|
||||
// either successful or failure - the pointer expresses it anyways
|
||||
return mScene;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
/** @file Implementation of the MD3 importer class */
|
||||
#include "MD3Loader.h"
|
||||
#include "MaterialSystem.h"
|
||||
#include "StringComparison.h"
|
||||
|
||||
#include "../include/IOStream.h"
|
||||
#include "../include/IOSystem.h"
|
||||
|
|
|
@ -38,10 +38,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "../include/aiMaterial.h"
|
||||
#include "MaterialSystem.h"
|
||||
#include "StringComparison.h"
|
||||
|
||||
|
||||
#include "../include/aiMaterial.h"
|
||||
#include "../include/aiAssert.h"
|
||||
|
||||
using namespace Assimp;
|
||||
|
@ -363,6 +363,13 @@ void MaterialHelper::CopyPropertyList(MaterialHelper* pcDest,
|
|||
return;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// we need this dummy because the compiler would otherwise complain about
|
||||
// empty, but controlled statements ...
|
||||
void DummyAssertFunction()
|
||||
{
|
||||
ai_assert(false);
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
aiReturn aiGetMaterialTexture(const aiMaterial* pcMat,
|
||||
unsigned int iIndex,
|
||||
unsigned int iTexType,
|
||||
|
@ -460,7 +467,12 @@ aiReturn aiGetMaterialTexture(const aiMaterial* pcMat,
|
|||
char szKey[256];
|
||||
|
||||
// get the path to the texture
|
||||
sprintf(szKey,"%s[%i]",szPathBase,iIndex);
|
||||
#if _MSC_VER >= 1400
|
||||
if(0 >= sprintf_s(szKey,"%s[%i]",szPathBase,iIndex))DummyAssertFunction();
|
||||
#else
|
||||
if(0 >= sprintf(szKey,"%s[%i]",szPathBase,iIndex))DummyAssertFunction();
|
||||
#endif
|
||||
|
||||
if (AI_SUCCESS != aiGetMaterialString(pcMat,szKey,szOut))
|
||||
{
|
||||
return AI_FAILURE;
|
||||
|
@ -469,7 +481,11 @@ aiReturn aiGetMaterialTexture(const aiMaterial* pcMat,
|
|||
if (piUVIndex)
|
||||
{
|
||||
int iUV;
|
||||
sprintf(szKey,"%s[%i]",szUVBase,iIndex);
|
||||
#if _MSC_VER >= 1400
|
||||
if(0 >= sprintf_s(szKey,"%s[%i]",szUVBase,iIndex))DummyAssertFunction();
|
||||
#else
|
||||
if(0 >= sprintf(szKey,"%s[%i]",szUVBase,iIndex))DummyAssertFunction();
|
||||
#endif
|
||||
if (AI_SUCCESS != aiGetMaterialInteger(pcMat,szKey,&iUV))
|
||||
iUV = 0;
|
||||
|
||||
|
@ -479,7 +495,11 @@ aiReturn aiGetMaterialTexture(const aiMaterial* pcMat,
|
|||
if (pfBlendFactor)
|
||||
{
|
||||
float fBlend;
|
||||
sprintf(szKey,"%s[%i]",szBlendBase,iIndex);
|
||||
#if _MSC_VER >= 1400
|
||||
if(0 >= sprintf_s(szKey,"%s[%i]",szBlendBase,iIndex))DummyAssertFunction();
|
||||
#else
|
||||
if(0 >= sprintf(szKey,"%s[%i]",szBlendBase,iIndex))DummyAssertFunction();
|
||||
#endif
|
||||
if (AI_SUCCESS != aiGetMaterialFloat(pcMat,szKey,&fBlend))
|
||||
fBlend = 1.0f;
|
||||
|
||||
|
@ -490,7 +510,11 @@ aiReturn aiGetMaterialTexture(const aiMaterial* pcMat,
|
|||
if (peTextureOp)
|
||||
{
|
||||
aiTextureOp op;
|
||||
sprintf(szKey,"%s[%i]",szOpBase,iIndex);
|
||||
#if _MSC_VER >= 1400
|
||||
if(0 >= sprintf_s(szKey,"%s[%i]",szOpBase,iIndex))DummyAssertFunction();
|
||||
#else
|
||||
if(0 >= sprintf(szKey,"%s[%i]",szOpBase,iIndex))DummyAssertFunction();
|
||||
#endif
|
||||
if (AI_SUCCESS != aiGetMaterialInteger(pcMat,szKey,(int*)&op))
|
||||
op = aiTextureOp_Multiply;
|
||||
|
||||
|
@ -503,7 +527,11 @@ aiReturn aiGetMaterialTexture(const aiMaterial* pcMat,
|
|||
aiTextureMapMode eMode;
|
||||
for (unsigned int q = 0; q < 3;++q)
|
||||
{
|
||||
sprintf(szKey,"%s[%i]",aszMapModeBase[q],iIndex);
|
||||
#if _MSC_VER >= 1400
|
||||
if(0 >= sprintf_s(szKey,"%s[%i]",aszMapModeBase[q],iIndex))DummyAssertFunction();
|
||||
#else
|
||||
if(0 >= sprintf(szKey,"%s[%i]",aszMapModeBase[q],iIndex))DummyAssertFunction();
|
||||
#endif
|
||||
if (AI_SUCCESS != aiGetMaterialInteger(pcMat,szKey,(int*)&eMode))
|
||||
{
|
||||
eMode = aiTextureMapMode_Wrap;
|
||||
|
|
|
@ -47,83 +47,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
namespace Assimp
|
||||
{
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Helper function to do platform independent string comparison.
|
||||
*
|
||||
* This is required since stricmp() is not consistently available on
|
||||
* all platforms. Some platforms use the '_' prefix, others don't even
|
||||
* have such a function. Yes, this is called an ISO standard.
|
||||
*
|
||||
* \param s1 First input string
|
||||
* \param s2 Second input string
|
||||
*/
|
||||
// ---------------------------------------------------------------------------
|
||||
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;
|
||||
|
||||
while (true)
|
||||
{
|
||||
char c1 = (char)tolower(*a1);
|
||||
char c2 = (char)tolower(*a2);
|
||||
if ((0 == c1) && (0 == c2)) return 0;
|
||||
if (c1 < c2) return-1;
|
||||
if (c1 > c2) return 1;
|
||||
++a1;
|
||||
++a2;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Helper function to do platform independent string comparison.
|
||||
*
|
||||
* This is required since strincmp() is not consistently available on
|
||||
* all platforms. Some platforms use the '_' prefix, others don't even
|
||||
* have such a function. Yes, this is called an ISO standard.
|
||||
*
|
||||
* \param s1 First input string
|
||||
* \param s2 Second input string
|
||||
* \param n Macimum number of characters to compare
|
||||
*/
|
||||
// ---------------------------------------------------------------------------
|
||||
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;
|
||||
|
||||
unsigned int p = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (p >= n)return 0;
|
||||
|
||||
char c1 = (char)tolower(*a1);
|
||||
char c2 = (char)tolower(*a2);
|
||||
if ((0 == c1) && (0 == c2)) return 0;
|
||||
if (c1 < c2) return-1;
|
||||
if (c1 > c2) return 1;
|
||||
++a1;
|
||||
++a2;
|
||||
++p;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Internal material helper class. Can be used to fill an aiMaterial
|
||||
structure easily. */
|
||||
|
|
|
@ -42,6 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
/** @file Implementation of the PLY importer class */
|
||||
#include "PlyLoader.h"
|
||||
#include "MaterialSystem.h"
|
||||
#include "StringComparison.h"
|
||||
|
||||
#include "../include/IOStream.h"
|
||||
#include "../include/IOSystem.h"
|
||||
|
@ -1063,7 +1064,7 @@ void PLYImporter::LoadMaterial(std::vector<MaterialHelper*>* pvOut)
|
|||
|
||||
// if shininess is 0 (and the pow() calculation would therefore always
|
||||
// become 1, not depending on the angle) use gouraud lighting
|
||||
if (0.0f != fSpec)
|
||||
if (fSpec)
|
||||
{
|
||||
|
||||
// scale this with 15 ... hopefully this is correct
|
||||
|
|
|
@ -44,7 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "PlyLoader.h"
|
||||
#include "MaterialSystem.h"
|
||||
#include "fast_atof.h"
|
||||
#include "../include/DefaultLogger.h"
|
||||
#include "StringComparison.h"
|
||||
#include "ByteSwap.h"
|
||||
|
||||
#include "../include/IOStream.h"
|
||||
|
@ -52,6 +52,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/DefaultLogger.h"
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
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 platform independent string comparison functions */
|
||||
#ifndef AI_STRINGCOMPARISON_H_INC
|
||||
#define AI_STRINGCOMPARISON_H_INC
|
||||
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Helper function to do platform independent string comparison.
|
||||
*
|
||||
* This is required since stricmp() is not consistently available on
|
||||
* all platforms. Some platforms use the '_' prefix, others don't even
|
||||
* have such a function. Yes, this is called an ISO standard.
|
||||
*
|
||||
* \param s1 First input string
|
||||
* \param s2 Second input string
|
||||
*/
|
||||
// ---------------------------------------------------------------------------
|
||||
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;
|
||||
|
||||
while (true)
|
||||
{
|
||||
char c1 = (char)::tolower(*a1);
|
||||
char c2 = (char)::tolower(*a2);
|
||||
if ((0 == c1) && (0 == c2)) return 0;
|
||||
if (c1 < c2) return-1;
|
||||
if (c1 > c2) return 1;
|
||||
++a1;
|
||||
++a2;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Helper function to do platform independent string comparison.
|
||||
*
|
||||
* This is required since strincmp() is not consistently available on
|
||||
* all platforms. Some platforms use the '_' prefix, others don't even
|
||||
* have such a function. Yes, this is called an ISO standard.
|
||||
*
|
||||
* \param s1 First input string
|
||||
* \param s2 Second input string
|
||||
* \param n Macimum number of characters to compare
|
||||
*/
|
||||
// ---------------------------------------------------------------------------
|
||||
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;
|
||||
|
||||
unsigned int p = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (p >= n)return 0;
|
||||
|
||||
char c1 = (char)::tolower(*a1);
|
||||
char c2 = (char)::tolower(*a2);
|
||||
if ((0 == c1) && (0 == c2)) return 0;
|
||||
if (c1 < c2) return-1;
|
||||
if (c1 > c2) return 1;
|
||||
++a1;
|
||||
++a2;
|
||||
++p;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
#endif // ! AI_STRINGCOMPARISON_H_INC
|
|
@ -0,0 +1,689 @@
|
|||
/*
|
||||
---------------------------------------------------------------------------
|
||||
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 post processing step to validate
|
||||
* the data structure returned by Assimp
|
||||
*/
|
||||
#include <vector>
|
||||
#include <assert.h>
|
||||
|
||||
#include "ValidateDataStructure.h"
|
||||
#include "BaseImporter.h"
|
||||
#include "StringComparison.h"
|
||||
#include "fast_atof.h"
|
||||
|
||||
#include "../include/DefaultLogger.h"
|
||||
#include "../include/aiPostProcess.h"
|
||||
#include "../include/aiMesh.h"
|
||||
#include "../include/aiScene.h"
|
||||
#include "../include/aiAssert.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
ValidateDSProcess::ValidateDSProcess()
|
||||
{
|
||||
// nothing to do here
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Destructor, private as well
|
||||
ValidateDSProcess::~ValidateDSProcess()
|
||||
{
|
||||
// nothing to do here
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns whether the processing step is present in the given flag field.
|
||||
bool ValidateDSProcess::IsActive( unsigned int pFlags) const
|
||||
{
|
||||
return (pFlags & aiProcess_ValidateDataStructure) != 0;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ValidateDSProcess::ReportError(const char* msg,...)
|
||||
{
|
||||
ai_assert(NULL != msg);
|
||||
|
||||
va_list args;
|
||||
va_start(args,msg);
|
||||
|
||||
char szBuffer[3000];
|
||||
|
||||
int iLen;
|
||||
#if _MSC_VER >= 1400
|
||||
iLen = vsprintf_s(szBuffer,msg,args);
|
||||
#else
|
||||
iLen = vsprintf(szBuffer,msg,args);
|
||||
#endif
|
||||
|
||||
if (0 >= iLen)
|
||||
{
|
||||
// :-) should not happen ...
|
||||
throw new ImportErrorException("Idiot ... learn coding!");
|
||||
}
|
||||
va_end(args);
|
||||
throw new ImportErrorException("Validation failed: " + std::string(szBuffer,iLen));
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ValidateDSProcess::ReportWarning(const char* msg,...)
|
||||
{
|
||||
ai_assert(NULL != msg);
|
||||
|
||||
va_list args;
|
||||
va_start(args,msg);
|
||||
|
||||
char szBuffer[3000];
|
||||
|
||||
int iLen;
|
||||
#if _MSC_VER >= 1400
|
||||
iLen = vsprintf_s(szBuffer,msg,args);
|
||||
#else
|
||||
iLen = vsprintf(szBuffer,msg,args);
|
||||
#endif
|
||||
|
||||
if (0 >= iLen)
|
||||
{
|
||||
// :-) should not happen ...
|
||||
throw new ImportErrorException("Idiot ... learn coding!");
|
||||
}
|
||||
va_end(args);
|
||||
DefaultLogger::get()->warn("Validation failed: " + std::string(szBuffer,iLen));
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
void ValidateDSProcess::Execute( aiScene* pScene)
|
||||
{
|
||||
this->mScene = pScene;
|
||||
DefaultLogger::get()->debug("ValidateDataStructureProcess begin");
|
||||
|
||||
// validate all meshes
|
||||
if (pScene->mNumMeshes)
|
||||
{
|
||||
if (!pScene->mMeshes)
|
||||
{
|
||||
this->ReportError("aiScene::mMeshes is NULL (aiScene::mNumMeshes is %i)",
|
||||
pScene->mNumMeshes);
|
||||
}
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
||||
{
|
||||
if (!pScene->mMeshes[i])
|
||||
{
|
||||
this->ReportError("aiScene::mMeshes[%i] is NULL (aiScene::mNumMeshes is %i)",
|
||||
i,pScene->mNumMeshes);
|
||||
}
|
||||
this->Validate(pScene->mMeshes[i]);
|
||||
}
|
||||
}
|
||||
else this->ReportError("aiScene::mNumMeshes is 0. At least one mesh must be there");
|
||||
|
||||
// validate all animations
|
||||
if (pScene->mNumAnimations)
|
||||
{
|
||||
if (!pScene->mAnimations)
|
||||
{
|
||||
this->ReportError("aiScene::mAnimations is NULL (aiScene::mNumAnimations is %i)",
|
||||
pScene->mNumAnimations);
|
||||
}
|
||||
for (unsigned int i = 0; i < pScene->mNumAnimations;++i)
|
||||
{
|
||||
if (!pScene->mAnimations[i])
|
||||
{
|
||||
this->ReportError("aiScene::mAnimations[%i] is NULL (aiScene::mNumAnimations is %i)",
|
||||
i,pScene->mNumAnimations);
|
||||
}
|
||||
this->Validate(pScene->mAnimations[i]);
|
||||
|
||||
// check whether there are duplicate animation names
|
||||
for (unsigned int a = i+1; a < pScene->mNumAnimations;++a)
|
||||
{
|
||||
if (pScene->mAnimations[i]->mName == pScene->mAnimations[a]->mName)
|
||||
{
|
||||
this->ReportError("aiScene::mAnimations[%i] has the same name as "
|
||||
"aiScene::mAnimations[%i]",i,a);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// validate all textures
|
||||
if (pScene->mNumTextures)
|
||||
{
|
||||
if (!pScene->mTextures)
|
||||
{
|
||||
this->ReportError("aiScene::mTextures is NULL (aiScene::mNumTextures is %i)",
|
||||
pScene->mNumTextures);
|
||||
}
|
||||
for (unsigned int i = 0; i < pScene->mNumTextures;++i)
|
||||
{
|
||||
if (!pScene->mTextures[i])
|
||||
{
|
||||
this->ReportError("aiScene::mTextures[%i] is NULL (aiScene::mNumTextures is %i)",
|
||||
i,pScene->mNumTextures);
|
||||
}
|
||||
this->Validate(pScene->mTextures[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// validate all materials
|
||||
if (pScene->mNumMaterials)
|
||||
{
|
||||
if (!pScene->mMaterials)
|
||||
{
|
||||
this->ReportError("aiScene::mMaterials is NULL (aiScene::mNumMaterials is %i)",
|
||||
pScene->mNumMaterials);
|
||||
}
|
||||
for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
|
||||
{
|
||||
if (!pScene->mMaterials[i])
|
||||
{
|
||||
this->ReportError("aiScene::mMaterials[%i] is NULL (aiScene::mNumMaterials is %i)",
|
||||
i,pScene->mNumMaterials);
|
||||
}
|
||||
this->Validate(pScene->mMaterials[i]);
|
||||
}
|
||||
}
|
||||
else this->ReportError("aiScene::mNumMaterials is 0. At least one material must be there.");
|
||||
|
||||
// validate the node graph of the scene
|
||||
this->Validate(pScene->mRootNode);
|
||||
|
||||
DefaultLogger::get()->debug("ValidateDataStructureProcess end");
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ValidateDSProcess::Validate( const aiMesh* pMesh)
|
||||
{
|
||||
// validate the material index of the mesh
|
||||
if (pMesh->mMaterialIndex >= this->mScene->mNumMaterials)
|
||||
{
|
||||
this->ReportError("aiMesh::mMaterialIndex is invalid (value: %i maximum: %i)",
|
||||
pMesh->mMaterialIndex,this->mScene->mNumMaterials-1);
|
||||
}
|
||||
|
||||
// positions must always be there ...
|
||||
if (!pMesh->mNumVertices || !pMesh->mVertices)
|
||||
{
|
||||
this->ReportError("The mesh contains no vertices");
|
||||
}
|
||||
|
||||
// faces, too
|
||||
if (!pMesh->mNumFaces || !pMesh->mFaces)
|
||||
{
|
||||
this->ReportError("The mesh contains no faces");
|
||||
}
|
||||
|
||||
// now check whether the face indexing layout is correct:
|
||||
// unique vertices, pseudo-indexed.
|
||||
std::vector<bool> abRefList;
|
||||
abRefList.resize(pMesh->mNumVertices,false);
|
||||
for (unsigned int i = 0; i < pMesh->mNumFaces;++i)
|
||||
{
|
||||
aiFace& face = pMesh->mFaces[i];
|
||||
if (!face.mIndices)this->ReportError("aiMesh::mFaces[%i].mIndices is NULL",i);
|
||||
if (face.mNumIndices < 3)this->ReportError(
|
||||
"aiMesh::mFaces[%i].mIndices is not a triangle or polygon",i);
|
||||
|
||||
for (unsigned int a = 0; a < face.mNumIndices;++a)
|
||||
{
|
||||
if (face.mIndices[a] >= pMesh->mNumVertices)
|
||||
{
|
||||
this->ReportError("aiMesh::mFaces[%i]::mIndices[%a] is out of range",i,a);
|
||||
}
|
||||
if (abRefList[face.mIndices[a]])
|
||||
{
|
||||
this->ReportError("aiMesh::mVertices[%i] is referenced twice - second "
|
||||
"time by aiMesh::mFaces[%i]::mIndices[%i]",face.mIndices[a],i,a);
|
||||
}
|
||||
abRefList[face.mIndices[a]] = true;
|
||||
}
|
||||
}
|
||||
abRefList.clear();
|
||||
|
||||
// texture channel 2 may not be set if channel 1 is zero ...
|
||||
{
|
||||
unsigned int i = 0;
|
||||
for (;i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
|
||||
{
|
||||
if (!pMesh->HasTextureCoords(i))break;
|
||||
}
|
||||
for (;i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
|
||||
if (pMesh->HasTextureCoords(i))
|
||||
{
|
||||
this->ReportError("Texture coordinate channel %i is existing, "
|
||||
"although the previous channel was NULL.",i);
|
||||
}
|
||||
}
|
||||
// the same for the vertex colors
|
||||
{
|
||||
unsigned int i = 0;
|
||||
for (;i < AI_MAX_NUMBER_OF_COLOR_SETS;++i)
|
||||
{
|
||||
if (!pMesh->HasVertexColors(i))break;
|
||||
}
|
||||
for (;i < AI_MAX_NUMBER_OF_COLOR_SETS;++i)
|
||||
if (pMesh->HasVertexColors(i))
|
||||
{
|
||||
this->ReportError("Vertex color channel %i is existing, "
|
||||
"although the previous channel was NULL.",i);
|
||||
}
|
||||
}
|
||||
|
||||
// now validate all bones
|
||||
if (pMesh->HasBones())
|
||||
{
|
||||
if (!pMesh->mBones)
|
||||
{
|
||||
this->ReportError("aiMesh::mBones is NULL (aiMesh::mNumBones is %i)",
|
||||
pMesh->mNumBones);
|
||||
}
|
||||
|
||||
// check whether there are duplicate bone names
|
||||
for (unsigned int i = 0; i < pMesh->mNumBones;++i)
|
||||
{
|
||||
if (!pMesh->mBones[i])
|
||||
{
|
||||
this->ReportError("aiMesh::mBones[%i] is NULL (aiMesh::mNumBones is %i)",
|
||||
i,pMesh->mNumBones);
|
||||
}
|
||||
this->Validate(pMesh,pMesh->mBones[i]);
|
||||
|
||||
for (unsigned int a = i+1; a < pMesh->mNumBones;++a)
|
||||
{
|
||||
if (pMesh->mBones[i]->mName == pMesh->mBones[a]->mName)
|
||||
{
|
||||
this->ReportError("aiMesh::mBones[%i] has the same name as "
|
||||
"aiMesh::mBones[%i]",i,a);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ValidateDSProcess::Validate( const aiMesh* pMesh,
|
||||
const aiBone* pBone)
|
||||
{
|
||||
// check whether all vertices affected by this bone are valid
|
||||
for (unsigned int i = 0; i < pBone->mNumWeights;++i)
|
||||
{
|
||||
if (pBone->mWeights[i].mVertexId > pMesh->mNumVertices)
|
||||
{
|
||||
this->ReportError("aiBone::mWeights[%i].mVertexId is out of range",i);
|
||||
}
|
||||
else if (!pBone->mWeights[i].mWeight || pBone->mWeights[i].mWeight > 1.0f)
|
||||
{
|
||||
this->ReportWarning("aiBone::mWeights[%i].mWeight has an invalid value",i);
|
||||
}
|
||||
}
|
||||
// TODO: check whether all bone weights for a vertex sum to 1.0 ...
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ValidateDSProcess::Validate( const aiAnimation* pAnimation)
|
||||
{
|
||||
// validate all materials
|
||||
if (pAnimation->mNumBones)
|
||||
{
|
||||
if (!pAnimation->mBones)
|
||||
{
|
||||
this->ReportError("aiAnimation::mBones is NULL (aiAnimation::mNumBones is %i)",
|
||||
pAnimation->mBones);
|
||||
}
|
||||
for (unsigned int i = 0; i < pAnimation->mNumBones;++i)
|
||||
{
|
||||
if (!pAnimation->mBones[i])
|
||||
{
|
||||
this->ReportError("aiAnimation::mBones[%i] is NULL (aiAnimation::mNumBones is %i)",
|
||||
i,pAnimation->mNumBones);
|
||||
}
|
||||
this->Validate(pAnimation, pAnimation->mBones[i]);
|
||||
}
|
||||
}
|
||||
else this->ReportError("aiAnimation::mNumBones is 0. At least one bone animation channel must be there.");
|
||||
if (!pAnimation->mDuration)this->ReportError("aiAnimation::mDuration is zero");
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial* pMaterial,
|
||||
const char* szType)
|
||||
{
|
||||
ai_assert(NULL != szType);
|
||||
|
||||
// search all keys of the material ...
|
||||
// textures must be specified with rising indices (e.g. diffuse #2 may not be
|
||||
// specified if diffuse #1 is not there ...)
|
||||
|
||||
// "$tex.file.<szType>[<index>]"
|
||||
char szBaseBuf[512];
|
||||
int iLen;
|
||||
#if _MSC_VER >= 1400
|
||||
iLen = ::sprintf_s(szBaseBuf,"$tex.file.%s",szType);
|
||||
#else
|
||||
iLen = ::sprintf(szBaseBuf,"$tex.file.%s",szType);
|
||||
#endif
|
||||
if (0 >= iLen)return;
|
||||
|
||||
int iNumIndices = 0;
|
||||
int iIndex = -1;
|
||||
for (unsigned int i = 0; i < pMaterial->mNumProperties;++i)
|
||||
{
|
||||
aiMaterialProperty* prop = pMaterial->mProperties[i];
|
||||
if (0 == ASSIMP_strincmp( prop->mKey->data, szBaseBuf, iLen ))
|
||||
{
|
||||
const char* sz = &prop->mKey->data[iLen];
|
||||
if (*sz)
|
||||
{
|
||||
++sz;
|
||||
iIndex = std::max(iIndex, (int)strtol10(sz,NULL));
|
||||
++iNumIndices;
|
||||
}
|
||||
|
||||
if (aiPTI_String != prop->mType)
|
||||
this->ReportError("Material property %s is expected to be a string",prop->mKey);
|
||||
}
|
||||
}
|
||||
if (iIndex +1 != iNumIndices)
|
||||
{
|
||||
this->ReportError("%s #%i is set, but there are only %i %s textures",
|
||||
szType,iIndex,iNumIndices,szType);
|
||||
}
|
||||
|
||||
// now check whether all UV indices are valid ...
|
||||
#if _MSC_VER >= 1400
|
||||
iLen = ::sprintf_s(szBaseBuf,"$tex.uvw.%s",szType);
|
||||
#else
|
||||
iLen = ::sprintf(szBaseBuf,"$tex.uvw.%s",szType);
|
||||
#endif
|
||||
if (0 >= iLen)return;
|
||||
|
||||
for (unsigned int i = 0; i < pMaterial->mNumProperties;++i)
|
||||
{
|
||||
aiMaterialProperty* prop = pMaterial->mProperties[i];
|
||||
if (0 == ASSIMP_strincmp( prop->mKey->data, szBaseBuf, iLen ))
|
||||
{
|
||||
if (aiPTI_Integer != prop->mType || sizeof(int) > prop->mDataLength)
|
||||
this->ReportError("Material property %s is expected to be an integer",prop->mKey);
|
||||
|
||||
const char* sz = &prop->mKey->data[iLen];
|
||||
if (*sz)
|
||||
{
|
||||
++sz;
|
||||
iIndex = strtol10(sz,NULL);
|
||||
|
||||
// ignore UV indices for texture channel that are not there ...
|
||||
if (iIndex >= iNumIndices)
|
||||
{
|
||||
// get the value
|
||||
iIndex = *((unsigned int*)prop->mData);
|
||||
|
||||
// check whether there is a mesh using this material
|
||||
// which has not enough UV channels ...
|
||||
for (unsigned int a = 0; a < this->mScene->mNumMeshes;++a)
|
||||
{
|
||||
aiMesh* mesh = this->mScene->mMeshes[a];
|
||||
if(mesh->mMaterialIndex == iIndex)
|
||||
{
|
||||
int iChannels = 0;
|
||||
while (mesh->HasTextureCoords(iChannels++));
|
||||
if (iIndex >= iChannels)
|
||||
{
|
||||
this->ReportError("Invalid UV index: %i (key %s). Mesh %i has only %i UV channels",
|
||||
iIndex,prop->mKey,a,iChannels);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ValidateDSProcess::Validate( const aiMaterial* pMaterial)
|
||||
{
|
||||
// check whether there are material keys that are obviously not legal
|
||||
for (unsigned int i = 0; i < pMaterial->mNumProperties;++i)
|
||||
{
|
||||
aiMaterialProperty* prop = pMaterial->mProperties[i];
|
||||
if (!prop)
|
||||
{
|
||||
this->ReportError("aiMaterial::mProperties[%i] is NULL (aiMaterial::mNumProperties is %i)",
|
||||
i,pMaterial->mNumProperties);
|
||||
}
|
||||
if (!prop->mDataLength || !prop->mData)
|
||||
{
|
||||
this->ReportError("aiMaterial::mProperties[%i].mDataLength or "
|
||||
"aiMaterial::mProperties[%i].mData is 0",i,i);
|
||||
}
|
||||
// TODO: check whether there is a key with an unknown name ...
|
||||
}
|
||||
|
||||
float fTemp;
|
||||
int iShading;
|
||||
if (AI_SUCCESS == aiGetMaterialInteger( pMaterial,AI_MATKEY_SHADING_MODEL,&iShading))
|
||||
{
|
||||
switch ((aiShadingMode)iShading)
|
||||
{
|
||||
case aiShadingMode_Blinn:
|
||||
case aiShadingMode_CookTorrance:
|
||||
case aiShadingMode_Phong:
|
||||
|
||||
if (AI_SUCCESS != aiGetMaterialFloat(pMaterial,AI_MATKEY_SHININESS,&fTemp))
|
||||
{
|
||||
this->ReportWarning("A specular shading model is specified but there is no "
|
||||
"AI_MATKEY_SHININESS key");
|
||||
}
|
||||
if (AI_SUCCESS == aiGetMaterialFloat(pMaterial,AI_MATKEY_SHININESS_STRENGTH,&fTemp) && !fTemp)
|
||||
{
|
||||
this->ReportWarning("A specular shading model is specified but the value of the "
|
||||
"AI_MATKEY_SHININESS_STRENGTH key is 0.0");
|
||||
}
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// check whether there are invalid texture keys
|
||||
SearchForInvalidTextures(pMaterial,"diffuse");
|
||||
SearchForInvalidTextures(pMaterial,"specular");
|
||||
SearchForInvalidTextures(pMaterial,"ambient");
|
||||
SearchForInvalidTextures(pMaterial,"emissive");
|
||||
SearchForInvalidTextures(pMaterial,"opacity");
|
||||
SearchForInvalidTextures(pMaterial,"shininess");
|
||||
SearchForInvalidTextures(pMaterial,"normals");
|
||||
SearchForInvalidTextures(pMaterial,"height");
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ValidateDSProcess::Validate( const aiTexture* pTexture)
|
||||
{
|
||||
// the data section may NEVER be NULL
|
||||
if (!pTexture->pcData)
|
||||
{
|
||||
this->ReportError("aiTexture::pcData is NULL");
|
||||
}
|
||||
if (pTexture->mHeight)
|
||||
{
|
||||
if (!pTexture->mWidth)this->ReportError("aiTexture::mWidth is zero "
|
||||
"(aiTexture::mHeight is %i, uncompressed texture)",pTexture->mHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!pTexture->mWidth)this->ReportError("aiTexture::mWidth is zero (compressed texture)");
|
||||
if ('.' == pTexture->achFormatHint[0])
|
||||
{
|
||||
char szTemp[5];
|
||||
szTemp[0] = pTexture->achFormatHint[0];
|
||||
szTemp[1] = pTexture->achFormatHint[1];
|
||||
szTemp[2] = pTexture->achFormatHint[2];
|
||||
szTemp[3] = pTexture->achFormatHint[3];
|
||||
szTemp[4] = '\0';
|
||||
|
||||
this->ReportWarning("aiTexture::achFormatHint should contain a file extension "
|
||||
"without a leading dot (format hint: %s).",szTemp);
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ValidateDSProcess::Validate( const aiAnimation* pAnimation,
|
||||
const aiBoneAnim* pBoneAnim)
|
||||
{
|
||||
// check whether there is a bone with this name ...
|
||||
unsigned int i = 0;
|
||||
for (; i < this->mScene->mNumMeshes;++i)
|
||||
{
|
||||
aiMesh* mesh = this->mScene->mMeshes[i];
|
||||
for (unsigned int a = 0; a < mesh->mNumBones;++a)
|
||||
{
|
||||
if (mesh->mBones[a]->mName == pBoneAnim->mBoneName)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == this->mScene->mNumMeshes)
|
||||
{
|
||||
this->ReportWarning("aiBoneAnim::mBoneName is %s. However, no bone with this name was found",
|
||||
pBoneAnim->mBoneName.data);
|
||||
}
|
||||
if (!pBoneAnim->mNumPositionKeys && !pBoneAnim->mNumRotationKeys && !pBoneAnim->mNumScalingKeys)
|
||||
{
|
||||
this->ReportWarning("A bone animation channel has no keys");
|
||||
}
|
||||
|
||||
// otherwise check whether one of the keys exceeds the total duration of the animation
|
||||
if (pBoneAnim->mNumPositionKeys)
|
||||
{
|
||||
if (!pBoneAnim->mPositionKeys)
|
||||
{
|
||||
this->ReportError("aiBoneAnim::mPositionKeys is NULL (aiBoneAnim::mNumPositionKeys is %i)",
|
||||
pBoneAnim->mNumPositionKeys);
|
||||
}
|
||||
for (unsigned int i = 0; i < pBoneAnim->mNumPositionKeys;++i)
|
||||
{
|
||||
if (pBoneAnim->mPositionKeys[i].mTime > pAnimation->mDuration)
|
||||
{
|
||||
this->ReportError("aiBoneAnim::mPositionKeys[%i].mTime (%.5f) is larger "
|
||||
"than aiAnimation::mDuration (which is %.5f)",i,
|
||||
(float)pBoneAnim->mPositionKeys[i].mTime,
|
||||
(float)pAnimation->mDuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
// rotation keys
|
||||
if (pBoneAnim->mNumRotationKeys)
|
||||
{
|
||||
if (!pBoneAnim->mRotationKeys)
|
||||
{
|
||||
this->ReportError("aiBoneAnim::mRotationKeys is NULL (aiBoneAnim::mNumRotationKeys is %i)",
|
||||
pBoneAnim->mNumRotationKeys);
|
||||
}
|
||||
for (unsigned int i = 0; i < pBoneAnim->mNumRotationKeys;++i)
|
||||
{
|
||||
if (pBoneAnim->mRotationKeys[i].mTime > pAnimation->mDuration)
|
||||
{
|
||||
this->ReportError("aiBoneAnim::mRotationKeys[%i].mTime (%.5f) is larger "
|
||||
"than aiAnimation::mDuration (which is %.5f)",i,
|
||||
(float)pBoneAnim->mRotationKeys[i].mTime,
|
||||
(float)pAnimation->mDuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
// scaling keys
|
||||
if (pBoneAnim->mNumScalingKeys)
|
||||
{
|
||||
if (!pBoneAnim->mScalingKeys)
|
||||
{
|
||||
this->ReportError("aiBoneAnim::mScalingKeys is NULL (aiBoneAnim::mNumScalingKeys is %i)",
|
||||
pBoneAnim->mNumScalingKeys);
|
||||
}
|
||||
for (unsigned int i = 0; i < pBoneAnim->mNumScalingKeys;++i)
|
||||
{
|
||||
if (pBoneAnim->mScalingKeys[i].mTime > pAnimation->mDuration)
|
||||
{
|
||||
this->ReportError("aiBoneAnim::mScalingKeys[%i].mTime (%.5f) is larger "
|
||||
"than aiAnimation::mDuration (which is %.5f)",i,
|
||||
(float)pBoneAnim->mScalingKeys[i].mTime,
|
||||
(float)pAnimation->mDuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ValidateDSProcess::Validate( const aiNode* pNode)
|
||||
{
|
||||
if (!pNode)this->ReportError("A node of the scenegraph is NULL");
|
||||
if (pNode != this->mScene->mRootNode && !pNode->mParent)
|
||||
this->ReportError("A node has no valid parent (aiNode::mParent is NULL)");
|
||||
|
||||
// validate all meshes
|
||||
if (pNode->mNumMeshes)
|
||||
{
|
||||
if (!pNode->mMeshes)
|
||||
{
|
||||
this->ReportError("aiNode::mMeshes is NULL (aiNode::mNumMeshes is %i)",
|
||||
pNode->mNumMeshes);
|
||||
}
|
||||
std::vector<bool> abHadMesh;
|
||||
abHadMesh.resize(this->mScene->mNumMeshes,false);
|
||||
for (unsigned int i = 0; i < pNode->mNumMeshes;++i)
|
||||
{
|
||||
if (pNode->mMeshes[i] >= this->mScene->mNumMeshes)
|
||||
{
|
||||
this->ReportError("aiNode::mMeshes[%i] is out of range (maximum is %i)",
|
||||
pNode->mMeshes[i],this->mScene->mNumMeshes-1);
|
||||
}
|
||||
if (abHadMesh[pNode->mMeshes[i]])
|
||||
{
|
||||
this->ReportError("aiNode::mMeshes[%i] is already referenced by this node (value: %i)",
|
||||
i,pNode->mMeshes[i]);
|
||||
}
|
||||
abHadMesh[pNode->mMeshes[i]] = true;
|
||||
}
|
||||
}
|
||||
if (pNode->mNumChildren)
|
||||
{
|
||||
if (!pNode->mChildren)
|
||||
{
|
||||
this->ReportError("aiNode::mChildren is NULL (aiNode::mNumChildren is %i)",
|
||||
pNode->mNumChildren);
|
||||
}
|
||||
for (unsigned int i = 0; i < pNode->mNumChildren;++i)
|
||||
{
|
||||
this->Validate(pNode->mChildren[i]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
Open Asset Import Library (ASSIMP)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2008, ASSIMP Development Team
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the ASSIMP team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the ASSIMP Development Team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file Defines a post processing step to validate the loader's
|
||||
* output data structure (for debugging)
|
||||
*/
|
||||
#ifndef AI_VALIDATEPROCESS_H_INC
|
||||
#define AI_VALIDATEPROCESS_H_INC
|
||||
|
||||
#include "BaseProcess.h"
|
||||
|
||||
struct aiBone;
|
||||
struct aiMesh;
|
||||
struct aiAnimation;
|
||||
struct aiBoneAnim;
|
||||
struct aiTexture;
|
||||
struct aiMaterial;
|
||||
struct aiNode;
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Validates the ASSIMP data structure
|
||||
*/
|
||||
class ValidateDSProcess : public BaseProcess
|
||||
{
|
||||
friend class Importer;
|
||||
|
||||
protected:
|
||||
/** Constructor to be privately used by Importer */
|
||||
ValidateDSProcess();
|
||||
|
||||
/** Destructor, private as well */
|
||||
~ValidateDSProcess();
|
||||
|
||||
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.
|
||||
* A process should throw an ImportErrorException* if it fails.
|
||||
* @param pScene The imported data to work at.
|
||||
*/
|
||||
void Execute( aiScene* pScene);
|
||||
|
||||
protected:
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Report a validation error. This will throw an exception,
|
||||
* control won't return.
|
||||
* @param msg Format string for sprintf().
|
||||
*/
|
||||
void ReportError(const char* msg,...);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Report a validation warning. This won't throw an exception,
|
||||
* control will return to the callera.
|
||||
* @param msg Format string for sprintf().
|
||||
*/
|
||||
void ReportWarning(const char* msg,...);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Validates a mesh
|
||||
* @param pMesh Input mesh
|
||||
*/
|
||||
void Validate( const aiMesh* pMesh);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Validates a bone
|
||||
* @param pMesh Input mesh
|
||||
* @param pBone Input bone
|
||||
*/
|
||||
void Validate( const aiMesh* pMesh,const aiBone* pBone);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Validates an animation
|
||||
* @param pAnimation Input animation
|
||||
*/
|
||||
void Validate( const aiAnimation* pAnimation);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Validates a material
|
||||
* @param pMaterial Input material
|
||||
*/
|
||||
void Validate( const aiMaterial* pMaterial);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Search the material data structure for invalid or corrupt
|
||||
* texture keys.
|
||||
* @param pMaterial Input material
|
||||
* @param szType Type of the texture (the purpose string that
|
||||
* occurs in material keys, e.g. "diffuse", "ambient")
|
||||
*/
|
||||
void SearchForInvalidTextures(const aiMaterial* pMaterial,
|
||||
const char* szType);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Validates a texture
|
||||
* @param pTexture Input texture
|
||||
*/
|
||||
void Validate( const aiTexture* pTexture);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Validates a bone animation channel
|
||||
* @param pAnimation Input animation
|
||||
* @param pBoneAnim Input bone animation
|
||||
*/
|
||||
void Validate( const aiAnimation* pAnimation,
|
||||
const aiBoneAnim* pBoneAnim);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Validates a node and all of its subnodes
|
||||
* @param Node Input node
|
||||
*/
|
||||
void Validate( const aiNode* pNode);
|
||||
|
||||
private:
|
||||
|
||||
aiScene* mScene;
|
||||
};
|
||||
|
||||
} // end of namespace Assimp
|
||||
|
||||
#endif // AI_VALIDATEPROCESS_H_INC
|
|
@ -208,27 +208,29 @@ struct aiMaterialProperty
|
|||
{
|
||||
/** Specifies the name of the property (key)
|
||||
*
|
||||
* Keys are case insensitive.
|
||||
* Keys are case insensitive.
|
||||
*/
|
||||
C_STRUCT aiString* mKey;
|
||||
|
||||
/** Size of the buffer mData is pointing to, in bytes
|
||||
* This value may not be 0.
|
||||
*/
|
||||
unsigned int mDataLength;
|
||||
|
||||
/** Type information for the property.
|
||||
*
|
||||
* Defines the data layout inside the
|
||||
* data buffer. This is used by the library
|
||||
* internally to perform debug checks.
|
||||
* Defines the data layout inside the
|
||||
* data buffer. This is used by the library
|
||||
* internally to perform debug checks.
|
||||
*/
|
||||
aiPropertyTypeInfo mType;
|
||||
|
||||
/** Binary buffer to hold the property's value
|
||||
*
|
||||
* The buffer has no terminal character. However,
|
||||
* if a string is stored inside it may use 0 as terminal,
|
||||
* but it would be contained in mDataLength.
|
||||
* The buffer has no terminal character. However,
|
||||
* if a string is stored inside it may use 0 as terminal,
|
||||
* but it would be contained in mDataLength. This member
|
||||
* is never 0
|
||||
*/
|
||||
char* mData;
|
||||
};
|
||||
|
@ -239,8 +241,8 @@ struct aiMaterialProperty
|
|||
*
|
||||
* Material data is stored using a key-value structure, called property
|
||||
* (to guarant that the system is maximally flexible).
|
||||
* The library defines a set of standard keys, which should be enough
|
||||
* for nearly all purposes.
|
||||
* The library defines a set of standard keys (AI_MATKEY) which should be
|
||||
* enough for nearly all purposes.
|
||||
*/
|
||||
// ---------------------------------------------------------------------------
|
||||
struct aiMaterial
|
||||
|
@ -261,6 +263,54 @@ public:
|
|||
unsigned int mNumAllocated;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** @def AI_BUILD_KEY
|
||||
* Builds a material texture key with a dynamic index.
|
||||
* Applications <b>could</b> do this (C-example):
|
||||
* @code
|
||||
* int i;
|
||||
* struct aiMaterial* pMat = ....
|
||||
* for (i = 0;true;++i) {
|
||||
* if (AI_SUCCESS != aiGetMaterialFloat(pMat,AI_MATKEY_TEXTURE_DIFFUSE(i),...)) {
|
||||
* ...
|
||||
* }
|
||||
* }
|
||||
* @endcode
|
||||
* However, this is wrong because AI_MATKEY_TEXTURE_DIFFUSE() builds the key
|
||||
* string at <b>compile time</b>. <br>
|
||||
* Therefore, the dynamic indexing results in a
|
||||
* material key like this : "$tex.file.diffuse[i]" - and it is not very
|
||||
* propable that there is a key with this name ... (except the programmer
|
||||
* of an ASSIMP loader has made the same mistake :-) ).<br>
|
||||
* This is the right way:
|
||||
* @code
|
||||
* int i;
|
||||
* char szBuffer[512];
|
||||
* struct aiMaterial* pMat = ....
|
||||
* for (i = 0;true;++i) {
|
||||
* AI_BUILD_KEY(AI_MATKEY_TEXTURE_DIFFUSE_,i,szBuffer);
|
||||
* if (AI_SUCCESS != aiGetMaterialFloat(pMat,szBuffer,...)) {
|
||||
* ...
|
||||
* }
|
||||
* }
|
||||
* @endcode
|
||||
* @param base Base material key. This is the same key you'd have used
|
||||
* normally with an underscore as suffix (e.g. AI_MATKEY_TEXTURE_DIFFUSE_)
|
||||
* @param index Index to be used. Here you may pass a variable!
|
||||
* @param out Array of chars to receive the output value. It must be
|
||||
* sufficiently large. This will be checked via a static assertion for
|
||||
* C++0x. For MSVC8 and later versions the security enhanced version of
|
||||
* sprintf() will be used. However, if your buffer is at least 512 bytes
|
||||
* long you'll never overrun.
|
||||
*/
|
||||
#if _MSC_VER >= 1400
|
||||
# define AI_BUILD_KEY(base,index,out) \
|
||||
::sprintf_s(out,"%s[%i]",base,index);
|
||||
#else
|
||||
# define AI_BUILD_KEY(base,index,out) \
|
||||
::sprintf(out,"%s[%i]",base,index);
|
||||
#endif
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** @def AI_MATKEY_NAME
|
||||
|
@ -370,6 +420,10 @@ public:
|
|||
* <br>
|
||||
* <b>Type:</b> string (aiString)<br>
|
||||
* <b>Default value:</b> none <br>
|
||||
* @note The key string is built at compile time, therefore it is not
|
||||
* posible to use this macro in a loop with varying values for N.
|
||||
* However, you can use the macro suffixed with '_' to build the key
|
||||
* dynamically. The AI_BUILD_KEY()-macro can be used to do this.
|
||||
*/
|
||||
#define AI_MATKEY_TEXTURE_DIFFUSE(N) "$tex.file.diffuse["#N"]"
|
||||
#define AI_MATKEY_TEXTURE_DIFFUSE_ "$tex.file.diffuse"
|
||||
|
@ -379,6 +433,10 @@ public:
|
|||
* <br>
|
||||
* <b>Type:</b> string (aiString)<br>
|
||||
* <b>Default value:</b> none <br>
|
||||
* @note The key string is built at compile time, therefore it is not
|
||||
* posible to use this macro in a loop with varying values for N.
|
||||
* However, you can use the macro suffixed with '_' to build the key
|
||||
* dynamically. The AI_BUILD_KEY()-macro can be used to do this.
|
||||
*/
|
||||
#define AI_MATKEY_TEXTURE_AMBIENT(N) "$tex.file.ambient["#N"]"
|
||||
#define AI_MATKEY_TEXTURE_AMBIENT_ "$tex.file.ambient"
|
||||
|
@ -388,6 +446,10 @@ public:
|
|||
* <br>
|
||||
* <b>Type:</b> string (aiString)<br>
|
||||
* <b>Default value:</b> none <br>
|
||||
* @note The key string is built at compile time, therefore it is not
|
||||
* posible to use this macro in a loop with varying values for N.
|
||||
* However, you can use the macro suffixed with '_' to build the key
|
||||
* dynamically. The AI_BUILD_KEY()-macro can be used to do this.
|
||||
*/
|
||||
#define AI_MATKEY_TEXTURE_SPECULAR(N) "$tex.file.specular["#N"]"
|
||||
#define AI_MATKEY_TEXTURE_SPECULAR_ "$tex.file.specular"
|
||||
|
@ -397,6 +459,10 @@ public:
|
|||
* <br>
|
||||
* <b>Type:</b> string (aiString)<br>
|
||||
* <b>Default value:</b> none <br>
|
||||
* @note The key string is built at compile time, therefore it is not
|
||||
* posible to use this macro in a loop with varying values for N.
|
||||
* However, you can use the macro suffixed with '_' to build the key
|
||||
* dynamically. The AI_BUILD_KEY()-macro can be used to do this.
|
||||
*/
|
||||
#define AI_MATKEY_TEXTURE_EMISSIVE(N) "$tex.file.emissive["#N"]"
|
||||
#define AI_MATKEY_TEXTURE_EMISSIVE_ "$tex.file.emissive"
|
||||
|
@ -406,6 +472,10 @@ public:
|
|||
* <br>
|
||||
* <b>Type:</b> string (aiString)<br>
|
||||
* <b>Default value:</b> none <br>
|
||||
* @note The key string is built at compile time, therefore it is not
|
||||
* posible to use this macro in a loop with varying values for N.
|
||||
* However, you can use the macro suffixed with '_' to build the key
|
||||
* dynamically. The AI_BUILD_KEY()-macro can be used to do this.
|
||||
*/
|
||||
#define AI_MATKEY_TEXTURE_NORMALS(N) "$tex.file.normals["#N"]"
|
||||
#define AI_MATKEY_TEXTURE_NORMALS_ "$tex.file.normals"
|
||||
|
@ -419,15 +489,23 @@ public:
|
|||
* <br>
|
||||
* <b>Type:</b> string (aiString)<br>
|
||||
* <b>Default value:</b> none <br>
|
||||
* @note The key string is built at compile time, therefore it is not
|
||||
* posible to use this macro in a loop with varying values for N.
|
||||
* However, you can use the macro suffixed with '_' to build the key
|
||||
* dynamically. The AI_BUILD_KEY()-macro can be used to do this.
|
||||
*/
|
||||
#define AI_MATKEY_TEXTURE_HEIGHT(N) "$tex.file.bump["#N"]"
|
||||
#define AI_MATKEY_TEXTURE_HEIGHT_ "$tex.file.bump"
|
||||
#define AI_MATKEY_TEXTURE_HEIGHT(N) "$tex.file.height["#N"]"
|
||||
#define AI_MATKEY_TEXTURE_HEIGHT_ "$tex.file.height"
|
||||
|
||||
/** @def AI_MATKEY_TEXTURE_SHININESS
|
||||
* Defines a specified shininess texture channel of the material
|
||||
* <br>
|
||||
* <b>Type:</b> string (aiString)<br>
|
||||
* <b>Default value:</b> none <br>
|
||||
* @note The key string is built at compile time, therefore it is not
|
||||
* posible to use this macro in a loop with varying values for N.
|
||||
* However, you can use the macro suffixed with '_' to build the key
|
||||
* dynamically. The AI_BUILD_KEY()-macro can be used to do this.
|
||||
*/
|
||||
#define AI_MATKEY_TEXTURE_SHININESS(N) "$tex.file.shininess["#N"]"
|
||||
#define AI_MATKEY_TEXTURE_SHININESS_ "$tex.file.shininess"
|
||||
|
@ -437,10 +515,15 @@ public:
|
|||
* <br>
|
||||
* <b>Type:</b> string (aiString)<br>
|
||||
* <b>Default value:</b> none <br>
|
||||
* @note The key string is built at compile time, therefore it is not
|
||||
* posible to use this macro in a loop with varying values for N.
|
||||
* However, you can use the macro suffixed with '_' to build the key
|
||||
* dynamically. The AI_BUILD_KEY()-macro can be used to do this.
|
||||
*/
|
||||
#define AI_MATKEY_TEXTURE_OPACITY(N) "$tex.file.opacity["#N"]"
|
||||
#define AI_MATKEY_TEXTURE_OPACITY_ "$tex.file.opacity"
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** @def AI_MATKEY_TEXOP_DIFFUSE
|
||||
* Specifies the blend operation too be used to combine the Nth
|
||||
|
@ -450,8 +533,10 @@ public:
|
|||
* <b>Type:</b> int (aiTextureOp)<br>
|
||||
* <b>Default value:</b> 0<br>
|
||||
* <b>Requires:</b> AI_MATKEY_TEXTURE_DIFFUSE(0)<br>
|
||||
* @note Never use an non-numeric index (like a variable) for this.
|
||||
* Remember, the key string is built by the preprocessor
|
||||
* @note The key string is built at compile time, therefore it is not posible
|
||||
* to use this macro in a loop with varying values for N. However, you can
|
||||
* use the macro suffixed with '_' to build the key dynamically. The
|
||||
* AI_BUILD_KEY()-macro can be used to do this.
|
||||
*/
|
||||
#define AI_MATKEY_TEXOP_DIFFUSE(N) "$tex.op.diffuse["#N"]"
|
||||
/** @see AI_MATKEY_TEXOP_DIFFUSE */
|
||||
|
@ -485,8 +570,10 @@ public:
|
|||
* <b>Type:</b> int<br>
|
||||
* <b>Default value:</b> 0<br>
|
||||
* <b>Requires:</b> AI_MATKEY_TEXTURE_DIFFUSE(0)<br>
|
||||
* @note Never use an non-numeric index (like a variable) for this.
|
||||
* Remember, the key string is built by the preprocessor
|
||||
* @note The key string is built at compile time, therefore it is not posible
|
||||
* to use this macro in a loop with varying values for N. However, you can
|
||||
* use the macro suffixed with '_' to build the key dynamically. The
|
||||
* AI_BUILD_KEY()-macro can be used to do this.
|
||||
*/
|
||||
#define AI_MATKEY_UVWSRC_DIFFUSE(N) "$tex.uvw.diffuse["#N"]"
|
||||
/** @see AI_MATKEY_UVWSRC_DIFFUSE */
|
||||
|
@ -520,8 +607,10 @@ public:
|
|||
* <b>Type:</b> float<br>
|
||||
* <b>Default value:</b> 1.0f<br>
|
||||
* <b>Requires:</b> AI_MATKEY_TEXTURE_DIFFUSE(0)<br>
|
||||
* @note Never use an non-numeric index (like a variable) for this.
|
||||
* Remember, the key string is built by the preprocessor
|
||||
* @note The key string is built at compile time, therefore it is not posible
|
||||
* to use this macro in a loop with varying values for N. However, you can
|
||||
* use the macro suffixed with '_' to build the key dynamically. The
|
||||
* AI_BUILD_KEY()-macro can be used to do this.
|
||||
*/
|
||||
#define AI_MATKEY_TEXBLEND_DIFFUSE(N) "$tex.blend.diffuse["#N"]"
|
||||
/** @see AI_MATKEY_TEXBLEND_DIFFUSE */
|
||||
|
@ -556,8 +645,10 @@ public:
|
|||
* <b>Type:</b> int (aiTextureMapMode)<br>
|
||||
* <b>Default value:</b> aiTextureMapMode_Wrap<br>
|
||||
* <b>Requires:</b> AI_MATKEY_TEXTURE_DIFFUSE(0)<br>
|
||||
* @note Never use an non-numeric index (like a variable) for this.
|
||||
* Remember, the key string is built by the preprocessor
|
||||
* @note The key string is built at compile time, therefore it is not posible
|
||||
* to use this macro in a loop with varying values for N. However, you can
|
||||
* use the macro suffixed with '_' to build the key dynamically. The
|
||||
* AI_BUILD_KEY()-macro can be used to do this.
|
||||
*/
|
||||
#define AI_MATKEY_MAPPINGMODE_U_DIFFUSE(N) "$tex.mapmodeu.diffuse["#N"]"
|
||||
/** @see AI_MATKEY_MAPPINGMODE_U_DIFFUSE */
|
||||
|
@ -592,8 +683,10 @@ public:
|
|||
* <b>Type:</b> int (aiTextureMapMode)<br>
|
||||
* <b>Default value:</b> aiTextureMapMode_Wrap<br>
|
||||
* <b>Requires:</b> AI_MATKEY_TEXTURE_DIFFUSE(0)<br>
|
||||
* @note Never use an non-numeric index (like a variable) for this.
|
||||
* Remember, the key string is built by the preprocessor
|
||||
* @note The key string is built at compile time, therefore it is not posible
|
||||
* to use this macro in a loop with varying values for N. However, you can
|
||||
* use the macro suffixed with '_' to build the key dynamically. The
|
||||
* AI_BUILD_KEY()-macro can be used to do this.
|
||||
*/
|
||||
#define AI_MATKEY_MAPPINGMODE_V_DIFFUSE(N) "$tex.mapmodev.diffuse["#N"]"
|
||||
/** @see AI_MATKEY_MAPPINGMODE_V_DIFFUSE */
|
||||
|
@ -628,8 +721,10 @@ public:
|
|||
* <b>Type:</b> int (aiTextureMapMode)<br>
|
||||
* <b>Default value:</b> aiTextureMapMode_Wrap<br>
|
||||
* <b>Requires:</b> AI_MATKEY_TEXTURE_DIFFUSE(0)<br>
|
||||
* @note Never use an non-numeric index (like a variable) for this.
|
||||
* Remember, the key string is built by the preprocessor
|
||||
* @note The key string is built at compile time, therefore it is not posible
|
||||
* to use this macro in a loop with varying values for N. However, you can
|
||||
* use the macro suffixed with '_' to build the key dynamically. The
|
||||
* AI_BUILD_KEY()-macro can be used to do this.
|
||||
*/
|
||||
#define AI_MATKEY_MAPPINGMODE_W_DIFFUSE(N) "$tex.mapmodew.diffuse["#N"]"
|
||||
/** @see AI_MATKEY_MAPPINGMODE_W_DIFFUSE */
|
||||
|
|
|
@ -395,7 +395,7 @@ struct aiMesh
|
|||
|
||||
//! Check whether the mesh contains a vertex color set
|
||||
//! \param pIndex Index of the vertex color set
|
||||
inline bool HasVertexColors( unsigned int pIndex)
|
||||
inline bool HasVertexColors( unsigned int pIndex) const
|
||||
{
|
||||
if( pIndex >= AI_MAX_NUMBER_OF_COLOR_SETS)
|
||||
return false;
|
||||
|
@ -405,7 +405,7 @@ struct aiMesh
|
|||
|
||||
//! Check whether the mesh contains a texture coordinate set
|
||||
//! \param pIndex Index of the texture coordinates set
|
||||
inline bool HasTextureCoords( unsigned int pIndex)
|
||||
inline bool HasTextureCoords( unsigned int pIndex) const
|
||||
{
|
||||
if( pIndex > AI_MAX_NUMBER_OF_TEXTURECOORDS)
|
||||
return false;
|
||||
|
|
|
@ -135,7 +135,16 @@ enum aiPostProcessSteps
|
|||
* If you intend to perform the skinning in hardware, this post processing step
|
||||
* might be of interest for you.
|
||||
*/
|
||||
aiProcess_LimitBoneWeights = 0x200
|
||||
aiProcess_LimitBoneWeights = 0x200,
|
||||
|
||||
/** Validates the aiScene data structure before it is returned.
|
||||
* This makes sure that all indices are valid, all animations and
|
||||
* bones are linked correctly, all material are correct and so on ...
|
||||
* This is primarily intended for our internal debugging stuff,
|
||||
* however, it could be of interest for applications like editors
|
||||
* where stability is more important than loading performance.
|
||||
*/
|
||||
aiProcess_ValidateDataStructure = 0x400
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
@ -83,6 +83,9 @@ class IOSystem;
|
|||
*/
|
||||
class Importer
|
||||
{
|
||||
// used internally
|
||||
friend class BaseProcess;
|
||||
|
||||
public:
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
|
|
@ -384,7 +384,7 @@ int CDisplay::ReplaceCurrentTexture(const char* szPath)
|
|||
pcMat->AddProperty(&szOld,szBuffer );
|
||||
}
|
||||
else if (szString.length == szOld.length &&
|
||||
0 == Assimp::ASSIMP_stricmp(szString.data,szOld.data))
|
||||
0 == ASSIMP_stricmp(szString.data,szOld.data))
|
||||
{
|
||||
pcMat->RemoveProperty(szBuffer);
|
||||
}
|
||||
|
|
|
@ -48,29 +48,6 @@ namespace AssimpView {
|
|||
|
||||
/*static */ CMaterialManager CMaterialManager::s_cInstance;
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Compiler idependent stricmp() function.
|
||||
//
|
||||
// Used for case insensitive string comparison
|
||||
//-------------------------------------------------------------------------------
|
||||
inline int ASSIMP_stricmp(const char *s1, const char *s2)
|
||||
{
|
||||
const char *a1, *a2;
|
||||
a1 = s1;
|
||||
a2 = s2;
|
||||
|
||||
while (true)
|
||||
{
|
||||
char c1 = (char)tolower(*a1);
|
||||
char c2 = (char)tolower(*a2);
|
||||
if ((0 == c1) && (0 == c2)) return 0;
|
||||
if (c1 < c2) return-1;
|
||||
if (c1 > c2) return 1;
|
||||
++a1;
|
||||
++a2;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// D3DX callback function to fill a texture with a checkers pattern
|
||||
//
|
||||
|
|
|
@ -1589,14 +1589,14 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg,
|
|||
|
||||
// check whether it is a typical texture file format ...
|
||||
++sz;
|
||||
if (0 == Assimp::ASSIMP_stricmp(sz,"png") ||
|
||||
0 == Assimp::ASSIMP_stricmp(sz,"bmp") ||
|
||||
0 == Assimp::ASSIMP_stricmp(sz,"jpg") ||
|
||||
0 == Assimp::ASSIMP_stricmp(sz,"tga") ||
|
||||
0 == Assimp::ASSIMP_stricmp(sz,"tif") ||
|
||||
0 == Assimp::ASSIMP_stricmp(sz,"hdr") ||
|
||||
0 == Assimp::ASSIMP_stricmp(sz,"ppm") ||
|
||||
0 == Assimp::ASSIMP_stricmp(sz,"pfm"))
|
||||
if (0 == ASSIMP_stricmp(sz,"png") ||
|
||||
0 == ASSIMP_stricmp(sz,"bmp") ||
|
||||
0 == ASSIMP_stricmp(sz,"jpg") ||
|
||||
0 == ASSIMP_stricmp(sz,"tga") ||
|
||||
0 == ASSIMP_stricmp(sz,"tif") ||
|
||||
0 == ASSIMP_stricmp(sz,"hdr") ||
|
||||
0 == ASSIMP_stricmp(sz,"ppm") ||
|
||||
0 == ASSIMP_stricmp(sz,"pfm"))
|
||||
{
|
||||
CBackgroundPainter::Instance().SetTextureBG(szFile);
|
||||
}
|
||||
|
|
|
@ -132,7 +132,8 @@ DWORD WINAPI LoadThreadProc(LPVOID lpParameter)
|
|||
aiProcess_Triangulate | // triangulate n-polygons
|
||||
aiProcess_GenSmoothNormals | // generate smooth normal vectors if not existing
|
||||
aiProcess_ConvertToLeftHanded | // convert everything to D3D left handed space
|
||||
aiProcess_SplitLargeMeshes); // split large, unrenderable meshes into submeshes
|
||||
aiProcess_SplitLargeMeshes | // split large, unrenderable meshes into submeshes
|
||||
aiProcess_ValidateDataStructure); // validate the output data structure
|
||||
|
||||
// get the end time of zje operation, calculate delta t
|
||||
double fEnd = (double)timeGetTime();
|
||||
|
|
|
@ -46,21 +46,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "resource.h"
|
||||
|
||||
// Include ASSIMP headers
|
||||
#include "aiAnim.h"
|
||||
#include "aiAssert.h"
|
||||
#include "aiFileIO.h"
|
||||
#include "aiMaterial.h"
|
||||
#include "aiPostProcess.h"
|
||||
#include "aiMesh.h"
|
||||
#include "aiScene.h"
|
||||
#include "aiTypes.h"
|
||||
#include "IOSystem.h"
|
||||
#include "IOStream.h"
|
||||
#include "assimp.h"
|
||||
#include "assimp.hpp"
|
||||
#include "LogStream.h"
|
||||
#include "DefaultLogger.h"
|
||||
#include "MaterialSystem.h"
|
||||
|
||||
#include "MaterialSystem.h" // MaterialHelper clas
|
||||
#include "StringComparison.h" // ASSIMP_stricmp and ASSIMP_strincmp
|
||||
|
||||
// in order for std::min and std::max to behave properly
|
||||
#ifdef min
|
||||
|
@ -73,6 +71,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
// default movement speed
|
||||
#define MOVE_SPEED 10.0f
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
namespace AssimpView {
|
||||
|
||||
#include "AssetHelper.h"
|
||||
|
|
|
@ -1033,6 +1033,10 @@
|
|||
RelativePath="..\..\code\SplitLargeMeshes.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\code\StringComparison.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\code\TextureTransform.h"
|
||||
>
|
||||
|
@ -1041,6 +1045,10 @@
|
|||
RelativePath="..\..\code\TriangulateProcess.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\code\ValidateDataStructure.h"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="ObjLoader"
|
||||
>
|
||||
|
@ -1333,6 +1341,10 @@
|
|||
RelativePath="..\..\code\TriangulateProcess.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\code\ValidateDataStructure.cpp"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="ObjLoader"
|
||||
>
|
||||
|
|
Loading…
Reference in New Issue