Ver código fonte

Added "ImproveCacheLocality"-Step; Added Unit tests (3 at the moment); Fixed hp spelling errors.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@68 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
aramis_acg 17 anos atrás
pai
commit
e8511e89ff
45 arquivos alterados com 2270 adições e 98 exclusões
  1. 10 0
      code/Importer.cpp
  2. 370 0
      code/ImproveCacheLocality.cpp
  3. 103 0
      code/ImproveCacheLocality.h
  4. 3 4
      code/JoinVerticesProcess.cpp
  5. 67 20
      code/LimitBoneWeightsProcess.cpp
  6. 4 2
      code/LimitBoneWeightsProcess.h
  7. 15 20
      code/RemoveComments.cpp
  8. 3 2
      code/TriangulateProcess.cpp
  9. 136 0
      code/VertexTriangleAdjacency.cpp
  10. 126 0
      code/VertexTriangleAdjacency.h
  11. 7 1
      include/aiMesh.h
  12. 9 1
      include/aiPostProcess.h
  13. 28 0
      test/unit/ExecuteStepWin32.bat
  14. 28 0
      test/unit/ExecuteStepWin64.bat
  15. 35 0
      test/unit/Main.cpp
  16. 0 0
      test/unit/ut3DSLoader.cpp
  17. 0 0
      test/unit/utASELoader.cpp
  18. 0 0
      test/unit/utFixInfacingNormals.cpp
  19. 0 0
      test/unit/utGenNormals.cpp
  20. 0 0
      test/unit/utGenSmoothNormals.cpp
  21. 0 0
      test/unit/utImproveCacheLocality.cpp
  22. 0 0
      test/unit/utJoinVertices.cpp
  23. 82 0
      test/unit/utLimitBoneWeights.cpp
  24. 38 0
      test/unit/utLimitBoneWeights.h
  25. 0 0
      test/unit/utMDLLoader.cpp
  26. 0 0
      test/unit/utMaterialSystem.cpp
  27. 0 0
      test/unit/utOBJLoader.cpp
  28. 0 0
      test/unit/utPretransformVertices.cpp
  29. 61 0
      test/unit/utRemoveComments.cpp
  30. 35 0
      test/unit/utRemoveComments.h
  31. 0 0
      test/unit/utSplitLargeMeshes.cpp
  32. 0 0
      test/unit/utTextureTransform.cpp
  33. 193 0
      test/unit/utVertexTriangleAdjacency.cpp
  34. 41 0
      test/unit/utVertexTriangleAdjacency.h
  35. 5 5
      tools/assimp_view/LogDisplay.cpp
  36. 4 0
      tools/assimp_view/MessageProc.cpp
  37. BIN
      tools/assimp_view/assimp_view.aps
  38. 2 1
      tools/assimp_view/assimp_view.cpp
  39. 4 0
      tools/assimp_view/assimp_view.h
  40. 6 6
      tools/assimp_view/assimp_view.rc
  41. 11 3
      tools/assimp_view/resource.h
  42. 762 0
      workspaces/vc8/UnitTest.vcproj
  43. 35 2
      workspaces/vc8/assimp.sln
  44. 17 1
      workspaces/vc8/assimp.vcproj
  45. 30 30
      workspaces/vc8/assimp_view.vcproj

+ 10 - 0
code/Importer.cpp

@@ -40,15 +40,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 */
 
 
 /** @file Implementation of the CPP-API class #Importer */
 /** @file Implementation of the CPP-API class #Importer */
+
+// STL/CSL heades
 #include <fstream>
 #include <fstream>
 #include <string>
 #include <string>
 
 
+// public Assimp API
 #include "../include/assimp.hpp"
 #include "../include/assimp.hpp"
 #include "../include/aiAssert.h"
 #include "../include/aiAssert.h"
 #include "../include/aiScene.h"
 #include "../include/aiScene.h"
 #include "../include/aiPostProcess.h"
 #include "../include/aiPostProcess.h"
 #include "../include/DefaultLogger.h"
 #include "../include/DefaultLogger.h"
 
 
+// internal headers
 #include "BaseImporter.h"
 #include "BaseImporter.h"
 #include "BaseProcess.h"
 #include "BaseProcess.h"
 #include "DefaultIOStream.h"
 #include "DefaultIOStream.h"
@@ -123,6 +127,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #if (!defined AI_BUILD_NO_VALIDATEDS_PROCESS)
 #if (!defined AI_BUILD_NO_VALIDATEDS_PROCESS)
 #	include "ValidateDataStructure.h"
 #	include "ValidateDataStructure.h"
 #endif
 #endif
+#if (!defined AI_BUILD_NO_IMPROVECACHELOCALITY_PROCESS)
+#	include "ImproveCacheLocality.h"
+#endif
 
 
 using namespace Assimp;
 using namespace Assimp;
 
 
@@ -210,6 +217,9 @@ Importer::Importer() :
 #if (!defined AI_BUILD_NO_LIMITBONEWEIGHTS_PROCESS)
 #if (!defined AI_BUILD_NO_LIMITBONEWEIGHTS_PROCESS)
 	mPostProcessingSteps.push_back( new LimitBoneWeightsProcess());
 	mPostProcessingSteps.push_back( new LimitBoneWeightsProcess());
 #endif
 #endif
+#if (!defined AI_BUILD_NO_IMPROVECACHELOCALITY_PROCESS)
+	mPostProcessingSteps.push_back( new ImproveCacheLocalityProcess());
+#endif
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------

+ 370 - 0
code/ImproveCacheLocality.cpp

@@ -0,0 +1,370 @@
+/*
+---------------------------------------------------------------------------
+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 join identical vertices
+ * for all imported meshes
+ * <br>
+ * The algorithm is roughly basing on this paper:
+ * http://www.cs.princeton.edu/gfx/pubs/Sander_2007_%3ETR/tipsy.pdf
+ */
+
+// STL headers
+#include <vector>
+#include <stack>
+#include <queue>
+
+// public ASSIMP headers
+#include "../include/DefaultLogger.h"
+#include "../include/aiPostProcess.h"
+#include "../include/aiMesh.h"
+#include "../include/aiScene.h"
+
+// internal headers
+#include "ImproveCacheLocality.h"
+#include "VertexTriangleAdjacency.h"
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+ImproveCacheLocalityProcess::ImproveCacheLocalityProcess()
+{
+	// nothing to do here
+	configCacheDepth = 12; // hardcoded to 12 at the moment
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+ImproveCacheLocalityProcess::~ImproveCacheLocalityProcess()
+{
+	// nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the processing step is present in the given flag field.
+bool ImproveCacheLocalityProcess::IsActive( unsigned int pFlags) const
+{
+	return (pFlags & aiProcess_ImproveCacheLocality) != 0;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Executes the post processing step on the given imported data.
+void ImproveCacheLocalityProcess::Execute( aiScene* pScene)
+{
+	DefaultLogger::get()->debug("ImproveCacheLocalityProcess begin");
+
+	for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
+	{
+		this->ProcessMesh( pScene->mMeshes[a]);
+	}
+	DefaultLogger::get()->debug("ImproveCacheLocalityProcess finished. ");
+}
+
+// ------------------------------------------------------------------------------------------------
+// Improves the cache coherency of a specific mesh
+void ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh)
+{
+	ai_assert(NULL != pMesh);
+
+	// check whether the input data is valid ->
+	// - there must be vertices and faces (haha)
+	// - all faces must be triangulated
+	if (!pMesh->HasFaces() || !pMesh->HasPositions())return;
+
+	// find the input ACMR ...
+	unsigned int* piFIFOStack = new unsigned int[this->configCacheDepth];
+	::memset(piFIFOStack,0xff,this->configCacheDepth*sizeof(unsigned int));
+	unsigned int* piCur = piFIFOStack;
+	const unsigned int* const piCurEnd = piFIFOStack + this->configCacheDepth;
+
+	// count the number of cache misses
+	unsigned int iCacheMisses = 0;
+
+	const aiFace* const pcEnd = pMesh->mFaces+pMesh->mNumFaces;
+	for (const aiFace* pcFace = pMesh->mFaces;pcFace != pcEnd;++pcFace)
+	{
+		if (3 != pcFace->mNumIndices)
+		{
+			DefaultLogger::get()->error("Unable to improve cache locality of non-triangulated faces");
+			delete[] piFIFOStack;
+			return;
+		}
+
+		// although it has not been tested, I'm quite sure degenerated triangles
+		// would crash if the algorithm was applied to them
+
+#if (defined _DEBUG)
+		if (pcFace->mIndices[0] == pcFace->mIndices[1] ||
+			pcFace->mIndices[2] == pcFace->mIndices[1] ||
+			pcFace->mIndices[2] == pcFace->mIndices[0])
+		{
+			DefaultLogger::get()->error("ImproveCacheLocalityProcess: There may be no degenerated triangles ");
+			return;
+		}
+#endif
+
+		for (unsigned int qq = 0; qq < 3;++qq)
+		{
+			bool bInCache = false;
+			for (unsigned int* pp = piFIFOStack;pp < piCurEnd;++pp)
+			{
+				if (*pp == pcFace->mIndices[qq])
+				{
+					// the vertex is in cache
+					bInCache = true;
+					break;
+				}
+			}
+			if (!bInCache)
+			{
+				++iCacheMisses;
+				if (piCurEnd == piCur)piCur = piFIFOStack;
+				*piCur++ = pcFace->mIndices[qq];
+			}
+		}
+	}
+	delete[] piFIFOStack;
+
+	float fACMR = (float)iCacheMisses / pMesh->mNumFaces;
+	char szBuff[16];
+	sprintf(szBuff,"%f",fACMR);
+	DefaultLogger::get()->debug("Input ACMR: " + std::string(szBuff));
+
+
+	// first we need to build a vertex-triangle adjacency list
+	VertexTriangleAdjacency adj(pMesh->mFaces,pMesh->mNumFaces, pMesh->mNumVertices,true);
+
+	// build a list to store per-vertex caching time stamps
+	unsigned int* const piCachingStamps = new unsigned int[pMesh->mNumVertices];
+	::memset(piCachingStamps,0x0,pMesh->mNumVertices*sizeof(unsigned int));
+
+	// allocate an empty output index buffer. We store the output
+	// indices in one large array. Since the number of triangles
+	// won't change the input faces can be reused. This is how we save
+	// thousands of redundant mini allocations for aiFace::mIndices
+	const unsigned int iIdxCnt = pMesh->mNumFaces*3;
+	unsigned int* const piIBOutput = new unsigned int[iIdxCnt];
+	unsigned int* piCSIter = piIBOutput;
+
+	// allocate the flag array to hold the information
+	// whether a face has already been emitted or not
+	std::vector<bool> abEmitted(pMesh->mNumFaces,false);
+
+	// dead-end vertex index stack
+	std::stack<unsigned int> sDeadEndVStack;
+
+	// create a copy of the piNumTriPtr buffer
+	unsigned int* const piNumTriPtr = adj.mLiveTriangles;
+	const unsigned int* const piNumTriPtrNoModify = new unsigned int[pMesh->mNumVertices];
+	::memcpy(const_cast<unsigned int* const> (piNumTriPtrNoModify),piNumTriPtr,
+		pMesh->mNumVertices * sizeof(unsigned int));
+
+	// get the largest number of referenced triangles
+	// and allocate the "candidate buffer"
+	unsigned int iMaxRefTris = 0;
+	{
+		const unsigned int* piCur = adj.mLiveTriangles;
+		const unsigned int* const piCurEnd = adj.mLiveTriangles+pMesh->mNumVertices;
+		for (;piCur != piCurEnd;++piCur)
+			iMaxRefTris = std::max(iMaxRefTris,*piCur);
+	}
+	unsigned int* piCandidates = new unsigned int[iMaxRefTris*3];
+	iCacheMisses = 0;
+
+	/** PSEUDOCODE for the algorithm
+
+		A = Build-Adjacency(I) Vertex-triangle adjacency
+		L = Get-Triangle-Counts(A) Per-vertex live triangle counts
+		C = Zero(Vertex-Count(I)) Per-vertex caching time stamps
+		D = Empty-Stack() Dead-end vertex stack
+		E = False(Triangle-Count(I)) Per triangle emitted flag
+		O = Empty-Index-Buffer() Empty output buffer
+		f = 0 Arbitrary starting vertex
+		s = k+1, i = 1 Time stamp and cursor
+		while f >= 0 For all valid fanning vertices
+			N = Empty-Set() 1-ring of next candidates
+			for each Triangle t in Neighbors(A, f)
+				if !Emitted(E,t)
+					for each Vertex v in t
+						Append(O,v) Output vertex
+						Push(D,v) Add to dead-end stack
+						Insert(N,v) Register as candidate
+						L[v] = L[v]-1 Decrease live triangle count
+						if s-C[v] > k If not in cache
+							C[v] = s Set time stamp
+							s = s+1 Increment time stamp
+					E[t] = true Flag triangle as emitted
+			Select next fanning vertex
+			f = Get-Next-Vertex(I,i,k,N,C,s,L,D)
+		return O
+		*/
+
+	int ivdx = 0;
+	int ics = 1;
+	int iStampCnt = this->configCacheDepth+1;
+	while (ivdx >= 0)
+	{
+		unsigned int icnt = piNumTriPtrNoModify[ivdx]; 
+		unsigned int* piList = adj.GetAdjacentTriangles(ivdx);
+		unsigned int* piCurCandidate = piCandidates;
+
+		// get all triangles in the neighborhood
+		for (unsigned int tri = 0; tri < icnt;++tri)
+		{
+			// if they have not yet been emitted, add them to the output IB
+			const unsigned int fidx = *piList++;
+			if (!abEmitted[fidx])
+			{
+				// so iterate through all vertices of the current triangle
+				const aiFace* pcFace = &pMesh->mFaces[ fidx ];
+				const unsigned int* const p2 = pcFace->mIndices+3;
+				for (unsigned int* p = pcFace->mIndices;p != p2;++p)
+				{
+					const unsigned int dp = *p;
+
+					// the current vertex won't have any free triangles after this step
+					if (ivdx != dp)
+					{
+						// append the vertex to the dead-end stack
+						sDeadEndVStack.push(dp);
+
+						// register as candidate for the next step
+						*piCurCandidate++ = dp;
+
+						// decrease the per-vertex triangle counts
+						piNumTriPtr[dp]--;
+					}
+
+					// append the vertex to the output index buffer
+					*piCSIter++ = dp;
+
+					// if the vertex is not yet in cache, set its cache count
+					if (iStampCnt-piCachingStamps[dp] > this->configCacheDepth)
+					{
+						piCachingStamps[dp] = iStampCnt++;
+						++iCacheMisses;
+					}
+				}
+				// flag triangle as emitted
+				abEmitted[fidx] = true;
+			}
+		}
+
+		// the vertex has now no living adjacent triangles anymore
+		piNumTriPtr[ivdx] = 0;
+
+		// get next fanning vertex
+		ivdx = -1; 
+		int max_priority = -1;
+		for (unsigned int* piCur = piCandidates;piCur != piCurCandidate;++piCur)
+		{
+			register const unsigned int dp = *piCur;
+
+			// must have live triangles
+			if (piNumTriPtr[dp] > 0)
+			{
+				int priority = 0;
+
+				// will the vertex be in cache, even after fanning occurs?
+				unsigned int tmp;
+				if ((tmp = iStampCnt-piCachingStamps[dp]) + 2*piNumTriPtr[dp] <= this->configCacheDepth)
+					priority = tmp;
+				// keep best candidate
+				if (priority > max_priority)
+				{
+					max_priority = priority;
+					ivdx = dp;
+				}
+			}
+		}
+		// did we reach a dead end?
+		if (-1 == ivdx)
+		{
+			// need to get a non-local vertex for which we have a good
+			// chance that it is still in the cache ...
+			while (!sDeadEndVStack.empty())
+			{
+				unsigned int iCachedIdx = sDeadEndVStack.top();
+				sDeadEndVStack.pop();
+				if (piNumTriPtr[ iCachedIdx ] > 0)
+				{
+					ivdx = iCachedIdx;
+					break;
+				}
+			}
+
+			if (-1 == ivdx)
+			{
+				// well, there isn't such a vertex. Simply get the next
+				// vertex in input order and hope it is not too bad ...
+				while (ics < (int)pMesh->mNumVertices)
+				{
+					++ics;
+					if (piNumTriPtr[ics] > 0)
+					{
+						ivdx = ics;
+						break;
+					}
+				}
+			}
+		}
+	}
+
+	fACMR = (float)iCacheMisses / pMesh->mNumFaces;
+	sprintf(szBuff,"%f",fACMR);
+	DefaultLogger::get()->debug("Output ACMR: " + std::string(szBuff));
+
+	// sort the output index buffer back to the input array
+	piCSIter = piIBOutput;
+
+	for (aiFace* pcFace = pMesh->mFaces; pcFace != pcEnd;++pcFace)
+	{
+		pcFace->mIndices[0] = *piCSIter++;
+		pcFace->mIndices[1] = *piCSIter++;
+		pcFace->mIndices[2] = *piCSIter++;
+	}
+
+	// delete temporary storage
+	delete[] piCachingStamps;
+	delete[] piIBOutput;
+	delete[] piCandidates;
+	delete[] piNumTriPtrNoModify;
+}

+ 103 - 0
code/ImproveCacheLocality.h

@@ -0,0 +1,103 @@
+/*
+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 reorder faces for 
+ better cache locality*/
+#ifndef AI_IMPROVECACHELOCALITY_H_INC
+#define AI_IMPROVECACHELOCALITY_H_INC
+
+#include "BaseProcess.h"
+#include "../include/aiTypes.h"
+
+struct aiMesh;
+
+namespace Assimp
+{
+
+// ---------------------------------------------------------------------------
+/** The ImproveCacheLocalityProcess reorders all faces for improved vertex
+ *  cache locality. It tries to arrange all faces to fans and to render
+ *  faces which share vertices directly one after the other.
+ *
+ *  @note This step expects the triagulated input data.
+ */
+class ImproveCacheLocalityProcess : public BaseProcess
+{
+	friend class Importer;
+
+protected:
+	/** Constructor to be privately used by Importer */
+	ImproveCacheLocalityProcess();
+
+	/** Destructor, private as well */
+	~ImproveCacheLocalityProcess();
+
+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);
+
+protected:
+	// -------------------------------------------------------------------
+	/** Executes the postprocessing step on the given mesh
+	 * @param pMesh The mesh to process.
+	 */
+	void ProcessMesh( aiMesh* pMesh);
+
+
+	//! Configuration parameter: specifies the size of the cache to
+	//! optimize the vertex data for.
+	unsigned int configCacheDepth;
+};
+
+} // end of namespace Assimp
+
+#endif // AI_IMPROVECACHELOCALITY_H_INC

+ 3 - 4
code/JoinVerticesProcess.cpp

@@ -44,7 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
  */
 
 
 #include <vector>
 #include <vector>
-#include <assert.h>
 #include "JoinVerticesProcess.h"
 #include "JoinVerticesProcess.h"
 #include "SpatialSort.h"
 #include "SpatialSort.h"
 #include "../include/DefaultLogger.h"
 #include "../include/DefaultLogger.h"
@@ -177,7 +176,7 @@ bool JoinVerticesProcess::ProcessMesh( aiMesh* pMesh)
 			if( (uv.mBitangent - v.mBitangent).SquareLength() > squareEpsilon)
 			if( (uv.mBitangent - v.mBitangent).SquareLength() > squareEpsilon)
 				continue;
 				continue;
 			// manually unrolled because continue wouldn't work as desired in an inner loop
 			// manually unrolled because continue wouldn't work as desired in an inner loop
-			assert( AI_MAX_NUMBER_OF_COLOR_SETS == 4);
+			ai_assert( AI_MAX_NUMBER_OF_COLOR_SETS == 4);
 			if( GetColorDifference( uv.mColors[0], v.mColors[0]) > squareEpsilon)
 			if( GetColorDifference( uv.mColors[0], v.mColors[0]) > squareEpsilon)
 				continue;
 				continue;
 			if( GetColorDifference( uv.mColors[1], v.mColors[1]) > squareEpsilon)
 			if( GetColorDifference( uv.mColors[1], v.mColors[1]) > squareEpsilon)
@@ -187,7 +186,7 @@ bool JoinVerticesProcess::ProcessMesh( aiMesh* pMesh)
 			if( GetColorDifference( uv.mColors[3], v.mColors[3]) > squareEpsilon)
 			if( GetColorDifference( uv.mColors[3], v.mColors[3]) > squareEpsilon)
 				continue;
 				continue;
 			// texture coord matching manually unrolled as well
 			// texture coord matching manually unrolled as well
-			assert( AI_MAX_NUMBER_OF_TEXTURECOORDS == 4);
+			ai_assert( AI_MAX_NUMBER_OF_TEXTURECOORDS == 4);
 			if( (uv.mTexCoords[0] - v.mTexCoords[0]).SquareLength() > squareEpsilon)
 			if( (uv.mTexCoords[0] - v.mTexCoords[0]).SquareLength() > squareEpsilon)
 				continue;
 				continue;
 			if( (uv.mTexCoords[1] - v.mTexCoords[1]).SquareLength() > squareEpsilon)
 			if( (uv.mTexCoords[1] - v.mTexCoords[1]).SquareLength() > squareEpsilon)
@@ -303,7 +302,7 @@ bool JoinVerticesProcess::ProcessMesh( aiMesh* pMesh)
 		}
 		}
 
 
 		// there should be some. At least I think there should be some
 		// there should be some. At least I think there should be some
-		assert( newWeights.size() > 0);
+		ai_assert( newWeights.size() > 0);
 
 
 		// kill the old and replace them with the translated weights
 		// kill the old and replace them with the translated weights
 		delete [] bone->mWeights;
 		delete [] bone->mWeights;

+ 67 - 20
code/LimitBoneWeightsProcess.cpp

@@ -48,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "../include/aiPostProcess.h"
 #include "../include/aiPostProcess.h"
 #include "../include/aiMesh.h"
 #include "../include/aiMesh.h"
 #include "../include/aiScene.h"
 #include "../include/aiScene.h"
+#include "../include/aiAssert.h"
 #include "../include/DefaultLogger.h"
 #include "../include/DefaultLogger.h"
 
 
 using namespace Assimp;
 using namespace Assimp;
@@ -122,11 +123,14 @@ void LimitBoneWeightsProcess::ProcessMesh( aiMesh* pMesh)
 	}
 	}
 
 
 	// now cut the weight count if it exceeds the maximum
 	// now cut the weight count if it exceeds the maximum
+	bool bChanged = false;
 	for( WeightsPerVertex::iterator vit = vertexWeights.begin(); vit != vertexWeights.end(); ++vit)
 	for( WeightsPerVertex::iterator vit = vertexWeights.begin(); vit != vertexWeights.end(); ++vit)
 	{
 	{
 		if( vit->size() <= mMaxWeights)
 		if( vit->size() <= mMaxWeights)
 			continue;
 			continue;
 
 
+		bChanged = true;
+
 		// more than the defined maximum -> first sort by weight in descending order. That's 
 		// more than the defined maximum -> first sort by weight in descending order. That's 
 		// why we defined the < operator in such a weird way.
 		// why we defined the < operator in such a weird way.
 		std::sort( vit->begin(), vit->end());
 		std::sort( vit->begin(), vit->end());
@@ -142,28 +146,71 @@ void LimitBoneWeightsProcess::ProcessMesh( aiMesh* pMesh)
 			it->mWeight /= sum;
 			it->mWeight /= sum;
 	}
 	}
 
 
-	// rebuild the vertex weight array for all bones 
-	typedef std::vector< std::vector< aiVertexWeight > > WeightsPerBone;
-	WeightsPerBone boneWeights( pMesh->mNumBones);
-	for( unsigned int a = 0; a < vertexWeights.size(); a++)
+	if (bChanged)
 	{
 	{
-		const std::vector<Weight>& vw = vertexWeights[a];
-		for( std::vector<Weight>::const_iterator it = vw.begin(); it != vw.end(); ++it)
-			boneWeights[it->mBone].push_back( aiVertexWeight( a, it->mWeight));
-	}
 
 
-	// and finally copy the vertex weight list over to the mesh's bones
-	for( unsigned int a = 0; a < pMesh->mNumBones; a++)
-	{
-		const std::vector<aiVertexWeight>& bw = boneWeights[a];
-		aiBone* bone = pMesh->mBones[a];
-		// ignore the bone if no vertex weights were removed there
-		if( bw.size() == bone->mNumWeights)
-			continue;
+		// rebuild the vertex weight array for all bones 
+		typedef std::vector< std::vector< aiVertexWeight > > WeightsPerBone;
+		WeightsPerBone boneWeights( pMesh->mNumBones);
+		for( unsigned int a = 0; a < vertexWeights.size(); a++)
+		{
+			const std::vector<Weight>& vw = vertexWeights[a];
+			for( std::vector<Weight>::const_iterator it = vw.begin(); it != vw.end(); ++it)
+				boneWeights[it->mBone].push_back( aiVertexWeight( a, it->mWeight));
+		}
 
 
-		// copy the weight list. should always be less weights than before, so we don't need a new allocation
-		assert( bw.size() < bone->mNumWeights);
-		bone->mNumWeights = (unsigned int) bw.size();
-		memcpy( bone->mWeights, &bw[0], bw.size() * sizeof( aiVertexWeight));
+		// and finally copy the vertex weight list over to the mesh's bones
+		std::vector<bool> abNoNeed(pMesh->mNumBones,false);
+		bChanged = false;
+
+		for( unsigned int a = 0; a < pMesh->mNumBones; a++)
+		{
+			const std::vector<aiVertexWeight>& bw = boneWeights[a];
+			aiBone* bone = pMesh->mBones[a];
+
+			// ignore the bone if no vertex weights were removed there
+
+			// FIX (Aramis, 07|22|08)
+			// NO! we can't ignore it in this case ... it is possible that
+			// the number of weights did not change, but the weight values did.
+
+			// if( bw.size() == bone->mNumWeights)
+			//	continue;
+
+			// FIX (Aramis, 07|21|08)
+			// It is possible that all weights of a bone have been removed.
+			// This would naturally cause an exception in &bw[0].
+			if ( bw.empty() )
+			{
+				abNoNeed[a] = bChanged = true;
+				continue;
+			}
+
+			// copy the weight list. should always be less weights than before, so we don't need a new allocation
+			ai_assert( bw.size() <= bone->mNumWeights);
+			bone->mNumWeights = (unsigned int) bw.size();
+			::memcpy( bone->mWeights, &bw[0], bw.size() * sizeof( aiVertexWeight));
+		}
+
+		if (bChanged)
+		{
+			// the number of new bones is smaller than before, so we can
+			// reuse the old array, too.
+			aiBone** ppcCur = pMesh->mBones;
+			aiBone** ppcSrc = ppcCur;
+
+			for (std::vector<bool>::const_iterator
+				iter  = abNoNeed.begin();
+				iter != abNoNeed.end()  ;++iter)
+			{
+				if (*iter)
+				{
+					delete *ppcSrc;
+					--pMesh->mNumBones;
+				}
+				else *ppcCur++ = *ppcSrc;
+				++ppcSrc;
+			}
+		}
 	}
 	}
 }
 }

+ 4 - 2
code/LimitBoneWeightsProcess.h

@@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "BaseProcess.h"
 #include "BaseProcess.h"
 
 
 struct aiMesh;
 struct aiMesh;
+class LimitBoneWeightsTest;
 
 
 namespace Assimp
 namespace Assimp
 {
 {
@@ -53,8 +54,8 @@ namespace Assimp
 // corresponding values in all Assimp ports
 // corresponding values in all Assimp ports
 
 
 // **********************************************************
 // **********************************************************
-// Java: PostProcessStep.java, 
-//  PostProcessStep.DEFAULT_BONE_WEIGHT_LIMIT
+// Java: ConfigProperty.java, 
+//  ConfigProperty.DEFAULT_BONE_WEIGHT_LIMIT
 // **********************************************************
 // **********************************************************
 
 
 #if (!defined AI_LMW_MAX_WEIGHTS)
 #if (!defined AI_LMW_MAX_WEIGHTS)
@@ -71,6 +72,7 @@ namespace Assimp
 class LimitBoneWeightsProcess : public BaseProcess
 class LimitBoneWeightsProcess : public BaseProcess
 {
 {
 	friend class Importer;
 	friend class Importer;
+	friend class ::LimitBoneWeightsTest;
 
 
 protected:
 protected:
 	/** Constructor to be privately used by Importer */
 	/** Constructor to be privately used by Importer */

+ 15 - 20
code/RemoveComments.cpp

@@ -57,15 +57,14 @@ void CommentRemover::RemoveLineComments(const char* szComment,
 	// validate parameters
 	// validate parameters
 	ai_assert(NULL != szComment && NULL != szBuffer && *szComment);
 	ai_assert(NULL != szComment && NULL != szBuffer && *szComment);
 
 
+	const size_t len = ::strlen(szComment);
+
 	while (*szBuffer)
 	while (*szBuffer)
 	{
 	{
-		if (*szBuffer == *szComment)
+		if (0 == ::strncmp(szBuffer,szComment,len))
 		{
 		{
-			if (0 == ::strcmp(szBuffer+1,szComment+1))
-			{
-				while (*szBuffer != '\r' && *szBuffer != '\n' && *szBuffer)
-					*szBuffer++ = chReplacement;
-			}
+			while (*szBuffer != '\r' && *szBuffer != '\n' && *szBuffer)
+				*szBuffer++ = chReplacement;
 		}
 		}
 		++szBuffer;
 		++szBuffer;
 	}
 	}
@@ -80,28 +79,24 @@ void CommentRemover::RemoveMultiLineComments(const char* szCommentStart,
 		NULL != szBuffer && '\0' != *szCommentStart && '\0' != *szCommentEnd);
 		NULL != szBuffer && '\0' != *szCommentStart && '\0' != *szCommentEnd);
 
 
 	const size_t len = ::strlen(szCommentEnd);
 	const size_t len = ::strlen(szCommentEnd);
+	const size_t len2 = ::strlen(szCommentStart);
 
 
 	while (*szBuffer)
 	while (*szBuffer)
 	{
 	{
-		if (*szBuffer == *szCommentStart)
+		if (0 == ::strncmp(szBuffer,szCommentStart,len2))
 		{
 		{
-			if (0 == ::strcmp(szBuffer+1,szCommentStart+1))
+			while (*szBuffer)
 			{
 			{
-				while (*szBuffer)
+					
+				if (0 == ::strncmp(szBuffer,szCommentEnd,len))
 				{
 				{
-					if (*szBuffer == *szCommentEnd)
-					{
-						if (0 == ::strcmp(szBuffer+1,szCommentEnd+1))
-						{
-							for (unsigned int i = 0; i < len;++i)
-								*szBuffer++ = chReplacement;
-							goto __continue_outer; // WUHHHAAAAHHAA!
-						}
-					}
-					*szBuffer++ = chReplacement;
+					for (unsigned int i = 0; i < len;++i)
+						*szBuffer++ = chReplacement;
+					goto __continue_outer; // WUHHHAAAAHHAA!
 				}
 				}
-				return;
+			*szBuffer++ = chReplacement;
 			}
 			}
+			return;
 		}
 		}
 		++szBuffer;
 		++szBuffer;
 __continue_outer:
 __continue_outer:

+ 3 - 2
code/TriangulateProcess.cpp

@@ -94,15 +94,16 @@ void TriangulateProcess::Execute( aiScene* pScene)
 bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
 bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
 {
 {
 	// check whether we will need to do something ...
 	// check whether we will need to do something ...
+	bool bNeed = false;
 	for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
 	for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
 	{
 	{
 		const aiFace& face = pMesh->mFaces[a];
 		const aiFace& face = pMesh->mFaces[a];
 		if( face.mNumIndices != 3)
 		if( face.mNumIndices != 3)
 		{
 		{
-			break;
+			bNeed = true;
 		}
 		}
-		return false;
 	}
 	}
+	if (!bNeed)return false;
 
 
 	std::vector<aiFace> newFaces;
 	std::vector<aiFace> newFaces;
 	newFaces.reserve( pMesh->mNumFaces*2);
 	newFaces.reserve( pMesh->mNumFaces*2);

+ 136 - 0
code/VertexTriangleAdjacency.cpp

@@ -0,0 +1,136 @@
+/*
+---------------------------------------------------------------------------
+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 VertexTriangleAdjacency helper class
+ */
+
+// public ASSIMP headers
+#include "../include/DefaultLogger.h"
+#include "../include/aiMesh.h"
+
+// internal headers
+#include "VertexTriangleAdjacency.h"
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+VertexTriangleAdjacency::VertexTriangleAdjacency(aiFace *pcFaces,
+	unsigned int iNumFaces,
+	unsigned int iNumVertices /*= 0*/,
+	bool bComputeNumTriangles /*= false*/)
+{
+	// compute the number of referenced vertices if it wasn't specified by the caller
+	const aiFace* const pcFaceEnd = pcFaces + iNumFaces;
+	if (!iNumVertices)
+	{
+		for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace)
+		{
+			iNumVertices = std::max(iNumVertices,pcFace->mIndices[0]);
+			iNumVertices = std::max(iNumVertices,pcFace->mIndices[1]);
+			iNumVertices = std::max(iNumVertices,pcFace->mIndices[2]);
+		}
+	}
+	unsigned int* pi;
+
+	// allocate storage
+	if (bComputeNumTriangles)
+	{
+		pi = this->mLiveTriangles = new unsigned int[iNumVertices+1];
+		::memset(this->mLiveTriangles,0,sizeof(unsigned int)*(iNumVertices+1));
+		this->mOffsetTable = new unsigned int[iNumVertices+2]+1;
+	}
+	else 
+	{
+		pi = this->mOffsetTable = new unsigned int[iNumVertices+2]+1;
+		::memset(this->mOffsetTable,0,sizeof(unsigned int)*(iNumVertices+1));
+		this->mLiveTriangles = NULL; // important, otherwise the d'tor would crash
+	}
+
+	// get a pointer to the end of the buffer
+	unsigned int* piEnd = pi+iNumVertices;
+	*piEnd++ = 0u;
+
+	// first pass: compute the number of faces referencing each vertex
+	for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace)
+	{
+		pi[pcFace->mIndices[0]]++;	
+		pi[pcFace->mIndices[1]]++;	
+		pi[pcFace->mIndices[2]]++;	
+	}
+
+	// second pass: compute the final offset table
+	unsigned int iSum = 0;
+	unsigned int* piCurOut = this->mOffsetTable;
+	for (unsigned int* piCur = pi; piCur != piEnd;++piCur,++piCurOut)
+	{
+		unsigned int iLastSum = iSum;
+		iSum += *piCur; 
+		*piCurOut = iLastSum;
+	}
+	pi = this->mOffsetTable;
+
+	// third pass: compute the final table
+	this->mAdjacencyTable = new unsigned int[iSum];
+	iSum = 0;
+	for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace,++iSum)
+	{
+		unsigned int idx = pcFace->mIndices[0];
+		this->mAdjacencyTable[pi[idx]++] = iSum;
+
+		idx = pcFace->mIndices[1];
+		this->mAdjacencyTable[pi[idx]++] = iSum;
+
+		idx = pcFace->mIndices[2];
+		this->mAdjacencyTable[pi[idx]++] = iSum;
+	}
+	// fourth pass: undo the offset computations made during the third pass
+	// We could do this in a separate buffer, but this would be TIMES slower.
+	--this->mOffsetTable;
+	*this->mOffsetTable = 0u;
+}
+// ------------------------------------------------------------------------------------------------
+VertexTriangleAdjacency::~VertexTriangleAdjacency()
+{
+	// delete all allocated storage
+	delete[] this->mOffsetTable;
+	delete[] this->mAdjacencyTable;
+	delete[] this->mLiveTriangles;
+}

+ 126 - 0
code/VertexTriangleAdjacency.h

@@ -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 Defines a helper class to compute a vertex-triangle adjacency map */
+#ifndef AI_VTADJACENCY_H_INC
+#define AI_VTADJACENCY_H_INC
+
+#include "BaseProcess.h"
+#include "../include/aiTypes.h"
+#include "../include/aiAssert.h"
+
+struct aiMesh;
+
+namespace Assimp
+{
+
+// ---------------------------------------------------------------------------
+/** The VertexTriangleAdjacency class computes a vertex-triangle
+ *  adjacency map from a given index buffer.
+ *
+ *  @note The input data is expected to be triangulated.
+ */
+class VertexTriangleAdjacency
+{
+public:
+
+
+	/** Construction from an existing index buffer
+	 * @param pcFaces Index buffer
+	 * @param iNumFaces Number of faces in the buffer
+	 * @param iNumVertices Number of referenced vertices. This value
+	 *   is computed automatically if 0 is specified.
+	 * @param bComputeNumTriangles If you want the class to compute
+	 *   a list which contains the number of referenced triangles
+	 *   per vertex - pass true.
+	 */
+	VertexTriangleAdjacency(aiFace* pcFaces,unsigned int iNumFaces,
+		unsigned int iNumVertices = 0,
+		bool bComputeNumTriangles = true);
+
+
+	/** Destructor
+	 */
+	~VertexTriangleAdjacency();
+
+
+	/** Get all triangles adjacent to a vertex
+	 * @param iVertIndex Index of the vertex
+	 * @return A pointer to the adjacency list
+	 */
+	inline unsigned int* GetAdjacentTriangles(unsigned int iVertIndex) const
+	{
+		ai_assert(iVertIndex < iNumVertices);
+
+		const unsigned int ofs = mOffsetTable[iVertIndex];
+		return &mAdjacencyTable[ofs];
+	}
+
+
+	/** Get the number of triangles that are referenced by
+	 *  a vertex. This function returns a reference that can be modified
+	 * @param iVertIndex Index of the vertex
+	 * @return Number of referenced triangles
+	 */
+	inline unsigned int& GetNumTrianglesPtr(unsigned int iVertIndex)
+	{
+		ai_assert(iVertIndex < iNumVertices && NULL != mLiveTriangles);
+		return mLiveTriangles[iVertIndex];
+	}
+
+
+public:
+
+	//! Offset table
+	unsigned int* mOffsetTable;
+
+	//! Adjacency table
+	unsigned int* mAdjacencyTable;
+
+	//! Table containing the number of referenced triangles per vertex
+	unsigned int* mLiveTriangles;
+
+	//! Debug: Number of referenced vertices
+	unsigned int iNumVertices;
+
+};
+}
+
+#endif // !! AI_VTADJACENCY_H_INC

+ 7 - 1
include/aiMesh.h

@@ -391,10 +391,16 @@ struct aiMesh
 		}
 		}
 	}
 	}
 
 
-	//! Check whether the mesh contains positions. Should always return true
+	//! Check whether the mesh contains positions. If no special scene flags
+	//! are set this should always return true
 	inline bool HasPositions() const 
 	inline bool HasPositions() const 
 		{ return mVertices != NULL; }
 		{ return mVertices != NULL; }
 
 
+	//! Check whether the mesh contains faces. If no special scene flags
+	//! are set this should always return true
+	inline bool HasFaces() const 
+		{ return mFaces != NULL; }
+
 	//! Check whether the mesh contains normal vectors
 	//! Check whether the mesh contains normal vectors
 	inline bool HasNormals() const 
 	inline bool HasNormals() const 
 		{ return mNormals != NULL; }
 		{ return mNormals != NULL; }

+ 9 - 1
include/aiPostProcess.h

@@ -146,7 +146,15 @@ enum aiPostProcessSteps
 	 * however, it could be of interest for applications like editors
 	 * however, it could be of interest for applications like editors
 	 * where stability is more important than loading performance.
 	 * where stability is more important than loading performance.
 	*/
 	*/
-	aiProcess_ValidateDataStructure = 0x400
+	aiProcess_ValidateDataStructure = 0x400,
+
+	/** Reorders triangles for vertex cache locality and thus better performance.
+	 * The step tries to improve the ACMR (average post-transform vertex cache
+	 * miss ratio) for all meshes. The step runs in O(n) and is roughly
+	 * basing on the algorithm described in this paper:
+	 * http://www.cs.princeton.edu/gfx/pubs/Sander_2007_%3ETR/tipsy.pdf
+	 */
+	aiProcess_ImproveCacheLocality = 0x1600
 };
 };
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------

+ 28 - 0
test/unit/ExecuteStepWin32.bat

@@ -0,0 +1,28 @@
+
+
+
+cd ..
+cd ..
+cd bin
+cd unittest_release_win32
+
+color 4e
+cls
+
+@echo off
+
+
+echo ----------------------------------------------------------------------
+echo _
+echo Open Asset Import Library - Unittests
+echo _
+echo ----------------------------------------------------------------------
+echo _
+echo _
+
+UnitTest.exe
+
+echo _
+echo ----------------------------------------------------------------------
+
+pause

+ 28 - 0
test/unit/ExecuteStepWin64.bat

@@ -0,0 +1,28 @@
+
+
+
+cd ..
+cd ..
+cd bin
+cd unittest_release_x64
+
+color 4e
+cls
+
+@echo off
+
+
+echo ----------------------------------------------------------------------
+echo _
+echo Open Asset Import Library - Unittests
+echo _
+echo ----------------------------------------------------------------------
+echo _
+echo _
+
+UnitTest.exe
+
+echo _
+echo ----------------------------------------------------------------------
+
+pause

+ 35 - 0
test/unit/Main.cpp

@@ -0,0 +1,35 @@
+
+
+#include <cppunit/CompilerOutputter.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/TestResult.h>
+#include <cppunit/TestResultCollector.h>
+#include <cppunit/TestRunner.h>
+#include <cppunit/BriefTestProgressListener.h>
+
+
+int main (int argc, char* argv[])
+{
+    // Informiert Test-Listener ueber Testresultate
+    CPPUNIT_NS :: TestResult testresult;
+
+    // Listener zum Sammeln der Testergebnisse registrieren
+    CPPUNIT_NS :: TestResultCollector collectedresults;
+    testresult.addListener (&collectedresults);
+
+    // Listener zur Ausgabe der Ergebnisse einzelner Tests
+    CPPUNIT_NS :: BriefTestProgressListener progress;
+    testresult.addListener (&progress);
+
+    // Test-Suite ueber die Registry im Test-Runner einfuegen
+    CPPUNIT_NS :: TestRunner testrunner;
+    testrunner.addTest (CPPUNIT_NS :: TestFactoryRegistry :: getRegistry ().makeTest ());
+    testrunner.run (testresult);
+
+    // Resultate im Compiler-Format ausgeben
+	CPPUNIT_NS :: CompilerOutputter compileroutputter (&collectedresults, std::cerr);
+    compileroutputter.write ();
+
+    // Rueckmeldung, ob Tests erfolgreich waren
+    return collectedresults.wasSuccessful () ? 0 : 1;
+}

+ 0 - 0
test/unit/ut3DSLoader.cpp


+ 0 - 0
test/unit/utASELoader.cpp


+ 0 - 0
test/unit/utFixInfacingNormals.cpp


+ 0 - 0
test/unit/utGenNormals.cpp


+ 0 - 0
test/unit/utGenSmoothNormals.cpp


+ 0 - 0
test/unit/utImproveCacheLocality.cpp


+ 0 - 0
test/unit/utJoinVertices.cpp


+ 82 - 0
test/unit/utLimitBoneWeights.cpp

@@ -0,0 +1,82 @@
+
+#include "utLimitBoneWeights.h"
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION (LimitBoneWeightsTest);
+
+void LimitBoneWeightsTest :: setUp (void)
+{
+	// construct the process
+	this->piProcess = new LimitBoneWeightsProcess();
+
+	// now need to create a nice mesh for testing purposes
+	this->pcMesh = new aiMesh();
+
+	pcMesh->mNumVertices = 500;
+	pcMesh->mVertices = new aiVector3D[500]; // uninit.
+	pcMesh->mNumBones = 30;
+	pcMesh->mBones = new aiBone*[30];
+	unsigned int iCur = 0;
+	for (unsigned int i = 0; i < 30;++i)
+	{
+		aiBone* pc = pcMesh->mBones[i] = new aiBone();
+		pc->mNumWeights = 250;
+		pc->mWeights = new aiVertexWeight[pc->mNumWeights];
+		for (unsigned int qq = 0; qq < pc->mNumWeights;++qq)
+		{
+			aiVertexWeight& v = pc->mWeights[qq];
+			v.mVertexId = iCur++;
+			if (500 == iCur)iCur = 0;
+			v.mWeight = 1.0f / 15; // each vertex should occur once in two bones
+		}
+	}
+}
+
+void LimitBoneWeightsTest :: tearDown (void)
+{
+	delete this->pcMesh;
+	delete this->piProcess;
+}
+
+void LimitBoneWeightsTest :: testProcess(void)
+{
+	// execute the step on the given data
+	this->piProcess->ProcessMesh(this->pcMesh);
+
+	// check whether everything is ok ...
+	typedef std::vector<LimitBoneWeightsProcess::Weight> VertexWeightList;
+	VertexWeightList* asWeights = new VertexWeightList[pcMesh->mNumVertices];
+
+	for (unsigned int i = 0; i < pcMesh->mNumVertices;++i)
+		asWeights[i].reserve(4);
+
+	// sort back as per-vertex lists
+	for (unsigned int i = 0; i < pcMesh->mNumBones;++i)
+	{
+		aiBone& pcBone = **(pcMesh->mBones+i);
+		for (unsigned int q = 0; q < pcBone.mNumWeights;++q)
+		{
+			aiVertexWeight weight = pcBone.mWeights[q];
+			asWeights[weight.mVertexId].push_back(LimitBoneWeightsProcess::Weight (i,weight.mWeight));
+		}
+	}
+
+	// now validate the size of the lists and check whether all weights sum to 1.0f
+	for (unsigned int i = 0; i < pcMesh->mNumVertices;++i)
+	{
+		CPPUNIT_ASSERT( asWeights[i].size() <= 4 );
+		float fSum = 0.0f;
+		for (VertexWeightList::const_iterator
+			iter =  asWeights[i].begin();
+			iter != asWeights[i].end();++iter)
+		{
+			fSum += (*iter).mWeight;
+		}
+		CPPUNIT_ASSERT( fSum >= 0.95 && fSum <= 1.04);
+	}
+
+	// delete allocated storage
+	delete[] asWeights;
+
+	// everything seems to be OK
+}

+ 38 - 0
test/unit/utLimitBoneWeights.h

@@ -0,0 +1,38 @@
+#ifndef TESTLBW_H
+#define TESTLBW_H
+
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <aiTypes.h>
+#include <aiMesh.h>
+#include <aiScene.h>
+#include <LimitBoneWeightsProcess.h>
+
+
+using namespace std;
+using namespace Assimp;
+
+class LimitBoneWeightsTest : public CPPUNIT_NS :: TestFixture
+{
+    CPPUNIT_TEST_SUITE (LimitBoneWeightsTest);
+    CPPUNIT_TEST (testProcess);
+    CPPUNIT_TEST_SUITE_END ();
+
+    public:
+        void setUp (void);
+        void tearDown (void);
+
+    protected:
+
+        void  testProcess (void);
+		
+   
+	private:
+
+		LimitBoneWeightsProcess* piProcess;
+		aiMesh* pcMesh;
+
+};
+
+#endif 

+ 0 - 0
test/unit/utMDLLoader.cpp


+ 0 - 0
test/unit/utMaterialSystem.cpp


+ 0 - 0
test/unit/utOBJLoader.cpp


+ 0 - 0
test/unit/utPretransformVertices.cpp


+ 61 - 0
test/unit/utRemoveComments.cpp

@@ -0,0 +1,61 @@
+
+
+#include "utRemoveComments.h"
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION (RemoveCommentsTest);
+
+void RemoveCommentsTest :: setUp (void)
+{
+	// nothing to do here
+}
+
+void RemoveCommentsTest :: tearDown (void)
+{
+	// nothing to do here
+}
+
+void RemoveCommentsTest :: testSingleLineComments (void)
+{
+	const char* szTest = "int i = 0; \n"
+		"if (4 == //)\n"
+		"\ttrue) { // do something here \n"
+		"\t// hello ... and bye //\n";
+
+	
+	char* szTest2 = new char[::strlen(szTest)+1];
+	::strcpy(szTest2,szTest);
+
+	const char* szTestResult = "int i = 0; \n"
+		"if (4 ==    \n"
+		"\ttrue) {                      \n"
+		"\t                       \n";
+
+	CommentRemover::RemoveLineComments("//",szTest2,' ');
+	CPPUNIT_ASSERT(0 == ::strcmp(szTest2,szTestResult));
+
+	delete[] szTest2;
+}
+
+void RemoveCommentsTest :: testMultiLineComments (void)
+{
+	char* szTest = 
+		"/* comment to be removed */\n"
+		"valid text /* \n "
+		" comment across multiple lines */"
+		" / * Incomplete comment */ /* /* multiple comments */ */";
+
+	const char* szTestResult = 
+		"                           \n"
+		"valid text      "
+		"                                 "
+		" / * Incomplete comment */                            */";
+
+	char* szTest2 = new char[::strlen(szTest)+1];
+	::strcpy(szTest2,szTest);
+
+	CommentRemover::RemoveMultiLineComments("/*","*/",szTest2,' ');
+	CPPUNIT_ASSERT(0 == ::strcmp(szTest2,szTestResult));
+
+	delete[] szTest2;
+}

+ 35 - 0
test/unit/utRemoveComments.h

@@ -0,0 +1,35 @@
+#ifndef REMOVECOMMENTS_H
+#define REMOVECOMMENTS_H
+
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include "aiTypes.h"
+#include <RemoveComments.h>
+
+
+using namespace std;
+using namespace Assimp;
+
+class RemoveCommentsTest : public CPPUNIT_NS :: TestFixture
+{
+    CPPUNIT_TEST_SUITE (RemoveCommentsTest);
+    CPPUNIT_TEST (testSingleLineComments);
+	CPPUNIT_TEST (testMultiLineComments);
+    CPPUNIT_TEST_SUITE_END ();
+
+    public:
+        void setUp (void);
+        void tearDown (void);
+
+    protected:
+
+        void testSingleLineComments (void);
+		void testMultiLineComments (void);
+		
+   
+	private:
+
+};
+
+#endif 

+ 0 - 0
test/unit/utSplitLargeMeshes.cpp


+ 0 - 0
test/unit/utTextureTransform.cpp


+ 193 - 0
test/unit/utVertexTriangleAdjacency.cpp

@@ -0,0 +1,193 @@
+
+
+
+#include "utVertexTriangleAdjacency.h"
+#include <math.h>
+#include <time.h>
+
+CPPUNIT_TEST_SUITE_REGISTRATION (VTAdjacency);
+
+void VTAdjacency :: setUp (void)
+{
+	// seed the randomizer
+	time_t t;time(&t);
+	srand((unsigned int)t);
+
+	// build a test mesh with randomized input data
+	// *******************************************************************************
+	pMesh = new aiMesh();
+
+	pMesh->mNumVertices = 500;
+	pMesh->mNumFaces = 600;
+
+	pMesh->mFaces = new aiFace[600];
+	unsigned int iCurrent = 0;
+	for (unsigned int i = 0; i < 600;++i)
+	{
+		aiFace& face = pMesh->mFaces[i];
+		face.mNumIndices = 3;
+		face.mIndices = new unsigned int[3];
+
+		if (499 == iCurrent)iCurrent = 0;
+		face.mIndices[0] = iCurrent++;
+
+
+		while(face.mIndices[0] == ( face.mIndices[1] = unsigned int(((float)rand()/RAND_MAX)*499)));
+		while(face.mIndices[0] == ( face.mIndices[2] = unsigned int(((float)rand()/RAND_MAX)*499)) ||
+			face.mIndices[1] == face.mIndices[2]);
+	}
+
+
+	// build a second test mesh - this one is extremely small
+	// *******************************************************************************
+	pMesh2 = new aiMesh();
+
+	pMesh2->mNumVertices = 5;
+	pMesh2->mNumFaces = 3;
+
+	pMesh2->mFaces = new aiFace[3];
+	pMesh2->mFaces[0].mIndices = new unsigned int[3];
+	pMesh2->mFaces[1].mIndices = new unsigned int[3];
+	pMesh2->mFaces[2].mIndices = new unsigned int[3];
+
+	pMesh2->mFaces[0].mIndices[0] = 1;
+	pMesh2->mFaces[0].mIndices[1] = 3;
+	pMesh2->mFaces[0].mIndices[2] = 2;
+
+	pMesh2->mFaces[1].mIndices[0] = 0;
+	pMesh2->mFaces[1].mIndices[1] = 2;
+	pMesh2->mFaces[1].mIndices[2] = 3;
+
+	pMesh2->mFaces[2].mIndices[0] = 3;
+	pMesh2->mFaces[2].mIndices[1] = 0;
+	pMesh2->mFaces[2].mIndices[2] = 4;
+
+
+	// build a third test mesh which does not reference all vertices
+	// *******************************************************************************
+	pMesh3 = new aiMesh();
+
+	pMesh3->mNumVertices = 500;
+	pMesh3->mNumFaces = 600;
+
+	pMesh3->mFaces = new aiFace[600];
+	iCurrent = 0;
+	for (unsigned int i = 0; i < 600;++i)
+	{
+		aiFace& face = pMesh3->mFaces[i];
+		face.mNumIndices = 3;
+		face.mIndices = new unsigned int[3];
+
+		if (499 == iCurrent)iCurrent = 0;
+		face.mIndices[0] = iCurrent++;
+
+		if (499 == iCurrent)iCurrent = 0;
+		face.mIndices[1] = iCurrent++;
+
+		if (499 == iCurrent)iCurrent = 0;
+		face.mIndices[2] = iCurrent++;
+
+		if (rand() > RAND_MAX/2 && face.mIndices[0])
+		{
+			face.mIndices[0]--;
+		}
+		else if (face.mIndices[1]) face.mIndices[1]--;
+	}
+}
+
+void VTAdjacency :: tearDown (void) 
+{
+	delete pMesh;
+	pMesh = 0;
+
+	delete pMesh2;
+	pMesh2 = 0;
+
+	delete pMesh3;
+	pMesh3 = 0;
+}
+
+void VTAdjacency :: largeRandomDataSet (void)
+{
+	checkMesh(pMesh);
+}
+
+void VTAdjacency :: smallDataSet (void)
+{
+	checkMesh(pMesh2);
+}
+
+void VTAdjacency :: unreferencedVerticesSet (void)
+{
+	checkMesh(pMesh3);
+}
+
+void VTAdjacency :: checkMesh (aiMesh* pMesh)
+{
+	pAdj = new VertexTriangleAdjacency(pMesh->mFaces,pMesh->mNumFaces,pMesh->mNumVertices,true);
+
+	
+	unsigned int* const piNum = pAdj->mLiveTriangles;
+
+	// check the primary adjacency table and check whether all faces
+	// are contained in the list
+	unsigned int maxOfs = 0;
+	for (unsigned int i = 0; i < pMesh->mNumFaces;++i)
+	{
+		aiFace& face = pMesh->mFaces[i];
+		for (unsigned int qq = 0; qq < 3 ;++qq)
+		{
+			const unsigned int idx = face.mIndices[qq];
+			const unsigned int num = piNum[idx];
+
+			// go to this offset
+			const unsigned int ofs = pAdj->mOffsetTable[idx];
+			maxOfs = std::max(ofs+num,maxOfs);
+			unsigned int* pi = &pAdj->mAdjacencyTable[ofs];
+
+			// and search for us ...
+			unsigned int tt = 0;
+			for (; tt < num;++tt,++pi)
+			{
+				if (i == *pi)
+				{
+					// mask our entry in the table. Finally all entries should be masked
+					*pi = 0xffffffff;
+
+					// there shouldn't be two entries for the same face
+					break;
+				}
+			}
+			// assert if *this* vertex has not been found in the table
+			CPPUNIT_ASSERT(tt < num);
+		}
+	}
+
+	// now check whether there are invalid faces
+	const unsigned int* pi = pAdj->mAdjacencyTable;
+	for (unsigned int i = 0; i < maxOfs;++i,++pi)
+	{
+		CPPUNIT_ASSERT(0xffffffff == *pi);
+	}
+
+	// check the numTrianglesPerVertex table
+	for (unsigned int i = 0; i < pMesh->mNumFaces;++i)
+	{
+		aiFace& face = pMesh->mFaces[i];
+		for (unsigned int qq = 0; qq < 3 ;++qq)
+		{
+			const unsigned int idx = face.mIndices[qq];
+
+			// we should not reach 0 here ...
+			CPPUNIT_ASSERT( 0 != piNum[idx]);
+			piNum[idx]--;
+		}
+	}
+
+	// check whether we reached 0 in all entries
+	for (unsigned int i = 0; i < pMesh->mNumVertices;++i)
+	{
+		CPPUNIT_ASSERT(!piNum[i]);
+	}
+	delete pAdj;
+}

+ 41 - 0
test/unit/utVertexTriangleAdjacency.h

@@ -0,0 +1,41 @@
+#ifndef VTADJ_H
+#define VTADJ_H
+
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include "aiTypes.h"
+#include "aiMesh.h"
+#include <VertexTriangleAdjacency.h>
+
+
+using namespace std;
+using namespace Assimp;
+
+class VTAdjacency : public CPPUNIT_NS :: TestFixture
+{
+    CPPUNIT_TEST_SUITE (VTAdjacency);
+    CPPUNIT_TEST (largeRandomDataSet);
+	CPPUNIT_TEST (smallDataSet);
+	CPPUNIT_TEST (unreferencedVerticesSet);
+    CPPUNIT_TEST_SUITE_END ();
+
+    public:
+        void setUp (void);
+        void tearDown (void);
+
+    protected:
+
+        void largeRandomDataSet (void);
+		void smallDataSet (void);
+		void unreferencedVerticesSet (void);
+
+		void checkMesh(aiMesh* pMesh);
+   
+	private:
+
+		VertexTriangleAdjacency* pAdj;
+		aiMesh* pMesh, *pMesh2, *pMesh3;
+};
+
+#endif 

+ 5 - 5
tools/assimp_view/LogDisplay.cpp

@@ -107,15 +107,18 @@ void CLogDisplay::OnRender()
 
 
 	unsigned int iCnt = 0;
 	unsigned int iCnt = 0;
 	RECT sRect;
 	RECT sRect;
-	sRect.left = 0;
+	sRect.left = 10;
 	sRect.top = 10;
 	sRect.top = 10;
-	
+
 	RECT sWndRect;
 	RECT sWndRect;
 	GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sWndRect);
 	GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sWndRect);
 	sWndRect.right -= sWndRect.left;
 	sWndRect.right -= sWndRect.left;
 	sWndRect.bottom -= sWndRect.top;
 	sWndRect.bottom -= sWndRect.top;
 	sWndRect.left = sWndRect.top = 0;
 	sWndRect.left = sWndRect.top = 0;
 
 
+	sRect.right = sWndRect.right - 30;
+	sRect.bottom = sWndRect.bottom;
+
 	// if no asset is loaded draw a "no asset loaded" text in the center
 	// if no asset is loaded draw a "no asset loaded" text in the center
 	if (!g_pcAsset)
 	if (!g_pcAsset)
 		{
 		{
@@ -153,9 +156,6 @@ void CLogDisplay::OnRender()
 			-1,&sWndRect,DT_CENTER | DT_VCENTER,D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0xFF));
 			-1,&sWndRect,DT_CENTER | DT_VCENTER,D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0xFF));
 		}
 		}
 
 
-	sRect.right = sWndRect.right - 30;
-	sRect.bottom = sWndRect.bottom;
-
 	// update all elements in the queue and render them
 	// update all elements in the queue and render them
 	for (std::list<SEntry>::iterator
 	for (std::list<SEntry>::iterator
 		i =  this->asEntries.begin();
 		i =  this->asEntries.begin();

+ 4 - 0
tools/assimp_view/MessageProc.cpp

@@ -56,6 +56,8 @@ std::vector<std::string> g_aPreviousFiles;
 // history menu item
 // history menu item
 HMENU g_hHistoryMenu = NULL;
 HMENU g_hHistoryMenu = NULL;
 
 
+float g_fACMR = 3.0f;
+
 #define AI_VIEW_NUM_RECENT_FILES 0x8
 #define AI_VIEW_NUM_RECENT_FILES 0x8
 #define AI_VIEW_RECENT_FILE_ID(_n_) (5678 + _n_)
 #define AI_VIEW_RECENT_FILE_ID(_n_) (5678 + _n_)
 
 
@@ -2252,9 +2254,11 @@ int APIENTRY _tWinMain(HINSTANCE hInstance,
 				}
 				}
 			}
 			}
 
 
+	
 		// render the scene
 		// render the scene
 		CDisplay::Instance().OnRender();
 		CDisplay::Instance().OnRender();
 
 
+
 		g_dCurTime     = timeGetTime();
 		g_dCurTime     = timeGetTime();
 		g_fElpasedTime = (float)((g_dCurTime - g_dLastTime) * 0.001);
 		g_fElpasedTime = (float)((g_dCurTime - g_dLastTime) * 0.001);
 		g_dLastTime    = g_dCurTime;
 		g_dLastTime    = g_dCurTime;

BIN
tools/assimp_view/assimp_view.aps


+ 2 - 1
tools/assimp_view/assimp_view.cpp

@@ -133,7 +133,7 @@ DWORD WINAPI LoadThreadProc(LPVOID lpParameter)
 		aiProcess_GenSmoothNormals		| // generate smooth normal vectors if not existing
 		aiProcess_GenSmoothNormals		| // generate smooth normal vectors if not existing
 		aiProcess_ConvertToLeftHanded	| // convert everything to D3D left handed space
 		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
+		aiProcess_ValidateDataStructure | aiProcess_ImproveCacheLocality); // validate the output data structure
 
 
 	// get the end time of zje operation, calculate delta t
 	// get the end time of zje operation, calculate delta t
 	double fEnd = (double)timeGetTime();
 	double fEnd = (double)timeGetTime();
@@ -871,6 +871,7 @@ int CreateDevice (bool p_bMultiSample,bool p_bSuperSample,bool bHW /*= true*/)
 	sParams.BackBufferWidth			= (UINT)sRect.right;
 	sParams.BackBufferWidth			= (UINT)sRect.right;
 	sParams.BackBufferHeight		= (UINT)sRect.bottom;
 	sParams.BackBufferHeight		= (UINT)sRect.bottom;
 	sParams.SwapEffect				= D3DSWAPEFFECT_DISCARD;
 	sParams.SwapEffect				= D3DSWAPEFFECT_DISCARD;
+	sParams.BackBufferCount			= 1;
 
 
 	// check whether we can use a D32 depth buffer format
 	// check whether we can use a D32 depth buffer format
 	if (SUCCEEDED ( g_piD3D->CheckDepthStencilMatch(0,eType,
 	if (SUCCEEDED ( g_piD3D->CheckDepthStencilMatch(0,eType,

+ 4 - 0
tools/assimp_view/assimp_view.h

@@ -251,6 +251,10 @@ enum EClickPos
 	// HUD texture
 	// HUD texture
 	//
 	//
 	extern unsigned char* g_szImageMask			/*= NULL*/;
 	extern unsigned char* g_szImageMask			/*= NULL*/;
+
+
+	extern float g_fACMR /*= 3.0f*/;
+	extern IDirect3DQuery9* g_piQuery;
 	};
 	};
 
 
 #endif // !! AV_MAIN_H_INCLUDED
 #endif // !! AV_MAIN_H_INCLUDED

+ 6 - 6
tools/assimp_view/assimp_view.rc

@@ -56,7 +56,7 @@ BEGIN
 END
 END
 
 
 IDD_DIALOGMAIN DIALOGEX 0, 0, 594, 384
 IDD_DIALOGMAIN DIALOGEX 0, 0, 594, 384
-STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
 EXSTYLE WS_EX_ACCEPTFILES
 EXSTYLE WS_EX_ACCEPTFILES
 CAPTION "Open Asset Import Library - ModelViewer "
 CAPTION "Open Asset Import Library - ModelViewer "
 MENU IDR_MENU1
 MENU IDR_MENU1
@@ -66,10 +66,10 @@ BEGIN
     CONTROL         "MultiSample image",IDC_TOGGLEMS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,173,80,10
     CONTROL         "MultiSample image",IDC_TOGGLEMS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,173,80,10
     CONTROL         "Toggle Wireframe",IDC_TOGGLEWIRE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,183,73,10
     CONTROL         "Toggle Wireframe",IDC_TOGGLEWIRE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,183,73,10
     CONTROL         "Disable Materials",IDC_TOGGLEMAT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,193,69,10
     CONTROL         "Disable Materials",IDC_TOGGLEMAT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,193,69,10
-    LTEXT           "Verts:",IDC_NUMVERTS,475,14,47,8
-    LTEXT           "Faces:\t",IDC_NUMFACES,539,14,27,8
-    LTEXT           "Mats:",IDC_NUMMATS,540,26,26,8
-    LTEXT           "FPS:",IDC_FPS,540,51,21,8
+    LTEXT           "Verts:",IDC_NUMVERTS,475,14,27,8
+    LTEXT           "Faces:\t",IDC_NUMFACES,539,14,22,8
+    LTEXT           "Mats:",IDC_NUMMATS,540,26,20,8
+    LTEXT           "FPS:",IDC_FPS,540,51,20,8
     CONTROL         "Display Normals",IDC_TOGGLENORMALS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,203,66,10
     CONTROL         "Display Normals",IDC_TOGGLENORMALS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,203,66,10
     CONTROL         "Toggle AutoRotate",IDC_AUTOROTATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,257,74,10
     CONTROL         "Toggle AutoRotate",IDC_AUTOROTATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,257,74,10
     CONTROL         130,IDC_STATIC,"Static",SS_BITMAP,0,360,600,25
     CONTROL         130,IDC_STATIC,"Static",SS_BITMAP,0,360,600,25
@@ -79,7 +79,7 @@ BEGIN
     EDITTEXT        IDC_EFPS,562,50,29,12,ES_AUTOHSCROLL | ES_READONLY
     EDITTEXT        IDC_EFPS,562,50,29,12,ES_AUTOHSCROLL | ES_READONLY
     CONTROL         "Rotate light sources",IDC_LIGHTROTATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,276,74,10
     CONTROL         "Rotate light sources",IDC_LIGHTROTATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,276,74,10
     CONTROL         "2 directional lights",IDC_3LIGHTS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,213,73,10
     CONTROL         "2 directional lights",IDC_3LIGHTS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,213,73,10
-    LTEXT           "Time:",IDC_LOADTIME,475,51,46,8
+    LTEXT           "Time:",IDC_LOADTIME,475,51,29,8
     EDITTEXT        IDC_ELOAD,504,50,32,12,ES_AUTOHSCROLL | ES_READONLY
     EDITTEXT        IDC_ELOAD,504,50,32,12,ES_AUTOHSCROLL | ES_READONLY
     CONTROL         "Zoom/Rotate",IDC_ZOOM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,267,58,10
     CONTROL         "Zoom/Rotate",IDC_ZOOM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,267,58,10
     CONTROL         "Low quality lighting",IDC_LOWQUALITY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,223,74,10
     CONTROL         "Low quality lighting",IDC_LOWQUALITY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,223,74,10

+ 11 - 3
tools/assimp_view/resource.h

@@ -151,6 +151,14 @@
 #define ID_SOLONG_SETSHADINGMODE        32820
 #define ID_SOLONG_SETSHADINGMODE        32820
 #define ID_SETSHADINGMODE_GOURAUD       32821
 #define ID_SETSHADINGMODE_GOURAUD       32821
 #define ID_SETSHADINGMODE_PHONG         32822
 #define ID_SETSHADINGMODE_PHONG         32822
+#define ID_OPTIMIZE_OPTIMIZEACMR        32823
+#define ID_OPTIMIZE_OPTIMIZEOVERDRAW    32824
+#define ID_OPTIMIZE_OPTIMIZEBOTH        32825
+#define ID_VERTEXCACHELOCALITY_FINDCURRENT 32826
+#define ID_VERTEXCACHELOCALITY_OPTIMIZE 32827
+#define ID_VERTEXCACHELOCALITY_FINDBEST 32828
+#define ID_OPTIMIZE_SCENEGRAPH          32829
+#define ID_SCENEGRAPH_SMALLESTPOSSIBLEGRAPH 32830
 #define IDC_STATIC                      -1
 #define IDC_STATIC                      -1
 
 
 // Next default values for new objects
 // Next default values for new objects
@@ -158,9 +166,9 @@
 #ifdef APSTUDIO_INVOKED
 #ifdef APSTUDIO_INVOKED
 #ifndef APSTUDIO_READONLY_SYMBOLS
 #ifndef APSTUDIO_READONLY_SYMBOLS
 #define _APS_NO_MFC                     1
 #define _APS_NO_MFC                     1
-#define _APS_NEXT_RESOURCE_VALUE        158
-#define _APS_NEXT_COMMAND_VALUE         32823
-#define _APS_NEXT_CONTROL_VALUE         1049
+#define _APS_NEXT_RESOURCE_VALUE        159
+#define _APS_NEXT_COMMAND_VALUE         32831
+#define _APS_NEXT_CONTROL_VALUE         1052
 #define _APS_NEXT_SYMED_VALUE           110
 #define _APS_NEXT_SYMED_VALUE           110
 #endif
 #endif
 #endif
 #endif

+ 762 - 0
workspaces/vc8/UnitTest.vcproj

@@ -0,0 +1,762 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8,00"
+	Name="UnitTest"
+	ProjectGUID="{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}"
+	RootNamespace="UnitTest"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+		<Platform
+			Name="x64"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="./../../bin/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
+			IntermediateDirectory="./../../obj/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\code;..\..\include"
+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="assimp.lib cppunitd.lib"
+				LinkIncremental="2"
+				SuppressStartupBanner="false"
+				AdditionalLibraryDirectories="..\..\lib\assimp_debug_win32"
+				IgnoreDefaultLibraryNames=""
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="./../../bin/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
+			IntermediateDirectory="./../../obj/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories="..\..\code;..\..\include"
+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+				RuntimeLibrary="0"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="assimp.lib cppunit.lib"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories="..\..\lib\assimp_release_win32"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|x64"
+			OutputDirectory="./../../bin/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
+			IntermediateDirectory="./../../obj/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\code;..\..\include"
+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="assimp.lib cppunitd.lib"
+				LinkIncremental="2"
+				SuppressStartupBanner="false"
+				AdditionalLibraryDirectories="..\..\lib\assimp_debug_x64"
+				IgnoreDefaultLibraryNames=""
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|x64"
+			OutputDirectory="./../../bin/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
+			IntermediateDirectory="./../../obj/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories="..\..\code;..\..\include"
+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+				RuntimeLibrary="0"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="assimp.lib cppunit.lib"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories="..\..\lib\assimp_release_x64"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release_DLL|Win32"
+			OutputDirectory="./../../bin/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
+			IntermediateDirectory="./../../obj/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories="..\..\code;..\..\include"
+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+				RuntimeLibrary="0"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="assimp.lib cppunit.lib"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories="..\..\lib\assimp_release_dll_win32"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release_DLL|x64"
+			OutputDirectory="./../../bin/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
+			IntermediateDirectory="./../../obj/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories="..\..\code;..\..\include"
+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+				RuntimeLibrary="0"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="assimp.lib cppunit.lib"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories="..\..\lib\assimp_release_dll_x64"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug_DLL|Win32"
+			OutputDirectory="./../../bin/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
+			IntermediateDirectory="./../../obj/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\code;..\..\include"
+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="assimp.lib cppunitd.lib"
+				LinkIncremental="2"
+				SuppressStartupBanner="false"
+				AdditionalLibraryDirectories="..\..\lib\assimp_debug_dll_win32"
+				IgnoreDefaultLibraryNames=""
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug_DLL|x64"
+			OutputDirectory="./../../bin/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
+			IntermediateDirectory="./../../obj/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\code;..\..\include"
+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="assimp.lib cppunitd.lib"
+				LinkIncremental="2"
+				SuppressStartupBanner="false"
+				AdditionalLibraryDirectories="..\..\lib\assimp_debug_dll_x64"
+				IgnoreDefaultLibraryNames=""
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="source"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath="..\..\test\unit\Main.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\test\unit\ut3DSLoader.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\test\unit\utASELoader.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\test\unit\utFixInfacingNormals.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\test\unit\utGenNormals.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\test\unit\utGenSmoothNormals.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\test\unit\utImproveCacheLocality.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\test\unit\utJoinVertices.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\test\unit\utLimitBoneWeights.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\test\unit\utMaterialSystem.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\test\unit\utMDLLoader.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\test\unit\utOBJLoader.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\test\unit\utPretransformVertices.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\test\unit\utRemoveComments.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\test\unit\utSplitLargeMeshes.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\test\unit\utTextureTransform.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\test\unit\utVertexTriangleAdjacency.cpp"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="headers"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath="..\..\test\unit\utLimitBoneWeights.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\test\unit\utRemoveComments.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\test\unit\utVertexTriangleAdjacency.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="resources"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>

+ 35 - 2
workspaces/vc8/assimp.sln

@@ -1,7 +1,7 @@
 
 
 Microsoft Visual Studio Solution File, Format Version 9.00
 Microsoft Visual Studio Solution File, Format Version 9.00
 # Visual Studio 2005
 # Visual Studio 2005
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "assimp_view", "assimp_view.vcproj", "{B17B959B-BB8A-4596-AF0F-A8C8DBBC3C5E}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AssimpView", "assimp_view.vcproj", "{B17B959B-BB8A-4596-AF0F-A8C8DBBC3C5E}"
 	ProjectSection(WebsiteProperties) = preProject
 	ProjectSection(WebsiteProperties) = preProject
 		Debug.AspNetCompiler.Debug = "True"
 		Debug.AspNetCompiler.Debug = "True"
 		Release.AspNetCompiler.Debug = "False"
 		Release.AspNetCompiler.Debug = "False"
@@ -10,12 +10,21 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "assimp_view", "assimp_view.
 		{5691E159-2D9B-407F-971F-EA5C592DC524} = {5691E159-2D9B-407F-971F-EA5C592DC524}
 		{5691E159-2D9B-407F-971F-EA5C592DC524} = {5691E159-2D9B-407F-971F-EA5C592DC524}
 	EndProjectSection
 	EndProjectSection
 EndProject
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "assimp", "assimp.vcproj", "{5691E159-2D9B-407F-971F-EA5C592DC524}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Assimp", "assimp.vcproj", "{5691E159-2D9B-407F-971F-EA5C592DC524}"
 	ProjectSection(WebsiteProperties) = preProject
 	ProjectSection(WebsiteProperties) = preProject
 		Debug.AspNetCompiler.Debug = "True"
 		Debug.AspNetCompiler.Debug = "True"
 		Release.AspNetCompiler.Debug = "False"
 		Release.AspNetCompiler.Debug = "False"
 	EndProjectSection
 	EndProjectSection
 EndProject
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTest", "UnitTest.vcproj", "{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}"
+	ProjectSection(WebsiteProperties) = preProject
+		Debug.AspNetCompiler.Debug = "True"
+		Release.AspNetCompiler.Debug = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{5691E159-2D9B-407F-971F-EA5C592DC524} = {5691E159-2D9B-407F-971F-EA5C592DC524}
+	EndProjectSection
+EndProject
 Global
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug_DLL_Java|Win32 = Debug_DLL_Java|Win32
 		Debug_DLL_Java|Win32 = Debug_DLL_Java|Win32
@@ -80,6 +89,30 @@ Global
 		{5691E159-2D9B-407F-971F-EA5C592DC524}.Release|Win32.Build.0 = Release|Win32
 		{5691E159-2D9B-407F-971F-EA5C592DC524}.Release|Win32.Build.0 = Release|Win32
 		{5691E159-2D9B-407F-971F-EA5C592DC524}.Release|x64.ActiveCfg = Release|x64
 		{5691E159-2D9B-407F-971F-EA5C592DC524}.Release|x64.ActiveCfg = Release|x64
 		{5691E159-2D9B-407F-971F-EA5C592DC524}.Release|x64.Build.0 = Release|x64
 		{5691E159-2D9B-407F-971F-EA5C592DC524}.Release|x64.Build.0 = Release|x64
+		{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug_DLL_Java|Win32.ActiveCfg = Debug_DLL|Win32
+		{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug_DLL_Java|Win32.Build.0 = Debug_DLL|Win32
+		{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug_DLL_Java|x64.ActiveCfg = Debug_DLL|x64
+		{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug_DLL_Java|x64.Build.0 = Debug_DLL|x64
+		{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug_DLL|Win32.ActiveCfg = Debug_DLL|Win32
+		{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug_DLL|Win32.Build.0 = Debug_DLL|Win32
+		{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug_DLL|x64.ActiveCfg = Debug_DLL|x64
+		{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug_DLL|x64.Build.0 = Debug_DLL|x64
+		{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug|Win32.ActiveCfg = Debug|Win32
+		{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug|Win32.Build.0 = Debug|Win32
+		{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug|x64.ActiveCfg = Debug|x64
+		{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug|x64.Build.0 = Debug|x64
+		{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release_DLL_Java|Win32.ActiveCfg = Release_DLL|Win32
+		{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release_DLL_Java|Win32.Build.0 = Release_DLL|Win32
+		{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release_DLL_Java|x64.ActiveCfg = Release_DLL|x64
+		{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release_DLL_Java|x64.Build.0 = Release_DLL|x64
+		{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release_DLL|Win32.ActiveCfg = Release_DLL|Win32
+		{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release_DLL|Win32.Build.0 = Release_DLL|Win32
+		{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release_DLL|x64.ActiveCfg = Release_DLL|x64
+		{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release_DLL|x64.Build.0 = Release_DLL|x64
+		{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release|Win32.ActiveCfg = Release|Win32
+		{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release|Win32.Build.0 = Release|Win32
+		{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release|x64.ActiveCfg = Release|x64
+		{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release|x64.Build.0 = Release|x64
 	EndGlobalSection
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
 		HideSolutionNode = FALSE

+ 17 - 1
workspaces/vc8/assimp.vcproj

@@ -2,7 +2,7 @@
 <VisualStudioProject
 <VisualStudioProject
 	ProjectType="Visual C++"
 	ProjectType="Visual C++"
 	Version="8,00"
 	Version="8,00"
-	Name="assimp"
+	Name="Assimp"
 	ProjectGUID="{5691E159-2D9B-407F-971F-EA5C592DC524}"
 	ProjectGUID="{5691E159-2D9B-407F-971F-EA5C592DC524}"
 	RootNamespace="assimp"
 	RootNamespace="assimp"
 	>
 	>
@@ -1014,6 +1014,10 @@
 				RelativePath="..\..\code\GenVertexNormalsProcess.h"
 				RelativePath="..\..\code\GenVertexNormalsProcess.h"
 				>
 				>
 			</File>
 			</File>
+			<File
+				RelativePath="..\..\code\ImproveCacheLocality.h"
+				>
+			</File>
 			<File
 			<File
 				RelativePath="..\..\code\JoinVerticesProcess.h"
 				RelativePath="..\..\code\JoinVerticesProcess.h"
 				>
 				>
@@ -1070,6 +1074,10 @@
 				RelativePath="..\..\code\ValidateDataStructure.h"
 				RelativePath="..\..\code\ValidateDataStructure.h"
 				>
 				>
 			</File>
 			</File>
+			<File
+				RelativePath="..\..\code\VertexTriangleAdjacency.h"
+				>
+			</File>
 			<Filter
 			<Filter
 				Name="ObjLoader"
 				Name="ObjLoader"
 				>
 				>
@@ -1342,6 +1350,10 @@
 				RelativePath="..\..\code\Importer.cpp"
 				RelativePath="..\..\code\Importer.cpp"
 				>
 				>
 			</File>
 			</File>
+			<File
+				RelativePath="..\..\code\ImproveCacheLocality.cpp"
+				>
+			</File>
 			<File
 			<File
 				RelativePath="..\..\code\JoinVerticesProcess.cpp"
 				RelativePath="..\..\code\JoinVerticesProcess.cpp"
 				>
 				>
@@ -1386,6 +1398,10 @@
 				RelativePath="..\..\code\ValidateDataStructure.cpp"
 				RelativePath="..\..\code\ValidateDataStructure.cpp"
 				>
 				>
 			</File>
 			</File>
+			<File
+				RelativePath="..\..\code\VertexTriangleAdjacency.cpp"
+				>
+			</File>
 			<Filter
 			<Filter
 				Name="ObjLoader"
 				Name="ObjLoader"
 				>
 				>

+ 30 - 30
workspaces/vc8/assimp_view.vcproj

@@ -2,7 +2,7 @@
 <VisualStudioProject
 <VisualStudioProject
 	ProjectType="Visual C++"
 	ProjectType="Visual C++"
 	Version="8,00"
 	Version="8,00"
-	Name="assimp_view"
+	Name="AssimpView"
 	ProjectGUID="{B17B959B-BB8A-4596-AF0F-A8C8DBBC3C5E}"
 	ProjectGUID="{B17B959B-BB8A-4596-AF0F-A8C8DBBC3C5E}"
 	RootNamespace="assimp_view"
 	RootNamespace="assimp_view"
 	Keyword="Win32Proj"
 	Keyword="Win32Proj"
@@ -100,12 +100,11 @@
 			/>
 			/>
 		</Configuration>
 		</Configuration>
 		<Configuration
 		<Configuration
-			Name="Release|Win32"
+			Name="Debug|x64"
 			OutputDirectory="$(SolutionDir)..\..\tools\build\$(ConfigurationName)_$(PlatformName)"
 			OutputDirectory="$(SolutionDir)..\..\tools\build\$(ConfigurationName)_$(PlatformName)"
 			IntermediateDirectory="$(SolutionDir)..\..\tools\build\$(ConfigurationName)_$(PlatformName)\obj"
 			IntermediateDirectory="$(SolutionDir)..\..\tools\build\$(ConfigurationName)_$(PlatformName)\obj"
 			ConfigurationType="1"
 			ConfigurationType="1"
 			CharacterSet="2"
 			CharacterSet="2"
-			WholeProgramOptimization="1"
 			>
 			>
 			<Tool
 			<Tool
 				Name="VCPreBuildEventTool"
 				Name="VCPreBuildEventTool"
@@ -121,15 +120,21 @@
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCMIDLTool"
 				Name="VCMIDLTool"
+				TargetEnvironment="3"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCCLCompilerTool"
 				Name="VCCLCompilerTool"
+				Optimization="0"
 				AdditionalIncludeDirectories="&quot;$(DXSDK_DIR)include&quot;;..\..\include;..\..\code"
 				AdditionalIncludeDirectories="&quot;$(DXSDK_DIR)include&quot;;..\..\include;..\..\code"
-				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS"
-				RuntimeLibrary="0"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				SmallerTypeCheck="true"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="true"
 				UsePrecompiledHeader="2"
 				UsePrecompiledHeader="2"
 				WarningLevel="3"
 				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
+				Detect64BitPortabilityProblems="false"
 				DebugInformationFormat="3"
 				DebugInformationFormat="3"
 			/>
 			/>
 			<Tool
 			<Tool
@@ -144,16 +149,12 @@
 			<Tool
 			<Tool
 				Name="VCLinkerTool"
 				Name="VCLinkerTool"
 				AdditionalDependencies="d3d9.lib d3dx9.lib comdlg32.lib assimp.lib winmm.lib comctl32.lib user32.lib advapi32.lib shell32.lib Gdi32.lib"
 				AdditionalDependencies="d3d9.lib d3dx9.lib comdlg32.lib assimp.lib winmm.lib comctl32.lib user32.lib advapi32.lib shell32.lib Gdi32.lib"
-				OutputFile="$(OutDir)\assimpview32.exe"
-				LinkIncremental="1"
-				AdditionalLibraryDirectories="..\..\lib\assimp_release_win32;&quot;$(DXSDK_DIR)lib\x86&quot;"
-				IgnoreAllDefaultLibraries="false"
-				IgnoreDefaultLibraryNames=""
+				OutputFile="$(OutDir)\assimpview64d.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="..\..\lib\assimp_debug_x64;&quot;$(DXSDK_DIR)lib\x64&quot;"
 				GenerateDebugInformation="true"
 				GenerateDebugInformation="true"
 				SubSystem="2"
 				SubSystem="2"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				TargetMachine="1"
+				TargetMachine="17"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCALinkTool"
 				Name="VCALinkTool"
@@ -181,11 +182,12 @@
 			/>
 			/>
 		</Configuration>
 		</Configuration>
 		<Configuration
 		<Configuration
-			Name="Debug|x64"
+			Name="Release|Win32"
 			OutputDirectory="$(SolutionDir)..\..\tools\build\$(ConfigurationName)_$(PlatformName)"
 			OutputDirectory="$(SolutionDir)..\..\tools\build\$(ConfigurationName)_$(PlatformName)"
 			IntermediateDirectory="$(SolutionDir)..\..\tools\build\$(ConfigurationName)_$(PlatformName)\obj"
 			IntermediateDirectory="$(SolutionDir)..\..\tools\build\$(ConfigurationName)_$(PlatformName)\obj"
 			ConfigurationType="1"
 			ConfigurationType="1"
 			CharacterSet="2"
 			CharacterSet="2"
+			WholeProgramOptimization="1"
 			>
 			>
 			<Tool
 			<Tool
 				Name="VCPreBuildEventTool"
 				Name="VCPreBuildEventTool"
@@ -201,21 +203,15 @@
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCMIDLTool"
 				Name="VCMIDLTool"
-				TargetEnvironment="3"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCCLCompilerTool"
 				Name="VCCLCompilerTool"
-				Optimization="0"
 				AdditionalIncludeDirectories="&quot;$(DXSDK_DIR)include&quot;;..\..\include;..\..\code"
 				AdditionalIncludeDirectories="&quot;$(DXSDK_DIR)include&quot;;..\..\include;..\..\code"
-				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS"
-				MinimalRebuild="true"
-				BasicRuntimeChecks="3"
-				SmallerTypeCheck="true"
-				RuntimeLibrary="1"
-				EnableFunctionLevelLinking="true"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS"
+				RuntimeLibrary="0"
 				UsePrecompiledHeader="2"
 				UsePrecompiledHeader="2"
 				WarningLevel="3"
 				WarningLevel="3"
-				Detect64BitPortabilityProblems="false"
+				Detect64BitPortabilityProblems="true"
 				DebugInformationFormat="3"
 				DebugInformationFormat="3"
 			/>
 			/>
 			<Tool
 			<Tool
@@ -230,12 +226,16 @@
 			<Tool
 			<Tool
 				Name="VCLinkerTool"
 				Name="VCLinkerTool"
 				AdditionalDependencies="d3d9.lib d3dx9.lib comdlg32.lib assimp.lib winmm.lib comctl32.lib user32.lib advapi32.lib shell32.lib Gdi32.lib"
 				AdditionalDependencies="d3d9.lib d3dx9.lib comdlg32.lib assimp.lib winmm.lib comctl32.lib user32.lib advapi32.lib shell32.lib Gdi32.lib"
-				OutputFile="$(OutDir)\assimpview64d.exe"
-				LinkIncremental="2"
-				AdditionalLibraryDirectories="..\..\lib\assimp_debug_x64;&quot;$(DXSDK_DIR)lib\x64&quot;"
+				OutputFile="$(OutDir)\assimpview32.exe"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories="..\..\lib\assimp_release_win32;&quot;$(DXSDK_DIR)lib\x86&quot;"
+				IgnoreAllDefaultLibraries="false"
+				IgnoreDefaultLibraryNames=""
 				GenerateDebugInformation="true"
 				GenerateDebugInformation="true"
 				SubSystem="2"
 				SubSystem="2"
-				TargetMachine="17"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCALinkTool"
 				Name="VCALinkTool"
@@ -417,7 +417,7 @@
 					/>
 					/>
 				</FileConfiguration>
 				</FileConfiguration>
 				<FileConfiguration
 				<FileConfiguration
-					Name="Release|Win32"
+					Name="Debug|x64"
 					>
 					>
 					<Tool
 					<Tool
 						Name="VCCLCompilerTool"
 						Name="VCCLCompilerTool"
@@ -425,7 +425,7 @@
 					/>
 					/>
 				</FileConfiguration>
 				</FileConfiguration>
 				<FileConfiguration
 				<FileConfiguration
-					Name="Debug|x64"
+					Name="Release|Win32"
 					>
 					>
 					<Tool
 					<Tool
 						Name="VCCLCompilerTool"
 						Name="VCCLCompilerTool"