Prechádzať zdrojové kódy

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

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@16 67173fc5-114c-0410-ac8e-9d2fd5bffc1f

aramis_acg 17 rokov pred
rodič
commit
2eb6fca408
60 zmenil súbory, kde vykonal 7025 pridanie a 1645 odobranie
  1. 3 3
      code/3DSHelper.h
  2. 1 1
      code/3DSLoader.cpp
  3. 1 1
      code/BaseProcess.h
  4. 128 0
      code/ByteSwap.h
  5. 5 0
      code/CalcTangentsProcess.cpp
  6. 5 4
      code/CalcTangentsProcess.h
  7. 7 0
      code/ConvertToLHProcess.cpp
  8. 42 1
      code/DefaultLogger.cpp
  9. 40 0
      code/DefaultLogger.h
  10. 24 14
      code/GenFaceNormalsProcess.cpp
  11. 2 2
      code/GenFaceNormalsProcess.h
  12. 23 10
      code/GenVertexNormalsProcess.cpp
  13. 35 35
      code/GenVertexNormalsProcess.h
  14. 7 0
      code/Importer.cpp
  15. 14 2
      code/JoinVerticesProcess.cpp
  16. 14 6
      code/JoinVerticesProcess.h
  17. 14 3
      code/KillNormalsProcess.cpp
  18. 34 35
      code/KillNormalsProcess.h
  19. 87 0
      code/MDLFileData.h
  20. 76 26
      code/MDLLoader.cpp
  21. 58 0
      code/MaterialSystem.cpp
  22. 21 0
      code/MaterialSystem.h
  23. 0 4
      code/ObjFileImporter.cpp
  24. 5 3
      code/PlyLoader.cpp
  25. 271 59
      code/PlyParser.cpp
  26. 3 3
      code/PlyParser.h
  27. 14 2
      code/SplitLargeMeshes.cpp
  28. 26 3
      code/TriangulateProcess.cpp
  29. 1 1
      code/TriangulateProcess.h
  30. 6 1
      code/XFileImporter.cpp
  31. 2 1
      include/aiMaterial.h
  32. 18 0
      include/aiTypes.h
  33. 7 0
      include/aiVector3D.h
  34. 78 10
      tools/assimp_view/AssetHelper.h
  35. 98 96
      tools/assimp_view/Background.cpp
  36. 2086 1
      tools/assimp_view/Display.cpp
  37. 442 0
      tools/assimp_view/Display.h
  38. 64 2
      tools/assimp_view/Input.cpp
  39. 0 1
      tools/assimp_view/LogDisplay.h
  40. 151 2
      tools/assimp_view/LogWindow.cpp
  41. 51 1
      tools/assimp_view/LogWindow.h
  42. 226 76
      tools/assimp_view/Material.cpp
  43. 187 0
      tools/assimp_view/MaterialManager.h
  44. 163 0
      tools/assimp_view/MeshRenderer.cpp
  45. 132 0
      tools/assimp_view/MeshRenderer.h
  46. 1003 71
      tools/assimp_view/MessageProc.cpp
  47. 213 0
      tools/assimp_view/Normals.cpp
  48. 5 1
      tools/assimp_view/RenderOptions.h
  49. 140 32
      tools/assimp_view/Shaders.cpp
  50. 3 0
      tools/assimp_view/Shaders.h
  51. BIN
      tools/assimp_view/assimp_view.aps
  52. 299 565
      tools/assimp_view/assimp_view.cpp
  53. 17 37
      tools/assimp_view/assimp_view.h
  54. 99 34
      tools/assimp_view/assimp_view.rc
  55. 246 243
      tools/assimp_view/help.rtf
  56. 51 3
      tools/assimp_view/resource.h
  57. 247 244
      tools/assimp_view/text1.bin
  58. BIN
      tools/assimp_view/txi.bmp
  59. 8 4
      workspaces/vc8/assimp.vcproj
  60. 22 2
      workspaces/vc8/assimp_view.vcproj

+ 3 - 3
code/3DSHelper.h

@@ -380,7 +380,7 @@ struct Material
 	{
 		static int iCnt = 0;
 		std::stringstream ss(mName);
-		ss << "%%_UNNAMED_" << iCnt++ << "_%%"; 
+		ss << "$$_UNNAMED_" << iCnt++ << "_$$"; 
 	}
 
 	//! Name of the material
@@ -433,7 +433,7 @@ struct Mesh
 	{
 		static int iCnt = 0;
 		std::stringstream ss(mName);
-		ss << "%%_UNNAMED_" << iCnt++ << "_%%"; 
+		ss << "$$_UNNAMED_" << iCnt++ << "_$$"; 
 	}
 
 	//! Name of the mesh
@@ -468,7 +468,7 @@ struct Node
 	{
 		static int iCnt = 0;
 		std::stringstream ss(mName);
-		ss << "%%_UNNAMED_" << iCnt++ << "_%%"; 
+		ss << "$$_UNNAMED_" << iCnt++ << "_$$"; 
 
 		mHierarchyPos = 0;
 		mHierarchyIndex = 0;

+ 1 - 1
code/3DSLoader.cpp

@@ -1213,7 +1213,7 @@ void Dot3DSImporter::ParseTextureChunk(int* piRemaining,Dot3DS::Texture* pcOut)
 		break;
 	// manually parse the blend factor
 	case Dot3DSFile::CHUNK_PERCENTW:
-		pcOut->mTextureBlend = (float)(*((short*)this->mCurrent)) / (float)0xFFFF;
+		pcOut->mTextureBlend = (float)(*((short*)this->mCurrent)) / (float)100;
 		break;
 
 	case Dot3DSFile::CHUNK_MAT_MAP_USCALE:

+ 1 - 1
code/BaseProcess.h

@@ -60,7 +60,7 @@ class BaseProcess
 {
 	friend class Importer;
 
-protected:
+public:
 	/** Constructor to be privately used by Importer */
 	BaseProcess();
 

+ 128 - 0
code/ByteSwap.h

@@ -0,0 +1,128 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development Team
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the 
+following conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the ASSIMP team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the ASSIMP Development Team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Helper class tp perform various byte oder swappings 
+   (e.g. little to big endian) */
+#ifndef AI_BYTESWAP_H_INC
+#define AI_BYTESWAP_H_INC
+
+#include "..\include\aiAssert.h"
+
+namespace Assimp
+{
+
+// ---------------------------------------------------------------------------
+/** \brief Defines some useful byte order swap routines.
+ * 
+ * This can e.g. be used for the conversion from and to littel and big endian.
+ * This is required by some loaders since some model formats
+ */
+class ByteSwap
+{
+	ByteSwap() {}
+
+public:
+	//! Swap the byte oder of 2 byte of data
+	//! \param szOut Buffer to be swapped
+	static inline void Swap2(char* szOut)
+	{
+		ai_assert(NULL != szOut);
+		std::swap(szOut[0],szOut[1]);
+	}
+
+	//! Swap the byte oder of 4 byte of data
+	//! \param szOut Buffer to be swapped
+	static inline void Swap4(char* szOut)
+	{
+		ai_assert(NULL != szOut);
+		std::swap(szOut[0],szOut[3]);
+		std::swap(szOut[1],szOut[2]);
+	}
+
+	//! Swap the byte oder of 8 byte of data
+	//! \param szOut Buffer to be swapped
+	static inline void Swap8(char* szOut)
+	{
+		ai_assert(NULL != szOut);
+		std::swap(szOut[0],szOut[7]);
+		std::swap(szOut[1],szOut[6]);
+		std::swap(szOut[2],szOut[5]);
+		std::swap(szOut[3],szOut[4]);
+	}
+
+	//! Swap a single precision float
+	//! \param fOut Float value to be swapped
+	static inline void Swap(float* fOut)
+	{
+		Swap4((char*)fOut);
+	}
+
+	//! Swap a double precision float
+	//! \param fOut Double value to be swapped
+	static inline void Swap(double* fOut)
+	{
+		Swap8((char*)fOut);
+	}
+
+	//! Swap a 16 bit integer
+	//! \param fOut Integer to be swapped
+	static inline void Swap(int16_t* fOut)
+	{
+		Swap2((char*)fOut);
+	}
+
+	//! Swap a 32 bit integer
+	//! \param fOut Integer to be swapped
+	static inline void Swap(int32_t* fOut)	
+	{
+		Swap4((char*)fOut);
+	}
+
+	//! Swap a 64 bit integer
+	//! \param fOut Integer to be swapped
+	static inline void Swap(int64_t* fOut)
+	{
+		Swap8((char*)fOut);
+	}
+};
+};
+
+
+#endif //!! AI_BYTESWAP_H_INC

+ 5 - 0
code/CalcTangentsProcess.cpp

@@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <vector>
 #include <assert.h>
+#include "DefaultLogger.h"
 #include "CalcTangentsProcess.h"
 #include "SpatialSort.h"
 #include "../include/aiPostProcess.h"
@@ -78,8 +79,12 @@ bool CalcTangentsProcess::IsActive( unsigned int pFlags) const
 // Executes the post processing step on the given imported data.
 void CalcTangentsProcess::Execute( aiScene* pScene)
 {
+	DefaultLogger::get()->debug("CalcTangentsProcess begin");
+
 	for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
 		ProcessMesh( pScene->mMeshes[a]);
+
+	DefaultLogger::get()->debug("CalcTangentsProcess finished");
 }
 
 // ------------------------------------------------------------------------------------------------

+ 5 - 4
code/CalcTangentsProcess.h

@@ -39,7 +39,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 
-/** @file Defines a post processing step to calculate tangents and bitangents on all imported meshes.*/
+/** @file Defines a post processing step to calculate tangents and 
+    bitangents on all imported meshes.*/
 #ifndef AI_CALCTANGENTSPROCESS_H_INC
 #define AI_CALCTANGENTSPROCESS_H_INC
 
@@ -53,14 +54,14 @@ namespace Assimp
 // ---------------------------------------------------------------------------
 /** The CalcTangentsProcess calculates the tangent and bitangent for any vertex
  * of all meshes. It is expected to be run before the JoinVerticesProcess runs
- * because the joining of vertices also considers tangents and bitangents for uniqueness.
-
+ * because the joining of vertices also considers tangents and bitangents for 
+ * uniqueness.
  */
 class CalcTangentsProcess : public BaseProcess
 {
 	friend class Importer;
 
-protected:
+public:
 	/** Constructor to be privately used by Importer */
 	CalcTangentsProcess();
 

+ 7 - 0
code/ConvertToLHProcess.cpp

@@ -2,6 +2,7 @@
  * to a left-handed coordinate system.
  */
 #include "ConvertToLHProcess.h"
+#include "DefaultLogger.h"
 #include "../include/aiPostProcess.h"
 #include "../include/aiMesh.h"
 #include "../include/aiAnim.h"
@@ -46,7 +47,12 @@ void ConvertToLHProcess::Execute( aiScene* pScene)
 {
 	// Check for an existent root node to proceed
 	if (NULL == pScene->mRootNode)
+	{
+		DefaultLogger::get()->error("ConvertToLHProcess fails, there is no root node");
 		return;
+	}
+
+	DefaultLogger::get()->debug("ConvertToLHProcess begin");
 
 	// transform the root node of the scene, the other nodes will follow then
 	ConvertToDX( pScene->mRootNode->mTransformation);
@@ -66,6 +72,7 @@ void ConvertToLHProcess::Execute( aiScene* pScene)
 				ProcessAnimation( boneAnim);
 		}
 	}
+	DefaultLogger::get()->debug("ConvertToLHProcess finished");
 }
 
 // ------------------------------------------------------------------------------------------------

+ 42 - 1
code/DefaultLogger.cpp

@@ -1,3 +1,44 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development Team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the ASSIMP team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the ASSIMP Development Team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
 #include "DefaultLogger.h"
 #include "aiAssert.h"
 #include "DefaultIOSystem.h"
@@ -142,11 +183,11 @@ void DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity )
 DefaultLogger::DefaultLogger( const std::string &name, LogSeverity severity ) :
 	m_Severity( severity )
 {
+	m_Streams.push_back( new Win32DebugLogStream() );
 	if (name.empty())
 		return;
 	
 	m_Streams.push_back( new FileLogStream( name ) );
-	m_Streams.push_back( new Win32DebugLogStream() );
 }
 
 // ---------------------------------------------------------------------------

+ 40 - 0
code/DefaultLogger.h

@@ -1,3 +1,43 @@
+/*
+Free Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development Team
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the 
+following conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the ASSIMP team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the ASSIMP Development Team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
 #include "Logger.h"
 #include <vector>
 

+ 24 - 14
code/GenFaceNormalsProcess.cpp

@@ -43,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * normals for all imported faces.
 */
 #include "GenFaceNormalsProcess.h"
+#include "DefaultLogger.h"
 #include "../include/aiPostProcess.h"
 #include "../include/aiMesh.h"
 #include "../include/aiScene.h"
@@ -71,23 +72,35 @@ bool GenFaceNormalsProcess::IsActive( unsigned int pFlags) const
 // Executes the post processing step on the given imported data.
 void GenFaceNormalsProcess::Execute( aiScene* pScene)
 {
+	DefaultLogger::get()->debug("GenFaceNormalsProcess begin");
+
+	bool bHas = false;
 	for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
-		this->GenMeshFaceNormals( pScene->mMeshes[a]);
+	{
+		if(this->GenMeshFaceNormals( pScene->mMeshes[a]))
+			bHas = true;
+	}
+	if (bHas)
+	{
+		DefaultLogger::get()->info("GenFaceNormalsProcess finished. "
+			"Face normals have been calculated");
+	}
+	else DefaultLogger::get()->debug("GenFaceNormalsProcess finished. "
+		"There was nothing to do");
 }
 
 // -------------------------------------------------------------------
 // Executes the post processing step on the given imported data.
-void GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh)
+bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh)
 {
-	if (NULL != pMesh->mNormals)return;
+	if (NULL != pMesh->mNormals)return false;
 
 	pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
 
 	for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
 	{
 		const aiFace& face = pMesh->mFaces[a];
-		
-		// assume it is a triangle
+
 		aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
 		aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
 		aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[2]];
@@ -95,14 +108,11 @@ void GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh)
 		aiVector3D pDelta1 = *pV2 - *pV1;
 		aiVector3D pDelta2 = *pV3 - *pV1;
 		aiVector3D vNor = pDelta1 ^ pDelta2;
-		
-		// NOTE: Never normalize here. Causes problems ...
-		//float fLength = vNor.Length();
-		//if (0.0f != fLength)vNor /= fLength;
-
-		pMesh->mNormals[face.mIndices[0]] = vNor;
-		pMesh->mNormals[face.mIndices[1]] = vNor;
-		pMesh->mNormals[face.mIndices[2]] = vNor;
+
+		for (unsigned int i = 0;i < face.mNumIndices;++i)
+		{
+			pMesh->mNormals[face.mIndices[i]] = vNor;
+		}
 	}
-	return;
+	return true;
 }

+ 2 - 2
code/GenFaceNormalsProcess.h

@@ -55,7 +55,7 @@ class GenFaceNormalsProcess : public BaseProcess
 {
 	friend class Importer;
 
-protected:
+public:
 	/** Constructor to be privately used by Importer */
 	GenFaceNormalsProcess();
 
@@ -80,7 +80,7 @@ public:
 
 
 private:
-	void GenMeshFaceNormals (aiMesh* pcMesh);
+	bool GenMeshFaceNormals (aiMesh* pcMesh);
 };
 
 } // end of namespace Assimp

+ 23 - 10
code/GenVertexNormalsProcess.cpp

@@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 #include "GenVertexNormalsProcess.h"
 #include "SpatialSort.h"
+#include "DefaultLogger.h"
 #include "../include/aiPostProcess.h"
 #include "../include/aiMesh.h"
 #include "../include/aiScene.h"
@@ -72,22 +73,35 @@ bool GenVertexNormalsProcess::IsActive( unsigned int pFlags) const
 // Executes the post processing step on the given imported data.
 void GenVertexNormalsProcess::Execute( aiScene* pScene)
 {
+	DefaultLogger::get()->debug("GenVertexNormalsProcess begin");
+
+	bool bHas = false;
 	for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
-		this->GenMeshVertexNormals( pScene->mMeshes[a]);
+	{
+		if(this->GenMeshVertexNormals( pScene->mMeshes[a]))
+			bHas = true;
+	}
+
+	if (bHas)
+	{
+		DefaultLogger::get()->info("GenVertexNormalsProcess finished. "
+			"Vertex normals have been calculated");
+	}
+	else DefaultLogger::get()->debug("GenVertexNormalsProcess finished. "
+		"There was nothing to do");
 }
 
 // -------------------------------------------------------------------
 // Executes the post processing step on the given imported data.
-void GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh)
+bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh)
 {
-	if (NULL != pMesh->mNormals)return;
+	if (NULL != pMesh->mNormals)return false;
 
 	pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
 	for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
 	{
 		const aiFace& face = pMesh->mFaces[a];
 
-		// assume it is a triangle
 		aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
 		aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
 		aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[2]];
@@ -95,12 +109,11 @@ void GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh)
 		aiVector3D pDelta1 = *pV2 - *pV1;
 		aiVector3D pDelta2 = *pV3 - *pV1;
 		aiVector3D vNor = pDelta1 ^ pDelta2;
-		float fLength = vNor.Length();
-		if (0.0f != fLength)vNor /= fLength;
 
-		pMesh->mNormals[face.mIndices[0]] = vNor;
-		pMesh->mNormals[face.mIndices[1]] = vNor;
-		pMesh->mNormals[face.mIndices[2]] = vNor;
+		for (unsigned int i = 0;i < face.mNumIndices;++i)
+		{
+			pMesh->mNormals[face.mIndices[i]] = vNor;
+		}
 	}
 
 	// calculate the position bounds so we have a reliable epsilon to 
@@ -141,5 +154,5 @@ void GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh)
 	delete pMesh->mNormals;
 	pMesh->mNormals = pcNew;
 
-	return;
+	return true;
 }

+ 35 - 35
code/GenVertexNormalsProcess.h

@@ -47,41 +47,41 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 namespace Assimp
 	{
 
-	// ---------------------------------------------------------------------------
-	/** The GenFaceNormalsProcess computes vertex normals for all vertizes of all meshes
+// ---------------------------------------------------------------------------
+/** The GenFaceNormalsProcess computes vertex normals for all vertizes of all meshes
+*/
+class GenVertexNormalsProcess : public BaseProcess
+{
+	friend class Importer;
+
+public:
+	/** Constructor to be privately used by Importer */
+	GenVertexNormalsProcess();
+
+	/** Destructor, private as well */
+	~GenVertexNormalsProcess();
+
+public:
+	// -------------------------------------------------------------------
+	/** Returns whether the processing step is present in the given flag field.
+	* @param pFlags The processing flags the importer was called with. A bitwise
+	*   combination of #aiPostProcessSteps.
+	* @return true if the process is present in this flag fields, false if not.
+	*/
+	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.
 	*/
-	class GenVertexNormalsProcess : public BaseProcess
-		{
-		friend class Importer;
-
-		protected:
-			/** Constructor to be privately used by Importer */
-			GenVertexNormalsProcess();
-
-			/** Destructor, private as well */
-			~GenVertexNormalsProcess();
-
-		public:
-			// -------------------------------------------------------------------
-			/** Returns whether the processing step is present in the given flag field.
-			* @param pFlags The processing flags the importer was called with. A bitwise
-			*   combination of #aiPostProcessSteps.
-			* @return true if the process is present in this flag fields, false if not.
-			*/
-			bool IsActive( unsigned int pFlags) const;
-
-			// -------------------------------------------------------------------
-			/** Executes the post processing step on the given imported data.
-			* At the moment a process is not supposed to fail.
-			* @param pScene The imported data to work at.
-			*/
-			void Execute( aiScene* pScene);
-
-
-		private:
-			void GenMeshVertexNormals (aiMesh* pcMesh);
-		};
-
-	} // end of namespace Assimp
+	void Execute( aiScene* pScene);
+
+
+private:
+	bool GenMeshVertexNormals (aiMesh* pcMesh);
+};
+
+}; // end of namespace Assimp
 
 #endif // !!AI_GENVERTEXNORMALPROCESS_H_INC

+ 7 - 0
code/Importer.cpp

@@ -86,6 +86,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "GenVertexNormalsProcess.h"
 #include "KillNormalsProcess.h"
 #include "SplitLargeMeshes.h"
+#include "DefaultLogger.h"
 
 using namespace Assimp;
 
@@ -96,6 +97,10 @@ Importer::Importer() :
 	mScene(NULL),
 	mErrorString("")	
 {
+	// construct a new logger
+	/*DefaultLogger::create( "test.log", DefaultLogger::VERBOSE );
+	DefaultLogger::get()->info("Start logging");*/
+
 	// allocate a default IO handler
 	mIOHandler = new DefaultIOSystem;
 
@@ -181,6 +186,7 @@ const aiScene* Importer::ReadFile( const std::string& pFile, unsigned int pFlags
 	if( !mIOHandler->Exists( pFile))
 	{
 		mErrorString = "Unable to open file \"" + pFile + "\".";
+		DefaultLogger::get()->error(mErrorString);
 		return NULL;
 	}
 
@@ -199,6 +205,7 @@ const aiScene* Importer::ReadFile( const std::string& pFile, unsigned int pFlags
 	if( !imp)
 	{
 		mErrorString = "No suitable reader found for the file format of file \"" + pFile + "\".";
+		DefaultLogger::get()->error(mErrorString);
 		return NULL;
 	}
 

+ 14 - 2
code/JoinVerticesProcess.cpp

@@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assert.h>
 #include "JoinVerticesProcess.h"
 #include "SpatialSort.h"
+#include "DefaultLogger.h"
 #include "../include/aiPostProcess.h"
 #include "../include/aiMesh.h"
 #include "../include/aiScene.h"
@@ -78,13 +79,21 @@ bool JoinVerticesProcess::IsActive( unsigned int pFlags) const
 // Executes the post processing step on the given imported data.
 void JoinVerticesProcess::Execute( aiScene* pScene)
 {
+	DefaultLogger::get()->debug("JoinVerticesProcess begin");
+
+	bool bHas = false;
 	for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
-		ProcessMesh( pScene->mMeshes[a]);
+	{
+		if(	this->ProcessMesh( pScene->mMeshes[a]))
+			bHas = true;
+	}
+	if (bHas)DefaultLogger::get()->info("JoinVerticesProcess finished. Found vertices to join");
+	else DefaultLogger::get()->debug("JoinVerticesProcess finished. There was nothing to do.");
 }
 
 // ------------------------------------------------------------------------------------------------
 // Unites identical vertices in the given mesh
-void JoinVerticesProcess::ProcessMesh( aiMesh* pMesh)
+bool JoinVerticesProcess::ProcessMesh( aiMesh* pMesh)
 {
 	// helper structure to hold all the data a single vertex can possibly have
 	typedef struct Vertex vertex;
@@ -100,6 +109,8 @@ void JoinVerticesProcess::ProcessMesh( aiMesh* pMesh)
 	std::vector<Vertex> uniqueVertices;
 	uniqueVertices.reserve( pMesh->mNumVertices);
 
+	unsigned int iOldVerts = pMesh->mNumVertices;
+
 	// For each vertex the index of the vertex it was replaced by. 
 	std::vector<unsigned int> replaceIndex( pMesh->mNumVertices, 0xffffffff);
 	// for each vertex whether it was replaced by an existing unique vertex (true) or a new vertex was created for it (false)
@@ -300,4 +311,5 @@ void JoinVerticesProcess::ProcessMesh( aiMesh* pMesh)
 		bone->mWeights = new aiVertexWeight[bone->mNumWeights];
 		memcpy( bone->mWeights, &newWeights[0], bone->mNumWeights * sizeof( aiVertexWeight));
 	}
+	return (iOldVerts != pMesh->mNumVertices);
 }

+ 14 - 6
code/JoinVerticesProcess.h

@@ -38,9 +38,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ----------------------------------------------------------------------
 */
 
-/** @file Defines a post processing step to join identical vertices on all imported meshes.*/
+/** @file Defines a post processing step to join identical vertices 
+    on all imported meshes.*/
 #ifndef AI_JOINVERTICESPROCESS_H_INC
-#define AI_CALCTANGENTSPROCESS_H_INC
+#define AI_JOINVERTICESPROCESS_H_INC
 
 #include "BaseProcess.h"
 #include "../include/aiTypes.h"
@@ -62,7 +63,7 @@ class JoinVerticesProcess : public BaseProcess
 {
 	friend class Importer;
 
-protected:
+public:
 	/** Constructor to be privately used by Importer */
 	JoinVerticesProcess();
 
@@ -90,12 +91,19 @@ protected:
 	/** Unites identical vertices in the given mesh.
 	 * @param pMesh The mesh to process.
 	 */
-	void ProcessMesh( aiMesh* pMesh);
+	bool ProcessMesh( aiMesh* pMesh);
 
-	/** Little helper function to calculate the quadratic difference of two colours. */
+	// -------------------------------------------------------------------
+	/** Little helper function to calculate the quadratic difference 
+	 * of two colours. 
+	 * @param pColor1 First color
+	 * @param pColor2 second color
+	 * @return Quadratic color difference
+	 */
 	float GetColorDifference( const aiColor4D& pColor1, const aiColor4D& pColor2) const
 	{
-		aiColor4D c( pColor1.r - pColor2.r, pColor1.g - pColor2.g, pColor1.b - pColor2.b, pColor1.a - pColor2.a);
+		aiColor4D c(	pColor1.r - pColor2.r, pColor1.g - pColor2.g, 
+						pColor1.b - pColor2.b, pColor1.a - pColor2.a);
 		return c.r*c.r + c.g*c.g + c.b*c.b + c.a*c.a;
 	}
 };

+ 14 - 3
code/KillNormalsProcess.cpp

@@ -41,6 +41,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 /** @file Implementation of the post processing step tokill mesh normals
 */
 #include "KillNormalsProcess.h"
+#include "DefaultLogger.h"
 #include "../include/aiPostProcess.h"
 #include "../include/aiMesh.h"
 #include "../include/aiScene.h"
@@ -69,15 +70,25 @@ bool KillNormalsProcess::IsActive( unsigned int pFlags) const
 // Executes the post processing step on the given imported data.
 void KillNormalsProcess::Execute( aiScene* pScene)
 {
+	DefaultLogger::get()->debug("KillNormalsProcess begin");
+
+	bool bHas = false;
 	for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
-		this->KillMeshNormals( pScene->mMeshes[a]);
+	{
+		if(	this->KillMeshNormals( pScene->mMeshes[a]))
+			bHas = true;
+	}
+	if (bHas)DefaultLogger::get()->info("KillNormalsProcess finished. Found normals to kill");
+	else DefaultLogger::get()->debug("KillNormalsProcess finished. There was nothing to do.");
+
 }
 
 // -------------------------------------------------------------------
 // Executes the post processing step on the given imported data.
-void KillNormalsProcess::KillMeshNormals(aiMesh* pMesh)
+bool KillNormalsProcess::KillMeshNormals(aiMesh* pMesh)
 {
+	if (!pMesh->mNormals)return false;
 	delete[] pMesh->mNormals;
 	pMesh->mNormals = NULL;
-	return;
+	return true;
 }

+ 34 - 35
code/KillNormalsProcess.h

@@ -47,41 +47,40 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 namespace Assimp
 	{
 
-	// ---------------------------------------------------------------------------
-	/** KillNormalsProcess: Class to kill all normals loaded
+// ---------------------------------------------------------------------------
+/** KillNormalsProcess: Class to kill all normals loaded
+*/
+class KillNormalsProcess : public BaseProcess
+{
+	friend class Importer;
+
+protected:
+	/** Constructor to be privately used by Importer */
+	KillNormalsProcess();
+
+	/** Destructor, private as well */
+	~KillNormalsProcess();
+
+public:
+	// -------------------------------------------------------------------
+	/** Returns whether the processing step is present in the given flag field.
+	* @param pFlags The processing flags the importer was called with. A bitwise
+	*   combination of #aiPostProcessSteps.
+	* @return true if the process is present in this flag fields, false if not.
+	*/
+	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.
 	*/
-	class KillNormalsProcess : public BaseProcess
-		{
-		friend class Importer;
-
-		protected:
-			/** Constructor to be privately used by Importer */
-			KillNormalsProcess();
-
-			/** Destructor, private as well */
-			~KillNormalsProcess();
-
-		public:
-			// -------------------------------------------------------------------
-			/** Returns whether the processing step is present in the given flag field.
-			* @param pFlags The processing flags the importer was called with. A bitwise
-			*   combination of #aiPostProcessSteps.
-			* @return true if the process is present in this flag fields, false if not.
-			*/
-			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);
-
-
-		private:
-			void KillMeshNormals (aiMesh* pcMesh);
-		};
-
-	} // end of namespace Assimp
+	void Execute( aiScene* pScene);
+
+
+private:
+	bool KillMeshNormals (aiMesh* pcMesh);
+};
+}; // end of namespace Assimp
 
 #endif // !!AI_KILLNORMALPROCESS_H_INC

+ 87 - 0
code/MDLFileData.h

@@ -95,6 +95,12 @@ namespace MDL
 #define AI_MDL_MAGIC_NUMBER_BE_GS7	'MDL7'
 #define AI_MDL_MAGIC_NUMBER_LE_GS7	'7LDM'
 
+// magic bytes used in Half Life 2 MDL models
+#define AI_MDL_MAGIC_NUMBER_BE_HL2a	'IDST'
+#define AI_MDL_MAGIC_NUMBER_LE_HL2a	'TSDI'
+#define AI_MDL_MAGIC_NUMBER_BE_HL2b	'IDSQ'
+#define AI_MDL_MAGIC_NUMBER_LE_HL2b	'QSDI'
+
 // common limitations for Quake1 meshes. The loader does not check them,
 // but models should not exceed these limits.
 #if (!defined AI_MDL_VERSION)
@@ -210,6 +216,87 @@ struct Header_MDL7
 	uint16_t frame_stc_size;
 } PACK_STRUCT;
 
+
+// ---------------------------------------------------------------------------
+/** \struct Header_HL2
+ *  \brief Data structure for the HL2 main header
+ */
+// ---------------------------------------------------------------------------
+struct Header_HL2 
+{
+	//! magic number: "IDST"/"IDSQ"
+	char	ident[4];		
+
+	//! Version number
+	int32_t	version;
+
+	//! Original file name in pak ?
+	char		name[64];
+
+	//! Length of file name/length of file?
+	int32_t		length;
+
+	//! For viewer, ignored
+	aiVector3D		eyeposition;	
+	aiVector3D		min;			
+	aiVector3D		max;			
+
+	//! AABB of the model
+	aiVector3D		bbmin;			
+	aiVector3D		bbmax;		
+
+	// File flags
+	int32_t			flags;
+
+	//! NUmber of bones contained in the file
+	int32_t			numbones;			
+	int32_t			boneindex;
+
+	//! Number of bone controllers for bone animation
+	int32_t			numbonecontrollers;		
+	int32_t			bonecontrollerindex;
+
+	//! More bounding boxes ...
+	int32_t			numhitboxes;			
+	int32_t			hitboxindex;			
+	
+	//! Animation sequences in the file
+	int32_t			numseq;				
+	int32_t			seqindex;
+
+	//! Loaded sequences. Ignored
+	int32_t			numseqgroups;		
+	int32_t			seqgroupindex;
+
+	//! Raw texture data
+	int32_t			numtextures;		
+	int32_t			textureindex;
+	int32_t			texturedataindex;
+
+	//! Number of skins (=textures?)
+	int32_t			numskinref;			
+	int32_t			numskinfamilies;
+	int32_t			skinindex;
+
+	//! Number of parts
+	int32_t			numbodyparts;		
+	int32_t			bodypartindex;
+
+	//! attachable points for gameplay and physics
+	int32_t			numattachments;		
+	int32_t			attachmentindex;
+
+	//! Table of sound effects associated with the model
+	int32_t			soundtable;
+	int32_t			soundindex;
+	int32_t			soundgroups;
+	int32_t			soundgroupindex;
+
+	//! Number of animation transitions
+	int32_t			numtransitions;		
+	int32_t			transitionindex;
+} PACK_STRUCT;
+
 #define AI_MDL7_MAX_BONENAMESIZE	20 
 
 // ---------------------------------------------------------------------------

+ 76 - 26
code/MDLLoader.cpp

@@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "MaterialSystem.h"
 #include "MDLLoader.h"
 #include "MDLDefaultColorMap.h"
+#include "DefaultLogger.h"
 
 #include "../include/IOStream.h"
 #include "../include/IOSystem.h"
@@ -640,7 +641,8 @@ void MDLImporter::InternReadFile_Quake1( )
 			if (iIndex >= (unsigned int)this->m_pcHeader->num_verts)
 			{
 				iIndex = this->m_pcHeader->num_verts-1;
-				// LOG
+				
+				DefaultLogger::get()->warn("Index overflow in Q1-MDL vertex list.");
 			}
 
 			aiVector3D& vec = pcMesh->mVertices[iCurrent];
@@ -809,7 +811,7 @@ void MDLImporter::InternReadFile_GameStudio( )
 				if (iIndex >= (unsigned int)this->m_pcHeader->num_verts)
 				{
 					iIndex = this->m_pcHeader->num_verts-1;
-					// LOG
+					DefaultLogger::get()->warn("Index overflow in MDL3/4/5/6 vertex list");
 				}
 
 				aiVector3D& vec = vPositions[iCurrent];
@@ -838,7 +840,7 @@ void MDLImporter::InternReadFile_GameStudio( )
 				if (iIndex >= (unsigned int)this->m_pcHeader->synctype)
 				{
 					iIndex = this->m_pcHeader->synctype-1;
-					// LOG
+					DefaultLogger::get()->warn("Index overflow in MDL3/4/5/6 UV coord list");
 				}
 
 				float s = (float)pcTexCoords[iIndex].u;
@@ -886,7 +888,7 @@ void MDLImporter::InternReadFile_GameStudio( )
 				if (iIndex >= (unsigned int)this->m_pcHeader->num_verts)
 				{
 					iIndex = this->m_pcHeader->num_verts-1;
-					// LOG
+					DefaultLogger::get()->warn("Index overflow in MDL3/4/5/6 vertex list");
 				}
 
 				aiVector3D& vec = vPositions[iCurrent];
@@ -914,7 +916,7 @@ void MDLImporter::InternReadFile_GameStudio( )
 				if (iIndex >= (unsigned int) this->m_pcHeader->synctype)
 				{
 					iIndex = this->m_pcHeader->synctype-1;
-					// LOG
+					DefaultLogger::get()->warn("Index overflow in MDL3/4/5/6 UV coord list");
 				}
 
 				float s = (float)pcTexCoords[iIndex].u;
@@ -1029,7 +1031,8 @@ void MDLImporter::ParseSkinLump_GameStudioA7(
 		// ***** EMBEDDED DDS FILE *****
 		if (1 != pcSkin->height)
 		{
-			// LOG
+			DefaultLogger::get()->warn("Found a reference to an embedded DDS texture, "
+				"but texture height is not equal to 1, which is not supported by MED");
 		}
 
 		pcNew = new aiTexture();
@@ -1048,7 +1051,8 @@ void MDLImporter::ParseSkinLump_GameStudioA7(
 		// ***** REFERENCE TO EXTERNAL FILE FILE *****
 		if (1 != pcSkin->height)
 		{
-			// LOG
+			DefaultLogger::get()->warn("Found a reference to an external texture, "
+				"but texture height is not equal to 1, which is not supported by MED");
 		}
 
 		aiString szFile;
@@ -1058,29 +1062,52 @@ void MDLImporter::ParseSkinLump_GameStudioA7(
 		memcpy(szFile.data,(const char*)szCurrent,iLen2);
 		szFile.length = iLen;
 
+		szCurrent += iLen2;
+
 		// place this as diffuse texture
-		pcMatOut->AddProperty<aiString>(&szFile,1,AI_MATKEY_TEXTURE_DIFFUSE(0));
+		pcMatOut->AddProperty(&szFile,AI_MATKEY_TEXTURE_DIFFUSE(0));
 	}
-	else if (0 != iMasked)
+	else if (0 != iMasked || 0 == pcSkin->typ)
 	{
 		// ***** STANDARD COLOR TEXTURE *****
+		pcNew = new aiTexture();
 		if (0 == pcSkin->height || 0 == pcSkin->width)
 		{
-			// LOG
-		}
+			DefaultLogger::get()->warn("Found embedded texture, but its width "
+				"an height are both 0. Is this a joke?");
 
-		// it is a standard color texture. Fill in width and height
-		// and call the same function we used for loading MDL5 files
+			// generate an empty chess pattern
+			pcNew->mWidth = pcNew->mHeight = 8;
+			pcNew->pcData = new aiTexel[64];
+			for (unsigned int x = 0; x < 8;++x)
+			{
+				for (unsigned int y = 0; y < 8;++y)
+				{
+					bool bSet = false;
+					if (0 == x % 2 && 0 != y % 2 ||
+						0 != x % 2 && 0 == y % 2)bSet = true;
+				
+					aiTexel* pc = &pcNew->pcData[y * 8 + x];
+					if (bSet)pc->r = pc->b = pc->g = 0xFF;
+					else pc->r = pc->b = pc->g = 0;
+					pc->a = 0xFF;
+				}
+			}
+		}
+		else
+		{
+			// it is a standard color texture. Fill in width and height
+			// and call the same function we used for loading MDL5 files
 
-		pcNew = new aiTexture();
-		pcNew->mWidth = pcSkin->width;
-		pcNew->mHeight = pcSkin->height;
+			pcNew->mWidth = pcSkin->width;
+			pcNew->mHeight = pcSkin->height;
 
-		unsigned int iSkip = 0;
-		this->ParseTextureColorData(szCurrent,iMasked,&iSkip,pcNew);
+			unsigned int iSkip = 0;
+			this->ParseTextureColorData(szCurrent,iMasked,&iSkip,pcNew);
 
-		// skip length of texture data
-		szCurrent += iSkip;
+			// skip length of texture data
+			szCurrent += iSkip;
+		}
 	}
 	
 	// check whether a material definition is contained in the skin
@@ -1169,6 +1196,17 @@ void MDLImporter::ParseSkinLump_GameStudioA7(
 		delete[] pc;
 	}
 
+	// place the name of the skin in the material
+	const size_t iLen = strlen(pcSkin->texture_name); 
+	if (0 != iLen)
+	{
+		aiString szFile;
+		memcpy(szFile.data,pcSkin->texture_name,sizeof(pcSkin->texture_name));
+		szFile.length = iLen;
+
+		pcMatOut->AddProperty(&szFile,AI_MATKEY_NAME);
+	}
+
 	*szCurrentOut = szCurrent;
 	return;
 }
@@ -1243,7 +1281,8 @@ void MDLImporter::InternReadFile_GameStudioA7( )
 		if (1 != pcGroup->typ)
 		{
 			// Not a triangle-based mesh
-			// LOGWRITE("[3DGS MDL7] Mesh group is no basing in triangles. Continuing happily");
+			DefaultLogger::get()->warn("[3DGS MDL7] Mesh group is not basing on"
+				"triangles. Continuing happily");
 		}
 
 		// read all skins
@@ -1315,6 +1354,8 @@ void MDLImporter::InternReadFile_GameStudioA7( )
 				{
 					// LOG
 					iIndex = pcGroup->numverts-1;
+
+					DefaultLogger::get()->warn("Index overflow in MDL7 vertex list");
 				}
 				unsigned int iOutIndex = iTriangle * 3 + c;
 
@@ -1439,7 +1480,10 @@ void MDLImporter::InternReadFile_GameStudioA7( )
 					// use the last material instead
 					aiSplit[iNumMaterials-1]->push_back(iFace);
 
-					// LOG
+					// sometimes MED writes -1, but normally only if there is only
+					// one skin assigned. No warning in this case
+					if(0xFFFFFFFF != pcFaces[iFace].iMatIndex[0])
+						DefaultLogger::get()->warn("Index overflow in MDL7 material list [#0]");
 				}
 				else aiSplit[pcFaces[iFace].iMatIndex[0]]->push_back(iFace);
 			}
@@ -1464,13 +1508,19 @@ void MDLImporter::InternReadFile_GameStudioA7( )
 				if (iMatIndex >= iNumMaterials)
 				{
 					iMatIndex = iNumMaterials-1;
-					// LOG
+
+					// sometimes MED writes -1, but normally only if there is only
+					// one skin assigned. No warning in this case
+					if(0xFFFFFFFF != iMatIndex)
+						DefaultLogger::get()->warn("Index overflow in MDL7 material list [#1]");
 				}
 				unsigned int iMatIndex2 = pcFaces[iFace].iMatIndex[1];
 				if (iMatIndex2 >= iNumMaterials)
 				{
-					iMatIndex2 = iNumMaterials-1;
-					// LOG
+					// sometimes MED writes -1, but normally only if there is only
+					// one skin assigned. No warning in this case
+					if(0xFFFFFFFF != iMatIndex2)
+						DefaultLogger::get()->warn("Index overflow in MDL7 material list [#2]");
 				}
 
 				// do a slow O(log(n)*n) seach in the list ...
@@ -1563,7 +1613,7 @@ void MDLImporter::InternReadFile_GameStudioA7( )
 
 			if (((unsigned int)szCurrent -  (unsigned int)pcHeader) + iAdd > (unsigned int)pcHeader->data_size)
 			{
-				// LOG
+				DefaultLogger::get()->warn("Index overflow in frame area. Ignoring frames");
 				// don't parse more groups if we can't even read one
 				goto __BREAK_OUT;
 			}

+ 58 - 0
code/MaterialSystem.cpp

@@ -232,6 +232,34 @@ aiReturn aiGetMaterialString(const aiMaterial* pMat,
 	return AI_FAILURE;
 }
 // ------------------------------------------------------------------------------------------------
+aiReturn MaterialHelper::RemoveProperty (const char* pKey)
+{
+	ai_assert(NULL != pKey);
+
+	for (unsigned int i = 0; i < this->mNumProperties;++i)
+	{
+		if (NULL != this->mProperties[i])
+		{
+			if (0 == ASSIMP_stricmp( this->mProperties[i]->mKey->data, pKey ))
+			{
+				// delete this entry
+				delete[] this->mProperties[i]->mData;
+				delete this->mProperties[i];
+				
+				// collapse the array behind --.
+				--this->mNumProperties;
+				for (unsigned int a = i; a < this->mNumProperties;++a)
+				{
+					this->mProperties[a] = this->mProperties[a+1];
+				}
+				return AI_SUCCESS;
+			}
+		}
+	}
+
+	return AI_FAILURE;
+}
+// ------------------------------------------------------------------------------------------------
 aiReturn MaterialHelper::AddBinaryProperty (const void* pInput,
 	const unsigned int pSizeInBytes,
 	const char* pKey,
@@ -241,6 +269,23 @@ aiReturn MaterialHelper::AddBinaryProperty (const void* pInput,
 	ai_assert (pKey != NULL);
 	ai_assert (0 != pSizeInBytes);
 
+	// first search the list whether there is already an entry
+	// with this name.
+	unsigned int iOutIndex = 0xFFFFFFFF;
+	for (unsigned int i = 0; i < this->mNumProperties;++i)
+	{
+		if (NULL != this->mProperties[i])
+		{
+			if (0 == ASSIMP_stricmp( this->mProperties[i]->mKey->data, pKey ))
+			{
+				// delete this entry
+				delete[] this->mProperties[i]->mData;
+				delete this->mProperties[i];
+				iOutIndex = i;
+			}
+		}
+	}
+
 	aiMaterialProperty* pcNew = new aiMaterialProperty();
 
 	// fill this
@@ -255,6 +300,12 @@ aiReturn MaterialHelper::AddBinaryProperty (const void* pInput,
 	ai_assert ( MAXLEN > pcNew->mKey->length);
 	strcpy( pcNew->mKey->data, pKey );
 
+	if (0xFFFFFFFF != iOutIndex)
+	{
+		this->mProperties[iOutIndex] = pcNew;
+		return AI_SUCCESS;
+	}
+
 	// resize the array ... allocate
 	// storage for 5 other properties
 	if (this->mNumProperties == this->mNumAllocated)
@@ -373,6 +424,12 @@ aiReturn aiGetMaterialTexture(const aiMaterial* pcMat,
 		szBlendBase = AI_MATKEY_TEXBLEND_SHININESS_;
 		szOpBase = AI_MATKEY_TEXOP_SHININESS_;
 		break;
+	case AI_TEXTYPE_OPACITY:
+		szPathBase = AI_MATKEY_TEXTURE_OPACITY_;
+		szUVBase = AI_MATKEY_UVWSRC_OPACITY_;
+		szBlendBase = AI_MATKEY_TEXBLEND_OPACITY_;
+		szOpBase = AI_MATKEY_TEXOP_OPACITY_;
+		break;
 	default: return AI_FAILURE;
 	};
 
@@ -404,6 +461,7 @@ aiReturn aiGetMaterialTexture(const aiMaterial* pcMat,
 
 		*pfBlendFactor = fBlend;
 	}
+
 	// get the texture operation of the texture
 	if (peTextureOp)
 	{

+ 21 - 0
code/MaterialSystem.h

@@ -60,6 +60,11 @@ namespace Assimp
 // ---------------------------------------------------------------------------
 inline int ASSIMP_stricmp(const char *s1, const char *s2)
 {
+#if (defined _MSC_VER)
+
+	return _stricmp(s1,s2);
+
+#else
 	const char *a1, *a2;
 	a1 = s1;
 	a2 = s2;
@@ -74,6 +79,7 @@ inline int ASSIMP_stricmp(const char *s1, const char *s2)
 		++a1; 
 		++a2;
 	}
+#endif
 }
 
 // ---------------------------------------------------------------------------
@@ -90,6 +96,11 @@ inline int ASSIMP_stricmp(const char *s1, const char *s2)
 // ---------------------------------------------------------------------------
 inline int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n)
 {
+#if (defined _MSC_VER)
+
+	return _strnicmp(s1,s2,n);
+
+#else
 	const char *a1, *a2;
 	a1 = s1;
 	a2 = s2;
@@ -109,6 +120,7 @@ inline int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n)
 		++a2;
 		++p;
 	}
+#endif
 }
 
 
@@ -159,6 +171,15 @@ public:
 		const unsigned int pNumValues,
 		const char* pKey);
 
+
+	// -------------------------------------------------------------------
+	/** Remove a given key from the list
+	 *  The function fails if the key isn't found
+	 *
+	 *  \param pKey Key/Usage to be deleted
+	 */
+	aiReturn RemoveProperty (const char* pKey);
+
 	// -------------------------------------------------------------------
 	/** Copy the property list of a material
 	 *  \param pcDest Destination material

+ 0 - 4
code/ObjFileImporter.cpp

@@ -26,8 +26,6 @@ ObjFileImporter::ObjFileImporter() :
 	m_pRootObject(NULL),
 	m_strAbsPath("\\")
 {
-	DefaultLogger::create( "test.log", DefaultLogger::VERBOSE );
-	DefaultLogger::get()->info("Start logging");
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -40,8 +38,6 @@ ObjFileImporter::~ObjFileImporter()
 		delete m_pRootObject;
 		m_pRootObject = NULL;
 	}
-
-	DefaultLogger::kill();
 }
 
 // ------------------------------------------------------------------------------------------------

+ 5 - 3
code/PlyLoader.cpp

@@ -108,7 +108,9 @@ void PLYImporter::InternReadFile(
 
 	// allocate storage and copy the contents of the file to a memory buffer
 	// (terminate it with zero)
-	this->mBuffer = new unsigned char[fileSize+1];
+	// FIX: Allocate an extra buffer of 12.5% to be sure we won't crash
+	// if an overrun occurs.
+	this->mBuffer = new unsigned char[fileSize+1 + (fileSize>>3)];
 	file->Read( (void*)mBuffer, 1, fileSize);
 	this->mBuffer[fileSize] = '\0';
 
@@ -131,7 +133,7 @@ void PLYImporter::InternReadFile(
 		{
 			szMe += 6;
 			SkipLine(szMe,(const char**)&szMe);
-			if(!PLY::DOM::ParseInstance(szMe,&sPlyDom))
+			if(!PLY::DOM::ParseInstance(szMe,&sPlyDom, fileSize))
 			{
 				throw new ImportErrorException( "Invalid .ply file: Unable to build DOM (#1)");
 			}
@@ -151,7 +153,7 @@ void PLYImporter::InternReadFile(
 
 			// skip the line, parse the rest of the header and build the DOM
 			SkipLine(szMe,(const char**)&szMe);
-			if(!PLY::DOM::ParseInstanceBinary(szMe,&sPlyDom,bIsBE))
+			if(!PLY::DOM::ParseInstanceBinary(szMe,&sPlyDom,bIsBE, fileSize))
 			{
 				throw new ImportErrorException( "Invalid .ply file: Unable to build DOM (#2)");
 			}

+ 271 - 59
code/PlyParser.cpp

@@ -44,6 +44,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "PLYLoader.h"
 #include "MaterialSystem.h"
 #include "fast_atof.h"
+#include "DefaultLogger.h"
+#include "ByteSwap.h"
 
 #include "../include/IOStream.h"
 #include "../include/IOSystem.h"
@@ -55,9 +57,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 using namespace Assimp;
 
+// ------------------------------------------------------------------------------------------------
+void ValidateOut(const char* szCur, const char* szMax)
+{
+	if (szCur > szMax)
+	{
+		throw new ImportErrorException("Buffer overflow. PLY file contains invalid indices");
+	}
+	return;
+}
 // ------------------------------------------------------------------------------------------------
 PLY::EDataType PLY::Property::ParseDataType(const char* p_szIn,const char** p_szOut)
 {
+	ai_assert(NULL != p_szIn);
+	ai_assert(NULL != p_szOut);
+
+	const char* szMax = *p_szOut;
+
 	PLY::EDataType eOut = PLY::EDT_INVALID;
 
 	if (0 == ASSIMP_strincmp(p_szIn,"char",4) ||
@@ -134,12 +150,22 @@ PLY::EDataType PLY::Property::ParseDataType(const char* p_szIn,const char** p_sz
 	{
 		eOut = PLY::EDT_INVALID;
 	}
+	if (PLY::EDT_INVALID == eOut)
+	{
+		DefaultLogger::get()->info("Found unknown data type in PLY file. This is OK");
+	}
 	*p_szOut = p_szIn;
+	ValidateOut(p_szIn,szMax);
 	return eOut;
 }
 // ------------------------------------------------------------------------------------------------
 PLY::ESemantic PLY::Property::ParseSemantic(const char* p_szIn,const char** p_szOut)
 {
+	ai_assert(NULL != p_szIn);
+	ai_assert(NULL != p_szOut);
+
+	const char* szMax = *p_szOut;
+
 	PLY::ESemantic eOut = PLY::EST_INVALID;
 	if (0 == ASSIMP_strincmp(p_szIn,"red",3))
 	{
@@ -298,6 +324,8 @@ PLY::ESemantic PLY::Property::ParseSemantic(const char* p_szIn,const char** p_sz
 	}
 	else
 	{
+		DefaultLogger::get()->info("Found unknown property in file. This is ok");
+
 		// ... find the next space or new line
 		while (*p_szIn != ' ' && *p_szIn != '\t'  && 
 			   *p_szIn != '\r' && *p_szIn != '\0' && *p_szIn != '\n')p_szIn++;
@@ -307,6 +335,7 @@ PLY::ESemantic PLY::Property::ParseSemantic(const char* p_szIn,const char** p_sz
 	{
 		eOut = PLY::EST_INVALID;
 	}
+	ValidateOut(p_szIn,szMax);
 	*p_szOut = p_szIn;
 	return eOut;
 }
@@ -315,9 +344,13 @@ bool PLY::Property::ParseProperty (const char* p_szIn,
 	const char** p_szOut,
 	PLY::Property* pOut)
 {
+	ai_assert(NULL != p_szIn);
+	ai_assert(NULL != p_szOut);
+
 	// Forms supported:
 	// "property float x"
 	// "property list uchar int vertex_index"
+	const char* szMax = *p_szOut;
 	*p_szOut = p_szIn;
 
 	// skip leading spaces
@@ -339,46 +372,56 @@ bool PLY::Property::ParseProperty (const char* p_szIn,
 
 		// seems to be a list.
 		p_szIn += 5;
-		if(EDT_INVALID == (pOut->eFirstType = PLY::Property::ParseDataType(p_szIn, &p_szIn)))
+		const char* szPass = szMax;
+		if(EDT_INVALID == (pOut->eFirstType = PLY::Property::ParseDataType(p_szIn, &szPass)))
 		{
 			// unable to parse list size data type
 			SkipLine(p_szIn,&p_szIn);
 			*p_szOut = p_szIn;
 			return false;
 		}
+		p_szIn = szPass;
 		if (!SkipSpaces(p_szIn,&p_szIn))return false;
-		if(EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(p_szIn, &p_szIn)))
+		szPass = szMax;
+		if(EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(p_szIn, &szPass)))
 		{
 			// unable to parse list data type
 			SkipLine(p_szIn,&p_szIn);
 			*p_szOut = p_szIn;
 			return false;
 		}
+		p_szIn = szPass;
 	}
 	else
 	{
-		if(EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(p_szIn, &p_szIn)))
+		const char* szPass = szMax;
+		if(EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(p_szIn, &szPass)))
 		{
 			// unable to parse data type. Skip the property
 			SkipLine(p_szIn,&p_szIn);
 			*p_szOut = p_szIn;
 			return false;
 		}
+		p_szIn = szPass;
 	}
 	
 	if (!SkipSpaces(p_szIn,&p_szIn))return false;
 	const char* szCur = p_szIn;
-	pOut->Semantic = PLY::Property::ParseSemantic(p_szIn, &p_szIn);
+	const char* szPass = szMax;
+	pOut->Semantic = PLY::Property::ParseSemantic(p_szIn, &szPass);
+	p_szIn = szPass;
 
 	if (PLY::EST_INVALID == pOut->Semantic)
 	{
 		// store the name of the semantic
 		uintptr_t iDiff = (uintptr_t)p_szIn - (uintptr_t)szCur;
 
+		DefaultLogger::get()->info("Found unknown semantic in PLY file. This is OK");
 		pOut->szName = std::string(szCur,iDiff);
 	}
 
 	SkipSpacesAndLineEnd(p_szIn,&p_szIn);
+	ValidateOut(p_szIn,szMax);
 	*p_szOut = p_szIn;
 	return true;
 }
@@ -386,6 +429,11 @@ bool PLY::Property::ParseProperty (const char* p_szIn,
 PLY::EElementSemantic PLY::Element::ParseSemantic(const char* p_szIn,
 	const char** p_szOut)
 {
+	ai_assert(NULL != p_szIn);
+	ai_assert(NULL != p_szOut);
+
+	const char* szMax = *p_szOut;
+
 	PLY::EElementSemantic eOut = PLY::EEST_INVALID;
 	if (0 == ASSIMP_strincmp(p_szIn,"vertex",6))
 	{
@@ -425,6 +473,7 @@ PLY::EElementSemantic PLY::Element::ParseSemantic(const char* p_szIn,
 	{
 		eOut = PLY::EEST_INVALID;
 	}
+	ValidateOut(p_szIn,szMax);
 	*p_szOut = p_szIn;
 	return eOut;
 }
@@ -433,7 +482,12 @@ bool PLY::Element::ParseElement (const char* p_szIn,
 	const char** p_szOut,
 	PLY::Element* pOut)
 {
+	ai_assert(NULL != p_szIn);
+	ai_assert(NULL != p_szOut);
+	ai_assert(NULL != pOut);
+
 	// Example format: "element vertex 8"
+	const char* szMax = *p_szOut;
 	*p_szOut = p_szIn;
 
 	// skip leading spaces
@@ -451,7 +505,9 @@ bool PLY::Element::ParseElement (const char* p_szIn,
 
 	// parse the semantic of the element
 	const char* szCur = p_szIn;
-	pOut->eSemantic = PLY::Element::ParseSemantic(p_szIn,&p_szIn);
+	const char* szPass = szMax;
+	pOut->eSemantic = PLY::Element::ParseSemantic(p_szIn,&szPass);
+	p_szIn = szPass;
 
 	if (PLY::EEST_INVALID == pOut->eSemantic)
 	{
@@ -476,11 +532,15 @@ bool PLY::Element::ParseElement (const char* p_szIn,
 		PLY::DOM::SkipComments(p_szIn,&p_szIn);
 
 		PLY::Property* prop = new PLY::Property();
-		if(!PLY::Property::ParseProperty(p_szIn,&p_szIn,prop))break;
+
+		const char* szPass = szMax;
+		if(!PLY::Property::ParseProperty(p_szIn,&szPass,prop))break;
+		p_szIn = szPass;
 
 		// add the property to the property list
 		pOut->alProperties.push_back(prop);
 	}
+	ValidateOut(p_szIn,szMax);
 	*p_szOut = p_szIn;
 	return true;
 }
@@ -488,6 +548,10 @@ bool PLY::Element::ParseElement (const char* p_szIn,
 bool PLY::DOM::SkipComments (const char* p_szIn,
 	const char** p_szOut)
 {
+	ai_assert(NULL != p_szIn);
+	ai_assert(NULL != p_szOut);
+
+	const char* szMax = *p_szOut;
 	*p_szOut = p_szIn;
 
 	// skip spaces
@@ -503,12 +567,20 @@ bool PLY::DOM::SkipComments (const char* p_szIn,
 		*p_szOut = p_szIn;
 		return true;
 	}
+	ValidateOut(p_szIn,szMax);
+	*p_szOut = p_szIn;
 	return false;
 }
 // ------------------------------------------------------------------------------------------------
 bool PLY::DOM::ParseHeader (const char* p_szIn,const char** p_szOut)
 {
+	ai_assert(NULL != p_szIn);
+	ai_assert(NULL != p_szOut);
+
+	DefaultLogger::get()->debug("PLY::DOM::ParseHeader() begin");
+
 	// after ply and format line
+	const char* szMax = *p_szOut;
 	*p_szOut = p_szIn;
 
 	// parse all elements
@@ -518,8 +590,11 @@ bool PLY::DOM::ParseHeader (const char* p_szIn,const char** p_szOut)
 		PLY::DOM::SkipComments(p_szIn,&p_szIn);
 
 		PLY::Element* out = new PLY::Element();
-		if(PLY::Element::ParseElement(p_szIn,&p_szIn,out))
+		const char* szPass = szMax;
+		if(PLY::Element::ParseElement(p_szIn,&szPass,out))
 		{
+			p_szIn = szPass;
+
 			// add the element to the list of elements
 			this->alElements.push_back(out);
 		}
@@ -532,7 +607,10 @@ bool PLY::DOM::ParseHeader (const char* p_szIn,const char** p_szOut)
 		// ignore unknown header elements
 	}
 	SkipSpacesAndLineEnd(p_szIn,&p_szIn);
+	ValidateOut(p_szIn,szMax);
 	*p_szOut = p_szIn;
+
+	DefaultLogger::get()->debug("PLY::DOM::ParseHeader() succeeded");
 	return true;
 }
 // ------------------------------------------------------------------------------------------------
@@ -540,6 +618,14 @@ bool PLY::DOM::ParseElementInstanceLists (
 	const char* p_szIn,
 	const char** p_szOut)
 {
+	ai_assert(NULL != p_szIn);
+	ai_assert(NULL != p_szOut);
+
+	DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() begin");
+
+	const char* szMax = *p_szOut;
+	*p_szOut = p_szIn;
+
 	this->alElementData.resize(this->alElements.size());
 
 	std::vector<PLY::Element*>::const_iterator i = this->alElements.begin();
@@ -549,8 +635,15 @@ bool PLY::DOM::ParseElementInstanceLists (
 	for (;i != this->alElements.end();++i,++a)
 	{
 		*a = new PLY::ElementInstanceList((*i)); // reserve enough storage
-		PLY::ElementInstanceList::ParseInstanceList(p_szIn,&p_szIn,(*i),(*a));
+
+		const char* szPass = szMax;
+		PLY::ElementInstanceList::ParseInstanceList(p_szIn,&szPass,(*i),(*a));
+		p_szIn = szPass;
 	}
+
+	DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() succeeded");
+	ValidateOut(p_szIn,szMax);
+	*p_szOut = p_szIn;
 	return true;
 }
 // ------------------------------------------------------------------------------------------------
@@ -559,6 +652,14 @@ bool PLY::DOM::ParseElementInstanceListsBinary (
 	const char** p_szOut,
 	bool p_bBE)
 {
+	ai_assert(NULL != p_szIn);
+	ai_assert(NULL != p_szOut);
+
+	DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() begin");
+
+	const char* szMax = *p_szOut;
+	*p_szOut = p_szIn;
+	
 	this->alElementData.resize(this->alElements.size());
 
 	std::vector<PLY::Element*>::const_iterator i = this->alElements.begin();
@@ -568,40 +669,80 @@ bool PLY::DOM::ParseElementInstanceListsBinary (
 	for (;i != this->alElements.end();++i,++a)
 	{
 		*a = new PLY::ElementInstanceList((*i)); // reserve enough storage
-		PLY::ElementInstanceList::ParseInstanceListBinary(p_szIn,&p_szIn,(*i),(*a),p_bBE);
+		const char* szPass = szMax;
+		PLY::ElementInstanceList::ParseInstanceListBinary(p_szIn,&szPass,(*i),(*a),p_bBE);
+		p_szIn = szPass;
 	}
+
+	DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() succeeded");
+	ValidateOut(p_szIn,szMax);
+	*p_szOut = p_szIn;
 	return true;
 }
 // ------------------------------------------------------------------------------------------------
-bool PLY::DOM::ParseInstanceBinary (const char* p_szIn,DOM* p_pcOut,bool p_bBE)
+bool PLY::DOM::ParseInstanceBinary (const char* p_szIn,DOM* p_pcOut,bool p_bBE,unsigned int iSize)
 {
-	if(!p_pcOut->ParseHeader(p_szIn,&p_szIn))
+	ai_assert(NULL != p_szIn);
+	ai_assert(NULL != p_pcOut);
+
+	DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() begin");
+
+	const char* szMax = p_szIn + iSize;
+	const char* szPass = szMax;
+	if(!p_pcOut->ParseHeader(p_szIn,&szPass))
 	{
+		DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure");
 		return false;
 	}
-	if(!p_pcOut->ParseElementInstanceListsBinary(p_szIn,&p_szIn,p_bBE))
+	p_szIn = szPass;
+	szPass = szMax;
+	if(!p_pcOut->ParseElementInstanceListsBinary(p_szIn,&szPass,p_bBE))
 	{
+		DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure");
 		return false;
 	}
+	DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() succeeded");
 	return true;
 }
 // ------------------------------------------------------------------------------------------------
-bool PLY::DOM::ParseInstance (const char* p_szIn,DOM* p_pcOut)
+bool PLY::DOM::ParseInstance (const char* p_szIn,DOM* p_pcOut,unsigned int iSize)
 {
-	if(!p_pcOut->ParseHeader(p_szIn,&p_szIn))
+	ai_assert(NULL != p_szIn);
+	ai_assert(NULL != p_pcOut);
+
+	DefaultLogger::get()->debug("PLY::DOM::ParseInstance() begin");
+
+	const char* szMax = p_szIn + iSize;
+	const char* szPass = szMax;
+	if(!p_pcOut->ParseHeader(p_szIn,&szPass))
 	{
+		DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure");
 		return false;
 	}
-	if(!p_pcOut->ParseElementInstanceLists(p_szIn,&p_szIn))
+	p_szIn = szPass;
+	szPass = szMax;
+	if(!p_pcOut->ParseElementInstanceLists(p_szIn,&szPass))
 	{
+		DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure");
 		return false;
 	}
+	DefaultLogger::get()->debug("PLY::DOM::ParseInstance() succeeded");
 	return true;
 }
 // ------------------------------------------------------------------------------------------------
-bool PLY::ElementInstanceList::ParseInstanceList (const char* p_szIn,const char** p_szOut,
-	 const PLY::Element* pcElement, PLY::ElementInstanceList* p_pcOut)
+bool PLY::ElementInstanceList::ParseInstanceList (
+	const char* p_szIn,
+	const char** p_szOut,
+	const PLY::Element* pcElement, 
+	PLY::ElementInstanceList* p_pcOut)
 {
+	ai_assert(NULL != p_szIn);
+	ai_assert(NULL != p_szOut);
+	ai_assert(NULL != pcElement);
+	ai_assert(NULL != p_pcOut);
+
+	const char* szMax = *p_szOut;
+
 	if (EEST_INVALID == pcElement->eSemantic)
 	{
 		// if the element has an unknown semantic we can skip all lines
@@ -621,11 +762,15 @@ bool PLY::ElementInstanceList::ParseInstanceList (const char* p_szIn,const char*
 			PLY::DOM::SkipComments(p_szIn,&p_szIn);
 
 			PLY::ElementInstance* out = new PLY::ElementInstance();
-			PLY::ElementInstance::ParseInstance(p_szIn, &p_szIn,pcElement, out);
+
+			const char* szPass = szMax;
+			PLY::ElementInstance::ParseInstance(p_szIn, &szPass,pcElement, out);
+			p_szIn = szPass;
 			// add it to the list
 			p_pcOut->alInstances[i] = out;
 		}
 	}
+	ValidateOut(p_szIn,szMax);
 	*p_szOut = p_szIn;
 	return true;
 }
@@ -637,6 +782,14 @@ bool PLY::ElementInstanceList::ParseInstanceListBinary (
 	PLY::ElementInstanceList* p_pcOut,
 	bool p_bBE /* = false */)
 {
+	ai_assert(NULL != p_szIn);
+	ai_assert(NULL != p_szOut);
+	ai_assert(NULL != pcElement);
+	ai_assert(NULL != p_pcOut);
+
+	const char* szMax = *p_szOut;
+	*p_szOut = p_szIn;
+
 	// we can add special handling code for unknown element semantics since
 	// we can't skip it as a whole block (we don't know its exact size
 	// due to the fact that lists could be contained in the property list 
@@ -644,10 +797,13 @@ bool PLY::ElementInstanceList::ParseInstanceListBinary (
 	for (unsigned int i = 0; i < pcElement->NumOccur;++i)
 	{
 		PLY::ElementInstance* out = new PLY::ElementInstance();
+		const char* szPass = szMax;
 		PLY::ElementInstance::ParseInstanceBinary(p_szIn, &p_szIn,pcElement, out, p_bBE);
+		p_szIn = szPass;
 		// add it to the list
 		p_pcOut->alInstances[i] = out;
 	}
+	ValidateOut(p_szIn,szMax);
 	*p_szOut = p_szIn;
 	return true;
 }
@@ -658,25 +814,38 @@ bool PLY::ElementInstance::ParseInstance (
 	const PLY::Element* pcElement,
 	PLY::ElementInstance* p_pcOut)
 {
+	ai_assert(NULL != p_szIn);
+	ai_assert(NULL != p_szOut);
+	ai_assert(NULL != pcElement);
+	ai_assert(NULL != p_pcOut);
+
 	if (!SkipSpaces(p_szIn, &p_szIn))return false;
 
 	// allocate enough storage
 	p_pcOut->alProperties.resize(pcElement->alProperties.size());
 
+	const char* szMax = *p_szOut;
 	*p_szOut = p_szIn;
+
 	std::vector<PLY::PropertyInstance>::iterator i = p_pcOut->alProperties.begin();
 	std::vector<PLY::Property*>::const_iterator a = pcElement->alProperties.begin();
 	for (;i != p_pcOut->alProperties.end();++i,++a)
 	{
-		if(!(PLY::PropertyInstance::ParseInstance(p_szIn, &p_szIn,(*a),&(*i))))
+		const char* szPass = szMax;
+		if(!(PLY::PropertyInstance::ParseInstance(p_szIn, &szPass,(*a),&(*i))))
 		{
+			DefaultLogger::get()->warn("Unable to parse property instance. "
+				"Skipping this element instance");
+
 			// skip the rest of the instance
 			SkipLine(p_szIn, &p_szIn);
 
 			PLY::PropertyInstance::ValueUnion v = PLY::PropertyInstance::DefaultValue((*a)->eType);
 			(*i).avList.push_back(v);
 		}
+		p_szIn = szPass;
 	}
+	ValidateOut(p_szIn,szMax);
 	*p_szOut = p_szIn;
 	return true;
 }
@@ -688,20 +857,33 @@ bool PLY::ElementInstance::ParseInstanceBinary (
 	PLY::ElementInstance* p_pcOut,
 	bool p_bBE /* = false */)
 {
+	ai_assert(NULL != p_szIn);
+	ai_assert(NULL != p_szOut);
+	ai_assert(NULL != pcElement);
+	ai_assert(NULL != p_pcOut);
+
+	const char* szMax = *p_szOut;
+	*p_szOut = p_szIn;
+
 	// allocate enough storage
 	p_pcOut->alProperties.resize(pcElement->alProperties.size());
 
-	*p_szOut = p_szIn;
 	std::vector<PLY::PropertyInstance>::iterator i =  p_pcOut->alProperties.begin();
 	std::vector<PLY::Property*>::const_iterator a =  pcElement->alProperties.begin();
 	for (;i != p_pcOut->alProperties.end();++i,++a)
 	{
-		if(!(PLY::PropertyInstance::ParseInstance(p_szIn, &p_szIn,(*a),&(*i))))
+		const char* szPass = szMax;
+		if(!(PLY::PropertyInstance::ParseInstanceBinary(p_szIn, &szPass,(*a),&(*i),p_bBE)))
 		{
+			DefaultLogger::get()->warn("Unable to parse binary property instance. "
+				"Skipping this element instance");
+
 			PLY::PropertyInstance::ValueUnion v = PLY::PropertyInstance::DefaultValue((*a)->eType);
 			(*i).avList.push_back(v);
 		}
+		p_szIn = szPass;
 	}
+	ValidateOut(p_szIn,szMax);
 	*p_szOut = p_szIn;
 	return true;
 }
@@ -709,6 +891,12 @@ bool PLY::ElementInstance::ParseInstanceBinary (
 bool PLY::PropertyInstance::ParseInstance (const char* p_szIn,const char** p_szOut,
 	const PLY::Property* prop, PLY::PropertyInstance* p_pcOut)
 {
+	ai_assert(NULL != p_szIn);
+	ai_assert(NULL != p_szOut);
+	ai_assert(NULL != prop);
+	ai_assert(NULL != p_pcOut);
+
+	const char* szMax = *p_szOut;
 	*p_szOut = p_szIn;
 
 	// skip spaces at the beginning
@@ -718,7 +906,10 @@ bool PLY::PropertyInstance::ParseInstance (const char* p_szIn,const char** p_szO
 	{
 		// parse the number of elements in the list
 		PLY::PropertyInstance::ValueUnion v;
-		PLY::PropertyInstance::ParseValue(p_szIn, &p_szIn,prop->eFirstType,&v);
+
+		const char* szPass = szMax;
+		PLY::PropertyInstance::ParseValue(p_szIn, &szPass,prop->eFirstType,&v);
+		p_szIn = szPass;
 
 		// convert to unsigned int
 		unsigned int iNum = PLY::PropertyInstance::ConvertTo<unsigned int>(v,prop->eFirstType);
@@ -728,7 +919,9 @@ bool PLY::PropertyInstance::ParseInstance (const char* p_szIn,const char** p_szO
 		{
 			if (!SkipSpaces(p_szIn, &p_szIn))return false;
 
-			PLY::PropertyInstance::ParseValue(p_szIn, &p_szIn,prop->eType,&v);
+			const char* szPass = szMax;
+			PLY::PropertyInstance::ParseValue(p_szIn, &szPass,prop->eType,&v);
+			p_szIn = szPass;
 			p_pcOut->avList.push_back(v);
 		}
 	}
@@ -736,10 +929,14 @@ bool PLY::PropertyInstance::ParseInstance (const char* p_szIn,const char** p_szO
 	{
 		// parse the property
 		PLY::PropertyInstance::ValueUnion v;
-		PLY::PropertyInstance::ParseValue(p_szIn, &p_szIn,prop->eType,&v);
+
+		const char* szPass = szMax;
+		PLY::PropertyInstance::ParseValue(p_szIn, &szPass,prop->eType,&v);
+		p_szIn = szPass;
 		p_pcOut->avList.push_back(v);
 	}
 	SkipSpacesAndLineEnd(p_szIn, &p_szIn);
+	ValidateOut(p_szIn,szMax);
 	*p_szOut = p_szIn;
 	return true;
 }
@@ -747,13 +944,21 @@ bool PLY::PropertyInstance::ParseInstance (const char* p_szIn,const char** p_szO
 bool PLY::PropertyInstance::ParseInstanceBinary (const char* p_szIn,const char** p_szOut,
 	const PLY::Property* prop, PLY::PropertyInstance* p_pcOut,bool p_bBE)
 {
+	ai_assert(NULL != p_szIn);
+	ai_assert(NULL != p_szOut);
+	ai_assert(NULL != prop);
+	ai_assert(NULL != p_pcOut);
+
+	const char* szMax = *p_szOut;
 	*p_szOut = p_szIn;
 
 	if (prop->bIsList)
 	{
 		// parse the number of elements in the list
 		PLY::PropertyInstance::ValueUnion v;
-		PLY::PropertyInstance::ParseValueBinary(p_szIn, &p_szIn,prop->eFirstType,&v,p_bBE);
+		const char* szPass = szMax;
+		PLY::PropertyInstance::ParseValueBinary(p_szIn, &szPass,prop->eFirstType,&v,p_bBE);
+		p_szIn = szPass;
 
 		// convert to unsigned int
 		unsigned int iNum = PLY::PropertyInstance::ConvertTo<unsigned int>(v,prop->eFirstType);
@@ -761,7 +966,9 @@ bool PLY::PropertyInstance::ParseInstanceBinary (const char* p_szIn,const char**
 		// parse all list elements
 		for (unsigned int i = 0; i < iNum;++i)
 		{
-			PLY::PropertyInstance::ParseValueBinary(p_szIn, &p_szIn,prop->eType,&v,p_bBE);
+			const char* szPass = szMax;
+			PLY::PropertyInstance::ParseValueBinary(p_szIn, &szPass,prop->eType,&v,p_bBE);
+			p_szIn = szPass;
 			p_pcOut->avList.push_back(v);
 		}
 	}
@@ -769,9 +976,12 @@ bool PLY::PropertyInstance::ParseInstanceBinary (const char* p_szIn,const char**
 	{
 		// parse the property
 		PLY::PropertyInstance::ValueUnion v;
-		PLY::PropertyInstance::ParseValueBinary(p_szIn, &p_szIn,prop->eType,&v,p_bBE);
+		const char* szPass = szMax;
+		PLY::PropertyInstance::ParseValueBinary(p_szIn, &szPass,prop->eType,&v,p_bBE);
+		p_szIn = szPass;
 		p_pcOut->avList.push_back(v);
 	}
+	ValidateOut(p_szIn,szMax);
 	*p_szOut = p_szIn;
 	return true;
 }
@@ -798,6 +1008,11 @@ PLY::PropertyInstance::ValueUnion PLY::PropertyInstance::DefaultValue(
 bool PLY::PropertyInstance::ParseValue(const char* p_szIn,const char** p_szOut,
 	PLY::EDataType eType,PLY::PropertyInstance::ValueUnion* out)
 {
+	ai_assert(NULL != p_szIn);
+	ai_assert(NULL != p_szOut);
+	ai_assert(NULL != out);
+
+	const char* szMax = *p_szOut;
 	*p_szOut = p_szIn;
 
 	switch (eType)
@@ -846,13 +1061,23 @@ bool PLY::PropertyInstance::ParseValue(const char* p_szIn,const char** p_szOut,
 	default:
 		return false;
 	}
+	ValidateOut(p_szIn,szMax);
 	*p_szOut = p_szIn;
 	return true;
 }
 // ------------------------------------------------------------------------------------------------
-bool PLY::PropertyInstance::ParseValueBinary(const char* p_szIn,const char** p_szOut,
-	PLY::EDataType eType,PLY::PropertyInstance::ValueUnion* out, bool p_bBE)
+bool PLY::PropertyInstance::ParseValueBinary(
+	const char* p_szIn,
+	const char** p_szOut,
+	PLY::EDataType eType,
+	PLY::PropertyInstance::ValueUnion* out, 
+	bool p_bBE)
 {
+	ai_assert(NULL != p_szIn);
+	ai_assert(NULL != p_szOut);
+	ai_assert(NULL != out);
+
+	const char* szMax = *p_szOut;
 	*p_szOut = p_szIn;
 
 	switch (eType)
@@ -863,8 +1088,7 @@ bool PLY::PropertyInstance::ParseValueBinary(const char* p_szIn,const char** p_s
 		
 		if (p_bBE)
 		{
-			std::swap(((unsigned char*)(&out->iUInt))[0],((unsigned char*)(&out->iUInt))[3]);
-			std::swap(((unsigned char*)(&out->iUInt))[1],((unsigned char*)(&out->iUInt))[2]);
+			ByteSwap::Swap((int32_t*)&out->iUInt);
 		}
 		break;
 
@@ -873,7 +1097,7 @@ bool PLY::PropertyInstance::ParseValueBinary(const char* p_szIn,const char** p_s
 		uint16_t i = *((uint16_t*)p_szIn);
 		if (p_bBE)
 			{
-			std::swap(((unsigned char*)(&i))[0],((unsigned char*)(&i))[1]);
+			ByteSwap::Swap((int16_t*)&i);
 			}
 		out->iUInt = (uint32_t)i;
 		p_szIn += 2;
@@ -884,7 +1108,7 @@ bool PLY::PropertyInstance::ParseValueBinary(const char* p_szIn,const char** p_s
 		{
 		uint8_t i = *((uint8_t*)p_szIn);
 		out->iUInt = (uint32_t)i;
-		p_szIn += 2;
+		p_szIn ++;
 		break;
 		}
 
@@ -894,8 +1118,7 @@ bool PLY::PropertyInstance::ParseValueBinary(const char* p_szIn,const char** p_s
 		
 		if (p_bBE)
 		{
-			std::swap(((unsigned char*)(&out->iInt))[0],((unsigned char*)(&out->iInt))[3]);
-			std::swap(((unsigned char*)(&out->iInt))[1],((unsigned char*)(&out->iInt))[2]);
+			ByteSwap::Swap((int32_t*)&out->iInt);
 		}
 		break;
 
@@ -904,7 +1127,7 @@ bool PLY::PropertyInstance::ParseValueBinary(const char* p_szIn,const char** p_s
 		int16_t i = *((int16_t*)p_szIn);
 		if (p_bBE)
 			{
-			std::swap(((unsigned char*)(&i))[0],((unsigned char*)(&i))[1]);
+			ByteSwap::Swap((int16_t*)&i);
 			}
 		out->iInt = (int32_t)i;
 		p_szIn += 2;
@@ -913,46 +1136,35 @@ bool PLY::PropertyInstance::ParseValueBinary(const char* p_szIn,const char** p_s
 
 	case EDT_Char:
 		out->iInt = (int32_t)*((int8_t*)p_szIn);
-		p_szIn += 1;
+		p_szIn ++;
 		break;
 
 	case EDT_Float:
+		{
+		int32_t* pf = (int32_t*)p_szIn;
 		if (p_bBE)
 		{
-			union {char szArray[4]; float fValue; } _X;
-
-			_X.szArray[0] = ((unsigned char*)p_szIn)[3];
-			_X.szArray[1] = ((unsigned char*)p_szIn)[2];
-			_X.szArray[2] = ((unsigned char*)p_szIn)[1];
-			_X.szArray[3] = ((unsigned char*)p_szIn)[0];
-			out->fFloat = _X.fValue;
+			ByteSwap::Swap((int32_t*)&pf);
 		}
-		else out->fFloat = *((float*)p_szIn);
 		p_szIn += 4;
+		out->fFloat = *((float*)&pf);
 		break;
-
+		}
 	case EDT_Double:
+		{
+		int64_t* pf = (int64_t*)p_szIn;
 		if (p_bBE)
 		{
-			union {char szArray[8]; double fValue; } _X;
-
-			_X.szArray[0] = ((unsigned char*)p_szIn)[7];
-			_X.szArray[1] = ((unsigned char*)p_szIn)[6];
-			_X.szArray[2] = ((unsigned char*)p_szIn)[5];
-			_X.szArray[3] = ((unsigned char*)p_szIn)[4];
-			_X.szArray[4] = ((unsigned char*)p_szIn)[3];
-			_X.szArray[5] = ((unsigned char*)p_szIn)[2];
-			_X.szArray[6] = ((unsigned char*)p_szIn)[1];
-			_X.szArray[7] = ((unsigned char*)p_szIn)[0];
-			out->fDouble = _X.fValue;
+			ByteSwap::Swap((int64_t*)&pf);
 		}
-		else out->fDouble = *((double*)p_szIn);
 		p_szIn += 8;
+		out->fDouble = *((double*)&pf);
 		break;
-
+		}
 	default:
 		return false;
 	}
+	ValidateOut(p_szIn,szMax);
 	*p_szOut = p_szIn;
 	return true;
 }

+ 3 - 3
code/PlyParser.h

@@ -411,7 +411,7 @@ public:
 	ElementInstanceList (const Element* pc)
 	{
 		// reserve enough storage to speedup the process
-		alInstances.reserve(pc->NumOccur);
+		alInstances.resize(pc->NumOccur);
 	}
 
 	//! Destructor. Dallocates all storage
@@ -479,9 +479,9 @@ public:
 
 	//! Parse the DOM for a PLY file. The input string is assumed
 	//! to be terminated with zero
-	static bool ParseInstance (const char* p_szIn,DOM* p_pcOut);
+	static bool ParseInstance (const char* p_szIn,DOM* p_pcOut, unsigned int iLen);
 	static bool ParseInstanceBinary (const char* p_szIn,
-		DOM* p_pcOut,bool p_bBE);
+		DOM* p_pcOut,bool p_bBE,  unsigned int iLen);
 
 	//! Skip all comment lines after this
 	static bool SkipComments (const char* p_szIn,const char** p_szOut);

+ 14 - 2
code/SplitLargeMeshes.cpp

@@ -42,6 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 /** @file Implementation of the SplitLargeMeshes postprocessing step
 */
 #include "SplitLargeMeshes.h"
+#include "DefaultLogger.h"
 #include "../include/aiPostProcess.h"
 #include "../include/aiMesh.h"
 #include "../include/aiScene.h"
@@ -63,6 +64,7 @@ aiReturn aiSetVertexSplitLimit(unsigned int pLimit)
 	}
 
 	SplitLargeMeshesProcess_Vertex::LIMIT = pLimit;
+	//DefaultLogger::get()->debug("aiSetVertexSplitLimit() - vertex split limit was changed");
 	return AI_SUCCESS;
 }
 // ------------------------------------------------------------------------------------------------
@@ -75,6 +77,7 @@ aiReturn aiSetTriangleSplitLimit(unsigned int pLimit)
 	}
 
 	SplitLargeMeshesProcess_Triangle::LIMIT = pLimit;
+	//DefaultLogger::get()->debug("aiSetTriangleSplitLimit() - triangle split limit was changed");
 	return AI_SUCCESS;
 }
 }; //! extern "C"
@@ -99,6 +102,7 @@ bool SplitLargeMeshesProcess_Triangle::IsActive( unsigned int pFlags) const
 // Executes the post processing step on the given imported data.
 void SplitLargeMeshesProcess_Triangle::Execute( aiScene* pScene)
 {
+	DefaultLogger::get()->debug("SplitLargeMeshesProcess_Triangle begin");
 	std::vector<std::pair<aiMesh*, unsigned int> > avList;
 
 	for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
@@ -116,7 +120,9 @@ void SplitLargeMeshesProcess_Triangle::Execute( aiScene* pScene)
 
 		// now we need to update all nodes
 		this->UpdateNode(pScene->mRootNode,avList);
+		DefaultLogger::get()->info("SplitLargeMeshesProcess_Triangle finished. Meshes have been splitted");
 	}
+	else DefaultLogger::get()->debug("SplitLargeMeshesProcess_Triangle finished. There was nothing to do");
 	return;
 }
 // ------------------------------------------------------------------------------------------------
@@ -160,8 +166,10 @@ void SplitLargeMeshesProcess_Triangle::SplitMesh(
 	aiMesh* pMesh,
 	std::vector<std::pair<aiMesh*, unsigned int> >& avList)
 {
-	if (pMesh->mNumFaces > LIMIT)
+	if (pMesh->mNumFaces > SplitLargeMeshesProcess_Triangle::LIMIT)
 	{
+		DefaultLogger::get()->info("Mesh exceeds the triangle limit. It will be split ...");
+
 		// we need to split this mesh into sub meshes
 		// determine the size of a submesh
 		const unsigned int iSubMeshes = (pMesh->mNumFaces / LIMIT) + 1;
@@ -318,6 +326,7 @@ void SplitLargeMeshesProcess_Vertex::Execute( aiScene* pScene)
 {
 	std::vector<std::pair<aiMesh*, unsigned int> > avList;
 
+	DefaultLogger::get()->debug("SplitLargeMeshesProcess_Vertex begin");
 	for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
 		this->SplitMesh(a, pScene->mMeshes[a],avList);
 
@@ -333,7 +342,9 @@ void SplitLargeMeshesProcess_Vertex::Execute( aiScene* pScene)
 
 		// now we need to update all nodes
 		SplitLargeMeshesProcess_Triangle::UpdateNode(pScene->mRootNode,avList);
+		DefaultLogger::get()->info("SplitLargeMeshesProcess_Vertex finished. Meshes have been splitted");
 	}
+	else DefaultLogger::get()->debug("SplitLargeMeshesProcess_Vertex finished. There was nothing to do");
 	return;
 }
 // ------------------------------------------------------------------------------------------------
@@ -510,7 +521,8 @@ void SplitLargeMeshesProcess_Vertex::SplitMesh(
 
 		// now delete the old mesh data
 		delete pMesh;
+		return;
 	}
-	else avList.push_back(std::pair<aiMesh*, unsigned int>(pMesh,a));
+	avList.push_back(std::pair<aiMesh*, unsigned int>(pMesh,a));
 	return;
 }

+ 26 - 3
code/TriangulateProcess.cpp

@@ -4,6 +4,7 @@
 #include <vector>
 #include <assert.h>
 #include "TriangulateProcess.h"
+#include "DefaultLogger.h"
 #include "../include/aiPostProcess.h"
 #include "../include/aiMesh.h"
 #include "../include/aiScene.h"
@@ -35,14 +36,33 @@ bool TriangulateProcess::IsActive( unsigned int pFlags) const
 // Executes the post processing step on the given imported data.
 void TriangulateProcess::Execute( aiScene* pScene)
 {
+	DefaultLogger::get()->debug("TriangulateProcess begin");
+
+	bool bHas = false;
 	for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
-		TriangulateMesh( pScene->mMeshes[a]);
+	{
+		if(	TriangulateMesh( pScene->mMeshes[a]))
+			bHas = true;
+	}
+	if (bHas)DefaultLogger::get()->info("TriangulateProcess finished. Found polygons to triangulate");
+	else DefaultLogger::get()->debug("TriangulateProcess finished. There was nothing to do.");
 }
 
 // ------------------------------------------------------------------------------------------------
 // Triangulates the given mesh.
-void TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
+bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
 {
+	// check whether we will need to do something ...
+	for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
+	{
+		const aiFace& face = pMesh->mFaces[a];
+		if( face.mNumIndices != 3)
+		{
+			break;
+		}
+		return false;
+	}
+
 	std::vector<aiFace> newFaces;
 	newFaces.reserve( pMesh->mNumFaces*2);
 	for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
@@ -57,7 +77,8 @@ void TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
 			nface.mNumIndices = face.mNumIndices;
 			nface.mIndices = new unsigned int[nface.mNumIndices];
 			memcpy( nface.mIndices, face.mIndices, nface.mNumIndices * sizeof( unsigned int));
-		} else
+		} 
+		else
 		{
 			assert( face.mNumIndices > 3);
 			for( unsigned int b = 0; b < face.mNumIndices - 2; b++)
@@ -80,4 +101,6 @@ void TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
 	pMesh->mFaces = new aiFace[pMesh->mNumFaces];
 	for( unsigned int a = 0; a < newFaces.size(); a++)
 		pMesh->mFaces[a] = newFaces[a];
+
+	return true;
 }

+ 1 - 1
code/TriangulateProcess.h

@@ -88,7 +88,7 @@ protected:
 	/** Triangulates the given mesh.
 	 * @param pMesh The mesh to triangulate.
 	 */
-	void TriangulateMesh( aiMesh* pMesh);
+	bool TriangulateMesh( aiMesh* pMesh);
 };
 
 } // end of namespace Assimp

+ 6 - 1
code/XFileImporter.cpp

@@ -561,8 +561,13 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, const std::vector<XFile::
 		aiString name;
 		name.Set( oldMat.mName);
 		mat->AddProperty( &name, AI_MATKEY_NAME);
+
 		// Shading model: hardcoded to PHONG, there is no such information in an XFile
-		int shadeMode = (int) aiShadingMode_Phong;
+		// FIX (aramis): If the specular exponent is 0, use gouraud shading. This is a bugfix
+		// for some models in the SDK (e.g. good old tiny.x)
+		int shadeMode = (int)oldMat.mSpecularExponent == 0.0f 
+			? aiShadingMode_Gouraud : aiShadingMode_Phong;
+
 		mat->AddProperty<int>( &shadeMode, 1, AI_MATKEY_SHADING_MODEL);
 		// material colours
 		mat->AddProperty( &oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE);

+ 2 - 1
include/aiMaterial.h

@@ -512,13 +512,14 @@ aiReturn aiGetMaterialString(const C_STRUCT aiMaterial* pMat,
 	aiString* pOut);
 
 
-#define AI_TEXTYPE_DIFFUSE		0x0
+#define AI_TEXTYPE_OPACITY		0x0
 #define AI_TEXTYPE_SPECULAR		0x1
 #define AI_TEXTYPE_AMBIENT		0x2
 #define AI_TEXTYPE_EMISSIVE		0x3
 #define AI_TEXTYPE_HEIGHT		0x4
 #define AI_TEXTYPE_NORMALS		0x5
 #define AI_TEXTYPE_SHININESS	0x6
+#define AI_TEXTYPE_DIFFUSE		0x7
 
 // ---------------------------------------------------------------------------
 /** Helper function to get a diffuse texture from a material

+ 18 - 0
include/aiTypes.h

@@ -144,6 +144,7 @@ struct aiString
 		// empty
 	}
 
+	//! construction from a given std::string
 	inline aiString(const aiString& rOther) : 
 		length(rOther.length) 
 	{
@@ -151,6 +152,7 @@ struct aiString
 		this->data[this->length] = '\0';
 	}
 
+	//! copy a std::string to the aiString
 	void Set( const std::string& pString)
 	{
 		if( pString.length() > MAXLEN - 1)
@@ -159,6 +161,22 @@ struct aiString
 		memcpy( data, pString.c_str(), length);
 		data[length] = 0;
 	}
+
+	//! comparison operator
+	bool operator==(const aiString& other) const
+	{
+		return  (this->length == other.length &&
+				 0 == strcmp(this->data,other.data));
+	}
+
+	//! inverse comparison operator
+	bool operator!=(const aiString& other) const
+	{
+		return  (this->length != other.length ||
+				 0 != strcmp(this->data,other.data));
+	}
+
+
 #endif // !__cplusplus
 
 	//! Length of the string excluding the terminal 0

+ 7 - 0
include/aiVector3D.h

@@ -28,6 +28,13 @@ struct aiVector3D
 
 	inline float operator[](unsigned int i) const {return *(&x + i);}
 	inline float& operator[](unsigned int i) {return *(&x + i);}
+
+	inline bool operator== (const aiVector3D& other) const
+		{return x == other.x && y == other.y && z == other.z;}
+
+	inline bool operator!= (const aiVector3D& other) const
+		{return x != other.x || y != other.y || z != other.z;}
+
 #endif // __cplusplus
 
 	float x, y, z;	

+ 78 - 10
tools/assimp_view/AssetHelper.h

@@ -1,12 +1,44 @@
-//-------------------------------------------------------------------------------
-/**
-*	This program is distributed under the terms of the GNU Lesser General
-*	Public License (LGPL). 
-*
-*	ASSIMP Viewer Utility
-*
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development Team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the ASSIMP team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the ASSIMP Development Team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
 */
-//-------------------------------------------------------------------------------
+
 
 #if (!defined AV_ASSET_HELPER_H_INCLUDED)
 #define AV_ASSET_HELPER_H_INCLUDED
@@ -19,6 +51,22 @@
 class AssetHelper
 	{
 	public:
+		enum 
+		{
+			// the original normal set will be used
+			ORIGINAL = 0x0u,
+
+			// a smoothed normal set will be used
+			SMOOTH = 0x1u,
+
+			// a hard normal set will be used
+			HARD = 0x2u,
+		};
+
+		// default constructor
+		AssetHelper()
+			: iNormalSet(ORIGINAL)
+		{}
 
 		//---------------------------------------------------------------
 		// default vertex data structure
@@ -71,6 +119,7 @@ class AssetHelper
 					: 
 					piVB				(NULL),
 					piIB				(NULL),
+					piEffect			(NULL),
 					piVBNormals			(NULL),
 					piDiffuseTexture	(NULL),
 					piSpecularTexture	(NULL),
@@ -78,6 +127,8 @@ class AssetHelper
 					piNormalTexture		(NULL),
 					piEmissiveTexture	(NULL),
 					piOpacityTexture	(NULL),
+					piShininessTexture	(NULL),
+					pvOriginalNormals	(NULL),
 					bSharedFX(false) {}
 
 				~MeshHelper ()
@@ -93,7 +144,9 @@ class AssetHelper
 				// vertex buffer
 				IDirect3DVertexBuffer9* piVB;
 
-				// index buffer
+				// index buffer. For partially transparent meshes
+				// created with dynamic usage to be able to update
+				// the buffer contents quickly
 				IDirect3DIndexBuffer9* piIB;
 
 				// vertex buffer to be used to draw vertex normals
@@ -111,6 +164,7 @@ class AssetHelper
 				IDirect3DTexture9* piEmissiveTexture;
 				IDirect3DTexture9* piNormalTexture;
 				IDirect3DTexture9* piOpacityTexture;
+				IDirect3DTexture9* piShininessTexture;
 
 				// material colors
 				D3DXVECTOR4 vDiffuseColor;
@@ -123,13 +177,27 @@ class AssetHelper
 
 				// shininess for the material
 				float fShininess;
+
+				// Stores a pointer to the original normal set of the asset
+				aiVector3D* pvOriginalNormals;
 			};
 
 		// One instance per aiMesh in the globally loaded asset
 		MeshHelper** apcMeshes;
 
 		// Scene wrapper instance
-		const aiScene* pcScene;
+		aiScene* pcScene;
+
+		// Specifies the normal set to be used
+		unsigned int iNormalSet;
+
+		// ------------------------------------------------------------------
+		// set the normal set to be used
+		void SetNormalSet(unsigned int iSet);
+
+		// ------------------------------------------------------------------
+		// flip all normal vectors
+		void FlipNormals();
 	};
 
 #endif // !! IG

+ 98 - 96
tools/assimp_view/Background.cpp

@@ -12,18 +12,18 @@ 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.
+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.
+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.
+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 
@@ -49,21 +49,21 @@ namespace AssimpView {
 // From: U3D build 1256 (src\kernel\graphic\scenegraph\SkyBox.cpp)
 // ------------------------------------------------------------------------------
 /**	\brief Vertex structure for the skybox
- */
+*/
 // ------------------------------------------------------------------------------
 struct SkyBoxVertex
-	{
-    float x,y,z;
-    float u,v,w;
-	};
+{
+	float x,y,z;
+	float u,v,w;
+};
 
 
 // ------------------------------------------------------------------------------
 /**	\brief Vertices for the skybox 
- */
+*/
 // ------------------------------------------------------------------------------
 SkyBoxVertex g_cubeVertices_indexed[] =
-	{
+{
 	{ -1.0f, 1.0f, -1.0f,	-1.0f,1.0f,-1.0f },		// 0
 	{ 1.0f, 1.0f,  -1.0f,	1.0f,1.0f,-1.0f },		// 1
 	{ -1.0f, -1.0f, -1.0f,	-1.0f,-1.0f,-1.0f },	// 2
@@ -72,70 +72,71 @@ SkyBoxVertex g_cubeVertices_indexed[] =
 	{-1.0f,-1.0f, 1.0f,		-1.0f,-1.0f,1.0f },		// 5
 	{ 1.0f, 1.0f, 1.0f,		1.0f,1.0f,1.0f },		// 6
 	{ 1.0f,-1.0f, 1.0f,		1.0f,-1.0f,1.0f }		// 7
-	};
+};
 
 
 // ------------------------------------------------------------------------------
 /**	\brief Indices for the skybox
- */
+*/
 // ------------------------------------------------------------------------------
 unsigned short g_cubeIndices[] =
-	{
+{
 	0, 1, 2, 3, 2, 1,4, 5, 6,
 	7, 6, 5, 4, 6,  0, 1, 6, 0, 
 	5, 2, 7,3, 2, 7, 1, 6, 3,
 	7, 3, 6, 0, 2, 4, 5, 4, 2,  
-	};
+};
 
 CBackgroundPainter CBackgroundPainter::s_cInstance;
 
 //-------------------------------------------------------------------------------
 void CBackgroundPainter::SetColor (D3DCOLOR p_clrNew)
-	{
+{
 	if (TEXTURE_CUBE == this->eMode)this->RemoveSBDeps();
 
 	this->clrColor = p_clrNew;
 	this->eMode = SIMPLE_COLOR;
 
 	if (this->pcTexture)
-		{
+	{
 		this->pcTexture->Release();
 		this->pcTexture = NULL;
-		}
 	}
+}
 //-------------------------------------------------------------------------------
 void CBackgroundPainter::RemoveSBDeps()
-	{
+{
 	MODE e = this->eMode;
 	this->eMode = SIMPLE_COLOR;
 	if (g_pcAsset && g_pcAsset->pcScene)
-		{
+	{
 		for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
-			{
+		{
 			if (aiShadingMode_Gouraud != g_pcAsset->apcMeshes[i]->eShadingMode)
-				{
-				DeleteMaterial(g_pcAsset->apcMeshes[i]);
-				CreateMaterial(g_pcAsset->apcMeshes[i],g_pcAsset->pcScene->mMeshes[i]);
-				}
+			{
+				CMaterialManager::Instance().DeleteMaterial(g_pcAsset->apcMeshes[i]);
+				CMaterialManager::Instance().CreateMaterial(
+					g_pcAsset->apcMeshes[i],g_pcAsset->pcScene->mMeshes[i]);
 			}
 		}
-	this->eMode = e;
 	}
+	this->eMode = e;
+}
 //-------------------------------------------------------------------------------
 void CBackgroundPainter::ResetSB()
-	{
+{
 	this->mMatrix = aiMatrix4x4();
-	}
+}
 //-------------------------------------------------------------------------------
 void CBackgroundPainter::SetCubeMapBG (const char* p_szPath)
-	{
+{
 	bool bHad = false;
 	if (this->pcTexture)
-		{
+	{
 		this->pcTexture->Release();
 		this->pcTexture = NULL;
 		if(TEXTURE_CUBE ==this->eMode)bHad = true;
-		}
+	}
 
 	this->eMode = TEXTURE_CUBE;
 
@@ -144,101 +145,102 @@ void CBackgroundPainter::SetCubeMapBG (const char* p_szPath)
 	// ARRRGHH... ugly. TODO: Rewrite this!
 	aiString sz;
 	sz.Set(this->szPath);
-	FindValidPath(&sz);
+	CMaterialManager::Instance().FindValidPath(&sz);
 	this->szPath = std::string( sz.data );
 
 	// now recreate all native resources
 	this->RecreateNativeResource();
 
 	if (SIMPLE_COLOR != this->eMode)
-		{
+	{
 		// this influences all material with specular components
 		if (!bHad)
-			{
+		{
 			if (g_pcAsset && g_pcAsset->pcScene)
-				{
+			{
 				for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
-					{
+				{
 					if (aiShadingMode_Phong == g_pcAsset->apcMeshes[i]->eShadingMode)
-						{
-						DeleteMaterial(g_pcAsset->apcMeshes[i]);
-						CreateMaterial(g_pcAsset->apcMeshes[i],g_pcAsset->pcScene->mMeshes[i]);
-						}
+					{
+						CMaterialManager::Instance().DeleteMaterial(g_pcAsset->apcMeshes[i]);
+						CMaterialManager::Instance().CreateMaterial(
+							g_pcAsset->apcMeshes[i],g_pcAsset->pcScene->mMeshes[i]);
 					}
 				}
 			}
+		}
 		else
-			{
+		{
 			if (g_pcAsset && g_pcAsset->pcScene)
-				{
+			{
 				for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
-					{
+				{
 					if (aiShadingMode_Phong == g_pcAsset->apcMeshes[i]->eShadingMode)
-						{
+					{
 						g_pcAsset->apcMeshes[i]->piEffect->SetTexture(
 							"lw_tex_envmap",CBackgroundPainter::Instance().GetTexture());
-						}
 					}
 				}
 			}
 		}
 	}
+}
 //-------------------------------------------------------------------------------
 void CBackgroundPainter::RotateSB(const aiMatrix4x4* pm)
-	{
+{
 	this->mMatrix = this->mMatrix * (*pm);
-	}
+}
 //-------------------------------------------------------------------------------
 void CBackgroundPainter::SetTextureBG (const char* p_szPath)
-	{
+{
 	if (TEXTURE_CUBE == this->eMode)this->RemoveSBDeps();
 
 	if (this->pcTexture)
-		{
+	{
 		this->pcTexture->Release();
 		this->pcTexture = NULL;
-		}
-	
+	}
+
 	this->eMode = TEXTURE_2D;
 	this->szPath = std::string( p_szPath );
 
 	// ARRRGHH... ugly. TODO: Rewrite this!
 	aiString sz;
 	sz.Set(this->szPath);
-	FindValidPath(&sz);
+	CMaterialManager::Instance().FindValidPath(&sz);
 	this->szPath = std::string( sz.data );
 
 	// now recreate all native resources
 	this->RecreateNativeResource();
-	}
+}
 //-------------------------------------------------------------------------------
 void CBackgroundPainter::OnPreRender()
-	{
+{
 	if (SIMPLE_COLOR != this->eMode)
-		{
+	{
 		// clear the z-buffer only (in wireframe mode we must also clear
 		// the color buffer )
 		if (g_sOptions.eDrawMode == RenderOptions::WIREFRAME)
-			{
+		{
 			g_piDevice->Clear(0,NULL,D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET,
 				D3DCOLOR_ARGB(0xff,100,100,100),1.0f,0);
-			}
+		}
 		else
-			{
+		{
 			g_piDevice->Clear(0,NULL,D3DCLEAR_ZBUFFER,0,1.0f,0);
-			}
+		}
 
 		if (TEXTURE_2D == this->eMode)
-			{
+		{
 			RECT sRect;
 			GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect);
 			sRect.right -= sRect.left;
 			sRect.bottom -= sRect.top;
 
 			struct SVertex
-				{
+			{
 				float x,y,z,w,u,v;
-				};
+			};
 
 			UINT dw;
 			this->piSkyBoxEffect->Begin(&dw,0);
@@ -286,18 +288,18 @@ void CBackgroundPainter::OnPreRender()
 			this->piSkyBoxEffect->End();
 
 			g_piDevice->SetFVF(dw2);
-			}
-		return;
 		}
+		return;
+	}
 	// clear both the render target and the z-buffer
 	g_piDevice->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
 		this->clrColor,1.0f,0);
-	}
+}
 //-------------------------------------------------------------------------------
 void CBackgroundPainter::OnPostRender()
-	{
+{
 	if (TEXTURE_CUBE == this->eMode)
-		{
+	{
 		aiMatrix4x4 pcProj;
 		GetProjectionMatrix(pcProj);
 
@@ -305,7 +307,7 @@ void CBackgroundPainter::OnPostRender()
 		aiVector3D vPos = GetCameraMatrix(pcCam);
 
 		aiMatrix4x4 aiMe;
-	    aiMe[3][0] = vPos.x;
+		aiMe[3][0] = vPos.x;
 		aiMe[3][1] = vPos.y;
 		aiMe[3][2] = vPos.z;
 		aiMe = this->mMatrix * aiMe;
@@ -331,28 +333,28 @@ void CBackgroundPainter::OnPostRender()
 
 		this->piSkyBoxEffect->EndPass();
 		this->piSkyBoxEffect->End();
-		}
 	}
+}
 //-------------------------------------------------------------------------------
 void CBackgroundPainter::ReleaseNativeResource()
-	{
+{
 	if (this->piSkyBoxEffect)
-		{
+	{
 		this->piSkyBoxEffect->Release();
 		this->piSkyBoxEffect = NULL;
-		}
+	}
 	if (this->pcTexture)
-		{
+	{
 		this->pcTexture->Release();
 		this->pcTexture = NULL;
-		}
 	}
+}
 //-------------------------------------------------------------------------------
 void CBackgroundPainter::RecreateNativeResource()
-	{
+{
 	if (SIMPLE_COLOR == this->eMode)return;
 	if (TEXTURE_CUBE == this->eMode)
-		{
+	{
 
 		// many skyboxes are 16bit FP format which isn't supported
 		// with bilinear filtering on older cards
@@ -377,25 +379,25 @@ void CBackgroundPainter::RecreateNativeResource()
 			NULL,
 			NULL,
 			(IDirect3DCubeTexture9**)&this->pcTexture)))
-			{
+		{
 			const char* szEnd = strrchr(this->szPath.c_str(),'\\');
 			if (!szEnd)szEnd = strrchr(this->szPath.c_str(),'/');
 			if (!szEnd)szEnd = this->szPath.c_str()-1;
 
 			char szTemp[1024];
 			sprintf(szTemp,"[ERROR] Unable to load background cubemap %s",szEnd+1);
-			
+
 			CLogDisplay::Instance().AddEntry(szTemp,
 				D3DCOLOR_ARGB(0xFF,0xFF,0,0));
 
 			this->eMode = SIMPLE_COLOR;
 			return;
-			}
+		}
 		else CLogDisplay::Instance().AddEntry("[OK] The skybox has been imported successfully",
 			D3DCOLOR_ARGB(0xFF,0,0xFF,0));
-		}
+	}
 	else
-		{
+	{
 		if (FAILED(D3DXCreateTextureFromFileEx(
 			g_piDevice,
 			this->szPath.c_str(),
@@ -411,25 +413,25 @@ void CBackgroundPainter::RecreateNativeResource()
 			NULL,
 			NULL,
 			(IDirect3DTexture9**)&this->pcTexture)))
-			{
+		{
 			const char* szEnd = strrchr(this->szPath.c_str(),'\\');
 			if (!szEnd)szEnd = strrchr(this->szPath.c_str(),'/');
 			if (!szEnd)szEnd = this->szPath.c_str()-1;
 
 			char szTemp[1024];
 			sprintf(szTemp,"[ERROR] Unable to load background texture %s",szEnd+1);
-			
+
 			CLogDisplay::Instance().AddEntry(szTemp,
 				D3DCOLOR_ARGB(0xFF,0xFF,0,0));
 
 			this->eMode = SIMPLE_COLOR;
 			return;
-			}
+		}
 		else CLogDisplay::Instance().AddEntry("[OK] The background texture has been imported successfully",
 			D3DCOLOR_ARGB(0xFF,0,0xFF,0));
-		}
+	}
 	if (!piSkyBoxEffect)
-		{
+	{
 		if(FAILED( D3DXCreateEffect(
 			g_piDevice,
 			g_szSkyboxShader.c_str(),
@@ -439,23 +441,23 @@ void CBackgroundPainter::RecreateNativeResource()
 			D3DXSHADER_USE_LEGACY_D3DX9_31_DLL,
 			NULL,
 			&this->piSkyBoxEffect,NULL)))
-			{
+		{
 			CLogDisplay::Instance().AddEntry("[ERROR] Unable to compile skybox shader",
 				D3DCOLOR_ARGB(0xFF,0xFF,0,0));
 			this->eMode = SIMPLE_COLOR;
 			return ;
-			}
 		}
+	}
 	// commit the correct textures to the shader
 	if (TEXTURE_CUBE == this->eMode)
-		{
+	{
 		this->piSkyBoxEffect->SetTexture("lw_tex_envmap",this->pcTexture);
 		this->piSkyBoxEffect->SetTechnique("RenderSkyBox");
-		}
+	}
 	else if (TEXTURE_2D == this->eMode)
-		{
+	{
 		this->piSkyBoxEffect->SetTexture("TEXTURE_2D",this->pcTexture);
 		this->piSkyBoxEffect->SetTechnique("RenderImage2D");
-		}
 	}
+}
 };

+ 2086 - 1
tools/assimp_view/Display.cpp

@@ -1 +1,2086 @@
-#include "stdafx.h"
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development Team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the ASSIMP team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the ASSIMP Development Team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+#include "stdafx.h"
+#include "assimp_view.h"
+
+
+namespace AssimpView {
+
+
+CDisplay CDisplay::s_cInstance;
+
+extern COLORREF g_aclCustomColors[16] /*= {0}*/;
+extern HKEY g_hRegistry;
+extern float g_fLoadTime;
+
+//-------------------------------------------------------------------------------
+// Table of colors used for normal vectors. 
+//-------------------------------------------------------------------------------
+D3DXVECTOR4 g_aclNormalColors[14] = 
+{
+	D3DXVECTOR4(0xFF / 255.0f,0xFF / 255.0f,0xFF / 255.0f, 1.0f), // white
+
+	D3DXVECTOR4(0xFF / 255.0f,0x00 / 255.0f,0x00 / 255.0f,1.0f), // red
+	D3DXVECTOR4(0x00 / 255.0f,0xFF / 255.0f,0x00 / 255.0f,1.0f), // green
+	D3DXVECTOR4(0x00 / 255.0f,0x00 / 255.0f,0xFF / 255.0f,1.0f), // blue
+
+	D3DXVECTOR4(0xFF / 255.0f,0xFF / 255.0f,0x00 / 255.0f,1.0f), // yellow
+	D3DXVECTOR4(0xFF / 255.0f,0x00 / 255.0f,0xFF / 255.0f,1.0f), // magenta
+	D3DXVECTOR4(0x00 / 255.0f,0xFF / 255.0f,0xFF / 255.0f,1.0f), // wtf
+
+	D3DXVECTOR4(0xFF / 255.0f,0x60 / 255.0f,0x60 / 255.0f,1.0f), // light red
+	D3DXVECTOR4(0x60 / 255.0f,0xFF / 255.0f,0x60 / 255.0f,1.0f), // light green
+	D3DXVECTOR4(0x60 / 255.0f,0x60 / 255.0f,0xFF / 255.0f,1.0f), // light blue
+
+	D3DXVECTOR4(0xA0 / 255.0f,0x00 / 255.0f,0x00 / 255.0f,1.0f), // dark red
+	D3DXVECTOR4(0x00 / 255.0f,0xA0 / 255.0f,0x00 / 255.0f,1.0f), // dark green
+	D3DXVECTOR4(0x00 / 255.0f,0x00 / 255.0f,0xA0 / 255.0f,1.0f), // dark blue
+
+	D3DXVECTOR4(0x88 / 255.0f,0x88 / 255.0f,0x88 / 255.0f, 1.0f) // gray
+};
+
+
+//-------------------------------------------------------------------------------
+// Recursivly count the number of nodes in an asset's node graph
+// Used by LoadAsset()
+//-------------------------------------------------------------------------------
+void GetNodeCount(aiNode* pcNode, unsigned int* piCnt)
+{
+	*piCnt = *piCnt+1;
+	for (unsigned int i = 0; i < pcNode->mNumChildren;++i)
+		GetNodeCount(pcNode->mChildren[i],piCnt);
+}
+
+//-------------------------------------------------------------------------------
+int CDisplay::FillAnimList(void)
+{
+	if (0 == g_pcAsset->pcScene->mNumAnimations)
+	{
+		// disable all UI components related to animations
+		EnableWindow(GetDlgItem(g_hDlg,IDC_PLAYANIM),FALSE);
+		EnableWindow(GetDlgItem(g_hDlg,IDC_SPEED),FALSE);
+		EnableWindow(GetDlgItem(g_hDlg,IDC_PINORDER),FALSE);
+
+		EnableWindow(GetDlgItem(g_hDlg,IDC_SSPEED),FALSE);
+		EnableWindow(GetDlgItem(g_hDlg,IDC_SANIMGB),FALSE);
+		EnableWindow(GetDlgItem(g_hDlg,IDC_SANIM),FALSE);
+		EnableWindow(GetDlgItem(g_hDlg,IDC_COMBO1),FALSE);
+	}
+	else
+	{
+		// reenable all animation components if they have been
+		// disabled for a previous mesh
+		EnableWindow(GetDlgItem(g_hDlg,IDC_PLAYANIM),TRUE);
+		EnableWindow(GetDlgItem(g_hDlg,IDC_SPEED),TRUE);
+		EnableWindow(GetDlgItem(g_hDlg,IDC_PINORDER),TRUE);
+
+		EnableWindow(GetDlgItem(g_hDlg,IDC_SSPEED),TRUE);
+		EnableWindow(GetDlgItem(g_hDlg,IDC_SANIMGB),TRUE);
+		EnableWindow(GetDlgItem(g_hDlg,IDC_SANIM),TRUE);
+		EnableWindow(GetDlgItem(g_hDlg,IDC_COMBO1),TRUE);
+
+		// now fill in all animation names
+		for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumAnimations;++i)
+		{
+			SendDlgItemMessage(g_hDlg,IDC_COMBO1,CB_ADDSTRING,0,
+				( LPARAM ) g_pcAsset->pcScene->mAnimations[i]->mName.data);
+		}
+	}
+	return 1;
+}
+//-------------------------------------------------------------------------------
+int CDisplay::ClearAnimList(void)
+{
+	// clear the combo box
+	SendDlgItemMessage(g_hDlg,IDC_COMBO1,CB_RESETCONTENT,0,0);
+	return 1;
+}
+//-------------------------------------------------------------------------------
+int CDisplay::ClearDisplayList(void)
+{
+	// clear the combo box
+	TreeView_DeleteAllItems(GetDlgItem(g_hDlg,IDC_TREE1));
+	return 1;
+}
+//-------------------------------------------------------------------------------
+int CDisplay::AddNodeToDisplayList(
+	unsigned int iIndex, 
+	unsigned int iDepth,
+	aiNode* pcNode,
+	HTREEITEM hRoot)
+{
+	ai_assert(NULL != pcNode);
+	ai_assert(NULL != hRoot);
+
+	char chTemp[512];
+
+	if(0 == pcNode->mName.length)
+	{
+		if (iIndex >= 100)
+		{
+			iIndex += iDepth  * 1000;
+		}
+		else if (iIndex >= 10)
+		{
+			iIndex += iDepth  * 100;
+		}
+		else iIndex += iDepth  * 10;
+		sprintf(chTemp,"Node %i",iIndex);
+	}
+	else strcpy(chTemp,pcNode->mName.data);
+
+	TVITEMEX tvi; 
+	TVINSERTSTRUCT sNew;
+	tvi.pszText = chTemp;
+	tvi.cchTextMax = (int)strlen(chTemp);
+	tvi.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_HANDLE | TVIF_PARAM;
+	tvi.iImage = this->m_aiImageList[AI_VIEW_IMGLIST_NODE];
+	tvi.iSelectedImage = this->m_aiImageList[AI_VIEW_IMGLIST_NODE];
+	tvi.lParam = (LPARAM)5; 
+
+	sNew.itemex = tvi; 
+	sNew.hInsertAfter = TVI_LAST; 
+	sNew.hParent = hRoot;
+
+	// add the item to the list
+	HTREEITEM hTexture = (HTREEITEM)SendMessage(GetDlgItem(g_hDlg,IDC_TREE1), 
+		TVM_INSERTITEM, 
+		0,
+		(LPARAM)(LPTVINSERTSTRUCT)&sNew);
+
+	// recursively add all child nodes
+	++iDepth;
+	for (unsigned int i = 0; i< pcNode->mNumChildren;++i)
+	{
+		AddNodeToDisplayList(i,iDepth,pcNode->mChildren[i],hTexture);
+	}
+
+	// add the node to the list
+	NodeInfo info;
+	info.hTreeItem = hTexture;
+	info.psNode = pcNode;
+	this->AddNode(info);
+	return 1;
+}
+//-------------------------------------------------------------------------------
+int CDisplay::ReplaceCurrentTexture(const char* szPath)
+{
+	ai_assert(NULL != szPath);
+
+	// well ... try to load it
+	IDirect3DTexture9* piTexture = NULL;
+	aiString szString;
+	strcpy(szString.data,szPath);
+	szString.length = strlen(szPath);
+	CMaterialManager::Instance().LoadTexture(&piTexture,&szString);
+
+	if (!piTexture)
+	{
+		CLogDisplay::Instance().AddEntry("[ERROR] Unable to load this texture",
+			D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0));
+		return 0;
+	}
+
+	// we must also change the icon of the corresponding tree
+	// view item if the default texture was previously set
+	TVITEMEX tvi; 
+	tvi.mask = TVIF_SELECTEDIMAGE | TVIF_IMAGE;
+	tvi.iImage = this->m_aiImageList[AI_VIEW_IMGLIST_MATERIAL];
+	tvi.iSelectedImage = this->m_aiImageList[AI_VIEW_IMGLIST_MATERIAL];
+
+	TreeView_SetItem(GetDlgItem(g_hDlg,IDC_TREE1),
+		this->m_pcCurrentTexture->hTreeItem);
+
+	// change this in the old aiMaterial structure, too
+	Assimp::MaterialHelper* pcMat = (Assimp::MaterialHelper*)
+		g_pcAsset->pcScene->mMaterials[this->m_pcCurrentTexture->iMatIndex];
+ 	
+	// update all meshes referencing this material
+	this->m_pcCurrentTexture->piTexture = piTexture;
+	for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
+	{
+		if (this->m_pcCurrentTexture->iMatIndex != g_pcAsset->pcScene->mMeshes[i]->mMaterialIndex)
+			continue;
+
+		AssetHelper::MeshHelper* pcMesh = g_pcAsset->apcMeshes[i];
+		switch (this->m_pcCurrentTexture->iType)
+		{
+		case AI_TEXTYPE_DIFFUSE:
+			if (pcMesh->piDiffuseTexture && pcMesh->piDiffuseTexture != piTexture)
+			{
+				pcMesh->piDiffuseTexture->Release();
+				pcMesh->piDiffuseTexture = piTexture;
+
+				if (!pcMesh->bSharedFX)
+				{
+					pcMesh->piEffect->SetTexture("DIFFUSE_TEXTURE",piTexture);
+				}
+			}
+			break;
+		case AI_TEXTYPE_AMBIENT:
+			if (pcMesh->piAmbientTexture && pcMesh->piAmbientTexture != piTexture)
+			{
+				pcMesh->piAmbientTexture->Release();
+				pcMesh->piAmbientTexture = piTexture;
+
+				if (!pcMesh->bSharedFX)
+				{
+					pcMesh->piEffect->SetTexture("AMBIENT_TEXTURE",piTexture);
+				}
+			}
+			break;
+		case AI_TEXTYPE_SPECULAR:
+			if (pcMesh->piSpecularTexture && pcMesh->piSpecularTexture != piTexture)
+			{
+				pcMesh->piSpecularTexture->Release();
+				pcMesh->piSpecularTexture = piTexture;
+
+				if (!pcMesh->bSharedFX)
+				{
+					pcMesh->piEffect->SetTexture("SPECULAR_TEXTURE",piTexture);
+				}
+			}
+			break;
+		case AI_TEXTYPE_EMISSIVE:
+			if (pcMesh->piEmissiveTexture && pcMesh->piEmissiveTexture != piTexture)
+			{
+				pcMesh->piEmissiveTexture->Release();
+				pcMesh->piEmissiveTexture = piTexture;
+
+				if (!pcMesh->bSharedFX)
+				{
+					pcMesh->piEffect->SetTexture("EMISSIVE_TEXTURE",piTexture);
+				}
+			}
+			break;
+		case AI_TEXTYPE_SHININESS:
+			if (pcMesh->piShininessTexture && pcMesh->piShininessTexture != piTexture)
+			{
+				pcMesh->piShininessTexture->Release();
+				pcMesh->piShininessTexture = piTexture;
+
+				if (!pcMesh->bSharedFX)
+				{
+					pcMesh->piEffect->SetTexture("SHININESS_TEXTURE",piTexture);
+				}
+			}
+			break;
+		case AI_TEXTYPE_NORMALS:
+		case AI_TEXTYPE_HEIGHT:
+			if (pcMesh->piNormalTexture && pcMesh->piNormalTexture != piTexture)
+			{
+				pcMesh->piNormalTexture->Release();
+				pcMesh->piNormalTexture = piTexture;
+
+				if (!pcMesh->bSharedFX)
+				{
+					pcMesh->piEffect->SetTexture("NORMAL_TEXTURE",piTexture);
+				}
+			}
+			break;
+		default: //case AI_TEXTYPE_OPACITY && case AI_TEXTYPE_OPACITY | 0x40000000:
+			if (pcMesh->piOpacityTexture && pcMesh->piOpacityTexture != piTexture)
+			{
+				pcMesh->piOpacityTexture->Release();
+				pcMesh->piOpacityTexture = piTexture;
+
+				if (!pcMesh->bSharedFX)
+				{
+					pcMesh->piEffect->SetTexture("OPACITY_TEXTURE",piTexture);
+				}
+			}
+			break;
+		};
+	}
+
+	// now update the material itself
+	aiString szOld;
+	const char* szKey = NULL;
+	switch (this->m_pcCurrentTexture->iType)
+	{
+	case AI_TEXTYPE_DIFFUSE:
+		szKey = AI_MATKEY_TEXTURE_DIFFUSE(0);
+		break;
+	case AI_TEXTYPE_AMBIENT:
+		szKey = AI_MATKEY_TEXTURE_AMBIENT(0);
+		break;
+	case AI_TEXTYPE_SPECULAR:
+		szKey = AI_MATKEY_TEXTURE_SPECULAR(0);
+		break;
+	case AI_TEXTYPE_EMISSIVE:
+		szKey = AI_MATKEY_TEXTURE_EMISSIVE(0);
+		break;
+	case AI_TEXTYPE_NORMALS:
+		szKey = AI_MATKEY_TEXTURE_NORMALS(0);
+		break;
+	case AI_TEXTYPE_HEIGHT:
+		szKey = AI_MATKEY_TEXTURE_HEIGHT(0);
+		break;
+	case AI_TEXTYPE_SHININESS:
+		szKey = AI_MATKEY_TEXTURE_SHININESS(0);
+		break;
+	default: //case AI_TEXTYPE_OPACITY && case AI_TEXTYPE_OPACITY | 0x40000000:
+		szKey = AI_MATKEY_TEXTURE_OPACITY(0);
+		break;
+	};
+	ai_assert(NULL != szKey);
+
+	aiGetMaterialString(pcMat,szKey,&szOld);
+	pcMat->AddProperty(&szString,szKey);
+
+	char szBuffer[512];
+	sprintf(szBuffer,"%s%s",szKey,"_old");
+
+	if (AI_SUCCESS != aiGetMaterialString(pcMat, szBuffer, &szOld))
+	{
+		pcMat->AddProperty(&szOld,szBuffer );
+	}
+	else if (szString.length == szOld.length && 
+		0 == Assimp::ASSIMP_stricmp(szString.data,szOld.data))
+	{
+		pcMat->RemoveProperty(szBuffer);
+	}
+	return 1;
+}
+//-------------------------------------------------------------------------------
+int CDisplay::AddTextureToDisplayList(unsigned int iType,
+	unsigned int iIndex,
+	const aiString* szPath,
+	HTREEITEM hFX, 
+	unsigned int iUVIndex		/*= 0*/,
+	const float fBlendFactor	/*= 0.0f*/,
+	aiTextureOp eTextureOp		/*= aiTextureOp_Multiply*/,
+	unsigned int iMesh		/*= 0*/)
+{
+	ai_assert(NULL != szPath);
+	ai_assert(NULL != pcMat);
+
+	char chTemp[512];
+	char chTempEmb[256];
+	const char* sz = strrchr(szPath->data,'\\');
+	if (!sz)sz = strrchr(szPath->data,'/');
+	if (!sz)
+	{
+		if ('*' == *szPath->data)
+		{
+			int iIndex = atoi(szPath->data+1);
+			sprintf(chTempEmb,"Embedded #%i",iIndex);
+			sz = chTempEmb;
+		}
+		else
+		{
+			sz = szPath->data;
+		}
+	}
+
+	bool bIsExtraOpacity = 0 != (iType & 0x40000000);
+	const char* szType;
+	IDirect3DTexture9* piTexture;
+	switch (iType)
+	{
+	case AI_TEXTYPE_DIFFUSE:
+		piTexture = g_pcAsset->apcMeshes[iMesh]->piDiffuseTexture;
+		szType = "Diffuse";break;
+	case AI_TEXTYPE_SPECULAR:
+		piTexture = g_pcAsset->apcMeshes[iMesh]->piSpecularTexture;
+		szType = "Specular";break;
+	case AI_TEXTYPE_AMBIENT:
+		piTexture = g_pcAsset->apcMeshes[iMesh]->piAmbientTexture;
+		szType = "Ambient";break;
+	case AI_TEXTYPE_EMISSIVE:
+		piTexture = g_pcAsset->apcMeshes[iMesh]->piEmissiveTexture;
+		szType = "Emissive";break;
+	case AI_TEXTYPE_HEIGHT:
+		piTexture = g_pcAsset->apcMeshes[iMesh]->piNormalTexture;
+		szType = "HeightMap";break;
+	case AI_TEXTYPE_NORMALS:
+		piTexture = g_pcAsset->apcMeshes[iMesh]->piNormalTexture;
+		szType = "NormalMap";break;
+	case AI_TEXTYPE_SHININESS:
+		piTexture = g_pcAsset->apcMeshes[iMesh]->piShininessTexture;
+		szType = "Shininess";break;
+	default: // opacity + opacity | mask
+		piTexture = g_pcAsset->apcMeshes[iMesh]->piOpacityTexture;
+		szType = "Opacity";break;
+	};
+	if (bIsExtraOpacity)
+	{
+		sprintf(chTemp,"%s %i (<copy of diffuse #1>)",szType,iIndex+1);
+	}
+	else sprintf(chTemp,"%s %i (%s)",szType,iIndex+1,sz);
+
+	TVITEMEX tvi; 
+	TVINSERTSTRUCT sNew;
+	tvi.pszText = chTemp;
+	tvi.cchTextMax = (int)strlen(chTemp);
+	tvi.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_HANDLE | TVIF_HANDLE;
+	tvi.lParam = (LPARAM)20;
+
+	// find out whether this is the default texture or not
+
+	if (piTexture)
+	{
+		// {9785DA94-1D96-426b-B3CB-BADC36347F5E}
+		static const GUID guidPrivateData = 
+			{ 0x9785da94, 0x1d96, 0x426b, 
+			{ 0xb3, 0xcb, 0xba, 0xdc, 0x36, 0x34, 0x7f, 0x5e } };
+
+		uint32_t iData = 0;
+		DWORD dwSize = 4;
+		piTexture->GetPrivateData(guidPrivateData,&iData,&dwSize);
+
+		if (0xFFFFFFFF == iData)
+		{
+			tvi.iImage = this->m_aiImageList[AI_VIEW_IMGLIST_TEXTURE_INVALID];
+			tvi.iSelectedImage = this->m_aiImageList[AI_VIEW_IMGLIST_TEXTURE_INVALID];
+		}
+		else
+		{
+			tvi.iImage = this->m_aiImageList[AI_VIEW_IMGLIST_TEXTURE];
+			tvi.iSelectedImage = this->m_aiImageList[AI_VIEW_IMGLIST_TEXTURE];
+		}
+	}
+	else
+	{
+		tvi.iImage = this->m_aiImageList[AI_VIEW_IMGLIST_TEXTURE_INVALID];
+		tvi.iSelectedImage = this->m_aiImageList[AI_VIEW_IMGLIST_TEXTURE_INVALID];
+	}
+
+	sNew.itemex = tvi; 
+	sNew.hInsertAfter = TVI_LAST; 
+	sNew.hParent = hFX;
+
+	// add the item to the list
+	HTREEITEM hTexture = (HTREEITEM)SendMessage(GetDlgItem(g_hDlg,IDC_TREE1), 
+		TVM_INSERTITEM, 
+		0,
+		(LPARAM)(LPTVINSERTSTRUCT)&sNew);
+
+	// add it to the list
+	CDisplay::TextureInfo sInfo;
+	sInfo.iUV = iUVIndex;
+	sInfo.fBlend = fBlendFactor;
+	sInfo.eOp = eTextureOp;
+	sInfo.szPath = szPath->data;
+	sInfo.hTreeItem = hTexture;
+	sInfo.piTexture = piTexture;
+	sInfo.iType = iType;
+	sInfo.iMatIndex = g_pcAsset->pcScene->mMeshes[iMesh]->mMaterialIndex;
+	this->AddTexture(sInfo);
+	return 1;
+}
+//-------------------------------------------------------------------------------
+int CDisplay::AddMaterialToDisplayList(HTREEITEM hRoot, 
+	unsigned int iIndex)
+{
+	ai_assert(NULL != hRoot);
+
+	aiMaterial* pcMat = g_pcAsset->pcScene->mMaterials[iIndex];
+
+	
+	// find the first mesh using this material index
+	unsigned int iMesh = 0;
+	for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
+	{
+		if (iIndex == g_pcAsset->pcScene->mMeshes[i]->mMaterialIndex)
+		{
+			iMesh = i;
+			break;
+		}
+	}
+
+	// use the name of the material, if possible
+	char chTemp[512];
+	aiString szOut;
+	if (AI_SUCCESS != aiGetMaterialString(pcMat,AI_MATKEY_NAME,&szOut))
+	{
+		sprintf(chTemp,"Material %i",iIndex+1);
+	}
+	else
+	{
+		sprintf(chTemp,"%s (%i)",szOut.data,iIndex+1);
+	}
+	TVITEMEX tvi; 
+	TVINSERTSTRUCT sNew;
+	tvi.pszText = chTemp;
+	tvi.cchTextMax = (int)strlen(chTemp);
+	tvi.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_HANDLE | TVIF_PARAM ;
+	tvi.iImage = this->m_aiImageList[AI_VIEW_IMGLIST_MATERIAL];
+	tvi.iSelectedImage = this->m_aiImageList[AI_VIEW_IMGLIST_MATERIAL];
+	tvi.lParam = (LPARAM)10; 
+	//tvi.state = TVIS_EXPANDED | TVIS_EXPANDEDONCE ;
+
+	sNew.itemex = tvi; 
+	sNew.hInsertAfter = TVI_LAST; 
+	sNew.hParent = hRoot;
+
+	// add the item to the list
+	HTREEITEM hTexture = (HTREEITEM)SendMessage(GetDlgItem(g_hDlg,IDC_TREE1), 
+		TVM_INSERTITEM, 
+		0,
+		(LPARAM)(LPTVINSERTSTRUCT)&sNew);
+
+	// for each texture in the list ... add it
+	// NOTE: This expects that AI_TEXTYPE_DIFFUSE is 7
+	ai_assert(7 == AI_TEXTYPE_DIFFUSE);
+	unsigned int iUV;
+	float fBlend;
+	aiTextureOp eOp;
+	aiString szPath;
+	bool bNoOpacity = true;
+	for (unsigned int i = 0; i < 8;++i)
+	{
+		unsigned int iNum = 0;
+		while (true)
+		{
+			if (AI_SUCCESS != aiGetMaterialTexture(pcMat,iNum,i,
+				&szPath,&iUV,&fBlend,&eOp))
+			{
+				break;
+			}
+			if (AI_TEXTYPE_OPACITY == i)bNoOpacity = false;
+			AddTextureToDisplayList(i,iNum,&szPath,hTexture,iUV,fBlend,eOp,iMesh);
+			++iNum;
+		}
+	}
+
+	AssetHelper::MeshHelper* pcMesh = g_pcAsset->apcMeshes[iIndex];
+	if (pcMesh->piDiffuseTexture && pcMesh->piDiffuseTexture == pcMesh->piOpacityTexture && bNoOpacity)
+	{
+		// seems the diffuse texture contains alpha, therefore it has been
+		// added to the opacity channel, too. Add a special value ...
+		AddTextureToDisplayList(AI_TEXTYPE_OPACITY | 0x40000000,
+			0,&szPath,hTexture,iUV,fBlend,eOp,iMesh);
+	}
+
+	// add the material to the list
+	MaterialInfo info;
+	info.hTreeItem = hTexture;
+	info.psMaterial = pcMat;
+	info.iIndex = iIndex;
+	info.piEffect = g_pcAsset->apcMeshes[iMesh]->piEffect;
+	this->AddMaterial(info);
+	return 1;
+}
+//-------------------------------------------------------------------------------
+int CDisplay::ExpandTree()
+{
+	// expand all materials
+	for (std::vector< MaterialInfo >::iterator
+		i =  this->m_asMaterials.begin();
+		i != this->m_asMaterials.end();++i)
+	{
+		TreeView_Expand(GetDlgItem(g_hDlg,IDC_TREE1),(*i).hTreeItem,TVE_EXPAND);
+	}
+	// expand all nodes
+	for (std::vector< NodeInfo >::iterator
+		i =  this->m_asNodes.begin();
+		i != this->m_asNodes.end();++i)
+	{
+		TreeView_Expand(GetDlgItem(g_hDlg,IDC_TREE1),(*i).hTreeItem,TVE_EXPAND);
+	}
+	TreeView_Expand(GetDlgItem(g_hDlg,IDC_TREE1),this->m_hRoot,TVE_EXPAND);
+	return 1;
+}
+//-------------------------------------------------------------------------------
+int CDisplay::LoadImageList(void)
+{
+	if (!this->m_hImageList)
+	{
+		// First, create the image list we will need.
+		// FIX: Need RGB888 color space to display all colors correctly
+		HIMAGELIST hIml = ImageList_Create( 16,16,ILC_COLOR24, 5, 0 );
+
+		// Load the bitmaps and add them to the image lists.
+		HBITMAP hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BFX));
+		this->m_aiImageList[AI_VIEW_IMGLIST_MATERIAL] = ImageList_Add(hIml, hBmp, NULL);
+		DeleteObject(hBmp);
+
+		hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BNODE));
+		this->m_aiImageList[AI_VIEW_IMGLIST_NODE] = ImageList_Add(hIml, hBmp, NULL);
+		DeleteObject(hBmp);
+
+		hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BTX));
+		this->m_aiImageList[AI_VIEW_IMGLIST_TEXTURE] = ImageList_Add(hIml, hBmp, NULL);
+		DeleteObject(hBmp);
+
+		hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BTXI));
+		this->m_aiImageList[AI_VIEW_IMGLIST_TEXTURE_INVALID] = ImageList_Add(hIml, hBmp, NULL);
+		DeleteObject(hBmp);
+
+		hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BROOT));
+		this->m_aiImageList[AI_VIEW_IMGLIST_MODEL] = ImageList_Add(hIml, hBmp, NULL);
+		DeleteObject(hBmp);
+
+		// Associate the image list with the tree.
+		TreeView_SetImageList(GetDlgItem(g_hDlg,IDC_TREE1), hIml, TVSIL_NORMAL);
+
+		this->m_hImageList = hIml;
+	}
+	return 1;
+}
+//-------------------------------------------------------------------------------
+int CDisplay::FillDisplayList(void)
+{
+	this->LoadImageList();
+
+	// Initialize the tree view window.
+	// fill in the first entry
+	TVITEMEX tvi; 
+	TVINSERTSTRUCT sNew;
+	tvi.pszText = "Model";
+	tvi.cchTextMax = (int)strlen(tvi.pszText);
+	tvi.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_HANDLE | TVIF_STATE;
+	tvi.state = TVIS_EXPANDED;
+	tvi.iImage = this->m_aiImageList[AI_VIEW_IMGLIST_MODEL];
+	tvi.iSelectedImage = this->m_aiImageList[AI_VIEW_IMGLIST_MODEL];
+	tvi.lParam = (LPARAM)0; 
+
+	sNew.itemex = tvi; 
+	sNew.hInsertAfter = TVI_ROOT; 
+	sNew.hParent = 0;
+
+	// add the root item to the tree
+	this->m_hRoot = (HTREEITEM)SendMessage(GetDlgItem(g_hDlg,IDC_TREE1), 
+		TVM_INSERTITEM, 
+		0,
+		(LPARAM)(LPTVINSERTSTRUCT)&sNew);
+
+	// add each loaded material to the tree
+	for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMaterials;++i)
+	{
+		AddMaterialToDisplayList(this->m_hRoot,i);
+	}
+
+	// now add all loaded nodes recursively
+	AddNodeToDisplayList(0,0,g_pcAsset->pcScene->mRootNode,this->m_hRoot);
+
+	// now expand all parent nodes in the tree
+	this->ExpandTree();
+
+	// everything reacts a little bit slowly if D3D is rendering,
+	// so give GDI a small hint to leave the couch and work ;-)
+	UpdateWindow(g_hDlg);
+	return 1;
+}
+//-------------------------------------------------------------------------------
+int CDisplay::OnRender()
+{
+	// begin the frame
+	g_piDevice->BeginScene();
+
+	switch (this->m_iViewMode)
+	{
+	case VIEWMODE_FULL:
+	case VIEWMODE_NODE:
+		this->RenderFullScene();
+		break;
+	case VIEWMODE_MATERIAL:
+		this->RenderMaterialView();
+		break;
+	case VIEWMODE_TEXTURE:
+		this->RenderTextureView();
+		break;
+	};
+
+	// Now render the log display in the upper right corner of the window
+	CLogDisplay::Instance().OnRender();
+
+	// present the backbuffer
+	g_piDevice->EndScene();
+	g_piDevice->Present(NULL,NULL,NULL,NULL);
+
+	// don't remove this, problems on some older machines (AMD timing bug)
+	Sleep(10);
+	return 1;
+}	
+//-------------------------------------------------------------------------------
+int CDisplay::FillDefaultStatistics(void)
+{
+	// get the number of vertices/faces in the model
+	unsigned int iNumVert = 0;
+	unsigned int iNumFaces = 0;
+	for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
+	{
+		iNumVert += g_pcAsset->pcScene->mMeshes[i]->mNumVertices;
+		iNumFaces += g_pcAsset->pcScene->mMeshes[i]->mNumFaces;
+	}
+	// and fill the statistic edit controls
+	char szOut[1024];
+	sprintf(szOut,"%i",(int)iNumVert);
+	SetDlgItemText(g_hDlg,IDC_EVERT,szOut);
+	sprintf(szOut,"%i",(int)iNumFaces);
+	SetDlgItemText(g_hDlg,IDC_EFACE,szOut);
+	sprintf(szOut,"%i",(int)g_pcAsset->pcScene->mNumMaterials);
+	SetDlgItemText(g_hDlg,IDC_EMAT,szOut);
+	sprintf(szOut,"%i",(int)g_pcAsset->pcScene->mNumMeshes);
+	SetDlgItemText(g_hDlg,IDC_EMESH,szOut);
+
+	// need to get the number of nodes
+	iNumVert = 0;
+	GetNodeCount(g_pcAsset->pcScene->mRootNode,&iNumVert);
+	sprintf(szOut,"%i",(int)iNumVert);
+	SetDlgItemText(g_hDlg,IDC_ENODEWND,szOut);
+
+	// now get the number of unique shaders generated for the asset
+	// (even if the environment changes this number won't change)
+	sprintf(szOut,"%i", CMaterialManager::Instance().GetShaderCount());
+	SetDlgItemText(g_hDlg,IDC_ESHADER,szOut);
+
+	sprintf(szOut,"%.5f",(float)g_fLoadTime);
+	SetDlgItemText(g_hDlg,IDC_ELOAD,szOut);
+
+	UpdateWindow(g_hDlg);
+	return 1;
+}
+//-------------------------------------------------------------------------------
+int CDisplay::Reset(void)
+{
+	// clear all lists
+	this->m_asMaterials.clear();
+	this->m_asTextures.clear();
+	this->m_asNodes.clear();
+
+	this->m_hRoot = NULL;
+
+	return this->OnSetupNormalView();
+}
+//-------------------------------------------------------------------------------
+int CDisplay::OnSetupNormalView()
+{
+	// now ... change the meaning of the statistics fields back
+	SetWindowText(GetDlgItem(g_hDlg,IDC_NUMVERTS),"Verts:");
+	SetWindowText(GetDlgItem(g_hDlg,IDC_NUMNODES),"Nodes:");
+	SetWindowText(GetDlgItem(g_hDlg,IDC_NUMFACES),"Faces:");
+	SetWindowText(GetDlgItem(g_hDlg,IDC_NUMSHADERS),"Shd:");
+	SetWindowText(GetDlgItem(g_hDlg,IDC_NUMMATS),"Mats:");
+	SetWindowText(GetDlgItem(g_hDlg,IDC_NUMMESHES),"Mesh:");
+	SetWindowText(GetDlgItem(g_hDlg,IDC_LOADTIME),"Time:");
+
+	this->FillDefaultStatistics();
+	this->SetViewMode(VIEWMODE_FULL);
+
+	// for debugging
+	this->m_pcCurrentMaterial = NULL;
+	this->m_pcCurrentTexture = NULL;
+	this->m_pcCurrentNode = NULL;
+
+	UpdateWindow(g_hDlg);
+	return 1;
+}
+//-------------------------------------------------------------------------------
+int CDisplay::OnSetupNodeView(NodeInfo* pcNew)
+{
+	ai_assert(NULL != pcNew);
+
+	if (this->m_pcCurrentNode == pcNew)return 2;
+
+	this->m_pcCurrentNode = pcNew;
+	this->SetViewMode(VIEWMODE_NODE);
+
+	return 1;
+}
+//-------------------------------------------------------------------------------
+int CDisplay::OnSetupMaterialView(MaterialInfo* pcNew)
+{
+	ai_assert(NULL != pcNew);
+
+	if (this->m_pcCurrentMaterial == pcNew)return 2;
+
+	this->m_pcCurrentMaterial = pcNew;
+	this->SetViewMode(VIEWMODE_MATERIAL);
+
+	return 1;
+}
+//-------------------------------------------------------------------------------
+int CDisplay::OnSetupTextureView(TextureInfo* pcNew)
+{
+	ai_assert(NULL != pcNew);
+
+	if (this->m_pcCurrentTexture == pcNew)return 2;
+	if ((AI_TEXTYPE_OPACITY | 0x40000000) == pcNew->iType)
+	{
+		// for opacity textures display a warn message
+		CLogDisplay::Instance().AddEntry("[INFO] This texture is not existing in the "
+			"original mesh",D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0));
+		CLogDisplay::Instance().AddEntry("It is a copy of the alpha channel of the first "
+			"diffuse texture",D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0));
+	}
+
+	this->m_fTextureZoom = 1000.0f;
+	this->m_vTextureOffset.x = this->m_vTextureOffset.y = 0.0f;
+
+	this->m_pcCurrentTexture = pcNew;
+	this->SetViewMode(VIEWMODE_TEXTURE);
+
+	// now ... change the meaning of the statistics fields
+	SetWindowText(GetDlgItem(g_hDlg,IDC_NUMVERTS),"Width:");
+	SetWindowText(GetDlgItem(g_hDlg,IDC_NUMNODES),"Height:");
+	SetWindowText(GetDlgItem(g_hDlg,IDC_NUMFACES),"Format:");
+	SetWindowText(GetDlgItem(g_hDlg,IDC_NUMSHADERS),"MIPs:");
+	SetWindowText(GetDlgItem(g_hDlg,IDC_NUMMATS),"UV:");
+	SetWindowText(GetDlgItem(g_hDlg,IDC_NUMMESHES),"Blend:");
+	SetWindowText(GetDlgItem(g_hDlg,IDC_LOADTIME),"Op:");
+
+	// and fill them with data
+	D3DSURFACE_DESC sDesc;
+	pcNew->piTexture->GetLevelDesc(0,&sDesc);
+	char szTemp[128];
+
+	sprintf(szTemp,"%i",sDesc.Width);
+	SetWindowText(GetDlgItem(g_hDlg,IDC_EVERT),szTemp);
+
+	sprintf(szTemp,"%i",sDesc.Height);
+	SetWindowText(GetDlgItem(g_hDlg,IDC_ENODEWND),szTemp);
+
+	sprintf(szTemp,"%i",pcNew->piTexture->GetLevelCount());
+	SetWindowText(GetDlgItem(g_hDlg,IDC_ESHADER),szTemp);
+
+	sprintf(szTemp,"%i",pcNew->iUV);
+	SetWindowText(GetDlgItem(g_hDlg,IDC_EMAT),szTemp);
+
+	sprintf(szTemp,"%f",pcNew->fBlend);
+	SetWindowText(GetDlgItem(g_hDlg,IDC_EMESH),szTemp);
+
+	const char* szOp;
+	switch (pcNew->eOp)
+	{
+	case aiTextureOp_Add:
+		szOp = "add";break;
+	case aiTextureOp_Subtract:
+		szOp = "sub";break;
+	case aiTextureOp_Divide:
+		szOp = "div";break;
+	case aiTextureOp_SignedAdd:
+		szOp = "addsign";break;
+	case aiTextureOp_SmoothAdd:
+		szOp = "addsmooth";break;
+	default: szOp = "mul";
+	};
+	SetWindowText(GetDlgItem(g_hDlg,IDC_ELOAD),szOp);
+
+	// NOTE: Format is always ARGB8888 since other formats are
+	// convert to this format ...
+	SetWindowText(GetDlgItem(g_hDlg,IDC_EFACE),"ARGB8");
+
+	// check whether this is the default texture
+	if (pcNew->piTexture)
+	{
+		// {9785DA94-1D96-426b-B3CB-BADC36347F5E}
+		static const GUID guidPrivateData = 
+		{ 0x9785da94, 0x1d96, 0x426b, 
+		{ 0xb3, 0xcb, 0xba, 0xdc, 0x36, 0x34, 0x7f, 0x5e } };
+
+		uint32_t iData = 0;
+		DWORD dwSize = 4;
+		pcNew->piTexture->GetPrivateData(guidPrivateData,&iData,&dwSize);
+
+		if (0xFFFFFFFF == iData)
+		{
+			CLogDisplay::Instance().AddEntry("[ERROR] Texture could not be loaded. "
+				"The displayed texture is a default texture",
+				D3DCOLOR_ARGB(0xFF,0xFF,0,0));
+			return 0;
+		}
+	}
+	UpdateWindow(g_hDlg);
+	return 1;
+}
+//-------------------------------------------------------------------------------
+int CDisplay::OnSetup(HTREEITEM p_hTreeItem)
+{
+	// search in our list for the item
+
+	union	{
+		TextureInfo* pcNew;
+		NodeInfo* pcNew2;
+		MaterialInfo* pcNew3;	};
+
+	pcNew = NULL;
+	for (std::vector<TextureInfo>::iterator
+		i =  this->m_asTextures.begin();
+		i != this->m_asTextures.end();++i)
+	{
+		if (p_hTreeItem == (*i).hTreeItem)
+		{
+			pcNew = &(*i);
+			break;
+		}
+	}
+	if (pcNew)
+	{
+		return this->OnSetupTextureView(pcNew);
+	}
+
+	// seach the node list
+	for (std::vector<NodeInfo>::iterator
+		i =  this->m_asNodes.begin();
+		i != this->m_asNodes.end();++i)
+	{
+		if (p_hTreeItem == (*i).hTreeItem)
+		{
+			pcNew2 = &(*i);
+			break;
+		}
+	}
+	if (pcNew2)
+	{
+		return this->OnSetupNodeView(pcNew2);
+	}
+
+	// seach the material list
+	for (std::vector<MaterialInfo>::iterator
+		i =  this->m_asMaterials.begin();
+		i != this->m_asMaterials.end();++i)
+	{
+		if (p_hTreeItem == (*i).hTreeItem)
+		{
+			pcNew3 = &(*i);
+			break;
+		}
+	}
+	if (pcNew3)
+	{
+		return this->OnSetupMaterialView(pcNew3);
+	}
+	return this->OnSetupNormalView();
+}
+//-------------------------------------------------------------------------------
+int CDisplay::ShowTreeViewContextMenu(HTREEITEM hItem)
+{
+	ai_assert(NULL != hItem);
+
+	HMENU hDisplay = NULL;
+
+	// search in our list for the item
+	TextureInfo* pcNew = NULL;
+	for (std::vector<TextureInfo>::iterator
+		i =  this->m_asTextures.begin();
+		i != this->m_asTextures.end();++i)
+	{
+		if (hItem == (*i).hTreeItem)
+		{
+			pcNew = &(*i);
+			break;
+		}
+	}
+	if (pcNew)
+	{
+		HMENU hMenu = LoadMenu(g_hInstance,MAKEINTRESOURCE(IDR_TXPOPUP));
+		hDisplay = GetSubMenu(hMenu,0);
+
+		//this->OnSetupTextureView(pcNew);
+	}
+
+	// search in the material list for the item
+	MaterialInfo* pcNew2 = NULL;
+	for (std::vector<MaterialInfo>::iterator
+		i =  this->m_asMaterials.begin();
+		i != this->m_asMaterials.end();++i)
+	{
+		if (hItem == (*i).hTreeItem)
+		{
+			pcNew2 = &(*i);
+			break;
+		}
+	}
+	if (pcNew2)
+	{
+		HMENU hMenu = LoadMenu(g_hInstance,MAKEINTRESOURCE(IDR_MATPOPUP));
+		hDisplay = GetSubMenu(hMenu,0);
+
+		//this->OnSetupMaterialView(pcNew2);
+	}
+	if (NULL != hDisplay)
+	{
+		// select this entry (this should all OnSetup())
+		TreeView_Select(GetDlgItem(g_hDlg,IDC_TREE1),hItem,TVGN_CARET);
+
+		// FIX: Render the scene once that the correct texture/material
+		// is displayed while the context menu is active
+		this->OnRender();
+
+		POINT sPoint;
+		GetCursorPos(&sPoint);
+		TrackPopupMenu(hDisplay, TPM_LEFTALIGN, sPoint.x, sPoint.y, 0,
+			g_hDlg,NULL);
+	}
+	return 1;
+}
+//-------------------------------------------------------------------------------
+template <class type, class intype>
+type clamp(intype in)
+{
+	// for unsigned types only ...
+	intype mask = (0x1u << (sizeof(type)*8))-1;
+	return (type)std::max((intype)0,std::min(in,mask));
+}
+//-------------------------------------------------------------------------------
+int CDisplay::HandleTreeViewPopup(WPARAM wParam,LPARAM lParam)
+{
+	// helper class
+	struct Info
+	{
+		Info(	D3DXVECTOR4* p1,
+				AssetHelper::MeshHelper* p2,
+				const char* p3)
+				: pclrColor(p1),pMesh(p2),szShaderParam(p3) {}
+
+		D3DXVECTOR4* pclrColor;
+		AssetHelper::MeshHelper* pMesh;
+		const char* szShaderParam;
+	};
+
+	// get the current selected material
+	std::vector<Info> apclrOut;
+	const char* szMatKey;
+
+	switch (LOWORD(wParam))
+	{
+	case ID_SOLONG_CLEARDIFFUSECOLOR:
+		for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
+		{
+			if (this->m_pcCurrentMaterial->iIndex == g_pcAsset->pcScene->mMeshes[i]->mMaterialIndex)
+			{
+				apclrOut.push_back( Info( &g_pcAsset->apcMeshes[i]->vDiffuseColor,
+					g_pcAsset->apcMeshes[i],"DIFFUSE_COLOR"));
+			}
+		}
+		szMatKey = AI_MATKEY_COLOR_DIFFUSE;
+		break;
+	case ID_SOLONG_CLEARSPECULARCOLOR:
+		for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
+		{
+			if (this->m_pcCurrentMaterial->iIndex == g_pcAsset->pcScene->mMeshes[i]->mMaterialIndex)
+			{
+				apclrOut.push_back( Info( &g_pcAsset->apcMeshes[i]->vSpecularColor,
+					g_pcAsset->apcMeshes[i],"SPECULAR_COLOR"));
+			}
+		}
+		szMatKey = AI_MATKEY_COLOR_SPECULAR;
+		break;
+	case ID_SOLONG_CLEARAMBIENTCOLOR:
+		for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
+		{
+			if (this->m_pcCurrentMaterial->iIndex == g_pcAsset->pcScene->mMeshes[i]->mMaterialIndex)
+			{
+				apclrOut.push_back( Info( &g_pcAsset->apcMeshes[i]->vAmbientColor,
+					g_pcAsset->apcMeshes[i],"AMBIENT_COLOR"));
+			}
+		}
+		szMatKey = AI_MATKEY_COLOR_AMBIENT;
+		break;
+	case ID_SOLONG_CLEAREMISSIVECOLOR:
+		for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
+		{
+			if (this->m_pcCurrentMaterial->iIndex == g_pcAsset->pcScene->mMeshes[i]->mMaterialIndex)
+			{
+				apclrOut.push_back( Info( &g_pcAsset->apcMeshes[i]->vEmissiveColor,
+					g_pcAsset->apcMeshes[i],"EMISSIVE_COLOR"));
+			}
+		}
+		szMatKey = AI_MATKEY_COLOR_EMISSIVE;
+		break;
+	default:
+
+		// let the next function do this ... no spaghetti code ;-)
+		this->HandleTreeViewPopup2(wParam,lParam);
+	};
+	if (!apclrOut.empty())
+	{
+		aiColor4D clrOld = *((aiColor4D*)(apclrOut.front().pclrColor));
+
+		CHOOSECOLOR clr;
+		clr.lStructSize = sizeof(CHOOSECOLOR);
+		clr.hwndOwner = g_hDlg;
+		clr.Flags = CC_RGBINIT | CC_FULLOPEN;
+		clr.rgbResult = RGB(
+			clamp<unsigned char>(clrOld.r * 255.0f),
+			clamp<unsigned char>(clrOld.g * 255.0f),
+			clamp<unsigned char>(clrOld.b * 255.0f));
+		clr.lpCustColors = g_aclCustomColors;
+		clr.lpfnHook = NULL;
+		clr.lpTemplateName = NULL;
+		clr.lCustData = NULL;
+
+		ChooseColor(&clr);
+
+		clrOld.r = (float)(((unsigned int)clr.rgbResult)       & 0xFF) / 255.0f;
+		clrOld.g = (float)(((unsigned int)clr.rgbResult >> 8)  & 0xFF) / 255.0f;
+		clrOld.b = (float)(((unsigned int)clr.rgbResult >> 16) & 0xFF) / 255.0f;
+
+		// update the color values in the mesh instances and
+		// update all shaders ...
+		for (std::vector<Info>::iterator
+			i =  apclrOut.begin();
+			i != apclrOut.end();++i)
+		{
+			*((*i).pclrColor) = *((D3DXVECTOR4*)&clrOld);
+			if (!(*i).pMesh->bSharedFX)
+			{
+				(*i).pMesh->piEffect->SetVector((*i).szShaderParam,(*i).pclrColor);
+			}
+		}
+
+		// change the material key ...
+		Assimp::MaterialHelper* pcMat = (Assimp::MaterialHelper*)g_pcAsset->pcScene->mMaterials[
+			this->m_pcCurrentMaterial->iIndex];
+		pcMat->AddProperty<aiColor4D>(&clrOld,1,szMatKey);
+
+		if (ID_SOLONG_CLEARSPECULARCOLOR == LOWORD(wParam) &&
+			aiShadingMode_Gouraud == apclrOut.front().pMesh->eShadingMode)
+		{
+			CLogDisplay::Instance().AddEntry("[INFO] You have just changed the specular "
+				"material color",D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0));
+			CLogDisplay::Instance().AddEntry(
+				"This is great, especially since there is currently no specular shading",
+				D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0));
+		}
+	}
+	return 1;
+}
+//-------------------------------------------------------------------------------
+int CALLBACK TreeViewCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
+{
+	if (lParamSort == lParam1)return -1;
+	if (lParamSort == lParam2)return 1;
+	return 0;
+}
+//-------------------------------------------------------------------------------
+int CDisplay::HandleTreeViewPopup2(WPARAM wParam,LPARAM lParam)
+{
+	char szFileName[MAX_PATH];
+	DWORD dwTemp = MAX_PATH;
+
+	switch (LOWORD(wParam))
+	{
+	case ID_HEY_REPLACE:
+		{
+		// get a path to a new texture
+		if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"ReplaceTextureSrc",NULL,NULL,
+			(BYTE*)szFileName,&dwTemp))
+		{
+			// Key was not found. Use C:
+			strcpy(szFileName,"");
+		}
+		else
+		{
+			// need to remove the file name
+			char* sz = strrchr(szFileName,'\\');
+			if (!sz)sz = strrchr(szFileName,'/');
+			if (!sz)*sz = 0;
+		}
+		OPENFILENAME sFilename1 = {
+			sizeof(OPENFILENAME),
+			g_hDlg,GetModuleHandle(NULL), 
+			"Textures\0*.png;*.dds;*.tga;*.bmp;*.tif;*.ppm;*.ppx;*.jpg;*.jpeg;*.exr\0*.*\0", 
+			NULL, 0, 1, 
+			szFileName, MAX_PATH, NULL, 0, NULL, 
+			"Replace this texture",
+			OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR, 
+			0, 1, ".jpg", 0, NULL, NULL
+		};
+		if(GetOpenFileName(&sFilename1) == 0) return 0;
+
+		// Now store the file in the registry
+		RegSetValueExA(g_hRegistry,"ReplaceTextureSrc",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH);
+		this->ReplaceCurrentTexture(szFileName);
+		}
+		return 1;
+
+	case ID_HEY_EXPORT:
+		{
+		if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"TextureExportDest",NULL,NULL,
+			(BYTE*)szFileName,&dwTemp))
+		{
+			// Key was not found. Use C:
+			strcpy(szFileName,"");
+		}
+		else
+		{
+			// need to remove the file name
+			char* sz = strrchr(szFileName,'\\');
+			if (!sz)sz = strrchr(szFileName,'/');
+			if (!sz)*sz = 0;
+		}
+		OPENFILENAME sFilename1 = {
+			sizeof(OPENFILENAME),
+			g_hDlg,GetModuleHandle(NULL), 
+			"Textures\0*.png;*.dds;*.bmp;*.tif;*.pfm;*.jpg;*.jpeg;*.hdr\0*.*\0", NULL, 0, 1, 
+			szFileName, MAX_PATH, NULL, 0, NULL, 
+			"Export texture to file",
+			OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR, 
+			0, 1, ".png", 0, NULL, NULL
+		};
+		if(GetSaveFileName(&sFilename1) == 0) return 0;
+
+		// Now store the file in the registry
+		RegSetValueExA(g_hRegistry,"TextureExportDest",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH);
+
+		// determine the file format ...
+		D3DXIMAGE_FILEFORMAT eFormat = D3DXIFF_PNG;
+		const char* sz = strrchr(szFileName,'.');
+		if (sz)
+		{
+			++sz;
+			if (0 == Assimp::ASSIMP_stricmp(sz,"pfm"))eFormat = D3DXIFF_PFM;
+			else if (0 == Assimp::ASSIMP_stricmp(sz,"dds"))eFormat = D3DXIFF_DDS;
+			else if (0 == Assimp::ASSIMP_stricmp(sz,"jpg"))eFormat = D3DXIFF_JPG;
+			else if (0 == Assimp::ASSIMP_stricmp(sz,"jpeg"))eFormat = D3DXIFF_JPG;
+			else if (0 == Assimp::ASSIMP_stricmp(sz,"hdr"))eFormat = D3DXIFF_HDR;
+			else if (0 == Assimp::ASSIMP_stricmp(sz,"bmp"))eFormat = D3DXIFF_BMP;
+		}
+
+		// get a pointer to the first surface of the current texture
+		IDirect3DSurface9* pi = NULL;
+		this->m_pcCurrentTexture->piTexture->GetSurfaceLevel(0,&pi);
+		if(!pi || FAILED(D3DXSaveSurfaceToFile(szFileName,eFormat,pi,NULL,NULL)))
+		{
+			CLogDisplay::Instance().AddEntry("[ERROR] Unable to export texture",
+				D3DCOLOR_ARGB(0xFF,0xFF,0,0));
+		}
+		else
+		{
+			CLogDisplay::Instance().AddEntry("[INFO] The texture has been exported",
+				D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0));
+		}
+		if(pi)pi->Release();
+		}
+		return 1;
+
+	case ID_HEY_REMOVE:
+		{
+
+		if(IDYES != MessageBox(g_hDlg,"To recover the texture you need to reload the model. Do you wish to continue?",
+			"Remove texture",MB_YESNO))
+		{
+			return 1;
+		}
+
+		Assimp::MaterialHelper* pcMat = (Assimp::MaterialHelper*)g_pcAsset->pcScene->mMaterials[
+			this->m_pcCurrentTexture->iMatIndex];
+
+		switch (this->m_pcCurrentTexture->iType)
+		{
+		case AI_TEXTYPE_DIFFUSE:
+			pcMat->RemoveProperty(AI_MATKEY_TEXTURE_DIFFUSE(0));
+			break;
+		case AI_TEXTYPE_SPECULAR:
+			pcMat->RemoveProperty(AI_MATKEY_TEXTURE_SPECULAR(0));
+			break;
+		case AI_TEXTYPE_AMBIENT:
+			pcMat->RemoveProperty(AI_MATKEY_TEXTURE_AMBIENT(0));
+			break;
+		case AI_TEXTYPE_EMISSIVE:
+			pcMat->RemoveProperty(AI_MATKEY_TEXTURE_EMISSIVE(0));
+			break;
+		case AI_TEXTYPE_NORMALS:
+			pcMat->RemoveProperty(AI_MATKEY_TEXTURE_NORMALS(0));
+			break;
+		case AI_TEXTYPE_HEIGHT:
+			pcMat->RemoveProperty(AI_MATKEY_TEXTURE_HEIGHT(0));
+			break;
+		case AI_TEXTYPE_SHININESS:
+			pcMat->RemoveProperty(AI_MATKEY_TEXTURE_SHININESS(0));
+			break;
+		case (AI_TEXTYPE_OPACITY | 0x40000000):
+		
+			// set a special property to indicate that no alpha channel is required
+			{int iVal = 1;
+			pcMat->AddProperty<int>(&iVal,1,"no_a_from_d");}
+
+			break;
+		default: //case AI_TEXTYPE_OPACITY
+			pcMat->RemoveProperty(AI_MATKEY_TEXTURE_OPACITY(0));
+		};
+
+		// need to update all meshes associated with this material
+		for (unsigned int i = 0;i < g_pcAsset->pcScene->mNumMeshes;++i)
+		{
+			if (this->m_pcCurrentTexture->iMatIndex == g_pcAsset->pcScene->mMeshes[i]->mMaterialIndex)
+			{
+				CMaterialManager::Instance().DeleteMaterial(g_pcAsset->apcMeshes[i]);
+				CMaterialManager::Instance().CreateMaterial(g_pcAsset->apcMeshes[i],g_pcAsset->pcScene->mMeshes[i]);
+			}
+		}
+		// find the corresponding MaterialInfo structure
+		const unsigned int iMatIndex = this->m_pcCurrentTexture->iMatIndex;
+		for (std::vector<MaterialInfo>::iterator
+			a =  this->m_asMaterials.begin();
+			a != this->m_asMaterials.end();++a)
+		{
+			if (iMatIndex == (*a).iIndex)
+			{
+				// good news. we will also need to find all other textures
+				// associated with this item ...
+				for (std::vector<TextureInfo>::iterator
+					n =  this->m_asTextures.begin();
+					n != this->m_asTextures.end();++n)
+				{
+					if ((*n).iMatIndex == iMatIndex)
+					{
+						n =  this->m_asTextures.erase(n);
+						if (this->m_asTextures.end() == n)break;
+					}
+				}
+				// delete this material from all lists ...
+				TreeView_DeleteItem(GetDlgItem(g_hDlg,IDC_TREE1),(*a).hTreeItem);
+				this->m_asMaterials.erase(a);
+				break;
+			}
+		}
+
+		// add the new material to the list and make sure it will be fully expanded
+		AddMaterialToDisplayList(this->m_hRoot,iMatIndex);
+		HTREEITEM hNewItem = this->m_asMaterials.back().hTreeItem;
+		TreeView_Expand(GetDlgItem(g_hDlg,IDC_TREE1),hNewItem,TVE_EXPAND);
+
+		// we need to sort the list, materials come first, then nodes
+		TVSORTCB sSort;
+		sSort.hParent = this->m_hRoot;
+		sSort.lParam = 10;
+		sSort.lpfnCompare = &TreeViewCompareFunc;
+		TreeView_SortChildrenCB(GetDlgItem(g_hDlg,IDC_TREE1),&sSort,0);
+
+		// the texture was selected, but the silly user has just deleted it
+		// ... go back to normal viewing mode
+		TreeView_Select(GetDlgItem(g_hDlg,IDC_TREE1),this->m_hRoot,TVGN_CARET);
+		return 1;
+		}
+
+	case ID_HEY_RESETTEXTURE:
+		{
+		aiString szOld;
+		aiMaterial* pcMat = g_pcAsset->pcScene->mMaterials[this->m_pcCurrentTexture->iMatIndex];
+		switch (this->m_pcCurrentTexture->iType)
+		{
+		case AI_TEXTYPE_DIFFUSE:
+			aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_DIFFUSE(0) "_old",&szOld);
+			break;
+		case AI_TEXTYPE_SPECULAR:
+			aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_SPECULAR(0) "_old",&szOld);
+			break;
+		case AI_TEXTYPE_AMBIENT:
+			aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_AMBIENT(0) "_old",&szOld);
+			break;
+		case AI_TEXTYPE_EMISSIVE:
+			aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_EMISSIVE(0) "_old",&szOld);
+			break;
+		case AI_TEXTYPE_NORMALS:
+			aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_NORMALS(0) "_old",&szOld);
+			break;
+		case AI_TEXTYPE_HEIGHT:
+			aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_HEIGHT(0) "_old",&szOld);
+			break;
+		case AI_TEXTYPE_SHININESS:
+			aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_SHININESS(0) "_old",&szOld);
+			break;
+		default : //case AI_TEXTYPE_OPACITY && case AI_TEXTYPE_OPACITY | 0x40000000:
+			aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_OPACITY(0) "_old",&szOld);
+			break;
+		};
+		if (0 != szOld.length)this->ReplaceCurrentTexture(szOld.data);
+		return 1;
+		}
+	}
+	return 0;
+}
+//-------------------------------------------------------------------------------
+int CDisplay::SetupStereoView()
+{
+	if (NULL != g_pcAsset && NULL != g_pcAsset->pcScene->mRootNode)
+	{
+		// enable the RED, GREEN and ALPHA channels
+		g_piDevice->SetRenderState(D3DRS_COLORWRITEENABLE,
+			D3DCOLORWRITEENABLE_RED |
+			D3DCOLORWRITEENABLE_ALPHA |
+			D3DCOLORWRITEENABLE_GREEN);
+
+		// move the camera a little bit to the left
+		g_sCamera.vPos -= g_sCamera.vRight * 0.03f;
+	}
+	return 1;
+}
+//-------------------------------------------------------------------------------
+int CDisplay::RenderStereoView(const aiMatrix4x4& m)
+{
+	// and rerender the scene
+	if (NULL != g_pcAsset && NULL != g_pcAsset->pcScene->mRootNode)
+	{
+		// enable the BLUE, GREEN and ALPHA channels
+		g_piDevice->SetRenderState(D3DRS_COLORWRITEENABLE,
+			D3DCOLORWRITEENABLE_GREEN |
+			D3DCOLORWRITEENABLE_ALPHA |
+			D3DCOLORWRITEENABLE_BLUE);
+
+		// clear the z-buffer
+		g_piDevice->Clear(0,NULL,D3DCLEAR_ZBUFFER,0,1.0f,0);
+
+		// move the camera a little bit to the right
+		g_sCamera.vPos += g_sCamera.vRight * 0.06f;
+
+		RenderNode(g_pcAsset->pcScene->mRootNode,m,false);
+		g_piDevice->SetRenderState(D3DRS_ZWRITEENABLE,FALSE);
+		RenderNode(g_pcAsset->pcScene->mRootNode,m,true);
+		g_piDevice->SetRenderState(D3DRS_ZWRITEENABLE,TRUE);
+
+		// (move back to the original position)
+		g_sCamera.vPos -= g_sCamera.vRight * 0.03f;
+
+		// reenable all channels
+		g_piDevice->SetRenderState(D3DRS_COLORWRITEENABLE,
+			D3DCOLORWRITEENABLE_RED |
+			D3DCOLORWRITEENABLE_GREEN |
+			D3DCOLORWRITEENABLE_ALPHA |
+			D3DCOLORWRITEENABLE_BLUE);
+	}
+	return 1;
+}
+//-------------------------------------------------------------------------------
+int CDisplay::HandleInputTextureView()
+{
+	HandleMouseInputTextureView();
+	HandleKeyboardInputTextureView();
+	return 1;
+}
+//-------------------------------------------------------------------------------
+int CDisplay::HandleInput()
+{
+	if(CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode())
+		HandleMouseInputSkyBox();
+
+	// handle input commands
+	HandleMouseInputLightRotate();
+	HandleMouseInputLightIntensityAndColor();
+	if(g_bFPSView)
+	{
+		HandleMouseInputFPS();
+		HandleKeyboardInputFPS();
+	}
+	else HandleMouseInputLocal();
+
+	// compute auto rotation depending on the time which has passed
+	if (g_sOptions.bRotate)
+	{
+		aiMatrix4x4 mMat;
+		D3DXMatrixRotationYawPitchRoll((D3DXMATRIX*)&mMat,
+			g_vRotateSpeed.x * g_fElpasedTime,
+			g_vRotateSpeed.y * g_fElpasedTime,
+			g_vRotateSpeed.z * g_fElpasedTime);
+		g_mWorldRotate = g_mWorldRotate * mMat;
+	}
+
+	// Handle rotations of light source(s)
+	if (g_sOptions.bLightRotate)
+	{
+		aiMatrix4x4 mMat;
+		D3DXMatrixRotationYawPitchRoll((D3DXMATRIX*)&mMat,
+			g_vRotateSpeed.x * g_fElpasedTime * 0.5f,
+			g_vRotateSpeed.y * g_fElpasedTime * 0.5f,
+			g_vRotateSpeed.z * g_fElpasedTime * 0.5f);
+
+		D3DXVec3TransformNormal((D3DXVECTOR3*)&g_avLightDirs[0],
+			(D3DXVECTOR3*)&g_avLightDirs[0],(D3DXMATRIX*)&mMat);
+
+		// 2 lights to rotate?
+		if (g_sOptions.b3Lights)
+		{
+			D3DXVec3TransformNormal((D3DXVECTOR3*)&g_avLightDirs[1],
+				(D3DXVECTOR3*)&g_avLightDirs[1],(D3DXMATRIX*)&mMat);
+
+			g_avLightDirs[1].Normalize();
+		}
+		g_avLightDirs[0].Normalize();
+	}
+	return 1;
+}
+//-------------------------------------------------------------------------------
+int CDisplay::HandleInputEmptyScene()
+{
+	if(CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode())
+	{
+		if (g_bFPSView)
+		{
+			HandleMouseInputFPS();
+			HandleKeyboardInputFPS();
+		}
+		HandleMouseInputSkyBox();
+
+		// need to store the last mouse position in the global variable
+		// HandleMouseInputFPS() is doing this internally
+		if (!g_bFPSView)
+		{
+			g_LastmousePos.x = g_mousePos.x;
+			g_LastmousePos.y = g_mousePos.y;
+		}
+	}
+	return 1;
+}
+//-------------------------------------------------------------------------------
+int CDisplay::DrawHUD()
+{
+	// get the dimension of the back buffer
+	RECT sRect;
+	GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect);
+	sRect.right -= sRect.left;
+	sRect.bottom -= sRect.top;
+
+	struct SVertex
+	{
+		float x,y,z,w,u,v;
+	};
+
+	// commit the texture to the shader
+	// FIX: Necessary because the texture view is also using this shader
+	g_piPassThroughEffect->SetTexture("TEXTURE_2D",g_pcTexture);
+
+	// NOTE: The shader might be used for other purposes, too.
+	// So ensure the right technique is there
+	g_piPassThroughEffect->SetTechnique("PassThrough");
+
+	// build vertices for drawing from system memory
+	UINT dw;
+	g_piPassThroughEffect->Begin(&dw,0);
+	g_piPassThroughEffect->BeginPass(0);
+
+	D3DSURFACE_DESC sDesc;
+	g_pcTexture->GetLevelDesc(0,&sDesc);
+	SVertex as[4];
+	float fHalfX = ((float)sRect.right-(float)sDesc.Width) / 2.0f;
+	float fHalfY = ((float)sRect.bottom-(float)sDesc.Height) / 2.0f;
+	as[1].x = fHalfX;
+	as[1].y = fHalfY;
+	as[1].z = 0.2f;
+	as[1].w = 1.0f;
+	as[1].u = 0.0f;
+	as[1].v = 0.0f;
+
+	as[3].x = (float)sRect.right-fHalfX;
+	as[3].y = fHalfY;
+	as[3].z = 0.2f;
+	as[3].w = 1.0f;
+	as[3].u = 1.0f;
+	as[3].v = 0.0f;
+
+	as[0].x = fHalfX;
+	as[0].y = (float)sRect.bottom-fHalfY;
+	as[0].z = 0.2f;
+	as[0].w = 1.0f;
+	as[0].u = 0.0f;
+	as[0].v = 1.0f;
+
+	as[2].x = (float)sRect.right-fHalfX;
+	as[2].y = (float)sRect.bottom-fHalfY;
+	as[2].z = 0.2f;
+	as[2].w = 1.0f;
+	as[2].u = 1.0f;
+	as[2].v = 1.0f;
+
+	as[0].x -= 0.5f;as[1].x -= 0.5f;as[2].x -= 0.5f;as[3].x -= 0.5f;
+	as[0].y -= 0.5f;as[1].y -= 0.5f;as[2].y -= 0.5f;as[3].y -= 0.5f;
+
+	// draw the screen-filling squad
+	DWORD dw2;g_piDevice->GetFVF(&dw2);
+	g_piDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
+	g_piDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,
+		&as,sizeof(SVertex));
+
+	// end the effect and recover the old vertex format
+	g_piPassThroughEffect->EndPass();
+	g_piPassThroughEffect->End();
+
+	g_piDevice->SetFVF(dw2);
+	return 1;
+}
+//-------------------------------------------------------------------------------
+int CDisplay::RenderFullScene()
+{
+	// reset the color index used for drawing normals
+	g_iCurrentColor = 0;
+
+	// reset frame counter and rotation tracker 
+	CMeshRenderer::Instance().OnBeginFrame();
+
+	// setup wireframe/solid rendering mode
+	if (g_sOptions.eDrawMode == RenderOptions::WIREFRAME)
+	{
+		g_piDevice->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME);
+	}
+	else g_piDevice->SetRenderState(D3DRS_FILLMODE,D3DFILL_SOLID);
+
+	// draw the scene background (clear and texture 2d)
+	CBackgroundPainter::Instance().OnPreRender();
+
+	// setup the stereo view if necessary
+	if (g_sOptions.bStereoView)
+	{
+		this->SetupStereoView();
+	}
+
+	// draw all opaque objects in the scene
+	aiMatrix4x4 m;
+	if (NULL != g_pcAsset && NULL != g_pcAsset->pcScene->mRootNode)
+	{
+		this->HandleInput();
+		m =  g_mWorld * g_mWorldRotate;
+		RenderNode(g_pcAsset->pcScene->mRootNode,m,false);
+	}
+
+	// if a cube texture is loaded as background image, the user
+	// should be able to rotate it even if no asset is loaded
+	this->HandleInputEmptyScene();
+
+	// draw the scene background
+	CBackgroundPainter::Instance().OnPostRender();
+
+	// draw all non-opaque objects in the scene
+	if (NULL != g_pcAsset && NULL != g_pcAsset->pcScene->mRootNode)
+	{
+		// disable the z-buffer
+		g_piDevice->SetRenderState(D3DRS_ZWRITEENABLE,FALSE);
+		RenderNode(g_pcAsset->pcScene->mRootNode,m,true);
+		g_piDevice->SetRenderState(D3DRS_ZWRITEENABLE,TRUE);
+	}
+
+	// setup the stereo view if necessary
+	if (g_sOptions.bStereoView)
+	{
+		this->RenderStereoView(m);
+	}
+
+	// draw the HUD texture on top of the rendered scene using
+	// pre-projected vertices
+	if (!g_bFPSView && g_pcAsset && g_pcTexture)
+	{
+		this->DrawHUD();
+	}
+	return 1;
+}
+//-------------------------------------------------------------------------------
+int CDisplay::RenderMaterialView()
+{
+	return 1;
+}
+//-------------------------------------------------------------------------------
+int CDisplay::RenderNode (aiNode* piNode,const aiMatrix4x4& piMatrix,
+						  bool bAlpha /*= false*/)
+{
+	aiMatrix4x4 mTemp = piNode->mTransformation;
+	mTemp.Transpose();
+	aiMatrix4x4 aiMe = mTemp * piMatrix;
+
+	bool bChangedVM = false;
+	if (VIEWMODE_NODE == this->m_iViewMode && this->m_pcCurrentNode)
+	{
+		if (piNode != this->m_pcCurrentNode->psNode)
+		{
+			if (0 != piNode->mNumChildren)
+			{
+				// directly call our children
+				for (unsigned int i = 0; i < piNode->mNumChildren;++i)
+				{
+					RenderNode(piNode->mChildren[i],aiMe,bAlpha );
+				}
+			}
+			return 1;
+		}
+		this->m_iViewMode = VIEWMODE_FULL;
+		bChangedVM = true;
+	}
+
+	aiMatrix4x4 pcProj;
+	GetProjectionMatrix(pcProj);
+
+	aiMatrix4x4 pcCam;
+	aiVector3D vPos = GetCameraMatrix(pcCam);
+	pcProj = (aiMe * pcCam) * pcProj;
+
+	pcCam = aiMe;
+	pcCam.Inverse().Transpose();
+
+	// VERY UNOPTIMIZED, much stuff is redundant. Who cares?
+	if (!g_sOptions.bRenderMats && !bAlpha)
+	{
+		// this is very similar to the code in SetupMaterial()
+		ID3DXEffect* piEnd = g_piDefaultEffect;
+
+		// commit transformation matrices to the shader
+		piEnd->SetMatrix("WorldViewProjection",
+			(const D3DXMATRIX*)&pcProj);
+
+		piEnd->SetMatrix("World",(const D3DXMATRIX*)&aiMe);
+		piEnd->SetMatrix("WorldInverseTranspose",
+			(const D3DXMATRIX*)&pcCam);
+
+		if ( CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode())
+		{
+			pcCam = pcCam * pcProj;
+			piEnd->SetMatrix("ViewProj",(const D3DXMATRIX*)&pcCam);
+			pcCam.Inverse();
+			piEnd->SetMatrix("InvViewProj",(const D3DXMATRIX*)&pcCam);
+		}
+
+		// commit light colors and direction to the shader
+		D3DXVECTOR4 apcVec[5];
+		apcVec[0].x = g_avLightDirs[0].x;
+		apcVec[0].y = g_avLightDirs[0].y;
+		apcVec[0].z = g_avLightDirs[0].z;
+		apcVec[1].x = g_avLightDirs[0].x * -1.0f;
+		apcVec[1].y = g_avLightDirs[0].y * -1.0f;
+		apcVec[1].z = g_avLightDirs[0].z * -1.0f;
+
+		D3DXVec4Normalize(&apcVec[0],&apcVec[0]);
+		D3DXVec4Normalize(&apcVec[1],&apcVec[1]);
+		piEnd->SetVectorArray("afLightDir",apcVec,5);
+
+		apcVec[0].x = ((g_avLightColors[0] >> 16) & 0xFF) / 255.0f;
+		apcVec[0].y = ((g_avLightColors[0] >> 8) & 0xFF) / 255.0f;
+		apcVec[0].z = ((g_avLightColors[0]) & 0xFF) / 255.0f;
+		apcVec[0].w = 1.0f;
+
+		apcVec[1].x = ((g_avLightColors[1] >> 16) & 0xFF) / 255.0f;
+		apcVec[1].y = ((g_avLightColors[1] >> 8) & 0xFF) / 255.0f;
+		apcVec[1].z = ((g_avLightColors[1]) & 0xFF) / 255.0f;
+		apcVec[1].w = 0.0f;
+
+		apcVec[0] *= g_fLightIntensity;
+		apcVec[1] *= g_fLightIntensity;
+		piEnd->SetVectorArray("afLightColor",apcVec,5);
+
+		apcVec[0].x = vPos.x;
+		apcVec[0].y = vPos.y;
+		apcVec[0].z = vPos.z;
+		piEnd->SetVector( "vCameraPos",&apcVec[0]);
+
+		// setup the best technique 
+		if (g_sCaps.PixelShaderVersion < D3DPS_VERSION(3,0) || g_sOptions.bLowQuality)
+		{
+			if (g_sOptions.b3Lights)
+				piEnd->SetTechnique("DefaultFXSpecular_PS20_D2");
+			else piEnd->SetTechnique("DefaultFXSpecular_PS20_D1");
+		}
+		else
+		{
+			if (g_sOptions.b3Lights)
+				piEnd->SetTechnique("DefaultFXSpecular_D2");
+			else piEnd->SetTechnique("DefaultFXSpecular_D1");
+		}
+
+		// setup the default material
+		UINT dwPasses = 0;
+		piEnd->Begin(&dwPasses,0);
+		piEnd->BeginPass(0);
+	}
+	D3DXVECTOR4 vVector = g_aclNormalColors[g_iCurrentColor];
+	if (++g_iCurrentColor == 14)
+	{
+		g_iCurrentColor = 0;
+	}
+	if (! (!g_sOptions.bRenderMats && bAlpha))
+	{
+		for (unsigned int i = 0; i < piNode->mNumMeshes;++i)
+		{
+			// don't render the mesh if the render pass is incorrect
+			if (g_sOptions.bRenderMats && (
+				g_pcAsset->apcMeshes[piNode->mMeshes[i]]->piOpacityTexture || 
+				g_pcAsset->apcMeshes[piNode->mMeshes[i]]->fOpacity != 1.0f))
+			{
+				if (!bAlpha)continue;
+			}
+			else if (bAlpha)continue;
+
+			// now setup the material
+			if (g_sOptions.bRenderMats)
+			{
+				CMaterialManager::Instance().SetupMaterial(
+					g_pcAsset->apcMeshes[piNode->mMeshes[i]],pcProj,aiMe,pcCam,vPos);
+			}
+
+			if (bAlpha)CMeshRenderer::Instance().DrawSorted(piNode->mMeshes[i],aiMe);
+			else CMeshRenderer::Instance().DrawUnsorted(piNode->mMeshes[i]);
+
+			// now end the material
+			if (g_sOptions.bRenderMats)
+			{
+				CMaterialManager::Instance().EndMaterial(
+					g_pcAsset->apcMeshes[piNode->mMeshes[i]]);
+			}
+
+			// render normal vectors?
+			if (g_sOptions.bRenderNormals && g_pcAsset->apcMeshes[piNode->mMeshes[i]]->piVBNormals)
+			{
+				// this is very similar to the code in SetupMaterial()
+				ID3DXEffect* piEnd = g_piNormalsEffect;
+
+				piEnd->SetVector("OUTPUT_COLOR",&vVector);
+
+				piEnd->SetMatrix("WorldViewProjection",
+					(const D3DXMATRIX*)&pcProj);
+
+				UINT dwPasses = 0;
+				piEnd->Begin(&dwPasses,0);
+				piEnd->BeginPass(0);
+
+				g_piDevice->SetStreamSource(0,
+					g_pcAsset->apcMeshes[piNode->mMeshes[i]]->piVBNormals,0,
+					sizeof(AssetHelper::LineVertex));
+
+				g_piDevice->DrawPrimitive(D3DPT_LINELIST,0,
+					g_pcAsset->pcScene->mMeshes[piNode->mMeshes[i]]->mNumVertices);
+
+				piEnd->EndPass();
+				piEnd->End();
+			}
+		}
+		// end the default material
+		if (!g_sOptions.bRenderMats)
+		{
+			g_piDefaultEffect->EndPass();
+			g_piDefaultEffect->End();
+		}
+	}
+	// render all child nodes
+	for (unsigned int i = 0; i < piNode->mNumChildren;++i)
+	{
+		RenderNode(piNode->mChildren[i],aiMe,bAlpha );
+	}
+	// need to reset the viewmode?
+	if (bChangedVM)
+		this->m_iViewMode = VIEWMODE_NODE;
+	return 1;
+}
+//-------------------------------------------------------------------------------
+int CDisplay::RenderPatternBG()
+{
+	if (!g_piPatternEffect)
+	{
+		// seems we have not yet compiled this shader.
+		// and NOW is the best time to do that ...
+		ID3DXBuffer* piBuffer = NULL;
+		if(FAILED( D3DXCreateEffect(g_piDevice,
+			g_szCheckerBackgroundShader.c_str(),
+			(UINT)g_szCheckerBackgroundShader.length(),
+			NULL,
+			NULL,
+			D3DXSHADER_USE_LEGACY_D3DX9_31_DLL,
+			NULL,
+			&g_piPatternEffect,&piBuffer)))
+		{
+			if( piBuffer) 
+			{
+				MessageBox(g_hDlg,(LPCSTR)piBuffer->GetBufferPointer(),"HLSL",MB_OK);
+				piBuffer->Release();
+			}
+			return 0;
+		}
+		if( piBuffer) 
+		{
+			piBuffer->Release();
+			piBuffer = NULL;
+		}
+	}
+	// clear the color buffer in magenta
+	g_piDevice->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
+		D3DCOLOR_ARGB(0xFF,0xFF,0,0xFF), 1.0f,0 );
+
+	if (!g_piPatternEffect)
+	{
+		return 0;
+	}
+
+	// setup the shader
+	UINT dw;
+	g_piPatternEffect->Begin(&dw,0);
+	g_piPatternEffect->BeginPass(0);
+
+	RECT sRect;
+	GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect);
+	sRect.right -= sRect.left;
+	sRect.bottom -= sRect.top;
+
+	struct SVertex
+	{
+		float x,y,z,w;
+	};
+	// build the screen-filling rectangle
+	SVertex as[4];
+	as[1].x = 0.0f;
+	as[1].y = 0.0f;
+	as[1].z = 0.2f;
+	as[3].x = (float)sRect.right;
+	as[3].y = 0.0f;
+	as[3].z = 0.2f;
+	as[0].x = 0.0f;
+	as[0].y = (float)sRect.bottom;
+	as[0].z = 0.2f;
+	as[2].x = (float)sRect.right;
+	as[2].y = (float)sRect.bottom;
+	as[2].z = 0.2f;
+
+	as[0].w = 1.0f;
+	as[1].w = 1.0f;
+	as[2].w = 1.0f;
+	as[3].w = 1.0f;
+	
+	as[0].x -= 0.5f;as[1].x -= 0.5f;as[2].x -= 0.5f;as[3].x -= 0.5f;
+	as[0].y -= 0.5f;as[1].y -= 0.5f;as[2].y -= 0.5f;as[3].y -= 0.5f;
+
+	// draw the rectangle
+	DWORD dw2;g_piDevice->GetFVF(&dw2);
+	g_piDevice->SetFVF(D3DFVF_XYZRHW);
+	g_piDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,
+		&as,sizeof(SVertex));
+	g_piDevice->SetFVF(dw2);
+
+	// cleanup
+	g_piPatternEffect->EndPass();
+	g_piPatternEffect->End();
+	return 1;
+}
+//-------------------------------------------------------------------------------
+int CDisplay::RenderTextureView()
+{
+	if (!g_pcAsset || !g_pcAsset->pcScene)return 0;
+
+	// handle input
+	this->HandleInputTextureView();
+
+	// render the background
+	this->RenderPatternBG();
+
+	// it might be that there is no texture ...
+	if (!this->m_pcCurrentTexture->piTexture)
+	{
+		// FIX: no such log message. it would be repeated to often
+		//CLogDisplay::Instance().AddEntry("Unable to display texture. Image is unreachable.",
+		//	D3DCOLOR_ARGB(0xFF,0xFF,0,0));
+		return 0;
+	}
+
+
+	RECT sRect;
+	GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect);
+	sRect.right -= sRect.left;
+	sRect.bottom -= sRect.top;
+
+	// commit the texture to the shader
+	g_piPassThroughEffect->SetTexture("TEXTURE_2D",this->m_pcCurrentTexture->piTexture);
+
+	if (AI_TEXTYPE_OPACITY == this->m_pcCurrentTexture->iType)
+	{
+		g_piPassThroughEffect->SetTechnique("PassThroughAlphaFromR");
+	}
+	else if ((AI_TEXTYPE_OPACITY | 0x40000000) == this->m_pcCurrentTexture->iType)
+	{
+		g_piPassThroughEffect->SetTechnique("PassThroughAlphaFromA");
+	}
+	else g_piPassThroughEffect->SetTechnique("PassThrough");
+
+	UINT dw;
+	g_piPassThroughEffect->Begin(&dw,0);
+	g_piPassThroughEffect->BeginPass(0);
+
+	if (AI_TEXTYPE_HEIGHT == this->m_pcCurrentTexture->iType ||
+		AI_TEXTYPE_NORMALS == this->m_pcCurrentTexture->iType)
+	{
+		// manually disable alpha blending
+		g_piDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,FALSE);
+	}
+
+	// build a rectangle which centers the texture
+	// scaling is OK, but no stretching
+	D3DSURFACE_DESC sDesc;
+	this->m_pcCurrentTexture->piTexture->GetLevelDesc(0,&sDesc);
+
+	struct SVertex{float x,y,z,w,u,v;};
+	SVertex as[4];
+
+	const float nx = (float)sRect.right;
+	const float ny = (float)sRect.bottom;
+	const float  x = (float)sDesc.Width;
+	const float  y = (float)sDesc.Height;
+	float f = std::min((nx-30) / x,(ny-30) / y) * (this->m_fTextureZoom/1000.0f);
+	
+	float fHalfX = (nx - (f * x)) / 2.0f;
+	float fHalfY = (ny - (f * y)) / 2.0f;
+	as[1].x = fHalfX + this->m_vTextureOffset.x;
+	as[1].y = fHalfY + this->m_vTextureOffset.y;
+	as[1].z = 0.2f;
+	as[1].w = 1.0f;
+	as[1].u = 0.0f;
+	as[1].v = 0.0f;
+	as[3].x = nx-fHalfX + this->m_vTextureOffset.x;
+	as[3].y = fHalfY + this->m_vTextureOffset.y;
+	as[3].z = 0.2f;
+	as[3].w = 1.0f;
+	as[3].u = 1.0f;
+	as[3].v = 0.0f;
+	as[0].x = fHalfX + this->m_vTextureOffset.x;
+	as[0].y = ny-fHalfY + this->m_vTextureOffset.y;
+	as[0].z = 0.2f;
+	as[0].w = 1.0f;
+	as[0].u = 0.0f;
+	as[0].v = 1.0f;
+	as[2].x = nx-fHalfX + this->m_vTextureOffset.x;
+	as[2].y = ny-fHalfY + this->m_vTextureOffset.y;
+	as[2].z = 0.2f;
+	as[2].w = 1.0f;
+	as[2].u = 1.0f;
+	as[2].v = 1.0f;
+	as[0].x -= 0.5f;as[1].x -= 0.5f;as[2].x -= 0.5f;as[3].x -= 0.5f;
+	as[0].y -= 0.5f;as[1].y -= 0.5f;as[2].y -= 0.5f;as[3].y -= 0.5f;
+
+	// draw the rectangle
+	DWORD dw2;g_piDevice->GetFVF(&dw2);
+	g_piDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
+	g_piDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,
+		&as,sizeof(SVertex));
+	g_piDevice->SetFVF(dw2);
+
+	g_piPassThroughEffect->EndPass();
+	g_piPassThroughEffect->End();
+
+	// do we need to draw UV coordinates?
+	return 1;
+}
+};
+

+ 442 - 0
tools/assimp_view/Display.h

@@ -0,0 +1,442 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development Team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the ASSIMP team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the ASSIMP Development Team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+#if (!defined AV_DISPLAY_H_INCLUDED)
+#define AV_DISPLAY_H_INCLUDE
+
+// see CDisplay::m_aiImageList
+#define AI_VIEW_IMGLIST_NODE			0x0
+#define AI_VIEW_IMGLIST_MATERIAL		0x1
+#define AI_VIEW_IMGLIST_TEXTURE			0x2
+#define AI_VIEW_IMGLIST_TEXTURE_INVALID 0x3
+#define AI_VIEW_IMGLIST_MODEL			0x4
+
+//-------------------------------------------------------------------------------
+/* Corresponds to the "Display" combobox in the UI
+*/
+//-------------------------------------------------------------------------------
+class CDisplay
+	{
+private:
+
+	// default constructor
+	CDisplay() 
+		:	m_iViewMode(VIEWMODE_FULL), 
+			m_pcCurrentTexture(NULL),
+			m_pcCurrentNode(NULL),
+			m_pcCurrentMaterial(NULL),
+			m_hImageList(NULL),
+			m_hRoot(NULL),
+			m_fTextureZoom(1000.0f)
+	{
+		this->m_aiImageList[0] = 0;
+		this->m_aiImageList[1] = 1;
+		this->m_aiImageList[2] = 2;
+		this->m_aiImageList[3] = 3;
+		this->m_aiImageList[4] = 4;
+	}
+
+public:
+
+
+	//------------------------------------------------------------------
+	enum 
+	{
+		// the full model is displayed
+		VIEWMODE_FULL,
+
+		// a material is displayed on a simple spjere as model
+		VIEWMODE_MATERIAL,
+
+		// a texture with an UV set mapped on it is displayed
+		VIEWMODE_TEXTURE,
+
+		// a single node in the scenegraph is displayed
+		VIEWMODE_NODE,
+	};
+
+
+	//------------------------------------------------------------------
+	// represents a texture in the tree view
+	struct TextureInfo
+	{
+		// texture info
+		IDirect3DTexture9* piTexture;
+
+		// Blend factor of the texture
+		float fBlend;
+
+		// blend operation for the texture
+		aiTextureOp eOp;
+
+		// UV index for the texture
+		unsigned int iUV;
+
+		// Associated tree item
+		HTREEITEM hTreeItem;
+
+		// Original path to the texture
+		std::string szPath;
+
+		// index of the corresponding material
+		unsigned int iMatIndex;
+
+		// type of the texture
+		unsigned int iType;
+	};
+
+	//------------------------------------------------------------------
+	// represents a node in the tree view
+	struct NodeInfo
+	{
+		// node object
+		aiNode* psNode;
+
+		// corresponding tree view item
+		HTREEITEM hTreeItem;
+	};
+
+	//------------------------------------------------------------------
+	// represents a material in the tree view
+	struct MaterialInfo
+	{
+		// material index
+		unsigned int iIndex;
+
+		// material object
+		aiMaterial* psMaterial;
+
+		// ID3DXEffect interface
+		ID3DXEffect* piEffect;
+
+		// corresponding tree view item
+		HTREEITEM hTreeItem;
+	};
+
+	//------------------------------------------------------------------
+	// Singleton accessors
+	static CDisplay s_cInstance;
+	inline static CDisplay& Instance ()
+		{
+		return s_cInstance;
+		}
+
+
+	//------------------------------------------------------------------
+	// Called during the render loop. Renders the scene (including the 
+	// HUD etc) in the current view mode
+	int OnRender();
+
+	//------------------------------------------------------------------
+	// called when the user selects another item in the "Display" tree 
+	// view the method determines the new view mode and performs all 
+	// required operations
+	// \param p_hTreeItem Selected tree view item
+	int OnSetup(HTREEITEM p_hTreeItem);
+
+	//------------------------------------------------------------------
+	// Variant 1: Render the full scene with the asset
+	int RenderFullScene();
+
+#if 0
+	//------------------------------------------------------------------
+	// Variant 2: Render only a part of the scene. One node to
+	// be exact
+	int RenderScenePart();
+#endif
+
+	//------------------------------------------------------------------
+	// Variant 3: Render a large sphere and map a given material on it
+	int RenderMaterialView();
+
+	//------------------------------------------------------------------
+	// Variant 4: Render a flat plane, map a texture on it and
+	// display the UV wire on it
+	int RenderTextureView();
+
+	//------------------------------------------------------------------
+	// Fill the UI combobox with a list of all supported view modi
+	//
+	// The display modes are added in order
+	int FillDisplayList(void);
+
+	//------------------------------------------------------------------
+	// Add a material and all sub textures to the display mode list
+	// hRoot - Handle to the root of the tree view
+	// iIndex - Material index
+	int AddMaterialToDisplayList(HTREEITEM hRoot, 
+		unsigned int iIndex);
+
+	//------------------------------------------------------------------
+	// Add a texture to the display list
+	// pcMat - material containing the texture
+	// hTexture - Handle to the material tree item
+	// szPath - Path to the texture
+	// iUVIndex - UV index to be used for the texture
+	// fBlendFactor - Blend factor to be used for the texture
+	// eTextureOp - texture operation to be used for the texture
+	int AddTextureToDisplayList(unsigned int iType,
+		unsigned int iIndex,
+		const aiString* szPath,
+		HTREEITEM hFX, 
+		unsigned int iUVIndex		= 0,
+		const float fBlendFactor	= 0.0f,
+		aiTextureOp eTextureOp		= aiTextureOp_Multiply,
+		unsigned int iMesh			= 0);
+
+	//------------------------------------------------------------------
+	// Add a node to the display list
+	// Recusrivly add all subnodes
+	// iIndex - Index of the node in the parent's child list
+	// iDepth - Current depth of the node
+	// pcNode - Node object
+	// hRoot - Parent tree view node
+	int AddNodeToDisplayList(
+		unsigned int iIndex, 
+		unsigned int iDepth,
+		aiNode* pcNode,
+		HTREEITEM hRoot);
+
+	//------------------------------------------------------------------
+	// Load the image list for the tree view item
+	int LoadImageList(void);
+
+	//------------------------------------------------------------------
+	// Expand all nodes in the tree 
+	int ExpandTree();
+
+	//------------------------------------------------------------------
+	// Fill the UI combobox with a list of all supported animations
+	// The animations are added in order
+	int FillAnimList(void);
+
+	//------------------------------------------------------------------
+	// Clear the combox box containing the list of animations
+	int ClearAnimList(void);
+
+	//------------------------------------------------------------------
+	// Clear the combox box containing the list of scenegraph items
+	int ClearDisplayList(void);
+
+	//------------------------------------------------------------------
+	// Fill in the default statistics
+	int FillDefaultStatistics(void);
+
+	//------------------------------------------------------------------
+	// Called by LoadAsset()
+	// reset the class instance to the default values
+	int Reset(void);
+
+	//------------------------------------------------------------------
+	// Replace the texture that is current selected with
+	// a new texture
+	int ReplaceCurrentTexture(const char* szPath);
+
+	//------------------------------------------------------------------
+	// Display the context menu (if there) for the specified tree item
+	// hItem Valid tree view item handle
+	int ShowTreeViewContextMenu(HTREEITEM hItem);
+
+	//------------------------------------------------------------------
+	// Event handling for pop-up menus displayed by th tree view
+	int HandleTreeViewPopup(WPARAM wParam,LPARAM lParam);
+
+	//------------------------------------------------------------------
+	// setter for m_iViewMode
+	inline void SetViewMode(unsigned int p_iNew)
+	{
+		this->m_iViewMode = p_iNew;
+	}
+
+	//------------------------------------------------------------------
+	// getter for m_iViewMode
+	inline unsigned int GetViewMode()
+	{
+		return m_iViewMode;
+	}
+
+	//------------------------------------------------------------------
+	// change the texture view's zoom factor
+	inline void SetTextureViewZoom(float f)
+	{
+		// FIX: Removed log(), seems to make more problems than it fixes
+		this->m_fTextureZoom += f* 15;
+		if (this->m_fTextureZoom < 0.05f)this->m_fTextureZoom = 0.05f;
+	}
+
+	//------------------------------------------------------------------
+	// change the texture view's offset on the x axis
+	inline void SetTextureViewOffsetX(float f)
+	{
+		this->m_vTextureOffset.x += f;
+	}
+
+	//------------------------------------------------------------------
+	// change the texture view's offset on the y axis
+	inline void SetTextureViewOffsetY(float f)
+	{
+		this->m_vTextureOffset.y += f;
+	}
+
+	//------------------------------------------------------------------
+	// add a new texture to the list
+	inline void AddTexture(const TextureInfo& info)
+	{
+		this->m_asTextures.push_back(info);
+	}
+
+	//------------------------------------------------------------------
+	// add a new node to the list
+	inline void AddNode(const NodeInfo& info)
+	{
+		this->m_asNodes.push_back(info);
+	}
+
+	//------------------------------------------------------------------
+	// add a new material to the list
+	inline void AddMaterial(const MaterialInfo& info)
+	{
+		this->m_asMaterials.push_back(info);
+	}
+
+private:
+
+	//------------------------------------------------------------------
+	// Render a screen-filling square using the checker pattern shader
+	int RenderPatternBG();
+
+	//------------------------------------------------------------------
+	// Render a given node in the scenegraph
+	// piNode Node to be rendered
+	// piMatrix Current transformation matrix
+	// bAlpha Render alpha or opaque objects only?
+	int RenderNode (aiNode* piNode,const aiMatrix4x4& piMatrix,
+		bool bAlpha = false);
+
+	//------------------------------------------------------------------
+	// Setup the camera for the stereo view rendering mode
+	int SetupStereoView();
+
+	//------------------------------------------------------------------
+	// Render the second view (for the right eye) in stereo mod
+	// m - World matrix
+	int RenderStereoView(const aiMatrix4x4& m);
+
+	//------------------------------------------------------------------
+	// Handle user input
+	int HandleInput();
+
+	//------------------------------------------------------------------
+	// Handle user input for the texture viewer
+	int HandleInputTextureView();
+
+	//------------------------------------------------------------------
+	// Handle user input if no asset is loaded
+	int HandleInputEmptyScene();
+
+	//------------------------------------------------------------------
+	// Draw the HUD (call only if FPS mode isn't active)
+	int DrawHUD();
+
+	//------------------------------------------------------------------
+	// Used by OnSetup().
+	// Do everything necessary to switch to texture view mode
+	int OnSetupTextureView(TextureInfo* pcNew);
+
+	//------------------------------------------------------------------
+	// Used by OnSetup().
+	// Do everything necessary to switch to material view mode
+	int OnSetupMaterialView(MaterialInfo* pcNew);
+
+	//------------------------------------------------------------------
+	// Used by OnSetup().
+	// Do everything necessary to switch to node view mode
+	int OnSetupNodeView(NodeInfo* pcNew);
+
+	//------------------------------------------------------------------
+	// Used by OnSetup().
+	// Do everything necessary to switch back to normal view mode
+	int OnSetupNormalView();
+
+	//------------------------------------------------------------------
+	// Used by HandleTreeViewPopup().
+	int HandleTreeViewPopup2(WPARAM wParam,LPARAM lParam);
+
+private:
+
+	// view mode
+	unsigned int m_iViewMode;
+
+	// List of all textures in the display CB
+	std::vector<TextureInfo> m_asTextures;
+
+	// current texture or NULL if no texture is active
+	TextureInfo* m_pcCurrentTexture;
+
+	// List of all node in the display CB
+	std::vector<NodeInfo> m_asNodes;
+
+	// current Node or NULL if no Node is active
+	NodeInfo* m_pcCurrentNode;
+
+	// List of all materials in the display CB
+	std::vector<MaterialInfo> m_asMaterials;
+
+	// current material or NULL if no material is active
+	MaterialInfo* m_pcCurrentMaterial;
+
+	// indices into the image list of the "display" tree view control
+	unsigned int m_aiImageList[5]; /* = {0,1,2,3,4};*/
+
+	// Image list
+	HIMAGELIST m_hImageList;
+
+	// Root node of the tree, "Model"
+	HTREEITEM m_hRoot;
+
+	// Current zoom factor of the texture viewer
+	float m_fTextureZoom;
+
+	// Current offset (in pixels) of the texture viewer
+	aiVector2D m_vTextureOffset;
+	};
+
+#endif // AV_DISPLAY_H_INCLUDE

+ 64 - 2
tools/assimp_view/Input.cpp

@@ -52,7 +52,6 @@ namespace AssimpView {
 //-------------------------------------------------------------------------------
 void HandleMouseInputFPS( void )
 	{
-
 	POINT mousePos;
 	GetCursorPos( &mousePos );
 	ScreenToClient( GetDlgItem(g_hDlg,IDC_RT), &mousePos );
@@ -72,6 +71,8 @@ void HandleMouseInputFPS( void )
 			D3DXMatrixRotationAxis( &matRotation, (D3DXVECTOR3*)& g_sCamera.vRight, D3DXToRadian((float)nYDiff / 3.0f));
 			D3DXVec3TransformCoord( (D3DXVECTOR3*)&g_sCamera.vLookAt, (D3DXVECTOR3*)& g_sCamera.vLookAt, &matRotation );
 			D3DXVec3TransformCoord( (D3DXVECTOR3*)&g_sCamera.vUp, (D3DXVECTOR3*)&g_sCamera.vUp, &matRotation );
+			
+			CMeshRenderer::Instance().SetRotationChangedFlag();
 			}
 
 		if( 0 != nXDiff )
@@ -80,6 +81,8 @@ void HandleMouseInputFPS( void )
 			D3DXMatrixRotationAxis( &matRotation, (D3DXVECTOR3*)&v, D3DXToRadian((float)nXDiff / 3.0f) );
 			D3DXVec3TransformCoord( (D3DXVECTOR3*)&g_sCamera.vLookAt, (D3DXVECTOR3*)&g_sCamera.vLookAt, &matRotation );
 			D3DXVec3TransformCoord( (D3DXVECTOR3*)&g_sCamera.vUp,(D3DXVECTOR3*) &g_sCamera.vUp, &matRotation );
+			
+			CMeshRenderer::Instance().SetRotationChangedFlag();
 			}
 		}
 
@@ -88,6 +91,32 @@ void HandleMouseInputFPS( void )
 	}
 
 
+//-------------------------------------------------------------------------------
+// Handle mouse input for the FPS input behaviour
+//
+// Movement in x and y axis is possible
+//-------------------------------------------------------------------------------
+void HandleMouseInputTextureView( void )
+	{
+	POINT mousePos;
+	GetCursorPos( &mousePos );
+	ScreenToClient( GetDlgItem(g_hDlg,IDC_RT), &mousePos );
+
+	g_mousePos.x = mousePos.x;
+	g_mousePos.y = mousePos.y;
+
+	D3DXMATRIX matRotation;
+
+	if (g_bMousePressed)
+		{
+		CDisplay::Instance().SetTextureViewOffsetX((float)(g_mousePos.x - g_LastmousePos.x));
+		CDisplay::Instance().SetTextureViewOffsetY((float)(g_mousePos.y - g_LastmousePos.y));
+		}
+
+	g_LastmousePos.x = g_mousePos.x;
+	g_LastmousePos.y = g_mousePos.y;
+	}
+
 //-------------------------------------------------------------------------------
 // handle mouse input for the light rotation
 //
@@ -186,7 +215,6 @@ void HandleMouseInputLightIntensityAndColor( void )
 		int nYDiff = -(g_mousePos.y - g_LastmousePos.y);
 
 		g_fLightIntensity -= (float)nXDiff / 400.0f;
-
 		if ((nYDiff > 2 || nYDiff < -2) && (nXDiff < 20 && nXDiff > -20))
 		{
 			if (!g_bFPSView)
@@ -228,6 +256,8 @@ void HandleMouseInputLocal( void )
 				aiVector3D v = aiVector3D(1.0f,0.0f,0.0f);
 				D3DXMatrixRotationAxis( (D3DXMATRIX*) &matWorld, (D3DXVECTOR3*)&v, D3DXToRadian((float)nYDiff / 2.0f));
 				g_mWorldRotate = g_mWorldRotate * matWorld;
+
+				CMeshRenderer::Instance().SetRotationChangedFlag();
 				}
 
 			if( 0 != nXDiff && g_eClick != EClickPos_CircleVert)
@@ -235,6 +265,8 @@ void HandleMouseInputLocal( void )
 				aiVector3D v = aiVector3D(0.0f,1.0f,0.0f);
 				D3DXMatrixRotationAxis( (D3DXMATRIX*)&matWorld, (D3DXVECTOR3*)&v, D3DXToRadian((float)nXDiff / 2.0f) );
 				g_mWorldRotate = g_mWorldRotate * matWorld;
+
+				CMeshRenderer::Instance().SetRotationChangedFlag();
 				}
 			}
 		else
@@ -296,6 +328,8 @@ void HandleKeyboardInputFPS( void )
 	aiVector3D tmpLook  = g_sCamera.vLookAt;
 	aiVector3D tmpRight = g_sCamera.vRight;
 
+	aiVector3D vOldPos = g_sCamera.vPos;
+
 	// Up Arrow Key - View moves forward
 	if( keys[VK_UP] & 0x80 )
 		g_sCamera.vPos -= (tmpLook*-MOVE_SPEED)*g_fElpasedTime;
@@ -319,5 +353,33 @@ void HandleKeyboardInputFPS( void )
 	// End Key - View elevates down
 	if( keys[VK_END] & 0x80 )
 		g_sCamera.vPos.y -= MOVE_SPEED*g_fElpasedTime;
+
+	if (vOldPos != g_sCamera.vPos)
+		CMeshRenderer::Instance().SetRotationChangedFlag();
+	}
+
+
+//-------------------------------------------------------------------------------
+//-------------------------------------------------------------------------------
+void HandleKeyboardInputTextureView( void )
+	{
+	unsigned char keys[256];
+	GetKeyboardState( keys );
+
+	// Up Arrow Key 
+	if( keys[VK_UP] & 0x80 )
+		CDisplay::Instance().SetTextureViewOffsetY ( g_fElpasedTime * 150.0f );
+
+	// Down Arrow Key 
+	if( keys[VK_DOWN] & 0x80 )
+		CDisplay::Instance().SetTextureViewOffsetY ( -g_fElpasedTime * 150.0f );
+
+	// Left Arrow Key 
+	if( keys[VK_LEFT] & 0x80 )
+		CDisplay::Instance().SetTextureViewOffsetX ( g_fElpasedTime * 150.0f );
+
+	// Right Arrow Key 
+	if( keys[VK_RIGHT] & 0x80 )
+		CDisplay::Instance().SetTextureViewOffsetX ( -g_fElpasedTime * 150.0f );
 	}
 };

+ 0 - 1
tools/assimp_view/LogDisplay.h

@@ -91,7 +91,6 @@ private:
 
 	std::list<SEntry> asEntries;
 	ID3DXFont* piFont;
-
 	};
 
 #endif // AV_LOG_DISPLAY_H_INCLUDE

+ 151 - 2
tools/assimp_view/LogWindow.cpp

@@ -41,11 +41,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "stdafx.h"
 #include "assimp_view.h"
-
+#include "RichEdit.h"
 
 namespace AssimpView {
 
 /* extern */ CLogWindow CLogWindow::s_cInstance;
+extern HKEY g_hRegistry;
+
+// header for the RTF log file
+static const char* AI_VIEW_RTF_LOG_HEADER =
+	"{\\rtf1" 
+		"\\ansi" 
+		"\\deff0"
+		"{" 
+			"\\fonttbl{\\f0 Courier New;}"
+		"}" 
+	"{\\colortbl;" 
+		"\\red255\\green0\\blue0;" 	  // red for errors
+		"\\red255\\green120\\blue0;"  // orange for warnings
+		"\\red0\\green150\\blue0;" 	  // green for infos
+		"\\red0\\green0\\blue180;" 	  // blue for debug messages
+		"\\red0\\green0\\blue0;" 	  // black for everything else
+	"}}";
 
 //-------------------------------------------------------------------------------
 // Message procedure for the log window
@@ -68,12 +85,14 @@ INT_PTR CALLBACK LogDialogProc(HWND hwndDlg,UINT uMsg,
 			int y = HIWORD(lParam);
 
 			SetWindowPos(GetDlgItem(hwndDlg,IDC_EDIT1),NULL,0,0,
-				x,y,SWP_NOMOVE|SWP_NOZORDER);
+				x-10,y-12,SWP_NOMOVE|SWP_NOZORDER);
 
 			return TRUE;
 			}
 		case WM_CLOSE:
 			EndDialog(hwndDlg,0);
+
+			CLogWindow::Instance().bIsVisible = false;
 			return TRUE;
 		};
 	return FALSE;
@@ -90,6 +109,10 @@ void CLogWindow::Init ()
 		CLogDisplay::Instance().AddEntry("[ERROR] Unable to create logger window",
 			D3DCOLOR_ARGB(0xFF,0,0xFF,0));
 	}
+
+	// setup the log text
+	this->szText = AI_VIEW_RTF_LOG_HEADER;;
+	this->szPlainText = "";
 }
 //-------------------------------------------------------------------------------
 void CLogWindow::Show()
@@ -97,7 +120,133 @@ void CLogWindow::Show()
 	if (this->hwnd)
 	{
 		ShowWindow(this->hwnd,SW_SHOW);
+		this->bIsVisible = true;
+
+		// contents aren't updated while the logger isn't displayed
+		this->Update();
+	}
+}
+//-------------------------------------------------------------------------------
+void CMyLogStream::write(const std::string &message)
+{
+	CLogWindow::Instance().WriteLine(message);
+}
+//-------------------------------------------------------------------------------
+void CLogWindow::Clear()
+{
+	this->szText = AI_VIEW_RTF_LOG_HEADER;;
+	this->szPlainText = "";
+	
+	this->Update();
+}
+//-------------------------------------------------------------------------------
+void CLogWindow::Update()
+{
+	if (this->bIsVisible)
+	{
+		SETTEXTEX sInfo;
+		sInfo.flags = ST_DEFAULT;
+		sInfo.codepage = CP_ACP;
+
+		SendDlgItemMessage(this->hwnd,IDC_EDIT1,
+			EM_SETTEXTEX,(WPARAM)&sInfo,( LPARAM)this->szText.c_str());
+	}
+}
+//-------------------------------------------------------------------------------
+void CLogWindow::Save()
+{
+	char szFileName[MAX_PATH];
+
+	DWORD dwTemp = MAX_PATH;
+	if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"LogDestination",NULL,NULL,
+		(BYTE*)szFileName,&dwTemp))
+	{
+		// Key was not found. Use C:
+		strcpy(szFileName,"");
+	}
+	else
+	{
+		// need to remove the file name
+		char* sz = strrchr(szFileName,'\\');
+		if (!sz)sz = strrchr(szFileName,'/');
+		if (!sz)*sz = 0;
+	}
+	OPENFILENAME sFilename1 = {
+		sizeof(OPENFILENAME),
+		g_hDlg,GetModuleHandle(NULL), 
+		"Log files\0*.txt", NULL, 0, 1, 
+		szFileName, MAX_PATH, NULL, 0, NULL, 
+		"Save log to file",
+		OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR, 
+		0, 1, ".txt", 0, NULL, NULL
+	};
+	if(GetSaveFileName(&sFilename1) == 0) return;
+
+	// Now store the file in the registry
+	RegSetValueExA(g_hRegistry,"LogDestination",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH);
+
+	FILE* pFile = fopen(szFileName,"wt");
+	fprintf(pFile,this->szPlainText.c_str());
+	fclose(pFile);
+
+	CLogDisplay::Instance().AddEntry("[INFO] The log file has been saved",
+			D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0));
+}
+//-------------------------------------------------------------------------------
+void CLogWindow::WriteLine(const std::string& message)
+{
+	this->szPlainText.append(message);
+	this->szPlainText.append("\r\n");
+
+	this->szText.resize(this->szText.length()-1);
+
+	switch (message.c_str()[0])
+	{
+	case 'e': 
+	case 'E':
+		this->szText.append("{\\pard \\cf1 \\b \\fs18 ");
+		break;
+	case 'w': 
+	case 'W':
+		this->szText.append("{\\pard \\cf2 \\b \\fs18 ");
+		break;
+	case 'i': 
+	case 'I':
+		this->szText.append("{\\pard \\cf3 \\b \\fs18 ");
+		break;
+	case 'd': 
+	case 'D':
+		this->szText.append("{\\pard \\cf4 \\b \\fs18 ");
+		break;
+	default:
+		this->szText.append("{\\pard \\cf5 \\b \\fs18 ");
+		break;
+	}
+
+	std::string _message = message;
+	for (unsigned int i = 0; i < _message.length();++i)
+	{
+		if ('\\' == _message[i] ||
+			'}'  == _message[i] ||
+			'{'  == _message[i])
+		{
+			_message.insert(i++,"\\");
+		}
+	}
+
+	this->szText.append(_message);
+	this->szText.append("\\par}}");
+
+	if (this->bIsVisible && this->bUpdate)
+	{
+		SETTEXTEX sInfo;
+		sInfo.flags = ST_DEFAULT;
+		sInfo.codepage = CP_ACP;
+
+		SendDlgItemMessage(this->hwnd,IDC_EDIT1,
+			EM_SETTEXTEX,(WPARAM)&sInfo,( LPARAM)this->szText.c_str());
 	}
+	return;
 }
 
 }; //! AssimpView

+ 51 - 1
tools/assimp_view/LogWindow.h

@@ -42,6 +42,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #if (!defined AV_LOG_WINDOW_H_INCLUDED)
 #define AV_LOG_WINDOW_H_INCLUDE
 
+
+//-------------------------------------------------------------------------------
+/**	\brief Subclass of Assimp::LogStream used to add all log messages to the
+ *         log window.
+*/
+//-------------------------------------------------------------------------------
+class CMyLogStream : Assimp::LogStream
+{
+public:
+	/**	@brief	Implementation of the abstract method	*/
+	void write(const std::string &message);
+};
+
+
 //-------------------------------------------------------------------------------
 /**	\brief Class to display log strings in a separate window
 */
@@ -50,7 +64,11 @@ class CLogWindow
 	{
 private:
 
-	CLogWindow() : hwnd(NULL)  {}
+	friend class CMyLogStream;
+	friend INT_PTR CALLBACK LogDialogProc(HWND hwndDlg,UINT uMsg,
+		WPARAM wParam,LPARAM lParam);
+
+	CLogWindow() : hwnd(NULL),  bIsVisible(false), bUpdate(true) {}
 
 public:
 
@@ -68,11 +86,43 @@ public:
 	// Shows the log window
 	void Show();
 
+	// Clears the log window
+	void Clear();
+
+	// Save the log window to an user-defined file
+	void Save();
+
+	// write a line to the log window
+	void WriteLine(const std::string& message);
+
+	// Set the bUpdate member
+	inline void SetAutoUpdate(bool b)
+	{
+		this->bUpdate = b;
+	}
+
+	// updates the log file
+	void Update();
+
 private:
 
 	// Window handle
 	HWND hwnd;
 
+	// current text of the window (contains RTF tags)
+	std::string szText;
+	std::string szPlainText;
+
+	// is the log window currently visible?
+	bool bIsVisible;
+
+	// Specified whether each new log message updates the log automatically
+	bool bUpdate;
+
+
+public:
+	// associated log stream
+	CMyLogStream pcStream;
 	};
 
 #endif // AV_LOG_DISPLA

+ 226 - 76
tools/assimp_view/Material.cpp

@@ -45,12 +45,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 namespace AssimpView {
 
-//
-// Specifies the number of different shaders generated for
-// the current asset. This number is incremented by CreateMaterial()
-// each time a shader isn't found in cache and needs to be created
-//
-unsigned int g_iShaderCount			 = 0 ;
+
+/*static */ CMaterialManager CMaterialManager::s_cInstance;
 
 //-------------------------------------------------------------------------------
 // Compiler idependent stricmp() function.
@@ -116,11 +112,23 @@ VOID WINAPI FillFunc(D3DXVECTOR4* pOut,
 }
 
 //-------------------------------------------------------------------------------
-// Setup the default texture for a texture channel
-//
-// Generates a default checker pattern for a texture
+int CMaterialManager::UpdateSpecularMaterials()
+	{
+	if (g_pcAsset && g_pcAsset->pcScene)
+		{
+		for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
+			{
+			if (aiShadingMode_Phong == g_pcAsset->apcMeshes[i]->eShadingMode)
+				{
+				this->DeleteMaterial(g_pcAsset->apcMeshes[i]);
+				this->CreateMaterial(g_pcAsset->apcMeshes[i],g_pcAsset->pcScene->mMeshes[i]);
+				}
+			}
+		}
+	return 1;
+	}
 //-------------------------------------------------------------------------------
-int SetDefaultTexture(IDirect3DTexture9** p_ppiOut)
+int CMaterialManager::SetDefaultTexture(IDirect3DTexture9** p_ppiOut)
 {
 	if(FAILED(g_piDevice->CreateTexture(
 		256,
@@ -134,19 +142,22 @@ int SetDefaultTexture(IDirect3DTexture9** p_ppiOut)
 	{
 		CLogDisplay::Instance().AddEntry("[ERROR] Unable to create default texture",
 			D3DCOLOR_ARGB(0xFF,0xFF,0,0));
+
+		*p_ppiOut = NULL;
 	}
 	D3DXFillTexture(*p_ppiOut,&FillFunc,NULL);
-	return 1;
-}
 
+	// {9785DA94-1D96-426b-B3CB-BADC36347F5E}
+	static const GUID guidPrivateData = 
+		{ 0x9785da94, 0x1d96, 0x426b, 
+		{ 0xb3, 0xcb, 0xba, 0xdc, 0x36, 0x34, 0x7f, 0x5e } };
 
+	uint32_t iData = 0xFFFFFFFF;
+	(*p_ppiOut)->SetPrivateData(guidPrivateData,&iData,4,0);
+	return 1;
+}
 //-------------------------------------------------------------------------------
-// find a valid path to a texture file
-//
-// Handle 8.3 syntax correctly, search the environment of the
-// executable and the asset for a texture with a name very similar to a given one
-//-------------------------------------------------------------------------------
-bool TryLongerPath(char* szTemp,aiString* p_szString)
+bool CMaterialManager::TryLongerPath(char* szTemp,aiString* p_szString)
 {
 	char szTempB[MAX_PATH];
 
@@ -225,15 +236,11 @@ bool TryLongerPath(char* szTemp,aiString* p_szString)
 	}
 	return false;
 }
-
 //-------------------------------------------------------------------------------
-// find a valid path to a texture file
-//
-// Handle 8.3 syntax correctly, search the environment of the
-// executable and the asset for a texture with a name very similar to a given one
-//-------------------------------------------------------------------------------
-int FindValidPath(aiString* p_szString)
+int CMaterialManager::FindValidPath(aiString* p_szString)
 {
+	ai_assert(NULL != p_szString);
+
 	if ('*' ==  p_szString->data[0])
 	{
 		// '*' as first character indicates an embedded file
@@ -313,14 +320,12 @@ int FindValidPath(aiString* p_szString)
 	}
 	return 1;
 }
-
 //-------------------------------------------------------------------------------
-// Load a texture into memory and create a native D3D texture resource
-//
-// The function tries to find a valid path for a texture
-//-------------------------------------------------------------------------------
-int LoadTexture(IDirect3DTexture9** p_ppiOut,aiString* szPath)
+int CMaterialManager::LoadTexture(IDirect3DTexture9** p_ppiOut,aiString* szPath)
 {
+	ai_assert(NULL != p_ppiOut);
+	ai_assert(NULL != szPath);
+
 	*p_ppiOut = NULL;
 
 	// first get a valid path to the texture
@@ -354,7 +359,7 @@ int LoadTexture(IDirect3DTexture9** p_ppiOut,aiString* szPath)
 					sz.append(szPath->data);
 					CLogDisplay::Instance().AddEntry(sz,D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0));
 
-					SetDefaultTexture(p_ppiOut);
+					this->SetDefaultTexture(p_ppiOut);
 					return 1;
 				}
 			}
@@ -370,7 +375,7 @@ int LoadTexture(IDirect3DTexture9** p_ppiOut,aiString* szPath)
 					sz.append(szPath->data);
 					CLogDisplay::Instance().AddEntry(sz,D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0));
 
-					SetDefaultTexture(p_ppiOut);
+					this->SetDefaultTexture(p_ppiOut);
 					return 1;
 				}
 
@@ -425,19 +430,12 @@ int LoadTexture(IDirect3DTexture9** p_ppiOut,aiString* szPath)
 		sz.append(szPath->data);
 		CLogDisplay::Instance().AddEntry(sz,D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0));
 
-		SetDefaultTexture(p_ppiOut);
+		this->SetDefaultTexture(p_ppiOut);
 	}
 	return 1;
 }
-
-
-
-//-------------------------------------------------------------------------------
-// Delete all resources of a given material
-//
-// Must be called before CreateMaterial() to prevent memory leaking
 //-------------------------------------------------------------------------------
-void DeleteMaterial(AssetHelper::MeshHelper* pcIn)
+void CMaterialManager::DeleteMaterial(AssetHelper::MeshHelper* pcIn)
 {
 	if (!pcIn || !pcIn->piEffect)return;
 	pcIn->piEffect->Release();
@@ -474,17 +472,15 @@ void DeleteMaterial(AssetHelper::MeshHelper* pcIn)
 		pcIn->piNormalTexture = NULL;
 	}
 }
-
-
 //-------------------------------------------------------------------------------
-// Convert a height map to a normal map if necessary
-//
-// The function tries to detect the type of a texture automatically.
-// However, this wont work in every case.
-//-------------------------------------------------------------------------------
-void HMtoNMIfNecessary(IDirect3DTexture9* piTexture,IDirect3DTexture9** piTextureOut,
-					   bool bWasOriginallyHM = true)
+void CMaterialManager::HMtoNMIfNecessary(
+	IDirect3DTexture9* piTexture,
+	IDirect3DTexture9** piTextureOut,
+	bool bWasOriginallyHM)
 {
+	ai_assert(NULL != piTexture);
+	ai_assert(NULL != piTextureOut);
+
 	bool bMustConvert = false;
 	uintptr_t iElement = 3;
 
@@ -664,15 +660,11 @@ void HMtoNMIfNecessary(IDirect3DTexture9* piTexture,IDirect3DTexture9** piTextur
 		piTexture->Release();
 	}
 }
-
-
 //-------------------------------------------------------------------------------
-// Search for non-opaque pixels in a texture
-//
-// A pixel is considered to be non-opaque if its alpha value s less than 255
-//-------------------------------------------------------------------------------
-bool HasAlphaPixels(IDirect3DTexture9* piTexture)
+bool CMaterialManager::HasAlphaPixels(IDirect3DTexture9* piTexture)
 {
+	ai_assert(NULL != piTexture);
+
 	D3DLOCKED_RECT sRect;
 	D3DSURFACE_DESC sDesc;
 	piTexture->GetLevelDesc(0,&sDesc);
@@ -710,20 +702,16 @@ bool HasAlphaPixels(IDirect3DTexture9* piTexture)
 	piTexture->UnlockRect(0);
 	return false;
 }
-
-
-//-------------------------------------------------------------------------------
-// Create the material for a mesh.
-//
-// The function checks whether an identical shader is already in use.
-// A shader is considered to be identical if it has the same input signature
-// and takes the same number of texture channels.
 //-------------------------------------------------------------------------------
-int CreateMaterial(AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSource)
+int CMaterialManager::CreateMaterial(
+	AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSource)
 {
+	ai_assert(NULL != pcMesh);
+	ai_assert(NULL != pcSource);
+
 	ID3DXBuffer* piBuffer;
 
-	D3DXMACRO sMacro[32];
+	D3DXMACRO sMacro[64];
 
 	// extract all properties from the ASSIMP material structure
 	const aiMaterial* pcMat = g_pcAsset->pcScene->mMaterials[pcSource->mMaterialIndex];
@@ -830,11 +818,18 @@ int CreateMaterial(AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSource)
 	else
 	{
 		// try to find out whether the diffuse texture has any
-		// non-opaque pixels. If we find a few use it as opacity texture
+		// non-opaque pixels. If we find a few, use it as opacity texture
 		if (pcMesh->piDiffuseTexture && HasAlphaPixels(pcMesh->piDiffuseTexture))
 		{
-			pcMesh->piOpacityTexture = pcMesh->piDiffuseTexture;
-			pcMesh->piOpacityTexture->AddRef();
+			int iVal;
+
+			// NOTE: This special value is set by the tree view if the user
+			// manually removes the alpha texture from the view ...
+			if (AI_SUCCESS != aiGetMaterialInteger(pcMat,"no_a_from_d",&iVal))
+			{
+				pcMesh->piOpacityTexture = pcMesh->piDiffuseTexture;
+				pcMesh->piOpacityTexture->AddRef();
+			}
 		}
 	}
 
@@ -854,6 +849,14 @@ int CreateMaterial(AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSource)
 		LoadTexture(&pcMesh->piEmissiveTexture,&szPath);
 	}
 
+	//
+	// Shininess TEXTURE ------------------------------------------------
+	//
+	if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_SHININESS(0),&szPath))
+	{
+		LoadTexture(&pcMesh->piShininessTexture,&szPath);
+	}
+
 	//
 	// NORMAL/HEIGHT MAP ------------------------------------------------
 	//
@@ -870,6 +873,7 @@ int CreateMaterial(AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSource)
 		}
 		bHM = true;
 	}
+
 	// normal/height maps are sometimes mixed up. Try to detect the type
 	// of the texture automatically
 	if (pcMesh->piNormalTexture)
@@ -886,6 +890,8 @@ int CreateMaterial(AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSource)
 
 	// BUGFIX: If the shininess is 0.0f disable phong lighting
 	// This is a workaround for some meshes in the DX SDK (e.g. tiny.x)
+	// FIX: Added this check to the x-loader, but the line remains to
+	// catch other loader doing the same ...
 	if (0.0f == pcMesh->fShininess)
 	{
 		pcMesh->eShadingMode = aiShadingMode_Gouraud;
@@ -919,6 +925,9 @@ int CreateMaterial(AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSource)
 		if  ((pcMesh->piOpacityTexture != NULL ? true : false) != 
 			(pc->piOpacityTexture != NULL ? true : false))
 			continue;
+		if  ((pcMesh->piShininessTexture != NULL ? true : false) != 
+			(pc->piShininessTexture != NULL ? true : false))
+			continue;
 		if ((pcMesh->eShadingMode != aiShadingMode_Gouraud ? true : false) != 
 			(pc->eShadingMode != aiShadingMode_Gouraud ? true : false))
 			continue;
@@ -935,7 +944,7 @@ int CreateMaterial(AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSource)
 			return 2;
 		}
 	}
-	g_iShaderCount++;
+	this->m_iShaderCount++;
 
 	// build macros for the HLSL compiler
 	unsigned int iCurrent = 0;
@@ -989,12 +998,18 @@ int CreateMaterial(AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSource)
 		}
 	}
 
-
 	if (pcMesh->eShadingMode  != aiShadingMode_Gouraud  && !g_sOptions.bNoSpecular)
 	{
 		sMacro[iCurrent].Name = "AV_SPECULAR_COMPONENT";
 		sMacro[iCurrent].Definition = "1";
 		++iCurrent;
+
+		if (pcMesh->piShininessTexture)
+		{
+			sMacro[iCurrent].Name = "AV_SHININESS_TEXTURE";
+			sMacro[iCurrent].Definition = "1";
+			++iCurrent;
+		}
 	}
 	if (1.0f != pcMesh->fOpacity)
 	{
@@ -1003,8 +1018,6 @@ int CreateMaterial(AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSource)
 		++iCurrent;
 	}
 
-
-
 	// If a cubemap is active, we'll need to lookup it for calculating
 	// a physically correct reflection
 	if (CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode())
@@ -1079,6 +1092,8 @@ int CreateMaterial(AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSource)
 		pcMesh->piEffect->SetTexture("EMISSIVE_TEXTURE",pcMesh->piEmissiveTexture);
 	if (pcMesh->piNormalTexture)
 		pcMesh->piEffect->SetTexture("NORMAL_TEXTURE",pcMesh->piNormalTexture);
+	if (pcMesh->piShininessTexture)
+		pcMesh->piEffect->SetTexture("SHININESS_TEXTURE",pcMesh->piShininessTexture);
 
 	if (CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode())
 	{
@@ -1086,4 +1101,139 @@ int CreateMaterial(AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSource)
 	}
 	return 1;
 }
-};
+//-------------------------------------------------------------------------------
+int CMaterialManager::SetupMaterial (
+	AssetHelper::MeshHelper* pcMesh,
+	const aiMatrix4x4& pcProj,
+	const aiMatrix4x4& aiMe,
+	const aiMatrix4x4& pcCam,
+	const aiVector3D& vPos)
+{
+	ai_assert(NULL != pcMesh);
+	if (!pcMesh->piEffect)return 0;
+
+	ID3DXEffect* piEnd = pcMesh->piEffect;
+
+	piEnd->SetMatrix("WorldViewProjection",
+		(const D3DXMATRIX*)&pcProj);
+
+	piEnd->SetMatrix("World",(const D3DXMATRIX*)&aiMe);
+	piEnd->SetMatrix("WorldInverseTranspose",
+		(const D3DXMATRIX*)&pcCam);
+
+	D3DXVECTOR4 apcVec[5];
+	memset(apcVec,0,sizeof(apcVec));
+	apcVec[0].x = g_avLightDirs[0].x;
+	apcVec[0].y = g_avLightDirs[0].y;
+	apcVec[0].z = g_avLightDirs[0].z;
+	apcVec[1].x = g_avLightDirs[0].x * -1.0f;
+	apcVec[1].y = g_avLightDirs[0].y * -1.0f;
+	apcVec[1].z = g_avLightDirs[0].z * -1.0f;
+	D3DXVec4Normalize(&apcVec[0],&apcVec[0]);
+	D3DXVec4Normalize(&apcVec[1],&apcVec[1]);
+	piEnd->SetVectorArray("afLightDir",apcVec,5);
+
+	apcVec[0].x = ((g_avLightColors[0] >> 16)	& 0xFF) / 255.0f;
+	apcVec[0].y = ((g_avLightColors[0] >> 8)	& 0xFF) / 255.0f;
+	apcVec[0].z = ((g_avLightColors[0])			& 0xFF) / 255.0f;
+	apcVec[0].w = 1.0f;
+
+	apcVec[1].x = ((g_avLightColors[1] >> 16)	& 0xFF) / 255.0f;
+	apcVec[1].y = ((g_avLightColors[1] >> 8)	& 0xFF) / 255.0f;
+	apcVec[1].z = ((g_avLightColors[1])			& 0xFF) / 255.0f;
+	apcVec[1].w = 0.0f;
+
+	apcVec[0] *= g_fLightIntensity;
+	apcVec[1] *= g_fLightIntensity;
+	piEnd->SetVectorArray("afLightColor",apcVec,5);
+
+	apcVec[0].x = ((g_avLightColors[2] >> 16)	& 0xFF) / 255.0f;
+	apcVec[0].y = ((g_avLightColors[2] >> 8)	& 0xFF) / 255.0f;
+	apcVec[0].z = ((g_avLightColors[2])			& 0xFF) / 255.0f;
+	apcVec[0].w = 1.0f;
+
+	apcVec[1].x = ((g_avLightColors[2] >> 16)	& 0xFF) / 255.0f;
+	apcVec[1].y = ((g_avLightColors[2] >> 8)	& 0xFF) / 255.0f;
+	apcVec[1].z = ((g_avLightColors[2])			& 0xFF) / 255.0f;
+	apcVec[1].w = 0.0f;
+
+	// FIX: light intensity doesn't apply to ambient color
+	//apcVec[0] *= g_fLightIntensity;
+	//apcVec[1] *= g_fLightIntensity;
+	piEnd->SetVectorArray("afLightColorAmbient",apcVec,5);
+
+
+	apcVec[0].x = vPos.x;
+	apcVec[0].y = vPos.y;
+	apcVec[0].z = vPos.z;
+	piEnd->SetVector( "vCameraPos",&apcVec[0]);
+
+	// if the effect instance is shared by multiple materials we need to
+	// recommit its whole state once per frame ...
+	if (pcMesh->bSharedFX)
+	{
+		// now commit all constants to the shader
+		if (1.0f != pcMesh->fOpacity)
+			pcMesh->piEffect->SetFloat("TRANSPARENCY",pcMesh->fOpacity);
+		if (pcMesh->eShadingMode  != aiShadingMode_Gouraud)
+			pcMesh->piEffect->SetFloat("SPECULARITY",pcMesh->fShininess);
+
+		pcMesh->piEffect->SetVector("DIFFUSE_COLOR",&pcMesh->vDiffuseColor);
+		pcMesh->piEffect->SetVector("SPECULAR_COLOR",&pcMesh->vSpecularColor);
+		pcMesh->piEffect->SetVector("AMBIENT_COLOR",&pcMesh->vAmbientColor);
+		pcMesh->piEffect->SetVector("EMISSIVE_COLOR",&pcMesh->vEmissiveColor);
+
+		if (pcMesh->piOpacityTexture)
+			pcMesh->piEffect->SetTexture("OPACITY_TEXTURE",pcMesh->piOpacityTexture);
+		if (pcMesh->piDiffuseTexture)
+			pcMesh->piEffect->SetTexture("DIFFUSE_TEXTURE",pcMesh->piDiffuseTexture);
+		if (pcMesh->piSpecularTexture)
+			pcMesh->piEffect->SetTexture("SPECULAR_TEXTURE",pcMesh->piSpecularTexture);
+		if (pcMesh->piAmbientTexture)
+			pcMesh->piEffect->SetTexture("AMBIENT_TEXTURE",pcMesh->piAmbientTexture);
+		if (pcMesh->piEmissiveTexture)
+			pcMesh->piEffect->SetTexture("EMISSIVE_TEXTURE",pcMesh->piEmissiveTexture);
+		if (pcMesh->piNormalTexture)
+			pcMesh->piEffect->SetTexture("NORMAL_TEXTURE",pcMesh->piNormalTexture);
+		if (pcMesh->piShininessTexture)
+			pcMesh->piEffect->SetTexture("SHININESS_TEXTURE",pcMesh->piShininessTexture);
+
+		if (CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode())
+		{
+			piEnd->SetTexture("lw_tex_envmap",CBackgroundPainter::Instance().GetTexture());
+		}
+	}
+
+	// setup the correct shader technique to be used for drawing
+	if (g_sCaps.PixelShaderVersion < D3DPS_VERSION(3,0) || g_sOptions.bLowQuality)
+	{
+		if (g_sOptions.b3Lights)
+			piEnd->SetTechnique("MaterialFXSpecular_PS20_D2");
+		else piEnd->SetTechnique("MaterialFXSpecular_PS20_D1");
+	}
+	else
+	{
+		if (g_sOptions.b3Lights)
+			piEnd->SetTechnique("MaterialFXSpecular_D2");
+		else piEnd->SetTechnique("MaterialFXSpecular_D1");
+	}
+
+	// activate the effect
+	UINT dwPasses = 0;
+	piEnd->Begin(&dwPasses,0);
+	piEnd->BeginPass(0);
+	return 1;
+}
+//-------------------------------------------------------------------------------
+int CMaterialManager::EndMaterial (AssetHelper::MeshHelper* pcMesh)
+{
+	ai_assert(NULL != pcMesh);
+	if (!pcMesh->piEffect)return 0;
+
+	// end the effect
+	pcMesh->piEffect->EndPass();
+	pcMesh->piEffect->End();
+
+	return 1;
+}
+}; // end namespace AssimpView

+ 187 - 0
tools/assimp_view/MaterialManager.h

@@ -0,0 +1,187 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development Team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the ASSIMP team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the ASSIMP Development Team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+#if (!defined AV_MATERIAL_H_INCLUDED)
+#define AV_MATERIAL_H_INCLUDE
+
+//-------------------------------------------------------------------------------
+/* Helper class to create, access and destroy materials
+*/
+//-------------------------------------------------------------------------------
+class CMaterialManager
+{
+private:
+
+	// default constructor
+	CMaterialManager() 
+		:	m_iShaderCount (0) {}
+
+public:
+
+	//------------------------------------------------------------------
+	// Singleton accessors
+	static CMaterialManager s_cInstance;
+	inline static CMaterialManager& Instance ()
+		{
+		return s_cInstance;
+		}
+
+	//------------------------------------------------------------------
+	// Delete all resources of a given material
+	//
+	// Must be called before CreateMaterial() to prevent memory leaking
+	void DeleteMaterial(AssetHelper::MeshHelper* pcIn);
+	
+	//------------------------------------------------------------------
+	// Create the material for a mesh.
+	//
+	// The function checks whether an identical shader is already in use.
+	// A shader is considered to be identical if it has the same input 
+	// signature and takes the same number of texture channels.
+	int CreateMaterial(AssetHelper::MeshHelper* pcMesh,
+		const aiMesh* pcSource);
+
+	//------------------------------------------------------------------
+	// Setup the material for a given mesh
+	// pcMesh Mesh to be rendered
+	// pcProj Projection matrix
+	// aiMe Current world matrix
+	// pcCam Camera matrix
+	// vPos Position of the camera
+	// TODO: Extract camera position from matrix ...
+	//
+	int SetupMaterial (AssetHelper::MeshHelper* pcMesh,
+		const aiMatrix4x4& pcProj,
+		const aiMatrix4x4& aiMe,
+		const aiMatrix4x4& pcCam,
+		const aiVector3D& vPos);
+
+	//------------------------------------------------------------------
+	// End the material for a given mesh
+	// Called after mesh rendering is complete
+	// pcMesh Mesh object
+	int EndMaterial (AssetHelper::MeshHelper* pcMesh);
+
+	//------------------------------------------------------------------
+	// Recreate all specular materials depending on the current 
+	// specularity settings
+	//
+	// Diffuse-only materials are ignored.
+	// Must be called after specular highlights have been toggled
+	int UpdateSpecularMaterials();
+
+	//------------------------------------------------------------------
+	// find a valid path to a texture file
+	//
+	// Handle 8.3 syntax correctly, search the environment of the
+	// executable and the asset for a texture with a name very similar 
+	// to a given one
+	int FindValidPath(aiString* p_szString);
+
+	//------------------------------------------------------------------
+	// Load a texture into memory and create a native D3D texture resource
+	//
+	// The function tries to find a valid path for a texture
+	int LoadTexture(IDirect3DTexture9** p_ppiOut,aiString* szPath);
+
+
+	//------------------------------------------------------------------
+	// Getter for m_iShaderCount
+	//
+	inline unsigned int GetShaderCount()
+	{
+		return this->m_iShaderCount;
+	}
+
+	//------------------------------------------------------------------
+	// Reset the state of the class
+	// Called whenever a new asset is loaded
+	inline void Reset()
+	{
+		this->m_iShaderCount = 0;
+	}
+
+private:
+
+	//------------------------------------------------------------------
+	// find a valid path to a texture file
+	//
+	// Handle 8.3 syntax correctly, search the environment of the
+	// executable and the asset for a texture with a name very similar 
+	// to a given one
+	bool TryLongerPath(char* szTemp,aiString* p_szString);
+
+	//------------------------------------------------------------------
+	// Setup the default texture for a texture channel
+	//
+	// Generates a default checker pattern for a texture
+	int SetDefaultTexture(IDirect3DTexture9** p_ppiOut);
+
+	//------------------------------------------------------------------
+	// Convert a height map to a normal map if necessary
+	//
+	// The function tries to detect the type of a texture automatically.
+	// However, this wont work in every case.
+	void HMtoNMIfNecessary(IDirect3DTexture9* piTexture,
+		IDirect3DTexture9** piTextureOut,
+		bool bWasOriginallyHM = true);
+
+	//------------------------------------------------------------------
+	// Search for non-opaque pixels in a texture
+	//
+	// A pixel is considered to be non-opaque if its alpha value is
+	// less than 255
+	//------------------------------------------------------------------
+	bool HasAlphaPixels(IDirect3DTexture9* piTexture);
+
+private:
+
+	//
+	// Specifies the number of different shaders generated for
+	// the current asset. This number is incremented by CreateMaterial()
+	// each time a shader isn't found in cache and needs to be created
+	//
+	unsigned int m_iShaderCount;
+
+
+};
+
+#endif //!! include guard

+ 163 - 0
tools/assimp_view/MeshRenderer.cpp

@@ -0,0 +1,163 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development Team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the ASSIMP team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the ASSIMP Development Team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+#include "stdafx.h"
+#include "assimp_view.h"
+
+#include <map>
+
+namespace AssimpView {
+
+
+CMeshRenderer CMeshRenderer::s_cInstance;
+
+//-------------------------------------------------------------------------------
+int CMeshRenderer::DrawUnsorted(unsigned int iIndex)
+{
+	ai_assert(iIndex < g_pcAsset->pcScene->mNumMeshes);
+
+	// set vertex and index buffer
+	g_piDevice->SetStreamSource(0,g_pcAsset->apcMeshes[iIndex]->piVB,0,
+		sizeof(AssetHelper::Vertex));
+
+	g_piDevice->SetIndices(g_pcAsset->apcMeshes[iIndex]->piIB);
+
+	// and draw the mesh
+	g_piDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,
+		0,0,
+		g_pcAsset->pcScene->mMeshes[iIndex]->mNumVertices,0,
+		g_pcAsset->pcScene->mMeshes[iIndex]->mNumFaces);
+
+	return 1;
+}
+//-------------------------------------------------------------------------------
+int CMeshRenderer::DrawSorted(unsigned int iIndex,const aiMatrix4x4& mWorld)
+{
+	ai_assert(iIndex < g_pcAsset->pcScene->mNumMeshes);
+
+	AssetHelper::MeshHelper* pcHelper = g_pcAsset->apcMeshes[iIndex]; 
+	const aiMesh* pcMesh = g_pcAsset->pcScene->mMeshes[iIndex];
+
+	// only resort the tree of the rotation/position of the object
+	// or camera have been changed
+	if (this->m_bRotationChanged)
+	{
+		if (AI_VIEW_ALPHA_SORT_DELTA == ++this->m_iFrameCount)
+		{
+			this->m_iFrameCount = 0;
+
+			// compute the position of the camera in worldspace
+			aiMatrix4x4 mWorldInverse = mWorld;
+			mWorldInverse.Inverse();
+			mWorldInverse.Transpose();
+			const aiVector3D vLocalCamera = mWorldInverse * g_sCamera.vPos;
+
+			// well ... this is really funny now. We must compute their distance
+			// from the camera. We take the average distance of a face and add it 
+			// to a map which sorts it
+			std::map<float,unsigned int, std::greater_equal<float>> smap;
+
+			for (unsigned int iFace = 0; iFace < pcMesh->mNumFaces;++iFace)
+			{
+				const aiFace* pcFace = &pcMesh->mFaces[iFace];
+				float fDist = 0.0f;
+				for (unsigned int c = 0; c < 3;++c)
+				{
+					aiVector3D vPos = pcMesh->mVertices[pcFace->mIndices[c]];
+					vPos -= vLocalCamera;
+					fDist += vPos.SquareLength();
+				}
+				// SOMETIMES THIS THROWS AWESOME EXCEPTIONS
+				// don't know why, and the first who comes here with the debugger
+				// has the honorous task to find out!
+				smap.insert(std::pair<float, unsigned int>(fDist,iFace));
+			}
+
+			// now we can lock the index buffer and rebuild it
+			D3DINDEXBUFFER_DESC sDesc;
+			pcHelper->piIB->GetDesc(&sDesc);
+
+			if (D3DFMT_INDEX16 == sDesc.Format)
+			{
+				uint16_t* aiIndices;
+				pcHelper->piIB->Lock(0,0,(void**)&aiIndices,D3DLOCK_DISCARD);
+
+				for (std::map<float,unsigned int, std::greater_equal<float>>::const_iterator
+					i =  smap.begin();
+					i != smap.end();++i)
+				{
+					const aiFace* pcFace =  &pcMesh->mFaces[(*i).second];
+					*aiIndices++ = (uint16_t)pcFace->mIndices[0];
+					*aiIndices++ = (uint16_t)pcFace->mIndices[1];
+					*aiIndices++ = (uint16_t)pcFace->mIndices[2];
+				}
+			}
+			else if (D3DFMT_INDEX32 == sDesc.Format)
+			{
+				uint32_t* aiIndices;
+				pcHelper->piIB->Lock(0,0,(void**)&aiIndices,D3DLOCK_DISCARD);
+
+				for (std::map<float,unsigned int, std::greater_equal<float>>::const_iterator
+					i =  smap.begin();
+					i != smap.end();++i)
+				{
+					const aiFace* pcFace =  &pcMesh->mFaces[(*i).second];
+					*aiIndices++ = (uint32_t)pcFace->mIndices[0];
+					*aiIndices++ = (uint32_t)pcFace->mIndices[1];
+					*aiIndices++ = (uint32_t)pcFace->mIndices[2];
+				}
+			}
+			pcHelper->piIB->Unlock();
+		}
+	}
+	// set vertex and index buffer
+	g_piDevice->SetStreamSource(0,pcHelper->piVB,0,sizeof(AssetHelper::Vertex));
+
+	// and draw the mesh
+	g_piDevice->SetIndices(pcHelper->piIB);
+	g_piDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,
+		0,0,
+		pcMesh->mNumVertices,0,
+		pcMesh->mNumFaces);
+
+	return 1;
+}
+};

+ 132 - 0
tools/assimp_view/MeshRenderer.h

@@ -0,0 +1,132 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development Team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the ASSIMP team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the ASSIMP Development Team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+#if (!defined AV_MESH_RENDERER_H_INCLUDED)
+#define AV_MESH_RENDERER_H_INCLUDED
+
+
+#define AI_VIEW_ALPHA_SORT_DELTA 3
+
+//-------------------------------------------------------------------------------
+/* Helper class tp render meshes
+*/
+//-------------------------------------------------------------------------------
+class CMeshRenderer
+{
+private:
+
+	// default constructor
+	CMeshRenderer() 
+		:	m_bRotationChanged(true),
+			m_iFrameCount(AI_VIEW_ALPHA_SORT_DELTA-1)
+	{
+		// no other members to initialize
+	}
+
+public:
+
+	//------------------------------------------------------------------
+	// Singleton accessors
+	static CMeshRenderer s_cInstance;
+	inline static CMeshRenderer& Instance ()
+	{
+		return s_cInstance;
+	}
+
+
+	//------------------------------------------------------------------
+	// Draw a mesh in the global mesh list using the current pipeline state
+	// iIndex Index of the mesh to be drawn
+	//
+	// The function draws all faces in order, regardless of their distance
+	int DrawUnsorted(unsigned int iIndex);
+
+	//------------------------------------------------------------------
+	// Draw a mesh in the global mesh list using the current pipeline state
+	// iIndex Index of the mesh to be drawn
+	//
+	// The method sorts all vertices by their distance (back to front)
+	//
+	// mWorld World matrix for the node
+	int DrawSorted(unsigned int iIndex,
+		const aiMatrix4x4& mWorld);
+
+
+	//------------------------------------------------------------------
+	// Indicate that the rotation of the object or the camera has
+	// been changed, thus the alpha order tree must be updated
+	inline void SetRotationChangedFlag()
+	{
+		this->m_bRotationChanged = true;
+	}
+
+	//------------------------------------------------------------------
+	// Reset the state of the class
+	// Called whenever a new asset is loaded
+	inline void Reset()
+	{
+		this->m_bRotationChanged = true;
+		this->m_iFrameCount = 2;
+	}
+
+	//------------------------------------------------------------------
+	// Called at the beginning of the frame. Reset the state
+	// of the instance
+	inline void OnBeginFrame()
+	{
+		if (0 == this->m_iFrameCount)
+		{
+			this->m_bRotationChanged = false;
+		}
+	}
+
+private:
+
+	// true if the rotation of the object or camera has changed
+	// in the last frame. If there were no changes it should
+	// not be necessary to update the alpha ordering tree
+	bool m_bRotationChanged;
+
+	// only update the alpha order each AI_VIEW_ALPHA_SORT_DELTA frames
+	unsigned int m_iFrameCount;
+};
+
+#endif //!! include guard

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 1003 - 71
tools/assimp_view/MessageProc.cpp


+ 213 - 0
tools/assimp_view/Normals.cpp

@@ -0,0 +1,213 @@
+/*
+---------------------------------------------------------------------------
+Free Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development Team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the ASSIMP team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the ASSIMP Development Team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+
+#include "stdafx.h"
+#include "assimp_view.h"
+
+#include "GenFaceNormalsProcess.h"
+#include "GenVertexNormalsProcess.h"
+#include "JoinVerticesProcess.h"
+#include "CalcTangentsProcess.h"
+
+namespace AssimpView {
+
+
+bool g_bWasFlipped = false;
+
+//-------------------------------------------------------------------------------
+// Flip all normal vectors
+//-------------------------------------------------------------------------------
+void AssetHelper::FlipNormals()
+{
+	// invert all normal vectors
+	for (unsigned int i = 0; i < this->pcScene->mNumMeshes;++i)
+	{
+		aiMesh* pcMesh = this->pcScene->mMeshes[i];
+		for (unsigned int a = 0; a < pcMesh->mNumVertices;++a)
+		{
+			pcMesh->mNormals[a] *= -1.0f;
+		}
+	}
+	// recreate native data
+	DeleteAssetData(true);
+	CreateAssetData();
+	g_bWasFlipped = ! g_bWasFlipped;
+}
+
+//-------------------------------------------------------------------------------
+// Set the normal set of the scene
+//-------------------------------------------------------------------------------
+void AssetHelper::SetNormalSet(unsigned int iSet)
+{
+	if (this->iNormalSet == iSet)return;
+
+	// we need to build an unique set of vertices for this ...
+	for (unsigned int i = 0; i < this->pcScene->mNumMeshes;++i)
+	{
+		aiMesh* pcMesh = this->pcScene->mMeshes[i];
+		const unsigned int iNumVerts = pcMesh->mNumFaces*3;
+
+		aiVector3D* pvPositions = new aiVector3D[iNumVerts];
+		aiVector3D* pvNormals = new aiVector3D[iNumVerts];
+		aiVector3D* pvTangents(NULL), *pvBitangents(NULL);
+
+		ai_assert(AI_MAX_NUMBER_OF_TEXTURECOORDS == 4);
+		ai_assert(AI_MAX_NUMBER_OF_COLOR_SETS == 4);
+		aiVector3D* apvTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS] = {NULL,NULL,NULL,NULL};
+		aiColor4D* apvColorSets[AI_MAX_NUMBER_OF_COLOR_SETS] = {NULL,NULL,NULL,NULL};
+
+
+		unsigned int p = 0;
+		while (pcMesh->HasTextureCoords(p))
+			apvTextureCoords[p++] = new aiVector3D[iNumVerts];
+
+		p = 0;
+		while (pcMesh->HasVertexColors(p))
+			apvColorSets[p++] = new aiColor4D[iNumVerts];
+
+		// iterate through all faces and build a clean list
+		unsigned int iIndex = 0;
+		for (unsigned int a = 0; a< pcMesh->mNumFaces;++a)
+		{
+			aiFace* pcFace = &pcMesh->mFaces[a];
+			for (unsigned int q = 0; q < 3;++q,++iIndex)
+			{
+				pvPositions[iIndex] = pcMesh->mVertices[pcFace->mIndices[q]];
+				pvNormals[iIndex] = pcMesh->mNormals[pcFace->mIndices[q]];
+
+				unsigned int p = 0;
+				while (pcMesh->HasTextureCoords(p))
+				{
+					apvTextureCoords[p][iIndex] = pcMesh->mTextureCoords[p][pcFace->mIndices[q]];
+					++p;
+				}
+				p = 0;
+				while (pcMesh->HasVertexColors(p))
+				{
+					apvColorSets[p][iIndex] = pcMesh->mColors[p][pcFace->mIndices[q]];
+					++p;
+				}
+				pcFace->mIndices[q] = iIndex;
+			}
+		}
+
+		// delete the old members
+		delete[] pcMesh->mVertices;
+		pcMesh->mVertices = pvPositions;
+
+		p = 0;
+		while (pcMesh->HasTextureCoords(p))
+		{
+			delete pcMesh->mTextureCoords[p];
+			pcMesh->mTextureCoords[p] = apvTextureCoords[p];
+			++p;
+		}
+		p = 0;
+		while (pcMesh->HasVertexColors(p))
+		{
+			delete pcMesh->mColors[p];
+			pcMesh->mColors[p] = apvColorSets[p];
+			++p;
+		}
+		pcMesh->mNumVertices = iNumVerts;
+
+		// keep the pointer to the normals 
+		delete[] pcMesh->mNormals;
+		pcMesh->mNormals = NULL;
+
+		if (!this->apcMeshes[i]->pvOriginalNormals)
+			this->apcMeshes[i]->pvOriginalNormals = pvNormals;
+	}
+
+	// now we can start to calculate a new set of normals
+	if (HARD == iSet)
+	{
+		Assimp::GenFaceNormalsProcess* pcProcess = new Assimp::GenFaceNormalsProcess();
+		pcProcess->Execute(this->pcScene);
+		delete pcProcess;
+	}
+	else if (SMOOTH == iSet)
+	{
+		Assimp::GenVertexNormalsProcess* pcProcess = new Assimp::GenVertexNormalsProcess();
+		pcProcess->Execute(this->pcScene);
+		delete pcProcess;
+	}
+	else if (ORIGINAL == iSet)
+	{
+		for (unsigned int i = 0; i < this->pcScene->mNumMeshes;++i)
+		{
+			this->pcScene->mMeshes[i]->mNormals = this->apcMeshes[i]->pvOriginalNormals;
+		}
+	}
+
+	// recalculate tangents and bitangents
+	Assimp::BaseProcess* pcProcess = new Assimp::CalcTangentsProcess();
+	pcProcess->Execute(this->pcScene);
+	delete pcProcess;
+
+	// join the mesh vertices again
+	pcProcess = new Assimp::JoinVerticesProcess();
+	pcProcess->Execute(this->pcScene);
+	delete pcProcess;
+
+	this->iNormalSet = iSet;
+
+	if (g_bWasFlipped && ORIGINAL != iSet)
+	{
+		// invert all normal vectors
+		for (unsigned int i = 0; i < this->pcScene->mNumMeshes;++i)
+		{
+			aiMesh* pcMesh = this->pcScene->mMeshes[i];
+			for (unsigned int a = 0; a < pcMesh->mNumVertices;++a)
+			{
+				pcMesh->mNormals[a] *= -1.0f;
+			}
+		}
+	}
+
+	// recreate native data
+	DeleteAssetData(true);
+	CreateAssetData();
+	return;
+}
+
+};

+ 5 - 1
tools/assimp_view/RenderOptions.h

@@ -34,7 +34,8 @@ class RenderOptions
 			bLightRotate	(false),
 			bRotate			(true),
 			bLowQuality		(false),
-			bNoSpecular		(false) {}
+			bNoSpecular		(false),
+			bStereoView		(false)	{}
 
 		bool bMultiSample;
 
@@ -62,6 +63,9 @@ class RenderOptions
 		// disable specular lighting got all elements in the scene
 		bool bNoSpecular;
 
+		// enable stereo view
+		bool bStereoView;
+
 		// wireframe or solid rendering?
 		DrawMode eDrawMode;
 	};

+ 140 - 32
tools/assimp_view/Shaders.cpp

@@ -466,6 +466,18 @@ std::string g_szMaterialShader = std::string(
 	"float4x3 InvViewProj;\n"
 	"#endif\n"
 
+	"float4 DIFFUSE_COLOR;\n"
+	"float4 SPECULAR_COLOR;\n"
+	"float4 AMBIENT_COLOR;\n"
+	"float4 EMISSIVE_COLOR;\n"
+
+	"#ifdef AV_SPECULAR_COMPONENT\n"
+	"float SPECULARITY;\n"
+	"#endif\n"
+	"#ifdef AV_OPACITY\n"
+	"float TRANSPARENCY;\n"
+	"#endif\n"
+
 	// light colors (diffuse and specular)\n"
 	"float4 afLightColor[5];\n"
 	"float4 afLightColorAmbient[5];\n"
@@ -556,18 +568,6 @@ std::string g_szMaterialShader = std::string(
 		"};\n"
 	"#endif // AV_SKYBOX_LOOKUP\n"
 
-	"float4 DIFFUSE_COLOR;\n"
-	"float4 SPECULAR_COLOR;\n"
-	"float4 AMBIENT_COLOR;\n"
-	"float4 EMISSIVE_COLOR;\n"
-
-	"#ifdef AV_SPECULAR_COMPONENT\n"
-	"float SPECULARITY;\n"
-	"#endif\n"
-	"#ifdef AV_OPACITY\n"
-	"float TRANSPARENCY;\n"
-	"#endif\n"
-
 	// ----------------------------------------------------------------------------\n"
 	// Vertex shader input structure\n"
 	// ----------------------------------------------------------------------------\n"
@@ -746,15 +746,15 @@ std::string g_szMaterialShader = std::string(
 		"#ifdef AV_SPECULAR_COMPONENT\n"
 			"#ifndef AV_SKYBOX_LOOKUP\n"
 				"#ifdef AV_SPECULAR_TEXTURE\n"
-					"SPECULAR_COLOR.rgb * afLightColor[0].rgb * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(fHalfLambert * 4.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n"
+					"SPECULAR_COLOR.rgb * afLightColor[0].rgb * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n"
 				"#else\n"
-					"SPECULAR_COLOR.rgb * afLightColor[0].rgb * (saturate(fHalfLambert * 4.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n"
+					"SPECULAR_COLOR.rgb * afLightColor[0].rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n"
 				"#endif // !AV_SPECULAR_TEXTURE\n"
 			"#else\n"
 				"#ifdef AV_SPECULAR_TEXTURE\n"
-					"SPECULAR_COLOR.rgb * afLightColor[0].rgb * GetSSSCubeMap(Reflect) * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(fHalfLambert * 4.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n"
+					"SPECULAR_COLOR.rgb * afLightColor[0].rgb * GetSSSCubeMap(Reflect) * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n"
 				"#else\n"
-					"SPECULAR_COLOR.rgb * afLightColor[0].rgb * GetSSSCubeMap(Reflect) * (saturate(fHalfLambert * 4.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n"
+					"SPECULAR_COLOR.rgb * afLightColor[0].rgb * GetSSSCubeMap(Reflect) * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n"
 				"#endif // !AV_SPECULAR_TEXTURE\n"
 			"#endif // !AV_SKYBOX_LOOKUP\n"
 		"#endif // !AV_SPECULAR_COMPONENT\n"
@@ -817,15 +817,15 @@ std::string g_szMaterialShader = std::string(
 		"#ifdef AV_SPECULAR_COMPONENT\n"
 			"#ifndef AV_SKYBOX_LOOKUP\n"
 				"#ifdef AV_SPECULAR_TEXTURE\n"
-					"SPECULAR_COLOR.rgb * afLightColor[0].rgb * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(fHalfLambert * 4.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n"
+					"SPECULAR_COLOR.rgb * afLightColor[0].rgb * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n"
 				"#else\n"
-					"SPECULAR_COLOR.rgb * afLightColor[0].rgb * (saturate(fHalfLambert * 4.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n"
+					"SPECULAR_COLOR.rgb * afLightColor[0].rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n"
 				"#endif // !AV_SPECULAR_TEXTURE\n"
 			"#else\n"
 				"#ifdef AV_SPECULAR_TEXTURE\n"
-					"SPECULAR_COLOR.rgb * afLightColor[0].rgb * GetSSSCubeMap(Reflect) * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(fHalfLambert * 4.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n"
+					"SPECULAR_COLOR.rgb * afLightColor[0].rgb * GetSSSCubeMap(Reflect) * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n"
 				"#else\n"
-					"SPECULAR_COLOR.rgb * afLightColor[0].rgb * GetSSSCubeMap(Reflect) * (saturate(fHalfLambert * 4.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n"
+					"SPECULAR_COLOR.rgb * afLightColor[0].rgb * GetSSSCubeMap(Reflect) * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n"
 				"#endif // !AV_SPECULAR_TEXTURE\n"
 			"#endif // !AV_SKYBOX_LOOKUP\n"
 		"#endif // !AV_SPECULAR_COMPONENT\n"
@@ -858,15 +858,15 @@ std::string g_szMaterialShader = std::string(
 		"#ifdef AV_SPECULAR_COMPONENT\n"
 			"#ifndef AV_SKYBOX_LOOKUP\n"
 				"#ifdef AV_SPECULAR_TEXTURE\n"
-					"SPECULAR_COLOR.rgb * afLightColor[1].rgb * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(fHalfLambert * 4.0f) * pow(dot(Reflect,AV_LIGHT_1),SPECULARITY)) + \n"
+					"SPECULAR_COLOR.rgb * afLightColor[1].rgb * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_1),SPECULARITY)) + \n"
 				"#else\n"
-					"SPECULAR_COLOR.rgb * afLightColor[1].rgb * (saturate(fHalfLambert * 4.0f) * pow(dot(Reflect,AV_LIGHT_1),SPECULARITY)) + \n"
+					"SPECULAR_COLOR.rgb * afLightColor[1].rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_1),SPECULARITY)) + \n"
 				"#endif // !AV_SPECULAR_TEXTURE\n"
 			"#else\n"
 				"#ifdef AV_SPECULAR_TEXTURE\n"
-					"SPECULAR_COLOR.rgb * afLightColor[1].rgb * GetSSSCubeMap(Reflect) * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(fHalfLambert * 4.0f) * pow(dot(Reflect,AV_LIGHT_1),SPECULARITY)) + \n"
+					"SPECULAR_COLOR.rgb * afLightColor[1].rgb * GetSSSCubeMap(Reflect) * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_1),SPECULARITY)) + \n"
 				"#else\n"
-					"SPECULAR_COLOR.rgb * afLightColor[1].rgb * GetSSSCubeMap(Reflect) * (saturate(fHalfLambert * 4.0f) * pow(dot(Reflect,AV_LIGHT_1),SPECULARITY)) + \n"
+					"SPECULAR_COLOR.rgb * afLightColor[1].rgb * GetSSSCubeMap(Reflect) * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_1),SPECULARITY)) + \n"
 				"#endif // !AV_SPECULAR_TEXTURE\n"
 			"#endif // !AV_SKYBOX_LOOKUP\n"
 		"#endif // !AV_SPECULAR_COMPONENT\n"
@@ -1134,7 +1134,6 @@ std::string g_szMaterialShader = std::string(
 		);
 
 std::string g_szPassThroughShader = std::string(
-
 		"texture TEXTURE_2D;\n"
 		"sampler TEXTURE_SAMPLER = sampler_state\n"
 			"{\n"
@@ -1166,29 +1165,138 @@ std::string g_szPassThroughShader = std::string(
 			"return Out;\n"
 			"}\n"
 
-
+		// simply lookup a texture
 		// ----------------------------------------------------------------------------\n"
 		"float4 PassThrough_PS(float2 IN : TEXCOORD0) : COLOR\n"
 		"{\n"
 		"return tex2D(TEXTURE_SAMPLER,IN);\n"
 		"}\n"
-	
+
+		// visualize the alpha channel (in black) -> use a
+		// ----------------------------------------------------------------------------\n"
+		"float4 PassThroughAlphaA_PS(float2 IN : TEXCOORD0) : COLOR\n"
+		"{\n"
+		"return float4(0.0f,0.0f,0.0f,tex2D(TEXTURE_SAMPLER,IN).a);\n"
+		"}\n"
+
+		// visualize the alpha channel (in black) -> use r
+		// ----------------------------------------------------------------------------\n"
+		"float4 PassThroughAlphaR_PS(float2 IN : TEXCOORD0) : COLOR\n"
+		"{\n"
+		"return float4(0.0f,0.0f,0.0f,tex2D(TEXTURE_SAMPLER,IN).r);\n"
+		"}\n"
 
 		// ----------------------------------------------------------------------------\n"
 		// Simple pass-through technique\n"
 		// ----------------------------------------------------------------------------\n"
 		"technique PassThrough\n"
+		"{\n"
+			"pass p0\n"
+			"{\n"
+				"FillMode=Solid;\n"
+				"ZEnable = FALSE;\n"
+				"CullMode = none;\n"
+				"AlphaBlendEnable = TRUE;\n"
+				"SrcBlend =srcalpha;\n"
+				"DestBlend =invsrcalpha;\n"
+				"PixelShader = compile ps_2_0 PassThrough_PS();\n"
+				"VertexShader = compile vs_2_0 DefaultVShader();\n"
+			"}\n"
+		"};\n"
+
+		// ----------------------------------------------------------------------------\n"
+		// Pass-through technique which visualizes the texture's alpha channel
+		// ----------------------------------------------------------------------------\n"
+		"technique PassThroughAlphaFromA\n"
+		"{\n"
+			"pass p0\n"
+			"{\n"
+				"FillMode=Solid;\n"
+				"ZEnable = FALSE;\n"
+				"CullMode = none;\n"
+				"AlphaBlendEnable = TRUE;\n"
+				"SrcBlend =srcalpha;\n"
+				"DestBlend =invsrcalpha;\n"
+				"PixelShader = compile ps_2_0 PassThroughAlphaA_PS();\n"
+				"VertexShader = compile vs_2_0 DefaultVShader();\n"
+			"}\n"
+		"};\n"
+
+		// ----------------------------------------------------------------------------\n"
+		// Pass-through technique which visualizes the texture's red channel
+		// ----------------------------------------------------------------------------\n"
+		"technique PassThroughAlphaFromR\n"
+		"{\n"
+			"pass p0\n"
+			"{\n"
+				"FillMode=Solid;\n"
+				"ZEnable = FALSE;\n"
+				"CullMode = none;\n"
+				"AlphaBlendEnable = TRUE;\n"
+				"SrcBlend =srcalpha;\n"
+				"DestBlend =invsrcalpha;\n"
+				"PixelShader = compile ps_2_0 PassThroughAlphaR_PS();\n"
+				"VertexShader = compile vs_2_0 DefaultVShader();\n"
+			"}\n"
+		"};\n"
+		);
+
+std::string g_szCheckerBackgroundShader = std::string(
+
+		// the two colors used to draw the checker pattern
+		"float3 COLOR_ONE = float3(0.4f,0.4f,0.4f);\n"
+		"float3 COLOR_TWO = float3(0.6f,0.6f,0.6f);\n"
+
+		// size of a square in both x and y direction
+		"float SQUARE_SIZE = 10.0f;\n"
+
+		// ----------------------------------------------------------------------------\n"
+		"struct VS_OUTPUT\n"
+			"{\n"
+			"// Position\n"
+			"float4 _Position : POSITION;\n"	
+			"};\n"
+
+
+		// ----------------------------------------------------------------------------\n"
+		"VS_OUTPUT DefaultVShader(float4 INPosition : POSITION,\n"
+			"float2 INTexCoord0 : TEXCOORD0 )\n"
+			"{\n"
+			"// Initialize the output structure with zero\n"
+			"VS_OUTPUT Out = (VS_OUTPUT)0;\n"
+
+			"Out._Position = INPosition;\n"
+
+			"return Out;\n"
+			"}\n"
+
+
+		// ----------------------------------------------------------------------------\n"
+		"float4 MakePattern_PS(float2 IN : VPOS) : COLOR\n"
+		"{\n"
+		"float2 fDiv = IN / SQUARE_SIZE;\n"
+		"float3 fColor = COLOR_ONE;\n"
+		"if (0 == round(fmod(round(fDiv.x),2)))\n"
+			"{\n"
+			"if (0 == round(fmod(round(fDiv.y),2))) fColor = COLOR_TWO;\n"
+			"}\n"
+		"else if (0 != round(fmod(round(fDiv.y),2)))fColor = COLOR_TWO;\n"
+		"return float4(fColor,1.0f);"
+		"}\n"
+	
+
+		// ----------------------------------------------------------------------------\n"
+		// Shader to generate a pattern\n"
+		// ----------------------------------------------------------------------------\n"
+		"technique MakePattern\n"
 		"{\n"
 		"pass p0\n"
 		"{\n"
 		"FillMode=Solid;\n"
 		"ZEnable = FALSE;\n"
 		"CullMode = none;\n"
-		"AlphaBlendEnable = TRUE;\n"
-		"SrcBlend =srcalpha;\n"
-		"DestBlend =invsrcalpha;\n"
-		"PixelShader = compile ps_2_0 PassThrough_PS();\n"
-		"VertexShader = compile vs_2_0 DefaultVShader();\n"
+		"PixelShader = compile ps_3_0 MakePattern_PS();\n"
+		"VertexShader = compile vs_3_0 DefaultVShader();\n"
 		"}\n"
 		"};\n"
 		);

+ 3 - 0
tools/assimp_view/Shaders.h

@@ -26,4 +26,7 @@ extern std::string  g_szMaterialShader;
 // Shader used to draw the yellow circle on top of everything
 extern std::string  g_szPassThroughShader;
 
+// Shader used to draw the checker pattern background for the texture view
+extern std::string  g_szCheckerBackgroundShader;
+
 #endif // !! AV_SHADERS_H_INCLUDED

BIN
tools/assimp_view/assimp_view.aps


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 299 - 565
tools/assimp_view/assimp_view.cpp


+ 17 - 37
tools/assimp_view/assimp_view.h

@@ -58,6 +58,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "IOStream.h"
 #include "assimp.h"
 #include "assimp.hpp"
+#include "LogStream.h"
+#include "DefaultLogger.h"
+#include "MaterialSystem.h"
 
 // in order for std::min and std::max to behave properly
 #ifdef min 
@@ -79,6 +82,9 @@ namespace AssimpView {
 #include "Background.h"
 #include "LogDisplay.h"
 #include "LogWindow.h"
+#include "Display.h"
+#include "MeshRenderer.h"
+#include "MaterialManager.h"
 
 //-------------------------------------------------------------------------------
 // Function prototypes
@@ -87,15 +93,15 @@ namespace AssimpView {
 	int ShutdownD3D(void);
 	int CreateDevice (bool p_bMultiSample,bool p_bSuperSample, bool bHW = true);
 	int CreateDevice (void);
-	int Render (void);
 	int ShutdownDevice(void);
 	int GetProjectionMatrix (aiMatrix4x4& p_mOut);
 	int LoadAsset(void);
 	int CreateAssetData(void);
-	int DeleteAssetData(void);
+	int DeleteAssetData(bool bNoMaterials = false);
 	int ScaleAsset(void);
 	int DeleteAsset(void);
 	int SetupFPSView();
+	
 	aiVector3D GetCameraMatrix (aiMatrix4x4& p_mOut);
 	int CreateMaterial(AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSource);
 
@@ -105,6 +111,8 @@ namespace AssimpView {
 	void HandleKeyboardInputFPS( void );
 	void HandleMouseInputLightIntensityAndColor( void );
 	void HandleMouseInputSkyBox( void );
+	void HandleKeyboardInputTextureView( void );
+	void HandleMouseInputTextureView( void );
 
 
 //-------------------------------------------------------------------------------
@@ -143,32 +151,6 @@ INT_PTR CALLBACK HelpDialogProc(HWND hwndDlg,UINT uMsg,
 	WPARAM wParam,LPARAM lParam);
 
 
-//-------------------------------------------------------------------------------
-// find a valid path to a texture file
-//
-// Handle 8.3 syntax correctly, search the environment of the
-// executable and the asset for a texture with a name very similar to a given one
-//-------------------------------------------------------------------------------
-int FindValidPath(aiString* p_szString);
-
-
-//-------------------------------------------------------------------------------
-// Delete all resources of a given material
-//
-// Must be called before CreateMaterial() to prevent memory leaking
-//-------------------------------------------------------------------------------
-void DeleteMaterial(AssetHelper::MeshHelper* pcIn);
-
-
-//-------------------------------------------------------------------------------
-// Recreate all specular materials depending on the current specularity settings
-//
-// Diffuse-only materials are ignored.
-// Must be called after specular highlights have been toggled
-//-------------------------------------------------------------------------------
-void UpdateSpecularMaterials();
-
-
 //-------------------------------------------------------------------------------
 // Handle command line parameters
 //
@@ -209,6 +191,7 @@ enum EClickPos
 	extern ID3DXEffect* g_piDefaultEffect		/*= NULL*/;
 	extern ID3DXEffect* g_piNormalsEffect		/*= NULL*/;
 	extern ID3DXEffect* g_piPassThroughEffect	/*= NULL*/;
+	extern ID3DXEffect* g_piPatternEffect		/*= NULL*/;
 	extern bool g_bMousePressed					/*= false*/;
 	extern bool g_bMousePressedR				/*= false*/;
 	extern bool g_bMousePressedM				/*= false*/;
@@ -237,8 +220,13 @@ enum EClickPos
 	extern EClickPos g_eClick;
 	extern unsigned int g_iCurrentColor			/*= 0*/;
 
+	// NOTE: The light intensity is separated from the color, it can
+	// directly be manipulated using the middle mouse button.
+	// When the user chooses a color from the palette the intensity
+	// is reset to 1.0
+	// index[2] is the ambient color
 	extern float g_fLightIntensity				/*=0.0f*/;
-	extern float g_fLightColor					/*=0.0f*/;
+	extern D3DCOLOR g_avLightColors[3];
 
 	extern RenderOptions g_sOptions;
 	extern Camera g_sCamera;
@@ -253,14 +241,6 @@ enum EClickPos
 	// HUD texture
 	//
 	extern unsigned char* g_szImageMask			/*= NULL*/;
-
-	
-	//
-	// Specifies the number of different shaders generated for
-	// the current asset. This number is incremented by CreateMaterial()
-	// each time a shader isn't found in cache and needs to be created
-	//
-	extern unsigned int g_iShaderCount			/* = 0 */;
 	};
 
 #endif // !! AV_MAIN_H_INCLUDED

+ 99 - 34
tools/assimp_view/assimp_view.rc

@@ -57,6 +57,7 @@ END
 
 IDD_DIALOGMAIN DIALOGEX 0, 0, 594, 384
 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_ACCEPTFILES
 CAPTION "Free Asset Import Library - ModelViewer "
 MENU IDR_MENU1
 FONT 8, "MS Shell Dlg", 400, 0, 0x1
@@ -65,59 +66,63 @@ BEGIN
     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         "Disable Materials",IDC_TOGGLEMAT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,193,69,10
-    LTEXT           "Verts:",IDC_NUMVERTS,475,15,47,8
-    LTEXT           "Faces:\t",IDC_NUMFACES,475,27,45,8
-    LTEXT           "Mats:",IDC_NUMMATS,540,27,26,8
-    LTEXT           "FPS:",IDC_FPS,475,65,21,8
+    LTEXT           "Verts:",IDC_NUMVERTS,475,14,47,8
+    LTEXT           "Faces:\t",IDC_NUMFACES,475,26,45,8
+    LTEXT           "Mats:",IDC_NUMMATS,540,26,26,8
+    LTEXT           "FPS:",IDC_FPS,540,51,21,8
     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         130,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,0,360,600,25
-    EDITTEXT        IDC_EVERT,504,12,32,12,ES_AUTOHSCROLL | ES_READONLY
-    EDITTEXT        IDC_EFACE,504,25,32,12,ES_AUTOHSCROLL | ES_READONLY
-    EDITTEXT        IDC_EMAT,564,25,27,12,ES_AUTOHSCROLL | ES_READONLY
-    EDITTEXT        IDC_EFPS,504,63,32,12,ES_AUTOHSCROLL | ES_READONLY
+    CONTROL         130,IDC_STATIC,"Static",SS_BITMAP,0,360,600,25
+    EDITTEXT        IDC_EVERT,504,11,32,12,ES_AUTOHSCROLL | ES_READONLY
+    EDITTEXT        IDC_EFACE,504,24,32,12,ES_AUTOHSCROLL | ES_READONLY
+    EDITTEXT        IDC_EMAT,564,24,27,12,ES_AUTOHSCROLL | ES_READONLY
+    EDITTEXT        IDC_EFPS,564,50,27,12,ES_AUTOHSCROLL | ES_READONLY
     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
-    LTEXT           "Time:",IDC_LOADTIME,475,76,46,8
-    EDITTEXT        IDC_ELOAD,504,75,32,12,ES_AUTOHSCROLL | ES_READONLY
-    CONTROL         "Zoom/Rotate",IDC_ZOOM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,266,58,10
+    LTEXT           "Time:",IDC_LOADTIME,475,51,46,8
+    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         "Low quality lighting",IDC_LOWQUALITY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,223,74,10
     CONTROL         "No specular lighting",IDC_NOSPECULAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,233,74,10
     CONTROL         "Play [OK]",IDC_PLAYANIM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,480,297,42,10
     CONTROL         "",IDC_SPEED,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | TBS_TOOLTIPS | WS_TABSTOP,480,309,90,12
     LTEXT           "Speed: [+/-]",IDC_SSPEED,526,297,42,8
-    LTEXT           "Shd:",IDC_NUMMATS2,476,41,23,8
-    EDITTEXT        IDC_ESHADER,504,39,32,12,ES_AUTOHSCROLL | ES_READONLY
-    LTEXT           "[M]",IDC_STATIC,570,173,11,8
-    LTEXT           "[W]",IDC_STATIC,570,183,11,8
-    LTEXT           "[D]",IDC_STATIC,570,193,11,8
-    LTEXT           "[N]",IDC_STATIC,570,203,11,8
-    LTEXT           "[L]",IDC_STATIC,570,213,11,8
-    LTEXT           "[P]",IDC_STATIC,570,223,11,8
-    LTEXT           "[S]",IDC_STATIC,570,233,11,8
-    LTEXT           "[A]",IDC_STATIC,569,257,11,8
-    LTEXT           "[Z]",IDC_STATIC,569,267,11,8
-    LTEXT           "[R]",IDC_STATIC,569,276,11,8
+    LTEXT           "Shd:",IDC_NUMSHADERS,476,40,23,8
+    EDITTEXT        IDC_ESHADER,504,37,32,12,ES_AUTOHSCROLL | ES_READONLY
+    LTEXT           "[M]",IDC_STATIC,553,173,11,8
+    LTEXT           "[W]",IDC_STATIC,553,183,11,8
+    LTEXT           "[D]",IDC_STATIC,553,193,11,8
+    LTEXT           "[N]",IDC_STATIC,553,203,11,8
+    LTEXT           "[L]",IDC_STATIC,553,213,11,8
+    LTEXT           "[P]",IDC_STATIC,553,223,11,8
+    LTEXT           "[S]",IDC_STATIC,553,233,11,8
+    LTEXT           "[A]",IDC_STATIC,552,257,11,8
+    LTEXT           "[Z]",IDC_STATIC,552,267,11,8
+    LTEXT           "[R]",IDC_STATIC,552,276,11,8
     COMBOBOX        IDC_COMBO1,480,331,90,30,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP
     LTEXT           "Anim: [Pg up/Pg down]",IDC_SANIM,483,320,74,8
-    CONTROL         "Play all in order [O]",IDC_PINORDER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,479,346,77,10
     CONTROL         149,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,470,0,114,9
     CONTROL         148,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,470,161,114,9
     CONTROL         147,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,470,245,114,9
     CONTROL         145,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,470,287,114,9
-    CONTROL         146,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,470,89,114,9
+    CONTROL         146,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,470,65,114,9
     CONTROL         "",IDC_STATIC,"Static",SS_ETCHEDVERT,469,0,1,360
     CONTROL         "<<",IDC_BLUBB,"Button",BS_AUTOCHECKBOX | BS_PUSHLIKE | WS_TABSTOP,439,367,27,10
     CONTROL         149,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,584,0,10,9
-    CONTROL         149,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,584,89,10,9
+    CONTROL         149,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,584,65,10,9
     CONTROL         149,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,583,161,10,9
     CONTROL         149,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,584,245,10,9
     CONTROL         149,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,584,287,10,9
-    LTEXT           "Nodes:",IDC_STATIC,540,14,24,8
-    EDITTEXT        IDC_ENODE,564,12,27,12,ES_AUTOHSCROLL | ES_READONLY
-    CONTROL         "",IDC_TREE1,"SysTreeView32",TVS_HASBUTTONS | TVS_HASLINES | WS_BORDER | WS_TABSTOP,470,98,123,64
-    LTEXT           "Tex:",IDC_STATIC,476,53,16,8
-    EDITTEXT        IDC_ETEX,504,51,32,12,ES_AUTOHSCROLL | ES_READONLY
+    LTEXT           "Nodes:",IDC_NUMNODES,540,13,24,8
+    EDITTEXT        IDC_ENODEWND,564,11,27,12,ES_AUTOHSCROLL | ES_READONLY
+    CONTROL         "",IDC_TREE1,"SysTreeView32",TVS_HASBUTTONS | TVS_HASLINES | TVS_SHOWSELALWAYS | WS_BORDER | WS_TABSTOP,470,74,123,88
+    LTEXT           "Mesh:",IDC_NUMMESHES,540,39,20,8
+    EDITTEXT        IDC_EMESH,564,37,27,12,ES_AUTOHSCROLL | ES_READONLY
+    CONTROL         "",IDC_STATIC,"Static",SS_ETCHEDVERT,567,170,1,75
+    CONTROL         "Button1",IDC_LCOLOR1,"Button",BS_OWNERDRAW | WS_TABSTOP,570,174,21,17
+    CONTROL         "Button1",IDC_LCOLOR2,"Button",BS_OWNERDRAW | WS_TABSTOP,570,194,21,17
+    CONTROL         "Button1",IDC_LCOLOR3,"Button",BS_OWNERDRAW | WS_TABSTOP,570,214,21,17
+    PUSHBUTTON      "R",IDC_LRESET,576,232,15,11,BS_BOTTOM
 END
 
 IDD_LOADDIALOG DIALOGEX 0, 0, 278, 99
@@ -146,7 +151,7 @@ EXSTYLE WS_EX_TOPMOST | WS_EX_WINDOWEDGE
 CAPTION "AssimpView Log Output"
 FONT 8, "Courier New", 400, 0, 0x0
 BEGIN
-    EDITTEXT        IDC_EDIT1,0,0,365,181,ES_MULTILINE | ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL
+    CONTROL         "",IDC_EDIT1,"RichEdit20A",ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER | WS_VSCROLL | WS_TABSTOP,3,4,358,174,WS_EX_STATICEDGE
 END
 
 
@@ -272,6 +277,7 @@ IDB_BTX                 BITMAP                  "tx.bmp"
 IDB_BFX                 BITMAP                  "fx.bmp"
 IDB_BNODE               BITMAP                  "n.bmp"
 IDB_BROOT               BITMAP                  "root.bmp"
+IDB_BTXI                BITMAP                  "txi.bmp"
 
 /////////////////////////////////////////////////////////////////////////////
 //
@@ -287,9 +293,13 @@ BEGIN
         MENUITEM SEPARATOR
         MENUITEM "Screenshot",                  ID_VIEWER_SAVESCREENSHOTTOFILE
         MENUITEM "Reset view",                  ID_VIEWER_RESETVIEW
+        MENUITEM "Memory consumption",          ID_VIEWER_MEMORYCONSUMATION
         MENUITEM SEPARATOR
         MENUITEM "Setup file associations",     ID_VIEWER_H
         MENUITEM SEPARATOR
+        MENUITEM "Recent files ",               ID_VIEWER_RECENTFILES
+        MENUITEM "Clear history",               ID_VIEWER_CLEARHISTORY
+        MENUITEM SEPARATOR
         MENUITEM "Quit",                        ID_VIEWER_QUIT
     END
     POPUP "Tools"
@@ -297,6 +307,14 @@ BEGIN
         MENUITEM "Log window",                  ID_TOOLS_LOGWINDOW
         MENUITEM "Save log to file",            ID_TOOLS_SAVELOGTOFILE
         MENUITEM "Clear log",                   ID_TOOLS_CLEARLOG
+        MENUITEM SEPARATOR
+        MENUITEM "Original normals",            ID_TOOLS_ORIGINALNORMALS, CHECKED
+        MENUITEM "Smooth normals",              ID_TOOLS_SMOOTHNORMALS
+        MENUITEM "Hard normals",                ID_TOOLS_HARDNORMALS
+        MENUITEM SEPARATOR
+        MENUITEM "Flip normals",                ID_TOOLS_FLIPNORMALS
+        MENUITEM SEPARATOR
+        MENUITEM "Stereo view",                 ID_TOOLS_STEREOVIEW
     END
     POPUP "Background"
     BEGIN
@@ -308,9 +326,56 @@ BEGIN
     END
     POPUP "?"
     BEGIN
-        MENUITEM "About",                       ID__ABOUT
+        POPUP "Feedback"
+        BEGIN
+            MENUITEM "Report bug",                  ID_FEEDBACK_GH
+            MENUITEM "Feature request",             ID_FEEDBACK_FEATUREREQUEST
+        END
         MENUITEM "Help",                        ID__HELP
+        MENUITEM SEPARATOR
+        MENUITEM "About",                       ID__ABOUT
+    END
+END
+
+IDR_TXPOPUP MENU 
+BEGIN
+    POPUP "Hey"
+    BEGIN
+        MENUITEM "Replace texture",             ID_HEY_REPLACE
+        MENUITEM "Export texture",              ID_HEY_EXPORT
+        MENUITEM "Remove texture",              ID_HEY_REMOVE
+        MENUITEM SEPARATOR
+        MENUITEM "Reset texture",               ID_HEY_RESETTEXTURE
+    END
+    MENUITEM "This is not an easter egg",   0
+END
+
+IDR_MATPOPUP MENU 
+BEGIN
+    POPUP "So long"
+    BEGIN
+        MENUITEM "Add diffuse texture",         ID_SOLONG_ADDDIFFUSETEXTURE
+        MENUITEM "Add specular texture",        ID_SOLONG_ADDSPECULARTEXTURE
+        MENUITEM "Add ambient texture",         ID_SOLONG_ADDAMBIENTTEXTURE
+        MENUITEM "Add emissive texture",        ID_SOLONG_ADDEMISSIVETEXTURE
+        MENUITEM "Add opacity texture",         ID_SOLONG_ADDOPACITYTEXTURE
+        MENUITEM "Add normal/height texture",   ID_SOLONG_ADDNORMAL
+        MENUITEM "Add shininess texture",       ID_SOLONG_ADDSHININESSTEXTURE
+        MENUITEM SEPARATOR
+        MENUITEM "Set diffuse color",           ID_SOLONG_CLEARDIFFUSECOLOR
+        MENUITEM "Set specular color",          ID_SOLONG_CLEARSPECULARCOLOR
+        MENUITEM "Set ambient color",           ID_SOLONG_CLEARAMBIENTCOLOR
+        MENUITEM "Set emissive color",          ID_SOLONG_CLEAREMISSIVECOLOR
+        MENUITEM "Set transparency",            ID_SOLONG_CLEARTRANSPARENCY
+        MENUITEM SEPARATOR
+        MENUITEM "Make default material",       ID_SOLONG_MAKEDEFAULTMATERIAL
+        POPUP "Set shading mode"
+        BEGIN
+            MENUITEM "Gouraud",                     ID_SETSHADINGMODE_GOURAUD
+            MENUITEM "Phong (specular)",            ID_SETSHADINGMODE_PHONG
+        END
     END
+    MENUITEM "and thanks for all the fish", 0
 END
 
 

+ 246 - 243
tools/assimp_view/help.rtf

@@ -1,26 +1,19 @@
-{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff31507\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi0\deflang1031\deflangfe1031\themelang1031\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f2\fbidi \fmodern\fcharset0\fprq1{\*\panose 02070309020205020404}Courier New;}
-{\f3\fbidi \froman\fcharset2\fprq2{\*\panose 05050102010706020507}Symbol;}{\f10\fbidi \fnil\fcharset2\fprq2{\*\panose 05000000000000000000}Wingdings;}{\f34\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;}
-{\f38\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0604030504040204}Tahoma;}{\f39\fbidi \fswiss\fcharset0\fprq2{\*\panose 00000000000000000000}MS Reference Sans Serif;}
-{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
-{\fhimajor\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;}{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
-{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
-{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f41\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
-{\f42\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f44\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f45\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f46\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
-{\f47\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f48\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f49\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f61\fbidi \fmodern\fcharset238\fprq1 Courier New CE;}
-{\f62\fbidi \fmodern\fcharset204\fprq1 Courier New Cyr;}{\f64\fbidi \fmodern\fcharset161\fprq1 Courier New Greek;}{\f65\fbidi \fmodern\fcharset162\fprq1 Courier New Tur;}{\f66\fbidi \fmodern\fcharset177\fprq1 Courier New (Hebrew);}
-{\f67\fbidi \fmodern\fcharset178\fprq1 Courier New (Arabic);}{\f68\fbidi \fmodern\fcharset186\fprq1 Courier New Baltic;}{\f69\fbidi \fmodern\fcharset163\fprq1 Courier New (Vietnamese);}{\f381\fbidi \froman\fcharset238\fprq2 Cambria Math CE;}
-{\f382\fbidi \froman\fcharset204\fprq2 Cambria Math Cyr;}{\f384\fbidi \froman\fcharset161\fprq2 Cambria Math Greek;}{\f385\fbidi \froman\fcharset162\fprq2 Cambria Math Tur;}{\f388\fbidi \froman\fcharset186\fprq2 Cambria Math Baltic;}
-{\f421\fbidi \fswiss\fcharset238\fprq2 Tahoma CE;}{\f422\fbidi \fswiss\fcharset204\fprq2 Tahoma Cyr;}{\f424\fbidi \fswiss\fcharset161\fprq2 Tahoma Greek;}{\f425\fbidi \fswiss\fcharset162\fprq2 Tahoma Tur;}
-{\f426\fbidi \fswiss\fcharset177\fprq2 Tahoma (Hebrew);}{\f427\fbidi \fswiss\fcharset178\fprq2 Tahoma (Arabic);}{\f428\fbidi \fswiss\fcharset186\fprq2 Tahoma Baltic;}{\f429\fbidi \fswiss\fcharset163\fprq2 Tahoma (Vietnamese);}
-{\f430\fbidi \fswiss\fcharset222\fprq2 Tahoma (Thai);}{\f431\fbidi \fswiss\fcharset238\fprq2 MS Reference Sans Serif CE;}{\f432\fbidi \fswiss\fcharset204\fprq2 MS Reference Sans Serif Cyr;}
-{\f434\fbidi \fswiss\fcharset161\fprq2 MS Reference Sans Serif Greek;}{\f435\fbidi \fswiss\fcharset162\fprq2 MS Reference Sans Serif Tur;}{\f438\fbidi \fswiss\fcharset186\fprq2 MS Reference Sans Serif Baltic;}
-{\f439\fbidi \fswiss\fcharset163\fprq2 MS Reference Sans Serif (Vietnamese);}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
-{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
-{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
-{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}
-{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
-{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhimajor\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}
-{\fhimajor\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\fhimajor\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\fhimajor\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;}
+{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff31507\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi31507\deflang1031\deflangfe1031\themelang1031\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f34\fbidi \froman\fcharset1\fprq2{\*\panose 02040503050406030204}Cambria Math;}
+{\f39\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0604030504040204}MS Reference Sans Serif;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
+{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;}
+{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
+{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}
+{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f40\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f41\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
+{\f43\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f44\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f45\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f46\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
+{\f47\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f48\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f430\fbidi \fswiss\fcharset238\fprq2 MS Reference Sans Serif CE;}
+{\f431\fbidi \fswiss\fcharset204\fprq2 MS Reference Sans Serif Cyr;}{\f433\fbidi \fswiss\fcharset161\fprq2 MS Reference Sans Serif Greek;}{\f434\fbidi \fswiss\fcharset162\fprq2 MS Reference Sans Serif Tur;}
+{\f437\fbidi \fswiss\fcharset186\fprq2 MS Reference Sans Serif Baltic;}{\f438\fbidi \fswiss\fcharset163\fprq2 MS Reference Sans Serif (Vietnamese);}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
+{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
+{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
+{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
+{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
+{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
+{\fhimajor\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\fhimajor\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\fhimajor\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\fhimajor\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;}
 {\fhimajor\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
 {\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
 {\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
@@ -37,227 +30,237 @@
 \red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;
 \red192\green192\blue192;}{\*\defchp \fs22\loch\af31506\hich\af31506\dbch\af31505 }{\*\defpap \ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{
 \ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1031\langfe1031\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 
-\snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \sunhideused \spriority1 Default Paragraph Font;}{\*
+\snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\*
 \ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tscellwidthfts0\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa200\sl276\slmult1
-\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1031\langfe1031\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 
-\snext11 \ssemihidden \sunhideused \sqformat Normal Table;}{\s15\ql \li720\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin720\itap0\contextualspace \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 
-\fs22\lang1031\langfe1031\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 \sbasedon0 \snext15 \sqformat \spriority34 \styrsid3683098 List Paragraph;}{
-\s16\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af38\afs16\alang1025 \ltrch\fcs0 \fs16\lang1031\langfe1031\loch\f38\hich\af38\dbch\af31505\cgrid\langnp1031\langfenp1031 
-\sbasedon0 \snext16 \slink17 \ssemihidden \sunhideused \styrsid8273515 Balloon Text;}{\*\cs17 \additive \rtlch\fcs1 \af38\afs16 \ltrch\fcs0 \f38\fs16 \sbasedon10 \slink16 \slocked \ssemihidden \styrsid8273515 Balloon Text Char;}}{\*\listtable
-{\list\listtemplateid-2111801688\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid1242219378\'01-;}{\levelnumbers;}
-\loch\af39\hich\af39\dbch\af31505\fbias0\hres0\chhres0 \fi-360\li700\lin700 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}
-\f2\fbias0\hres0\chhres0 \fi-360\li1420\lin1420 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}
-\f10\fbias0\hres0\chhres0 \fi-360\li2140\lin2140 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}
-\f3\fbias0\hres0\chhres0 \fi-360\li2860\lin2860 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0\hres0\chhres0 
-\fi-360\li3580\lin3580 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0\hres0\chhres0 
-\fi-360\li4300\lin4300 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0\hres0\chhres0 
-\fi-360\li5020\lin5020 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0\hres0\chhres0 \fi-360\li5740\lin5740 }
-{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0\hres0\chhres0 \fi-360\li6460\lin6460 }{\listname 
-;}\listid256792316}{\list\listtemplateid1110873036\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat0\levelspace0\levelindent0{\leveltext\leveltemplateid680798618\'01-;}{\levelnumbers;}
-\fs20\loch\af39\hich\af39\dbch\af31505\fbias0\hres0\chhres0 \fi-360\li700\lin700 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567619
-\'01o;}{\levelnumbers;}\f2\fbias0\hres0\chhres0 \fi-360\li1420\lin1420 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers
-;}\f10\fbias0\hres0\chhres0 \fi-360\li2140\lin2140 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}
-\f3\fbias0\hres0\chhres0 \fi-360\li2860\lin2860 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0\hres0\chhres0 
-\fi-360\li3580\lin3580 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0\hres0\chhres0 
-\fi-360\li4300\lin4300 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0\hres0\chhres0 
-\fi-360\li5020\lin5020 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0\hres0\chhres0 \fi-360\li5740\lin5740 }
-{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0\hres0\chhres0 \fi-360\li6460\lin6460 }{\listname 
-;}\listid483863136}{\list\listtemplateid338825902\listhybrid{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid-1769051580\'02\'00);}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \fbias0\hres0\chhres0 \fi-360\li700\lin700 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567641\'02\'01.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-360\li1420\lin1420 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567643\'02\'02.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-180\li2140\lin2140 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567631\'02\'03.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-360\li2860\lin2860 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567641\'02\'04.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-360\li3580\lin3580 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567643\'02\'05.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-180\li4300\lin4300 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567631\'02\'06.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-360\li5020\lin5020 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567641\'02\'07.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-360\li5740\lin5740 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567643\'02\'08.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-180\li6460\lin6460 }{\listname ;}\listid649408911}{\list\listtemplateid-371049066\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat0\levelspace360\levelindent0{\leveltext
-\leveltemplateid680798618\'01-;}{\levelnumbers;}\fs20\loch\af39\hich\af39\dbch\af31505\fbias0\hres0\chhres0 \fi-360\li720\lin720 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0
-{\leveltext\leveltemplateid67567641\'02\'01.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-360\li1440\lin1440 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0
-{\leveltext\leveltemplateid67567643\'02\'02.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-180\li2160\lin2160 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0
-{\leveltext\leveltemplateid67567631\'02\'03.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-360\li2880\lin2880 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0
-{\leveltext\leveltemplateid67567641\'02\'04.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-360\li3600\lin3600 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0
-{\leveltext\leveltemplateid67567643\'02\'05.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-180\li4320\lin4320 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0
-{\leveltext\leveltemplateid67567631\'02\'06.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-360\li5040\lin5040 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0
-{\leveltext\leveltemplateid67567641\'02\'07.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-360\li5760\lin5760 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0
-{\leveltext\leveltemplateid67567643\'02\'08.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-180\li6480\lin6480 }{\listname ;}\listid780539952}{\list\listtemplateid1158591540\listhybrid{\listlevel\levelnfc1\levelnfcn1\leveljc2
-\leveljcn2\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567635\'02\'00.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fbias0\hres0\chhres0 \fi-360\li1440\lin1440 }{\listlevel\levelnfc4\levelnfcn4\leveljc0
-\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567641\'02\'01.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-360\li2160\lin2160 }{\listlevel\levelnfc2\levelnfcn2\leveljc2
-\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567643\'02\'02.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-180\li2880\lin2880 }{\listlevel\levelnfc0\levelnfcn0\leveljc0
-\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567631\'02\'03.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-360\li3600\lin3600 }{\listlevel\levelnfc4\levelnfcn4\leveljc0
-\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567641\'02\'04.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-360\li4320\lin4320 }{\listlevel\levelnfc2\levelnfcn2\leveljc2
-\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567643\'02\'05.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-180\li5040\lin5040 }{\listlevel\levelnfc0\levelnfcn0\leveljc0
-\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567631\'02\'06.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-360\li5760\lin5760 }{\listlevel\levelnfc4\levelnfcn4\leveljc0
-\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567641\'02\'07.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-360\li6480\lin6480 }{\listlevel\levelnfc2\levelnfcn2\leveljc2
-\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567643\'02\'08.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-180\li7200\lin7200 }{\listname ;}\listid823008862}
-{\list\listtemplateid1985747632\listhybrid{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid-1722268864\'02\'00);}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 
-\fbias0\hres0\chhres0 \fi-720\li1080\lin1080 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567641\'02\'01.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-360\li1440\lin1440 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567643\'02\'02.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-180\li2160\lin2160 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567631\'02\'03.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-360\li2880\lin2880 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567641\'02\'04.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-360\li3600\lin3600 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567643\'02\'05.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-180\li4320\lin4320 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567631\'02\'06.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-360\li5040\lin5040 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567641\'02\'07.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-360\li5760\lin5760 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567643\'02\'08.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-180\li6480\lin6480 }{\listname ;}\listid1527327967}}{\*\listoverridetable{\listoverride\listid1527327967\listoverridecount0\ls1}{\listoverride\listid823008862\listoverridecount0\ls2}{\listoverride\listid256792316
-\listoverridecount0\ls3}{\listoverride\listid483863136\listoverridecount0\ls4}{\listoverride\listid649408911\listoverridecount0\ls5}{\listoverride\listid780539952\listoverridecount0\ls6}}{\*\rsidtbl \rsid67262\rsid74094\rsid602054\rsid1405492\rsid2175529
-\rsid2186087\rsid2961835\rsid3277197\rsid3683098\rsid5404161\rsid5460125\rsid5513066\rsid5860386\rsid7360491\rsid7429996\rsid7677524\rsid8273515\rsid8350123\rsid8745149\rsid9194405\rsid9529660\rsid9575707\rsid9635109\rsid9712802\rsid10617294\rsid10752424
-\rsid10762577\rsid11029790\rsid11880680\rsid12914594\rsid14115297\rsid14187505\rsid14293319}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\author Alexander Gessler}
-{\operator Alexander Gessler}{\creatim\yr2008\mo4\dy12\hr23\min23}{\revtim\yr2008\mo4\dy13\hr18\min11}{\version32}{\edmins0}{\nofpages2}{\nofwords446}{\nofchars2811}{\*\company UtopicTechnologies}{\nofcharsws3251}{\vern32893}}{\*\xmlnstbl {\xmlns1 http://
-schemas.microsoft.com/office/word/2003/wordml}}\paperw11906\paperh16838\margl1417\margr1417\margt1417\margb1134\gutter0\ltrsect 
-\deftab708\widowctrl\ftnbj\aenddoc\hyphhotz425\trackmoves1\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0
-\showxmlerrors1\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin1417\dgvorigin1417\dghshow1\dgvshow1
-\jexpand\viewkind1\viewscale100\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel\wrppunct
-\asianbrkrule\rsidroot3683098\newtblstyruls\nogrowautofit\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal \nouicompat \fet0
-{\*\wgrffmtfilter 2450}\nofeaturethrottle1\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\headery708\footery708\colsx708\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2
-\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6
-\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang 
-{\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 
-\fs22\lang1031\langfe1031\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 {\rtlch\fcs1 \af0\afs32 \ltrch\fcs0 \b\f39\fs32\lang1033\langfe1031\langnp1033\insrsid3683098\charrsid3683098 \hich\af39\dbch\af31505\loch\f39 
-ASSIMP Viewer Utility}{\rtlch\fcs1 \af0\afs32 \ltrch\fcs0 \b\f39\fs32\lang1033\langfe1031\langnp1033\insrsid10617294 \hich\af39\dbch\af31505\loch\f39  }{\rtlch\fcs1 \af0\afs32 \ltrch\fcs0 \b\f39\fs32\lang1033\langfe1031\langnp1033\insrsid11029790 
-\par }{\rtlch\fcs1 \af0\afs16 \ltrch\fcs0 \b\f39\fs16\lang1033\langfe1031\langnp1033\insrsid10617294 \hich\af39\dbch\af31505\loch\f39 Document version 1.0, April 2008}{\rtlch\fcs1 \af0\afs16 \ltrch\fcs0 
-\b\f39\fs16\lang1033\langfe1031\langnp1033\insrsid10617294\charrsid10617294 
-\par }{\rtlch\fcs1 \af0\afs32 \ltrch\fcs0 \b\f39\fs32\lang1033\langfe1031\langnp1033\insrsid12914594 
-\par {\listtext\pard\plain\ltrpar \s15 \rtlch\fcs1 \af0 \ltrch\fcs0 \f39\lang1033\langfe1031\langnp1033\insrsid12914594 \hich\af39\dbch\af31505\loch\f39 I.\tab}}\pard\plain \ltrpar\s15\ql \fi-360\li340\ri0\sa200\sl276\slmult1
-\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls2\adjustright\rin0\lin340\itap0\pararsid3683098\contextualspace \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 
-\fs22\lang1031\langfe1031\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid12914594 \hich\af39\dbch\af31505\loch\f39 Usage}{\rtlch\fcs1 \af0\afs20 
-\ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid12914594\charrsid12914594 \hich\af39\dbch\af31505\loch\f39  }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid12914594\charrsid12914594 
-\par }\pard \ltrpar\s15\ql \li340\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin340\itap0\pararsid12914594\contextualspace {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid12914594\charrsid3683098 \hich\af39\dbch\af31505\loch\f39 The }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid12914594 \hich\af39\dbch\af31505\loch\f39 ASSIMP Viewer 
-\hich\af39\dbch\af31505\loch\f39 Utility is a small and fast stand-alone viewer utility which is using the ASSIMP library to import assets from files. It consists of a si}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid9575707 \hich\af39\dbch\af31505\loch\f39 ngle executable file and has no}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid12914594 \hich\af39\dbch\af31505\loch\f39 
- external dependencies.}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9529660 \hich\af39\dbch\af31505\loch\f39  It will display assets with complex materials and animations correctly.}{\rtlch\fcs1 \af0\afs20 
-\ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid12914594 
-\par }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9575707 
-\par }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \b\f39\fs20\lang1033\langfe1031\langnp1033\insrsid12914594\charrsid12914594 \hich\af39\dbch\af31505\loch\f39 System requirements}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid12914594 \hich\af39\dbch\af31505\loch\f39 :
-\par {\listtext\pard\plain\ltrpar \s15 \rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5860386 \hich\af39\dbch\af31505\loch\f39 -\tab}}\pard \ltrpar\s15\ql \fi-360\li700\ri0\sa200\sl276\slmult1
-\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls4\adjustright\rin0\lin700\itap0\pararsid5860386\contextualspace {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5860386 \hich\af39\dbch\af31505\loch\f39 
-A Direct3D 9.0c compliant video card with at least support for Shader Model 2.0.}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid5860386\charrsid9575707 
-\par {\listtext\pard\plain\ltrpar \s15 \rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9575707 \hich\af39\dbch\af31505\loch\f39 -\tab}}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid9575707 \hich\af39\dbch\af31505\loch\f39 Shader Model 3.0 cards are recommended}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid9575707\charrsid5860386 
-\par {\listtext\pard\plain\ltrpar \s15 \rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5860386 \hich\af39\dbch\af31505\loch\f39 -\tab}}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5860386 \hich\af39\dbch\af31505\loch\f39 Windows 2000 or higher}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid5860386\charrsid5860386 
-\par }\pard \ltrpar\s15\ql \li340\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin340\itap0\pararsid12914594\contextualspace {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
-\f39\fs24\lang1033\langfe1031\langnp1033\insrsid3683098\charrsid3683098 \hich\af39\dbch\af31505\loch\f39  }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid3683098 
-\par {\listtext\pard\plain\ltrpar \s15 \rtlch\fcs1 \af0 \ltrch\fcs0 \f39\lang1033\langfe1031\langnp1033\insrsid5460125 \hich\af39\dbch\af31505\loch\f39 II.\tab}}\pard \ltrpar\s15\ql \fi-360\li340\ri0\sa200\sl276\slmult1
-\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls2\adjustright\rin0\lin340\itap0\pararsid3683098\contextualspace {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid5460125 \hich\af39\dbch\af31505\loch\f39 User i
-\hich\af39\dbch\af31505\loch\f39 nterface}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid12914594 
-\par }\pard \ltrpar\s15\ql \li340\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin340\itap0\pararsid9712802\contextualspace {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5460125\charrsid3683098 \hich\af39\dbch\af31505\loch\f39 The }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5460125 \hich\af39\dbch\af31505\loch\f39 viewer\hich\f39 
-\rquote \loch\f39 s user interface mainly consists}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5513066 \hich\af39\dbch\af31505\loch\f39  of three components:}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid602054 \hich\af39\dbch\af31505\loch\f39  }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5460125\charrsid9712802 
-\par }\pard\plain \ltrpar\ql \fi340\li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid2186087 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 
-\fs22\lang1031\langfe1031\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5404161 \hich\af39\dbch\af31505\loch\f39 
-The menu bar provides access to the viewer\hich\f39 \rquote \loch\f39 s basic options.}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9712802\charrsid2186087 
-\par {\listtext\pard\plain\ltrpar \s15 \rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5404161 \hich\af39\dbch\af31505\loch\f39 -\tab}}\pard\plain \ltrpar\s15\ql \fi-360\li720\ri0\sa200\sl276\slmult1
-\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls6\adjustright\rin0\lin720\itap0\pararsid5404161\contextualspace \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 
-\fs22\lang1031\langfe1031\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5404161 \loch\af39\dbch\af31505\hich\f39 \'93}{\rtlch\fcs1 \af0\afs20 
-\ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5404161\charrsid9712802 \hich\af39\dbch\af31505\loch\f39 Viewer}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5404161 \loch\af39\dbch\af31505\hich\f39 \'94
-\loch\f39 : Items to load / unload assets, take screenshots and open the viewer\hich\f39 \rquote \loch\f39 s options dialog.
-\par {\listtext\pard\plain\ltrpar \s15 \rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5404161 \hich\af39\dbch\af31505\loch\f39 -\tab}}\pard \ltrpar\s15\ql \fi-360\li720\ri0\sa200\sl276\slmult1
-\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls6\adjustright\rin0\lin720\itap0\pararsid3277197\contextualspace {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5404161 \loch\af39\dbch\af31505\hich\f39 \'93}{\rtlch\fcs1 
-\af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5404161\charrsid9712802 \hich\af39\dbch\af31505\loch\f39 Background}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5404161 
-\loch\af39\dbch\af31505\hich\f39 \'94\loch\f39 : \hich\af39\dbch\af31505\loch\f39 Set the background color or use a texture (cubemaps are supported}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid11880680 
-\hich\af39\dbch\af31505\loch\f39  as skyboxes}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5404161 \hich\af39\dbch\af31505\loch\f39 ) as background image for the viewer.}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid9194405\charrsid3277197 
-\par }\pard \ltrpar\s15\ql \li340\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin340\itap0\pararsid5460125\contextualspace {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid602054 
+\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1031\langfe1031\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 
+\snext11 \ssemihidden \sunhideused \sqformat Normal Table;}}{\*\rsidtbl \rsid3942873\rsid5053873\rsid5338181\rsid6912689\rsid7213193\rsid8068556\rsid9465848\rsid13463017}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0
+\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\operator Alexander Gessler}{\creatim\yr2008\mo5\dy13\hr12\min5}{\revtim\yr2008\mo5\dy13\hr12\min23}{\version8}{\edmins0}{\nofpages4}{\nofwords1365}{\nofchars6976}{\nofcharsws8325}{\vern32893}}
+{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}\paperw12240\paperh15840\margl1417\margr1417\margt1417\margb1134\gutter0\ltrsect 
+\deftab708\widowctrl\ftnbj\aenddoc\hyphhotz425\trackmoves1\trackformatting1\donotembedsysfont0\relyonvml0\donotembedlingdata1\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\horzdoc\dghspace120\dgvspace120
+\dghorigin1701\dgvorigin1984\dghshow0\dgvshow3\jcompress\viewkind1\viewscale91\viewzk1\rsidroot13463017 \fet0{\*\wgrffmtfilter 2450}\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang 
+{\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}
+{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9
+\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\ql \li0\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 
+\fs22\lang1031\langfe1031\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 {\rtlch\fcs1 \ab\af39\afs32 \ltrch\fcs0 \b\f39\fs32\lang1033\langfe1031\langnp1033\insrsid5338181 
+\par \hich\af39\dbch\af31505\loch\f39 ASSIMP Viewer Utility 
+\par }{\rtlch\fcs1 \ab\af39\afs16 \ltrch\fcs0 \b\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 Document version 1.0, April 2008
+\par }{\rtlch\fcs1 \ab\af39\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 
+\par }\pard \ltrpar\ql \fi-360\li340\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin340\itap0 {\rtlch\fcs1 \af39\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 I.\tab 
+\hich\af39\dbch\af31505\loch\f39 Usage\hich\af39\dbch\af31505\loch\f39  
+\par }\pard \ltrpar\qj \li340\ri850\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin850\lin340\itap0\pararsid5338181 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 
+The ASSIMP Viewer Utility is a small and fast stand-alone viewer utility which is us\hich\af39\dbch\af31505\loch\f39 
+ing the ASSIMP library to import assets from files. It consists of a single executable file and has no external dependencies. It displays assets with even highly complex materials and bone animations correctly.
+\par \hich\af39\dbch\af31505\loch\f39 AssimpView allows you to modify the textures \hich\af39\dbch\af31505\loch\f39 
+and material properties sets of your models at runtime, easy and fast per Drag&Drop. Furthermore it can visualize normals, UV sets, bounding boxes ... It allows artists and engine }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 
+\f39\fs20\lang1033\langfe1031\langnp1033\insrsid6912689 \hich\af39\dbch\af31505\loch\f39 programmers}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 
+ to work together with maximal efficiency and find the ideal mod\hich\af39\dbch\af31505\loch\f39 el format for your internal workflow.
+\par }{\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 System requirements}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 
+\hich\af39\dbch\af31505\loch\f39 :
+\par }\pard \ltrpar\qj \fi-360\li700\ri850\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin850\lin700\itap0\pararsid5338181 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 -\tab 
+\hich\af39\dbch\af31505\loch\f39 A Direct3D 9.0c compliant video card with at least support for Shader Model 2.0.}{\rtlch\fcs1 \af39\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid5338181 
+\par }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 -\tab \hich\af39\dbch\af31505\loch\f39 Shader Model 3.0 cards are recommended. Shader Model 2.0 cards always render the lighting in low-quality and hav
+\hich\af39\dbch\af31505\loch\f39 e some limitations concerning complex materials.}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39  
+\par }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 -\tab \hich\af39\dbch\af31505\loch\f39 
+Windows 2000 or higher. AssimpView should also run on older versions, with DirectX 9 installed, but this has never been tested. If you're a proud owner of such a version and AssimpView works for you, let u\hich\af39\dbch\af31505\loch\f39 s know.}{
+\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid8068556 
+\par }\pard \ltrpar\ql \li340\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin340\itap0 {\rtlch\fcs1 \af39\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39  
+\par }\pard \ltrpar\ql \fi-360\li340\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin340\itap0 {\rtlch\fcs1 \af39\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 II.\tab 
+User interface
+\par }\pard \ltrpar\ql \li340\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin340\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 The viewer\hich\f39 \rquote 
+\loch\f39 s user interface mainly consists of three components: 
+\par }\pard \ltrpar\ql \fi340\li0\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 
+The menu bar provides access to the viewer\hich\f39 \rquote \loch\f39 s basic options.
+\par }\pard \ltrpar\ql \fi-360\li720\ri850\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin850\lin720\itap0\pararsid5338181 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 -\tab }{\rtlch\fcs1 \af39\afs20 
+\ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5338181 \loch\af39\dbch\af31505\hich\f39 \'93}{\rtlch\fcs1 \ab\ai\af39\afs20 \ltrch\fcs0 \b\i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5338181 
+\hich\af39\dbch\af31505\loch\f39 Viewer}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5338181 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39 
+: Items to load / unload assets, take screenshots and open the viewer\hich\f39 \rquote \loch\f39 s options dialog.
+\par }\pard \ltrpar\qj \fi-360\li720\ri1206\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin1206\lin720\itap0\pararsid13463017 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \tab }{\rtlch\fcs1 \af39\afs16 
+\ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 * \hich\af39\dbch\af31505\loch\f39 "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 
+\hich\af39\dbch\af31505\loch\f39 Open Asset}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 
+": Displays the file system dialog where you can choose a new asset to load. Note that you can also Drag&Drop models onto the viewer panel.
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Close Asset}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 ": Closes the current asset and releases all resources associated with it. No action if no\hich\af39\dbch\af31505\loch\f39  asset is loaded.
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Screenshot}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 
+": Save a snapshot of the viewer to a file. The snapshot does only include the preview panel, the rest of the user interface is not visible. Saved screenshots have no watermarks. This is }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid6912689 \hich\af39\dbch\af31505\loch\f39 Open Source}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39  Software!
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Reset View}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 ": Reset the viewing position and direction to the default settings. This is: Camera position at 0|0|0, looking at 0|0|1.
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Memory consumption}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 ": Display a box with approximated memory statistics. Note that the total memory consumption needn'\hich\af39\dbch\af31505\loch\f39 
+t be equal to the physical memory allocated to the process (as displayed by Windows }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid6912689 \hich\af39\dbch\af31505\loch\f39 Task Manager}{\rtlch\fcs1 \af39\afs16 
+\ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 ). The memory consumption does only refer to the memory required for the asset itself, not for the rest of the viewer.
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Setup file associations}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 ": Associate al\hich\af39\dbch\af31505\loch\f39 l file formats which can be read by ASSIMP with the viewer. If you double }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid6912689 \hich\af39\dbch\af31505\loch\f39 click}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 
+ on such a file in Windows Explorer, it will be automatically opened with AssimpView.
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Recent files}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 ": Displays a popup menu with a list of recently opened assets. Simply cli\hich\af39\dbch\af31505\loch\f39 ck on one to reload it.
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Clear history}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 ": Clear the file history
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Quit}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 ": What do you think?
+\par }\pard \ltrpar\ql \fi-360\li720\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin720\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 - \tab }{\rtlch\fcs1 
+\ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5338181 \hich\af39\dbch\af31505\loch\f39 "}{\rtlch\fcs1 \ab\ai\af39\afs20 \ltrch\fcs0 \b\i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5338181 
+\hich\af39\dbch\af31505\loch\f39 Tools}{\rtlch\fcs1 \ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5338181 \hich\af39\dbch\af31505\loch\f39 "}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 
+\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5338181 \hich\af39\dbch\af31505\loch\f39 : Additional utilities like stereo view, normal type.
+\par }\pard \ltrpar\qj \fi-360\li720\ri1208\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin1208\lin720\itap0\pararsid3942873 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \tab }{\rtlch\fcs1 \af39\afs16 
+\ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 
+Log window}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 ": Displays the output window of the logger. Warnings are displayed in orange/yel\hich\af39\dbch\af31505\loch\f39 
+low, errors in red, debug messages in blue and status }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid7213193 \hich\af39\dbch\af31505\loch\f39 information}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid9465848 \hich\af39\dbch\af31505\loch\f39  messages}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39  in green.
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Save log to file}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 ": Saves the contents of the log window to a file.
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Clear log}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 " Clear the contents of the log window
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Original normals}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 ": Specifies that the original norma\hich\af39\dbch\af31505\loch\f39 
+l set from the model file is used in the preview. Normally this is the best choice, as smoothing groups etc. are handled correctly, but there are many models out there which have invalid or corrupt normal sets. However, if a model has no normal set, ASSIM
+\hich\af39\dbch\af31505\loch\f39 P\hich\af39\dbch\af31505\loch\f39  computes a smooth normal set for it. "Original normals" is in this case equivalent to "Smooth normals"
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Smooth normals}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 ": Specifies that a smoothed, per-vertex, normal set is used in the preview window.
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Hard normals}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 ": Specifies that a hard, per-face\hich\af39\dbch\af31505\loch\f39 , normal set is used
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Flip normals}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 ": Flip all normal vectors
+\par }\pard \ltrpar\qj \fi-360\li720\ri850\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin850\lin720\itap0\pararsid5338181 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 -}{\rtlch\fcs1 \af39\afs20 
+\ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5338181 \tab \loch\af39\dbch\af31505\hich\f39 \'93}{\rtlch\fcs1 \ab\ai\af39\afs20 \ltrch\fcs0 \b\i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5338181 
+\hich\af39\dbch\af31505\loch\f39 Background}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5338181 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39 : Set the background color or use a texture (}{
+\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9465848\charrsid5338181 \hich\af39\dbch\af31505\loch\f39 cube maps}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 
+\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5338181 \hich\af39\dbch\af31505\loch\f39  are supported as skyboxes) as background image for the viewer.
+\par }\pard \ltrpar\qj \fi-360\li720\ri1208\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin1208\lin720\itap0\pararsid3942873 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \tab }{\rtlch\fcs1 \af39\afs16 
+\ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 
+\hich\af39\dbch\af31505\loch\f39 Set color}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 ": Displays a color picker where you can choose 
+\hich\af39\dbch\af31505\loch\f39 a new background color for the viewer.
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Load skybox}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 ": Opens a file system dialog where you can select a skybox as background image. Accepted file formats are: *.dds, *.hdr.
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Load texture}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 ": Opens a file system dialog where you can select a texture as \hich\af39\dbch\af31505\loch\f39 
+background image. If the format of the texture doesn't fit to the proportions of the preview window, the texture will be stretched. }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid3942873 
+\par }\pard \ltrpar\qj \fi-12\li720\ri1208\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin1208\lin720\itap0\pararsid3942873 {\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 
+\hich\af39\dbch\af31505\loch\f39 Accepted file formats are: *.jpg;*.png;*.tif;*.tga;*.dds;*.hdr;*.ppm;*.bmp
+\par }\pard \ltrpar\ql \fi-360\li720\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin720\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 - "}{\rtlch\fcs1 
+\ab\af39\afs20 \ltrch\fcs0 \b\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 ?}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 ": }{
+\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \b\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Help and feedback}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 
 
-\par }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid3277197 \hich\af39\dbch\af31505\loch\f39 \hich\f39 The side panel \'93}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid3277197\charrsid3277197 \hich\af39\dbch\af31505\loch\f39 Statistics}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid3277197 \loch\af39\dbch\af31505\hich\f39 \'94
-\loch\f39  displays rendering statistics (\hich\af39\dbch\af31505\loch\f39 number of vertices loaded, number of faces, number of materials, frames per second, time required for loading).}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid602054\charrsid9194405 
-\par }\pard \ltrpar\s15\ql \li340\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin340\itap0\pararsid2186087\contextualspace {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid3277197 
-\hich\af39\dbch\af31505\loch\f39 \hich\f39 The \'93}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid3277197\charrsid3277197 \hich\af39\dbch\af31505\loch\f39 Rendering}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid3277197 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39 \hich\f39  panel provides rendering-related options, such as wireframe/normal visualization. \'93}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid3277197\charrsid3277197 \hich\af39\dbch\af31505\loch\f39 Interaction}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid3277197 \loch\af39\dbch\af31505\hich\f39 \'94
-\loch\f39  bundles all input related option\hich\af39\dbch\af31505\loch\f39 s.}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid2186087\charrsid2186087 
-\par }\pard \ltrpar\s15\ql \li340\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin340\itap0\pararsid5460125\contextualspace {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid2175529 
-\hich\af39\dbch\af31505\loch\f39 The main component is the large viewer panel where the assets are displayed. Status messages (e.g. if a texture could not be loaded) are displayed in the upper-left edge.}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid9194405\charrsid2175529 
-\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid9194405 
-\par {\listtext\pard\plain\ltrpar \s15 \rtlch\fcs1 \af0 \ltrch\fcs0 \f39\lang1033\langfe1031\langnp1033\insrsid5460125 \hich\af39\dbch\af31505\loch\f39 III.\tab}}\pard \ltrpar\s15\ql \fi-360\li340\ri0\sa200\sl276\slmult1
-\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls2\adjustright\rin0\lin340\itap0\pararsid3683098\contextualspace {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid5460125 \hich\af39\dbch\af31505\loch\f39 Input}{
-\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid5460125\charrsid3683098 
-\par }\pard \ltrpar\s15\ql \li340\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin340\itap0\pararsid9635109\contextualspace {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid3683098\charrsid3683098 \hich\af39\dbch\af31505\loch\f39 The input mode depends on the selected input }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8350123\charrsid3683098 \hich\af39\dbch\af31505\loch\f39 behavior}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid3683098\charrsid3683098 \hich\af39\dbch\af31505\loch\f39 
-\hich\f39 . If \'84}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid3683098\charrsid8350123 \hich\af39\dbch\af31505\loch\f39 Zoom/Rotate}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8350123 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid3683098\charrsid3683098 \hich\af39\dbch\af31505\loch\f39 is }{
-\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \b\f39\fs20\lang1033\langfe1031\langnp1033\insrsid3683098\charrsid8350123 \hich\af39\dbch\af31505\loch\f39 NOT}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid3683098\charrsid3683098 
-\hich\af39\dbch\af31505\loch\f39  selected the following scheme applies:}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109 
-\par }\pard \ltrpar\s15\ql \fi368\li340\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin340\itap0\pararsid9635109\contextualspace {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid9635109 \loch\af39\dbch\af31505\hich\f39 \lquote }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8745149 \hich\af39\dbch\af31505\loch\f39 Arrow up}{
-\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid9635109 \loch\af39\dbch\af31505\hich\f39 \rquote \loch\f39  }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109 
-\tab }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid9635109 \hich\af39\dbch\af31505\loch\f39 = Move forward}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109 
-\hich\af39\dbch\af31505\loch\f39 s
-\par }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid9635109 \loch\af39\dbch\af31505\hich\f39 \lquote }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid74094 \hich\af39\dbch\af31505\loch\f39 A}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8745149 \hich\af39\dbch\af31505\loch\f39 rrow left}{
-\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid74094 \loch\af39\dbch\af31505\hich\f39 \rquote }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid9635109 \hich\af39\dbch\af31505\loch\f39  }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109 \tab }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid9635109 \hich\af39\dbch\af31505\loch\f39 = Move }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109 \hich\af39\dbch\af31505\loch\f39 to the left
+\par \tab }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Feedback}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 
+\hich\af39\dbch\af31505\loch\f39 ": Opens a p\hich\af39\dbch\af31505\loch\f39 opup menu with two options:
+\par }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556 \tab }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 * "}{
+\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Report bug}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 ": Report a bug in AssimpView or in Assimp
+\par }\pard \ltrpar\qj \fi-360\li720\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin720\itap0\pararsid13463017 {\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556 \tab }{\rtlch\fcs1 \af39\afs16 
+\ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 
+\hich\af39\dbch\af31505\loch\f39 Feature request}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 ": Tell us what}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid9465848 \hich\af39\dbch\af31505\loch\f39  you'd like us to support. Any }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid13463017 
+\hich\af39\dbch\af31505\loch\f39 exotic file formats? 
+\par }\pard \ltrpar\qj \li340\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin340\itap0\pararsid13463017 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 \hich\f39 
+The side panel \'93}{\rtlch\fcs1 \ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 Statistics}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 
+\loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  displays rendering statistics. The meanings of the fi\hich\af39\dbch\af31505\loch\f39 elds change if you change between normal and texture/material mode.
+\par }\pard \ltrpar\qj \li340\ri1474\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin1474\lin340\itap0\pararsid13463017 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 
+Normal view mode:
+\par }\pard \ltrpar\qj \li340\ri1208\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin1208\lin340\itap0\pararsid5053873 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \tab }{\rtlch\fcs1 \af39\afs16 
+\ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 
+\hich\af39\dbch\af31505\loch\f39 Verts}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 ": Number of unique vertices in the asset
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 Faces}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid6912689 \hich\af39\dbch\af31505\loch\f39 ": Numb}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 
+er of faces (= triangles) in the asset
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 Nodes}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 ": Number of nodes in the scenegraph, including the root node
+\par }\pard \ltrpar\qj \fi-368\li708\ri1208\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin1208\lin708\itap0\pararsid5053873 {\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 \tab 
+\hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 Mats:}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 " Number of different materials found in the mesh. Most loaders \tab remove unreferenced materials.
+\par }\pard \ltrpar\qj \li700\ri1208\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin1208\lin700\itap0\pararsid5053873 {\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 
+\hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 Mesh}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 ": Number of }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid6912689\charrsid5053873 
+\hich\af39\dbch\af31505\loch\f39 sub meshes}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 . Each mesh has only one material \tab assigned, so thi
+\hich\af39\dbch\af31505\loch\f39 s number is in most cases equal to or higher than the \tab number of materials.
+\par \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 Shd}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 ": Number of unique shaders created}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5053873 
+\hich\af39\dbch\af31505\loch\f39  for this asset. If AssimpView }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 
+detects that two materials can be rendered using }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5053873 \hich\af39\dbch\af31505\loch\f39 the same }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid6912689 \hich\af39\dbch\af31505\loch\f39 Shader}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5053873 \hich\af39\dbch\af31505\loch\f39  code, 
+\hich\af39\dbch\af31505\loch\f39 but \hich\af39\dbch\af31505\loch\f39 with }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid6912689\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 different}{\rtlch\fcs1 \af39\afs16 
+\ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 \hich\af39\dbch\af31505\loch\f39  }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid6912689\charrsid5053873 
+\hich\af39\dbch\af31505\loch\f39 parameterizations}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 , it do}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5053873 \hich\af39\dbch\af31505\loch\f39 esn't create the }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid6912689 \hich\af39\dbch\af31505\loch\f39 Shader}{\rtlch\fcs1 
+\af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5053873 \hich\af39\dbch\af31505\loch\f39  twice. }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 
+\hich\af39\dbch\af31505\loch\f39 Most engines do so, too. 
+\par \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 Time}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 ": Time required for loading, in seco}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5053873 
+\hich\af39\dbch\af31505\loch\f39 nds. This time is the raw time }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 the process spent in Assimp loading the mod}{
+\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5053873 \hich\af39\dbch\af31505\loch\f39 el itself, it does not include }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 texture loading, }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid6912689\charrsid5053873 
+\hich\af39\dbch\af31505\loch\f39 Shader}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 \hich\af39\dbch\af31505\loch\f39  compilation ...
+\par }\pard \ltrpar\qj \li700\ri1208\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin1208\lin700\itap0\pararsid9465848 {\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 
+\hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 FPS}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 ": Current frame rate, in frames per se}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5053873 
+\hich\af39\dbch\af31505\loch\f39 cond. Note that this number }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid13463017\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 is }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 not really exact.}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5053873 \hich\af39\dbch\af31505\loch\f39 
+ It is only an approximation to the real frame rate. The maximum frame rate \hich\af39\dbch\af31505\loch\f39 will\hich\af39\dbch\af31505\loch\f39  \hich\af39\dbch\af31505\loch\f39 never be reached since there is a 10 ms blocker included (
+\hich\af39\dbch\af31505\loch\f39 to work around good old AMD timing bug\hich\af39\dbch\af31505\loch\f39 )}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5338181\charrsid9465848 
+\par }\pard \ltrpar\ql \li340\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin340\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 \hich\f39 The \'93}{
+\rtlch\fcs1 \ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 Rendering}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 
+\loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  panel provides rendering-related options, such as wireframe/normal visualization.}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9465848 
+\par }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 \hich\f39  \'93}{\rtlch\fcs1 \ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 
+\hich\af39\dbch\af31505\loch\f39 Interaction}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  bundles all input related options.
+\par \hich\af39\dbch\af31505\loch\f39 The main \hich\af39\dbch\af31505\loch\f39 component is the large viewer panel where the assets are displayed. Status messages (e.g. if a texture could not be loaded)}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 
+\f39\fs20\lang1033\langfe1031\langnp1033\insrsid9465848 \hich\af39\dbch\af31505\loch\f39  \hich\af39\dbch\af31505\loch\f39 are displayed in the upper-right}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 
+\hich\af39\dbch\af31505\loch\f39  edge.}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9465848 \hich\af39\dbch\af31505\loch\f39 
+ Yellow messages are simple information messages, red messages are error messages. Green messages\hich\af39\dbch\af31505\loch\f39 , however, are coming from heart ;-)}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 
+\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 
+\par }{\rtlch\fcs1 \af39\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid5338181 
+\par }\pard \ltrpar\ql \fi-360\li340\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin340\itap0 {\rtlch\fcs1 \af39\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 III.\tab Input
+\par }\pard \ltrpar\ql \li340\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin340\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 \hich\f39 
+The input mode depends on the selected input behavior. If \'84}{\rtlch\fcs1 \ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 Zoom/Rotate}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 
+\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  is }{\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 NOT}{
+\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39  selected the following scheme applies:
+\par }\pard \ltrpar\ql \fi368\li340\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin340\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \loch\af39\dbch\af31505\hich\f39 \lquote }{\rtlch\fcs1 
+\ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 Arrow up}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \loch\af39\dbch\af31505\hich\f39 
+\rquote \loch\f39  \tab = Move forwards
+\par \loch\af39\dbch\af31505\hich\f39 \lquote }{\rtlch\fcs1 \ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 Arrow left\hich\f39 \rquote }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 
+\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39  \tab = Move to the left
+\par \loch\af39\dbch\af31505\hich\f39 \lquote }{\rtlch\fcs1 \ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 Arrow down}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 
+\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \loch\af39\dbch\af31505\hich\f39 \rquote \loch\f39  \tab = Move backwards
+\par \loch\af39\dbch\af31505\hich\f39 \lquote }{\rtlch\fcs1 \ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 Arrow right}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 
+\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \loch\af39\dbch\af31505\hich\f39 \rquote \loch\f39  \tab = Move to the right
+\par }\pard \ltrpar\ql \fi340\li0\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 
+The mouse specifies the view direction. This is the typical FPS input behavior.
+\par }{\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 Otherwise\hich\af39\dbch\af31505\loch\f39 \hich\f39 , if \'84}{\rtlch\fcs1 \ab\ai\af39\afs20 \ltrch\fcs0 
+\b\i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 Zoom/Rotate}{\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39 
+ is enabled:
+\par }\pard \ltrpar\ql \li340\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin340\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \loch\af39\dbch\af31505\hich\f39 \'93}{\rtlch\fcs1 
+\ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 Left Mouse Button}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 
+\loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  = Keep pressed and move the mouse to rotate the asset around its local axes. Inside the yellow circle: x/y-axis, outside: Z-axis. To rotate around one axis only use the axis snap-ins (yellow squares with a
+\hich\af39\dbch\af31505\loch\f39  cross inside).
+\par \loch\af39\dbch\af31505\hich\f39 \'93}{\rtlch\fcs1 \ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 Right Mouse Button}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 
+\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  = Keep pressed and move the mouse to rotate the light source(s) around their x and y axes.
+\par \loch\af39\dbch\af31505\hich\f39 \'93}{\rtlch\fcs1 \ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 Middle Mouse Button}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 
+\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  = Keep pressed and move the mouse from the left to the right or the other way round to increase/decrease t\hich\af39\dbch\af31505\loch\f39 
+he intensity of the light source(s)
+\par \loch\af39\dbch\af31505\hich\f39 \'93}{\rtlch\fcs1 \ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 Right }{\rtlch\fcs1 \ab\ai\af39\afs20 \ltrch\fcs0 
+\b\i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 AND}{\rtlch\fcs1 \ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39  Left Mouse Button}{
+\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  = Keep pressed and move the mouse to rotate skybox (if existing) around the global x/y axes.
+\par \loch\af39\dbch\af31505\hich\f39 \'93}{\rtlch\fcs1 \ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 Mouse wheel}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 
+\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  = Zoom in/out
+\par }\pard \ltrpar\ql \fi-360\li340\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin340\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 IV.\tab }{\rtlch\fcs1 
+\af39\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 Rendering
+\par }\pard \ltrpar\ql \li340\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin340\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 
+Enabling MultiSampling improves rendering\hich\af39\dbch\af31505\loch\f39  quality. MultiSampling is activated by default. The highest quality MultiSampling mode supported by the video card is used.
+\par \hich\af39\dbch\af31505\loch\f39 MultiSampling is especially useful to remove line artifacts in wireframe/normals mode. Note that the transition between normal and \hich\af39\dbch\af31505\loch\f39 multisampled rendering may take a few seconds.
+\par \hich\af39\dbch\af31505\loch\f39 \hich\f39 Rendering is done via Direct3D\'99\loch\f39 \hich\f39  9.0c. Note that the \'93}{\rtlch\fcs1 \ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 
+Low-quality lighting}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39 -Option is not available for PS 2.0 cards. Lighting on PS 2.0 cards is always low quality.
 
-\par }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid9635109 \loch\af39\dbch\af31505\hich\f39 \lquote }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8745149 
-\hich\af39\dbch\af31505\loch\f39 Arrow down}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid9635109 \loch\af39\dbch\af31505\hich\f39 \rquote \loch\f39  }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109 \tab }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid9635109 \hich\af39\dbch\af31505\loch\f39 = }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109 \hich\af39\dbch\af31505\loch\f39 Move backwards
-\par }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid9635109 \loch\af39\dbch\af31505\hich\f39 \lquote }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8745149 
-\hich\af39\dbch\af31505\loch\f39 Arrow right}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid9635109 \loch\af39\dbch\af31505\hich\f39 \rquote \loch\f39  }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109 \tab }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid9635109 \hich\af39\dbch\af31505\loch\f39 = }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109 \hich\af39\dbch\af31505\loch\f39 Move to the right
-\par }\pard\plain \ltrpar\ql \fi340\li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid9635109 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 
-\fs22\lang1031\langfe1031\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid9635109 \hich\af39\dbch\af31505\loch\f39 The}{\rtlch\fcs1 
-\af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109 \hich\af39\dbch\af31505\loch\f39  mouse specifies the view direction. This is the typical FPS input behavior.
-\par }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \b\f39\fs20\lang1033\langfe1031\langnp1033\insrsid14293319\charrsid67262 \hich\af39\dbch\af31505\loch\f39 \hich\f39 Otherwise, if \'84}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\b\i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid14293319\charrsid67262 \hich\af39\dbch\af31505\loch\f39 Zoom/Rotate}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \b\f39\fs20\lang1033\langfe1031\langnp1033\insrsid14293319\charrsid67262 
-\loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  is enabled:
-\par }\pard \ltrpar\ql \li340\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin340\itap0\pararsid14293319 {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid14293319 
-\loch\af39\dbch\af31505\hich\f39 \'93}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid14293319\charrsid74094 \hich\af39\dbch\af31505\loch\f39 Left Mouse Button}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid14293319 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  = Keep pressed and move the mouse to rotate the asset around its local axes. Inside the yellow circle: x/y-axis, outside: Z-axis}{\rtlch\fcs1 
-\af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid11029790 \hich\af39\dbch\af31505\loch\f39 . To rotate around one axis only use the axis snap-ins (yellow squar\hich\af39\dbch\af31505\loch\f39 es with a cross inside).}{\rtlch\fcs1 
-\af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid14293319 
-\par \loch\af39\dbch\af31505\hich\f39 \'93}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid14293319\charrsid74094 \hich\af39\dbch\af31505\loch\f39 Right Mouse Button}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid14293319 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  = Keep pressed and move the mouse to rotate the light source(s) around their x and y axes.
-\par \loch\af39\dbch\af31505\hich\f39 \'93}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid14293319\charrsid74094 \hich\af39\dbch\af31505\loch\f39 Middle Mouse Button}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid14293319 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  = Keep pressed and move the mouse }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid1405492 
-\hich\af39\dbch\af31505\loch\f39 from the left to the right or the other way round to increase/decrease the intensity of the light source(s)}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid14293319 
-\par }\pard \ltrpar\ql \li340\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin340\itap0\pararsid7677524 {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid7677524 
-\loch\af39\dbch\af31505\hich\f39 \'93}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid7677524\charrsid74094 \hich\af39\dbch\af31505\loch\f39 Right }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\b\i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid7677524\charrsid7677524 \hich\af39\dbch\af31505\loch\f39 AND}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid7677524 \hich\af39\dbch\af31505\loch\f39  Left }{
-\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid7677524\charrsid74094 \hich\af39\dbch\af31505\loch\f39 Mouse Button}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid7677524 
-\loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  = Keep pressed and move the mouse to rotate \hich\af39\dbch\af31505\loch\f39 skybox (\hich\af39\dbch\af31505\loch\f39 if existing\hich\af39\dbch\af31505\loch\f39 )\hich\af39\dbch\af31505\loch\f39 
- around the global x/y axes.
-\par }\pard \ltrpar\ql \li340\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin340\itap0\pararsid14293319 {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid7360491 
-\loch\af39\dbch\af31505\hich\f39 \'93}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid7360491 \hich\af39\dbch\af31505\loch\f39 Mouse wheel}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid7360491 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  = Zoom in/out
-\par {\listtext\pard\plain\ltrpar \s15 \rtlch\fcs1 \af0 \ltrch\fcs0 \f39\lang1033\langfe1031\langnp1033\insrsid10752424 \hich\af39\dbch\af31505\loch\f39 IV.\tab}}\pard\plain \ltrpar\s15\ql \fi-360\li340\ri0\sa200\sl276\slmult1
-\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls2\adjustright\rin0\lin340\itap0\pararsid10752424\contextualspace \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 
-\fs22\lang1031\langfe1031\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid10752424 \hich\af39\dbch\af31505\loch\f39 Rendering
-\par }\pard \ltrpar\s15\ql \li340\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin340\itap0\pararsid10752424\contextualspace {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid10752424 
-\hich\af39\dbch\af31505\loch\f39 Enabling MultiSampling improves rendering quality. MultiSampling is activated by default. The highest qual\hich\af39\dbch\af31505\loch\f39 ity MultiSampling mode supported by the video card is used.
-\par }\pard \ltrpar\s15\ql \li340\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin340\itap0\pararsid2961835\contextualspace {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid10752424 
-\hich\af39\dbch\af31505\loch\f39 MultiSampling is especially useful to remove line artifacts in wireframe/normals mode. Note that the transition between normal and multisampled rendering may take a few seconds.}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid14187505\charrsid2961835 
-\par }\pard \ltrpar\s15\ql \li340\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin340\itap0\pararsid10752424\contextualspace {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid14187505 
-\hich\af39\dbch\af31505\loch\f39 Rendering is done \hich\af39\dbch\af31505\loch\f39 via Direct3D}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid14187505\charrsid14187505 \loch\af39\dbch\af31505\hich\f39 \'99}{
-\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5860386 \hich\af39\dbch\af31505\loch\f39  9.0c.}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid14187505 
-\hich\af39\dbch\af31505\loch\f39 \hich\f39  Note that the \'93}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid14187505\charrsid14187505 \hich\af39\dbch\af31505\loch\f39 Low-quality lighting}{\rtlch\fcs1 \af0\afs20 
-\ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid14187505 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39 -Option is not available for PS 2.0 cards. Lighting on PS 2.0 cards is always low quality.
-\par }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid14115297 
-\par {\listtext\pard\plain\ltrpar \s15 \rtlch\fcs1 \af0 \ltrch\fcs0 \f39\lang1033\langfe1031\langnp1033\insrsid14115297 \hich\af39\dbch\af31505\loch\f39 V.\tab}}\pard \ltrpar\s15\ql \fi-360\li340\ri0\sa200\sl276\slmult1
-\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls2\adjustright\rin0\lin340\itap0\pararsid14115297\contextualspace {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid14115297 \hich\af39\dbch\af31505\loch\f39 Known issues}{
-\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid14115297\charrsid3683098 \hich\af39\dbch\af31505\loch\f39  }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid14115297 
-\par {\listtext\pard\plain\ltrpar \s15 \rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid14115297 \hich\af39\dbch\af31505\loch\f39 -\tab}}\pard \ltrpar\s15\ql \fi-360\li700\ri0\sa200\sl276\slmult1
-\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls4\adjustright\rin0\lin700\itap0\pararsid2961835\contextualspace {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid14115297 \hich\af39\dbch\af31505\loch\f39 
-If a loading process is canceled it is not guaranteed that further loading processes will succeed. ASSIMP Viewer might even crash in this case. }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid14115297\charrsid2961835 
-
-\par {\listtext\pard\plain\ltrpar \s15 \rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid2961835 \hich\af39\dbch\af31505\loch\f39 -\tab}}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid2961835 \hich\af39\dbch\af31505\loch\f39 Some very complex materials involving real time reflection/refraction are not displayed properly.}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
-\f39\fs24\lang1033\langfe1031\langnp1033\insrsid2961835\charrsid2961835 
-\par {\listtext\pard\plain\ltrpar \s15 \rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid2961835 \hich\af39\dbch\af31505\loch\f39 -\tab}}\pard \ltrpar\s15\ql \fi-360\li700\ri0\sa200\sl276\slmult1
-\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls4\adjustright\rin0\lin700\itap0\pararsid9635109\contextualspace {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid2961835 \hich\af39\dbch\af31505\loch\f39 When rend
-\hich\af39\dbch\af31505\loch\f39 ering non-opaque objects some triangle artifacts might occur}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid10617294 .}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
-\f39\fs24\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid10617294 
+\par 
+\par }\pard \ltrpar\ql \fi-360\li340\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin340\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 V.\tab }{\rtlch\fcs1 
+\af39\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid5338181 \hich\af39\dbch\af31505\loch\f39 Known issues 
+\par }\pard \ltrpar\ql \fi-360\li700\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin700\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 -\tab \hich\af39\dbch\af31505\loch\f39 
+If a loading process is \hich\af39\dbch\af31505\loch\f39 canceled it is not guaranteed that further loading processes will succeed. ASSIMP Viewer might even crash in this case. }{\rtlch\fcs1 \af39\afs24 \ltrch\fcs0 
+\f39\fs24\lang1033\langfe1031\langnp1033\insrsid5338181 
+\par }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 -\tab \hich\af39\dbch\af31505\loch\f39 Some very complex materials involving real time reflection/refraction are not displayed properly.}{\rtlch\fcs1 
+\af39\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid5338181 
+\par }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5338181 -\tab \hich\af39\dbch\af31505\loch\f39 When rendering non-opaque objects\hich\af39\dbch\af31505\loch\f39  some triangle artifacts might occur.}{\rtlch\fcs1 
+\af39\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid5338181 
 \par }{\*\themedata 504b030414000600080000002100828abc13fa0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb6ac3301045f785fe83d0b6d8
 72ba28a5d8cea249777d2cd20f18e4b12d6a8f843409c9df77ecb850ba082d74231062ce997b55ae8fe3a00e1893f354e9555e6885647de3a8abf4fbee29bbd7
 2a3150038327acf409935ed7d757e5ee14302999a654e99e393c18936c8f23a4dc072479697d1c81e51a3b13c07e4087e6b628ee8cf5c4489cf1c4d075f92a0b
@@ -363,8 +366,8 @@ fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff
 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffffec69d9888b8b3d4c859eaf6cd158be0f00000000000000000000000060e3
-1310819dc801feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000
+ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffffec69d9888b8b3d4c859eaf6cd158be0f000000000000000000000000a034
+b356e3b4c801feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000
 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000
 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000
 0000000000000000000000000000000000000000000000000105000000000000}}

+ 51 - 3
tools/assimp_view/resource.h

@@ -37,6 +37,9 @@
 #define IDB_BITMAP10                    153
 #define IDB_BROOT                       153
 #define IDD_LOGVIEW                     154
+#define IDB_BTXI                        155
+#define IDR_TXPOPUP                     156
+#define IDR_MATPOPUP                    157
 #define IDC_CHECK1                      1000
 #define IDC_TOGGLEMS                    1000
 #define IDC_CHECK2                      1001
@@ -67,8 +70,10 @@
 #define IDC_CHECK8                      1020
 #define IDC_LOWQUALITY                  1020
 #define IDC_NUMMATS2                    1021
+#define IDC_NUMSHADERS                  1021
 #define IDC_ESHADER                     1022
 #define IDC_RICHEDIT21                  1023
+#define IDC_EMESH                       1023
 #define IDC_CHECK9                      1024
 #define IDC_NOSPECULAR                  1024
 #define IDC_PLAYANIM                    1025
@@ -84,6 +89,14 @@
 #define IDC_TREE1                       1033
 #define IDC_EDIT1                       1034
 #define IDC_BLUBB                       1037
+#define IDC_BLABLA                      1038
+#define IDC_NUMNODES                    1038
+#define IDC_LCOLOR1                     1041
+#define IDC_LCOLOR2                     1042
+#define IDC_ENODEWND                    1043
+#define IDC_LCOLOR3                     1044
+#define IDC_LRESET                      1046
+#define IDC_NUMMESHES                   1047
 #define ID_VIEWER_OPEN                  32771
 #define ID_VIEWER_CLOSETHIS             32772
 #define ID_VIEWER_CLOSEASSET            32773
@@ -101,6 +114,41 @@
 #define ID_TOOLS_LOGWINDOW              32785
 #define ID_TOOLS_SAVELOGTOFILE          32786
 #define ID_TOOLS_CLEARLOG               32787
+#define ID_VIEWER_RECENTFILES           32788
+#define ID_VIEWER_MEMORYCONSUMATION     32789
+#define ID_VIEWER_CLEARHISTORY          32790
+#define ID_TOOLS_ORIGINALNORMALS        32791
+#define ID_TOOLS_SMOOTHNORMALS          32792
+#define ID_TOOLS_HARDNORMALS            32793
+#define ID_TOOLS_FLIPNORMALS            32794
+#define ID__S                           32795
+#define ID__FEEDBACK                    32796
+#define ID_FEEDBACK_GH                  32797
+#define ID_FEEDBACK_FEATUREREQUEST      32798
+#define ID_FEEDBACK_DONATE              32799
+#define ID_ANIMATION_PLAYALLINORDER     32800
+#define ID_TOOLS_STEREOVIEW             32801
+#define ID_EGNEKLGEG_EGEG               32802
+#define ID_HEY_REPLACE                  32803
+#define ID_HEY_EXPORT                   32804
+#define ID_HEY_REMOVE                   32805
+#define ID_SOLONG_ADDDIFFUSETEXTURE     32806
+#define ID_SOLONG_ADDSPECULARTEXTURE    32807
+#define ID_SOLONG_ADDAMBIENTTEXTURE     32808
+#define ID_SOLONG_ADDEMISSIVETEXTURE    32809
+#define ID_SOLONG_ADDOPACITYTEXTURE     32810
+#define ID_SOLONG_ADDNORMAL             32811
+#define ID_SOLONG_ADDSHININESSTEXTURE   32812
+#define ID_SOLONG_CLEARDIFFUSECOLOR     32813
+#define ID_SOLONG_CLEARSPECULARCOLOR    32814
+#define ID_SOLONG_CLEARAMBIENTCOLOR     32815
+#define ID_SOLONG_CLEAREMISSIVECOLOR    32816
+#define ID_SOLONG_CLEARTRANSPARENCY     32817
+#define ID_SOLONG_MAKEDEFAULTMATERIAL   32818
+#define ID_HEY_RESETTEXTURE             32819
+#define ID_SOLONG_SETSHADINGMODE        32820
+#define ID_SETSHADINGMODE_GOURAUD       32821
+#define ID_SETSHADINGMODE_PHONG         32822
 #define IDC_STATIC                      -1
 
 // Next default values for new objects
@@ -108,9 +156,9 @@
 #ifdef APSTUDIO_INVOKED
 #ifndef APSTUDIO_READONLY_SYMBOLS
 #define _APS_NO_MFC                     1
-#define _APS_NEXT_RESOURCE_VALUE        155
-#define _APS_NEXT_COMMAND_VALUE         32788
-#define _APS_NEXT_CONTROL_VALUE         1038
+#define _APS_NEXT_RESOURCE_VALUE        158
+#define _APS_NEXT_COMMAND_VALUE         32823
+#define _APS_NEXT_CONTROL_VALUE         1048
 #define _APS_NEXT_SYMED_VALUE           110
 #endif
 #endif

+ 247 - 244
tools/assimp_view/text1.bin

@@ -1,26 +1,19 @@
-{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff31507\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi0\deflang1031\deflangfe1031\themelang1031\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f2\fbidi \fmodern\fcharset0\fprq1{\*\panose 02070309020205020404}Courier New;}
-{\f3\fbidi \froman\fcharset2\fprq2{\*\panose 05050102010706020507}Symbol;}{\f10\fbidi \fnil\fcharset2\fprq2{\*\panose 05000000000000000000}Wingdings;}{\f34\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;}
-{\f38\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0604030504040204}Tahoma;}{\f39\fbidi \fswiss\fcharset0\fprq2{\*\panose 00000000000000000000}MS Reference Sans Serif;}
-{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
-{\fhimajor\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;}{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
-{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
-{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f41\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
-{\f42\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f44\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f45\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f46\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
-{\f47\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f48\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f49\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f61\fbidi \fmodern\fcharset238\fprq1 Courier New CE;}
-{\f62\fbidi \fmodern\fcharset204\fprq1 Courier New Cyr;}{\f64\fbidi \fmodern\fcharset161\fprq1 Courier New Greek;}{\f65\fbidi \fmodern\fcharset162\fprq1 Courier New Tur;}{\f66\fbidi \fmodern\fcharset177\fprq1 Courier New (Hebrew);}
-{\f67\fbidi \fmodern\fcharset178\fprq1 Courier New (Arabic);}{\f68\fbidi \fmodern\fcharset186\fprq1 Courier New Baltic;}{\f69\fbidi \fmodern\fcharset163\fprq1 Courier New (Vietnamese);}{\f381\fbidi \froman\fcharset238\fprq2 Cambria Math CE;}
-{\f382\fbidi \froman\fcharset204\fprq2 Cambria Math Cyr;}{\f384\fbidi \froman\fcharset161\fprq2 Cambria Math Greek;}{\f385\fbidi \froman\fcharset162\fprq2 Cambria Math Tur;}{\f388\fbidi \froman\fcharset186\fprq2 Cambria Math Baltic;}
-{\f421\fbidi \fswiss\fcharset238\fprq2 Tahoma CE;}{\f422\fbidi \fswiss\fcharset204\fprq2 Tahoma Cyr;}{\f424\fbidi \fswiss\fcharset161\fprq2 Tahoma Greek;}{\f425\fbidi \fswiss\fcharset162\fprq2 Tahoma Tur;}
-{\f426\fbidi \fswiss\fcharset177\fprq2 Tahoma (Hebrew);}{\f427\fbidi \fswiss\fcharset178\fprq2 Tahoma (Arabic);}{\f428\fbidi \fswiss\fcharset186\fprq2 Tahoma Baltic;}{\f429\fbidi \fswiss\fcharset163\fprq2 Tahoma (Vietnamese);}
-{\f430\fbidi \fswiss\fcharset222\fprq2 Tahoma (Thai);}{\f431\fbidi \fswiss\fcharset238\fprq2 MS Reference Sans Serif CE;}{\f432\fbidi \fswiss\fcharset204\fprq2 MS Reference Sans Serif Cyr;}
-{\f434\fbidi \fswiss\fcharset161\fprq2 MS Reference Sans Serif Greek;}{\f435\fbidi \fswiss\fcharset162\fprq2 MS Reference Sans Serif Tur;}{\f438\fbidi \fswiss\fcharset186\fprq2 MS Reference Sans Serif Baltic;}
-{\f439\fbidi \fswiss\fcharset163\fprq2 MS Reference Sans Serif (Vietnamese);}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
-{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
-{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
-{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}
-{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
-{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhimajor\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}
-{\fhimajor\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\fhimajor\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\fhimajor\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;}
+{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff31507\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi31507\deflang1031\deflangfe1031\themelang1031\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f34\fbidi \froman\fcharset1\fprq2{\*\panose 02040503050406030204}Cambria Math;}
+{\f39\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0604030504040204}MS Reference Sans Serif;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
+{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;}
+{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
+{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}
+{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f40\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f41\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
+{\f43\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f44\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f45\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f46\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
+{\f47\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f48\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f430\fbidi \fswiss\fcharset238\fprq2 MS Reference Sans Serif CE;}
+{\f431\fbidi \fswiss\fcharset204\fprq2 MS Reference Sans Serif Cyr;}{\f433\fbidi \fswiss\fcharset161\fprq2 MS Reference Sans Serif Greek;}{\f434\fbidi \fswiss\fcharset162\fprq2 MS Reference Sans Serif Tur;}
+{\f437\fbidi \fswiss\fcharset186\fprq2 MS Reference Sans Serif Baltic;}{\f438\fbidi \fswiss\fcharset163\fprq2 MS Reference Sans Serif (Vietnamese);}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
+{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
+{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
+{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
+{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
+{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
+{\fhimajor\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\fhimajor\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\fhimajor\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\fhimajor\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;}
 {\fhimajor\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
 {\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
 {\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
@@ -37,227 +30,237 @@
 \red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;
 \red192\green192\blue192;}{\*\defchp \fs22\loch\af31506\hich\af31506\dbch\af31505 }{\*\defpap \ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{
 \ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1031\langfe1031\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 
-\snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \sunhideused \spriority1 Default Paragraph Font;}{\*
+\snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\*
 \ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tscellwidthfts0\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa200\sl276\slmult1
-\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1031\langfe1031\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 
-\snext11 \ssemihidden \sunhideused \sqformat Normal Table;}{\s15\ql \li720\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin720\itap0\contextualspace \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 
-\fs22\lang1031\langfe1031\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 \sbasedon0 \snext15 \sqformat \spriority34 \styrsid3683098 List Paragraph;}{
-\s16\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af38\afs16\alang1025 \ltrch\fcs0 \fs16\lang1031\langfe1031\loch\f38\hich\af38\dbch\af31505\cgrid\langnp1031\langfenp1031 
-\sbasedon0 \snext16 \slink17 \ssemihidden \sunhideused \styrsid8273515 Balloon Text;}{\*\cs17 \additive \rtlch\fcs1 \af38\afs16 \ltrch\fcs0 \f38\fs16 \sbasedon10 \slink16 \slocked \ssemihidden \styrsid8273515 Balloon Text Char;}}{\*\listtable
-{\list\listtemplateid-2111801688\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid1242219378\'01-;}{\levelnumbers;}
-\loch\af39\hich\af39\dbch\af31505\fbias0\hres0\chhres0 \fi-360\li700\lin700 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}
-\f2\fbias0\hres0\chhres0 \fi-360\li1420\lin1420 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}
-\f10\fbias0\hres0\chhres0 \fi-360\li2140\lin2140 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}
-\f3\fbias0\hres0\chhres0 \fi-360\li2860\lin2860 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0\hres0\chhres0 
-\fi-360\li3580\lin3580 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0\hres0\chhres0 
-\fi-360\li4300\lin4300 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0\hres0\chhres0 
-\fi-360\li5020\lin5020 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0\hres0\chhres0 \fi-360\li5740\lin5740 }
-{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0\hres0\chhres0 \fi-360\li6460\lin6460 }{\listname 
-;}\listid256792316}{\list\listtemplateid1110873036\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat0\levelspace0\levelindent0{\leveltext\leveltemplateid680798618\'01-;}{\levelnumbers;}
-\fs20\loch\af39\hich\af39\dbch\af31505\fbias0\hres0\chhres0 \fi-360\li700\lin700 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567619
-\'01o;}{\levelnumbers;}\f2\fbias0\hres0\chhres0 \fi-360\li1420\lin1420 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers
-;}\f10\fbias0\hres0\chhres0 \fi-360\li2140\lin2140 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}
-\f3\fbias0\hres0\chhres0 \fi-360\li2860\lin2860 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0\hres0\chhres0 
-\fi-360\li3580\lin3580 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0\hres0\chhres0 
-\fi-360\li4300\lin4300 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0\hres0\chhres0 
-\fi-360\li5020\lin5020 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0\hres0\chhres0 \fi-360\li5740\lin5740 }
-{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0\hres0\chhres0 \fi-360\li6460\lin6460 }{\listname 
-;}\listid483863136}{\list\listtemplateid338825902\listhybrid{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid-1769051580\'02\'00);}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \fbias0\hres0\chhres0 \fi-360\li700\lin700 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567641\'02\'01.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-360\li1420\lin1420 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567643\'02\'02.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-180\li2140\lin2140 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567631\'02\'03.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-360\li2860\lin2860 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567641\'02\'04.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-360\li3580\lin3580 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567643\'02\'05.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-180\li4300\lin4300 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567631\'02\'06.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-360\li5020\lin5020 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567641\'02\'07.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-360\li5740\lin5740 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567643\'02\'08.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-180\li6460\lin6460 }{\listname ;}\listid649408911}{\list\listtemplateid-371049066\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat0\levelspace360\levelindent0{\leveltext
-\leveltemplateid680798618\'01-;}{\levelnumbers;}\fs20\loch\af39\hich\af39\dbch\af31505\fbias0\hres0\chhres0 \fi-360\li720\lin720 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0
-{\leveltext\leveltemplateid67567641\'02\'01.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-360\li1440\lin1440 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0
-{\leveltext\leveltemplateid67567643\'02\'02.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-180\li2160\lin2160 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0
-{\leveltext\leveltemplateid67567631\'02\'03.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-360\li2880\lin2880 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0
-{\leveltext\leveltemplateid67567641\'02\'04.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-360\li3600\lin3600 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0
-{\leveltext\leveltemplateid67567643\'02\'05.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-180\li4320\lin4320 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0
-{\leveltext\leveltemplateid67567631\'02\'06.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-360\li5040\lin5040 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0
-{\leveltext\leveltemplateid67567641\'02\'07.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-360\li5760\lin5760 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0
-{\leveltext\leveltemplateid67567643\'02\'08.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-180\li6480\lin6480 }{\listname ;}\listid780539952}{\list\listtemplateid1158591540\listhybrid{\listlevel\levelnfc1\levelnfcn1\leveljc2
-\leveljcn2\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567635\'02\'00.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fbias0\hres0\chhres0 \fi-360\li1440\lin1440 }{\listlevel\levelnfc4\levelnfcn4\leveljc0
-\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567641\'02\'01.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-360\li2160\lin2160 }{\listlevel\levelnfc2\levelnfcn2\leveljc2
-\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567643\'02\'02.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-180\li2880\lin2880 }{\listlevel\levelnfc0\levelnfcn0\leveljc0
-\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567631\'02\'03.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-360\li3600\lin3600 }{\listlevel\levelnfc4\levelnfcn4\leveljc0
-\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567641\'02\'04.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-360\li4320\lin4320 }{\listlevel\levelnfc2\levelnfcn2\leveljc2
-\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567643\'02\'05.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-180\li5040\lin5040 }{\listlevel\levelnfc0\levelnfcn0\leveljc0
-\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567631\'02\'06.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-360\li5760\lin5760 }{\listlevel\levelnfc4\levelnfcn4\leveljc0
-\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567641\'02\'07.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-360\li6480\lin6480 }{\listlevel\levelnfc2\levelnfcn2\leveljc2
-\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567643\'02\'08.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \hres0\chhres0 \fi-180\li7200\lin7200 }{\listname ;}\listid823008862}
-{\list\listtemplateid1985747632\listhybrid{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid-1722268864\'02\'00);}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 
-\fbias0\hres0\chhres0 \fi-720\li1080\lin1080 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567641\'02\'01.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-360\li1440\lin1440 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567643\'02\'02.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-180\li2160\lin2160 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567631\'02\'03.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-360\li2880\lin2880 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567641\'02\'04.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-360\li3600\lin3600 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567643\'02\'05.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-180\li4320\lin4320 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567631\'02\'06.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-360\li5040\lin5040 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567641\'02\'07.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-360\li5760\lin5760 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567643\'02\'08.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 
-\ltrch\fcs0 \hres0\chhres0 \fi-180\li6480\lin6480 }{\listname ;}\listid1527327967}}{\*\listoverridetable{\listoverride\listid1527327967\listoverridecount0\ls1}{\listoverride\listid823008862\listoverridecount0\ls2}{\listoverride\listid256792316
-\listoverridecount0\ls3}{\listoverride\listid483863136\listoverridecount0\ls4}{\listoverride\listid649408911\listoverridecount0\ls5}{\listoverride\listid780539952\listoverridecount0\ls6}}{\*\rsidtbl \rsid67262\rsid74094\rsid602054\rsid1405492\rsid2175529
-\rsid2186087\rsid2961835\rsid3277197\rsid3683098\rsid5404161\rsid5460125\rsid5513066\rsid5860386\rsid7360491\rsid7429996\rsid7677524\rsid8273515\rsid8350123\rsid8745149\rsid9194405\rsid9529660\rsid9575707\rsid9635109\rsid9712802\rsid10617294\rsid10752424
-\rsid10762577\rsid11029790\rsid11880680\rsid12914594\rsid14115297\rsid14187505\rsid14293319}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\author Alexander Gessler}
-{\operator Alexander Gessler}{\creatim\yr2008\mo4\dy12\hr23\min23}{\revtim\yr2008\mo4\dy13\hr18\min11}{\version32}{\edmins0}{\nofpages2}{\nofwords446}{\nofchars2811}{\*\company UtopicTechnologies}{\nofcharsws3251}{\vern32893}}{\*\xmlnstbl {\xmlns1 http://
-schemas.microsoft.com/office/word/2003/wordml}}\paperw11906\paperh16838\margl1417\margr1417\margt1417\margb1134\gutter0\ltrsect 
-\deftab708\widowctrl\ftnbj\aenddoc\hyphhotz425\trackmoves1\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0
-\showxmlerrors1\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin1417\dgvorigin1417\dghshow1\dgvshow1
-\jexpand\viewkind1\viewscale100\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel\wrppunct
-\asianbrkrule\rsidroot3683098\newtblstyruls\nogrowautofit\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal \nouicompat \fet0
-{\*\wgrffmtfilter 2450}\nofeaturethrottle1\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\headery708\footery708\colsx708\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2
-\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6
-\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang 
-{\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 
-\fs22\lang1031\langfe1031\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 {\rtlch\fcs1 \af0\afs32 \ltrch\fcs0 \b\f39\fs32\lang1033\langfe1031\langnp1033\insrsid3683098\charrsid3683098 \hich\af39\dbch\af31505\loch\f39 
-ASSIMP Viewer Utility}{\rtlch\fcs1 \af0\afs32 \ltrch\fcs0 \b\f39\fs32\lang1033\langfe1031\langnp1033\insrsid10617294 \hich\af39\dbch\af31505\loch\f39  }{\rtlch\fcs1 \af0\afs32 \ltrch\fcs0 \b\f39\fs32\lang1033\langfe1031\langnp1033\insrsid11029790 
-\par }{\rtlch\fcs1 \af0\afs16 \ltrch\fcs0 \b\f39\fs16\lang1033\langfe1031\langnp1033\insrsid10617294 \hich\af39\dbch\af31505\loch\f39 Document version 1.0, April 2008}{\rtlch\fcs1 \af0\afs16 \ltrch\fcs0 
-\b\f39\fs16\lang1033\langfe1031\langnp1033\insrsid10617294\charrsid10617294 
-\par }{\rtlch\fcs1 \af0\afs32 \ltrch\fcs0 \b\f39\fs32\lang1033\langfe1031\langnp1033\insrsid12914594 
-\par {\listtext\pard\plain\ltrpar \s15 \rtlch\fcs1 \af0 \ltrch\fcs0 \f39\lang1033\langfe1031\langnp1033\insrsid12914594 \hich\af39\dbch\af31505\loch\f39 I.\tab}}\pard\plain \ltrpar\s15\ql \fi-360\li340\ri0\sa200\sl276\slmult1
-\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls2\adjustright\rin0\lin340\itap0\pararsid3683098\contextualspace \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 
-\fs22\lang1031\langfe1031\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid12914594 \hich\af39\dbch\af31505\loch\f39 Usage}{\rtlch\fcs1 \af0\afs20 
-\ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid12914594\charrsid12914594 \hich\af39\dbch\af31505\loch\f39  }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid12914594\charrsid12914594 
-\par }\pard \ltrpar\s15\ql \li340\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin340\itap0\pararsid12914594\contextualspace {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid12914594\charrsid3683098 \hich\af39\dbch\af31505\loch\f39 The }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid12914594 \hich\af39\dbch\af31505\loch\f39 ASSIMP Viewer 
-\hich\af39\dbch\af31505\loch\f39 Utility is a small and fast stand-alone viewer utility which is using the ASSIMP library to import assets from files. It consists of a si}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid9575707 \hich\af39\dbch\af31505\loch\f39 ngle executable file and has no}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid12914594 \hich\af39\dbch\af31505\loch\f39 
- external dependencies.}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9529660 \hich\af39\dbch\af31505\loch\f39  It will display assets with complex materials and animations correctly.}{\rtlch\fcs1 \af0\afs20 
-\ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid12914594 
-\par }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9575707 
-\par }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \b\f39\fs20\lang1033\langfe1031\langnp1033\insrsid12914594\charrsid12914594 \hich\af39\dbch\af31505\loch\f39 System requirements}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid12914594 \hich\af39\dbch\af31505\loch\f39 :
-\par {\listtext\pard\plain\ltrpar \s15 \rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5860386 \hich\af39\dbch\af31505\loch\f39 -\tab}}\pard \ltrpar\s15\ql \fi-360\li700\ri0\sa200\sl276\slmult1
-\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls4\adjustright\rin0\lin700\itap0\pararsid5860386\contextualspace {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5860386 \hich\af39\dbch\af31505\loch\f39 
-A Direct3D 9.0c compliant video card with at least support for Shader Model 2.0.}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid5860386\charrsid9575707 
-\par {\listtext\pard\plain\ltrpar \s15 \rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9575707 \hich\af39\dbch\af31505\loch\f39 -\tab}}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid9575707 \hich\af39\dbch\af31505\loch\f39 Shader Model 3.0 cards are recommended}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid9575707\charrsid5860386 
-\par {\listtext\pard\plain\ltrpar \s15 \rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5860386 \hich\af39\dbch\af31505\loch\f39 -\tab}}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5860386 \hich\af39\dbch\af31505\loch\f39 Windows 2000 or higher}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid5860386\charrsid5860386 
-\par }\pard \ltrpar\s15\ql \li340\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin340\itap0\pararsid12914594\contextualspace {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
-\f39\fs24\lang1033\langfe1031\langnp1033\insrsid3683098\charrsid3683098 \hich\af39\dbch\af31505\loch\f39  }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid3683098 
-\par {\listtext\pard\plain\ltrpar \s15 \rtlch\fcs1 \af0 \ltrch\fcs0 \f39\lang1033\langfe1031\langnp1033\insrsid5460125 \hich\af39\dbch\af31505\loch\f39 II.\tab}}\pard \ltrpar\s15\ql \fi-360\li340\ri0\sa200\sl276\slmult1
-\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls2\adjustright\rin0\lin340\itap0\pararsid3683098\contextualspace {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid5460125 \hich\af39\dbch\af31505\loch\f39 User i
-\hich\af39\dbch\af31505\loch\f39 nterface}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid12914594 
-\par }\pard \ltrpar\s15\ql \li340\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin340\itap0\pararsid9712802\contextualspace {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5460125\charrsid3683098 \hich\af39\dbch\af31505\loch\f39 The }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5460125 \hich\af39\dbch\af31505\loch\f39 viewer\hich\f39 
-\rquote \loch\f39 s user interface mainly consists}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5513066 \hich\af39\dbch\af31505\loch\f39  of three components:}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid602054 \hich\af39\dbch\af31505\loch\f39  }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5460125\charrsid9712802 
-\par }\pard\plain \ltrpar\ql \fi340\li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid2186087 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 
-\fs22\lang1031\langfe1031\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5404161 \hich\af39\dbch\af31505\loch\f39 
-The menu bar provides access to the viewer\hich\f39 \rquote \loch\f39 s basic options.}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9712802\charrsid2186087 
-\par {\listtext\pard\plain\ltrpar \s15 \rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5404161 \hich\af39\dbch\af31505\loch\f39 -\tab}}\pard\plain \ltrpar\s15\ql \fi-360\li720\ri0\sa200\sl276\slmult1
-\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls6\adjustright\rin0\lin720\itap0\pararsid5404161\contextualspace \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 
-\fs22\lang1031\langfe1031\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5404161 \loch\af39\dbch\af31505\hich\f39 \'93}{\rtlch\fcs1 \af0\afs20 
-\ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5404161\charrsid9712802 \hich\af39\dbch\af31505\loch\f39 Viewer}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5404161 \loch\af39\dbch\af31505\hich\f39 \'94
-\loch\f39 : Items to load / unload assets, take screenshots and open the viewer\hich\f39 \rquote \loch\f39 s options dialog.
-\par {\listtext\pard\plain\ltrpar \s15 \rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5404161 \hich\af39\dbch\af31505\loch\f39 -\tab}}\pard \ltrpar\s15\ql \fi-360\li720\ri0\sa200\sl276\slmult1
-\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls6\adjustright\rin0\lin720\itap0\pararsid3277197\contextualspace {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5404161 \loch\af39\dbch\af31505\hich\f39 \'93}{\rtlch\fcs1 
-\af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid5404161\charrsid9712802 \hich\af39\dbch\af31505\loch\f39 Background}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5404161 
-\loch\af39\dbch\af31505\hich\f39 \'94\loch\f39 : \hich\af39\dbch\af31505\loch\f39 Set the background color or use a texture (cubemaps are supported}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid11880680 
-\hich\af39\dbch\af31505\loch\f39  as skyboxes}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5404161 \hich\af39\dbch\af31505\loch\f39 ) as background image for the viewer.}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid9194405\charrsid3277197 
-\par }\pard \ltrpar\s15\ql \li340\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin340\itap0\pararsid5460125\contextualspace {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid602054 
+\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1031\langfe1031\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 
+\snext11 \ssemihidden \sunhideused \sqformat Normal Table;}}{\*\rsidtbl \rsid3942873\rsid5053873\rsid6912689\rsid7213193\rsid8068556\rsid9465848\rsid13463017}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1
+\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\operator Alexander Gessler}{\creatim\yr2008\mo5\dy13\hr12\min5}{\revtim\yr2008\mo5\dy13\hr12\min20}{\version7}{\edmins0}{\nofpages4}{\nofwords1365}{\nofchars6975}{\nofcharsws8324}{\vern32893}}
+{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}\paperw12240\paperh15840\margl1417\margr1417\margt1417\margb1134\gutter0\ltrsect 
+\deftab708\widowctrl\ftnbj\aenddoc\hyphhotz425\trackmoves1\trackformatting1\donotembedsysfont0\relyonvml0\donotembedlingdata1\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\horzdoc\dghspace120\dgvspace120
+\dghorigin1701\dgvorigin1984\dghshow0\dgvshow3\jcompress\viewkind1\viewscale91\viewzk1\rsidroot13463017 \fet0{\*\wgrffmtfilter 2450}\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang 
+{\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}
+{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9
+\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\ql \li0\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 
+\fs22\lang1031\langfe1031\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 {\rtlch\fcs1 \ab\af39\afs32 \ltrch\fcs0 \b\f39\fs32\lang1033\langfe1031\langnp1033\insrsid8068556 
+\par \hich\af39\dbch\af31505\loch\f39 ASSIMP Viewer Utility 
+\par }{\rtlch\fcs1 \ab\af39\afs16 \ltrch\fcs0 \b\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 Document version 1.0, April 2008
+\par }{\rtlch\fcs1 \ab\af39\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 
+\par }\pard \ltrpar\ql \fi-360\li340\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin340\itap0 {\rtlch\fcs1 \af39\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 I.\tab 
+\hich\af39\dbch\af31505\loch\f39 Usage\hich\af39\dbch\af31505\loch\f39  
+\par }\pard \ltrpar\qj \li340\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin340\itap0\pararsid13463017 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 
+The ASSIMP Viewer Utility is a small and fast stand-alone viewer utility which is us\hich\af39\dbch\af31505\loch\f39 
+ing the ASSIMP library to import assets from files. It consists of a single executable file and has no external dependencies. It displays assets with even highly complex materials and bone animations correctly.
+\par \hich\af39\dbch\af31505\loch\f39 AssimpView allows you to modify the textures \hich\af39\dbch\af31505\loch\f39 
+and material properties sets of your models at runtime, easy and fast per Drag&Drop. Furthermore it can visualize normals, UV sets, bounding boxes ... It allows artists and engine }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 
+\f39\fs20\lang1033\langfe1031\langnp1033\insrsid6912689 \hich\af39\dbch\af31505\loch\f39 programmers}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 
+ to work together with maximal efficiency and find the ideal mod\hich\af39\dbch\af31505\loch\f39 el format for your internal workflow.
+\par }{\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 System requirements}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 
+\hich\af39\dbch\af31505\loch\f39 :
+\par }\pard \ltrpar\qj \fi-360\li700\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin700\itap0\pararsid13463017 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 -\tab \hich\af39\dbch\af31505\loch\f39 
+A Direct3D 9.0c compliant video card with at least support for Shader Model 2.0.}{\rtlch\fcs1 \af39\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid8068556 
+\par }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 -\tab \hich\af39\dbch\af31505\loch\f39 Shader Model 3.0 cards are recommended. Shader Model 2.0 cards always render the lighting in low-quality and hav
+\hich\af39\dbch\af31505\loch\f39 e some limitations concerning complex materials.}{\rtlch\fcs1 \af39\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid8068556 
+\par }\pard \ltrpar\qj \fi-360\li700\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin700\itap0\pararsid8068556 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 -\tab \hich\af39\dbch\af31505\loch\f39 
+Windows 2000 or higher. AssimpView should also run on older versions, with DirectX 9 installed, but this has never been tested. If you're a proud owner of such a version and AssimpView works for you, let u\hich\af39\dbch\af31505\loch\f39 s know.}{
+\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid8068556 
+\par }\pard \ltrpar\ql \li340\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin340\itap0 {\rtlch\fcs1 \af39\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39  
+\par }\pard \ltrpar\ql \fi-360\li340\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin340\itap0 {\rtlch\fcs1 \af39\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 II.\tab 
+User interface
+\par }\pard \ltrpar\ql \li340\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin340\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 The viewer\hich\f39 \rquote 
+\loch\f39 s user interface mainly consists of three components: 
+\par }\pard \ltrpar\ql \fi340\li0\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 
+The menu bar provides access to the viewer\hich\f39 \rquote \loch\f39 s basic options.
+\par }\pard \ltrpar\ql \fi-360\li720\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin720\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 -\tab }{\rtlch\fcs1 \af39 \ltrch\fcs0 
+\f39\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \loch\af39\dbch\af31505\hich\f39 \'93}{\rtlch\fcs1 \ab\ai\af39 \ltrch\fcs0 \b\i\f39\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Viewer}
+{\rtlch\fcs1 \af39 \ltrch\fcs0 \f39\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39 : Items to load / unload assets, take screenshots and open the viewer\hich\f39 \rquote \loch\f39 
+s options dialog.}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 
+\par }\pard \ltrpar\qj \fi-360\li720\ri1206\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin1206\lin720\itap0\pararsid13463017 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \tab }{\rtlch\fcs1 \af39\afs16 
+\ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 * \hich\af39\dbch\af31505\loch\f39 "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 
+\hich\af39\dbch\af31505\loch\f39 Open Asset}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 
+": Displays the file system dialog where you can choose a new asset to load. Note that you can also Drag&Drop models onto the viewer panel.
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Close Asset}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 ": Closes the current asset and releases all resources associated with it. No action if no\hich\af39\dbch\af31505\loch\f39  asset is loaded.
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Screenshot}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 
+": Save a snapshot of the viewer to a file. The snapshot does only include the preview panel, the rest of the user interface is not visible. Saved screenshots have no watermarks. This is }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid6912689 \hich\af39\dbch\af31505\loch\f39 Open Source}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39  Software!
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Reset View}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 ": Reset the viewing position and direction to the default settings. This is: Camera position at 0|0|0, looking at 0|0|1.
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Memory consumption}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 ": Display a box with approximated memory statistics. Note that the total memory consumption needn'\hich\af39\dbch\af31505\loch\f39 
+t be equal to the physical memory allocated to the process (as displayed by Windows }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid6912689 \hich\af39\dbch\af31505\loch\f39 Task Manager}{\rtlch\fcs1 \af39\afs16 
+\ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 ). The memory consumption does only refer to the memory required for the asset itself, not for the rest of the viewer.
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Setup file associations}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 ": Associate al\hich\af39\dbch\af31505\loch\f39 l file formats which can be read by ASSIMP with the viewer. If you double }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid6912689 \hich\af39\dbch\af31505\loch\f39 click}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 
+ on such a file in Windows Explorer, it will be automatically opened with AssimpView.
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Recent files}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 ": Displays a popup menu with a list of recently opened assets. Simply cli\hich\af39\dbch\af31505\loch\f39 ck on one to reload it.
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Clear history}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 ": Clear the file history
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Quit}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 ": What do you think?
+\par }\pard \ltrpar\ql \fi-360\li720\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin720\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 - \tab }{\rtlch\fcs1 
+\ai\af39 \ltrch\fcs0 \i\f39\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 "}{\rtlch\fcs1 \ab\ai\af39 \ltrch\fcs0 \b\i\f39\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 
+\hich\af39\dbch\af31505\loch\f39 Tools}{\rtlch\fcs1 \ai\af39 \ltrch\fcs0 \i\f39\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 "}{\rtlch\fcs1 \af39 \ltrch\fcs0 
+\f39\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 : Additional utilities like stereo view, normal type.
+\par }\pard \ltrpar\qj \fi-360\li720\ri1208\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin1208\lin720\itap0\pararsid3942873 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \tab }{\rtlch\fcs1 \af39\afs16 
+\ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 
+Log window}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 ": Displays the output window of the logger. Warnings are displayed in orange/yel\hich\af39\dbch\af31505\loch\f39 
+low, errors in red, debug messages in blue and status }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid7213193 \hich\af39\dbch\af31505\loch\f39 information}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid9465848 \hich\af39\dbch\af31505\loch\f39  messages}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39  in green.
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Save log to file}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 ": Saves the contents of the log window to a file.
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Clear log}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 " Clear the contents of the log window
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Original normals}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 ": Specifies that the original norma\hich\af39\dbch\af31505\loch\f39 
+l set from the model file is used in the preview. Normally this is the best choice, as smoothing groups etc. are handled correctly, but there are many models out there which have invalid or corrupt normal sets. However, if a model has no normal set, ASSIM
+\hich\af39\dbch\af31505\loch\f39 P\hich\af39\dbch\af31505\loch\f39  computes a smooth normal set for it. "Original normals" is in this case equivalent to "Smooth normals"
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Smooth normals}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 ": Specifies that a smoothed, per-vertex, normal set is used in the preview window.
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Hard normals}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 ": Specifies that a hard, per-face\hich\af39\dbch\af31505\loch\f39 , normal set is used
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Flip normals}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 ": Flip all normal vectors
+\par }\pard \ltrpar\ql \fi-360\li720\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin720\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 -\tab }{\rtlch\fcs1 \af39 \ltrch\fcs0 
+\f39\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \loch\af39\dbch\af31505\hich\f39 \'93}{\rtlch\fcs1 \ab\ai\af39 \ltrch\fcs0 \b\i\f39\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 
+Background}{\rtlch\fcs1 \af39 \ltrch\fcs0 \f39\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39 : Set the background color or use a texture (}{\rtlch\fcs1 \af39 \ltrch\fcs0 
+\f39\lang1033\langfe1031\langnp1033\insrsid9465848\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 cube maps}{\rtlch\fcs1 \af39 \ltrch\fcs0 \f39\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 
+ are supported as skyboxes) as background image for the viewer.
+\par }\pard \ltrpar\qj \fi-360\li720\ri1208\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin1208\lin720\itap0\pararsid3942873 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \tab }{\rtlch\fcs1 \af39\afs16 
+\ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 
+\hich\af39\dbch\af31505\loch\f39 Set color}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 ": Displays a color picker where you can choose 
+\hich\af39\dbch\af31505\loch\f39 a new background color for the viewer.
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Load skybox}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 ": Opens a file system dialog where you can select a skybox as background image. Accepted file formats are: *.dds, *.hdr.
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Load texture}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 ": Opens a file system dialog where you can select a texture as \hich\af39\dbch\af31505\loch\f39 
+background image. If the format of the texture doesn't fit to the proportions of the preview window, the texture will be stretched. }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid3942873 
+\par }\pard \ltrpar\qj \fi-12\li720\ri1208\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin1208\lin720\itap0\pararsid3942873 {\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 
+\hich\af39\dbch\af31505\loch\f39 Accepted file formats are: *.jpg;*.png;*.tif;*.tga;*.dds;*.hdr;*.ppm;*.bmp
+\par }\pard \ltrpar\ql \fi-360\li720\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin720\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 - "}{\rtlch\fcs1 
+\ab\af39\afs20 \ltrch\fcs0 \b\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 ?}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 ": }{
+\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \b\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Help and feedback}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 
 
-\par }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid3277197 \hich\af39\dbch\af31505\loch\f39 \hich\f39 The side panel \'93}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid3277197\charrsid3277197 \hich\af39\dbch\af31505\loch\f39 Statistics}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid3277197 \loch\af39\dbch\af31505\hich\f39 \'94
-\loch\f39  displays rendering statistics (\hich\af39\dbch\af31505\loch\f39 number of vertices loaded, number of faces, number of materials, frames per second, time required for loading).}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid602054\charrsid9194405 
-\par }\pard \ltrpar\s15\ql \li340\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin340\itap0\pararsid2186087\contextualspace {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid3277197 
-\hich\af39\dbch\af31505\loch\f39 \hich\f39 The \'93}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid3277197\charrsid3277197 \hich\af39\dbch\af31505\loch\f39 Rendering}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid3277197 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39 \hich\f39  panel provides rendering-related options, such as wireframe/normal visualization. \'93}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid3277197\charrsid3277197 \hich\af39\dbch\af31505\loch\f39 Interaction}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid3277197 \loch\af39\dbch\af31505\hich\f39 \'94
-\loch\f39  bundles all input related option\hich\af39\dbch\af31505\loch\f39 s.}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid2186087\charrsid2186087 
-\par }\pard \ltrpar\s15\ql \li340\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin340\itap0\pararsid5460125\contextualspace {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid2175529 
-\hich\af39\dbch\af31505\loch\f39 The main component is the large viewer panel where the assets are displayed. Status messages (e.g. if a texture could not be loaded) are displayed in the upper-left edge.}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid9194405\charrsid2175529 
-\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid9194405 
-\par {\listtext\pard\plain\ltrpar \s15 \rtlch\fcs1 \af0 \ltrch\fcs0 \f39\lang1033\langfe1031\langnp1033\insrsid5460125 \hich\af39\dbch\af31505\loch\f39 III.\tab}}\pard \ltrpar\s15\ql \fi-360\li340\ri0\sa200\sl276\slmult1
-\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls2\adjustright\rin0\lin340\itap0\pararsid3683098\contextualspace {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid5460125 \hich\af39\dbch\af31505\loch\f39 Input}{
-\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid5460125\charrsid3683098 
-\par }\pard \ltrpar\s15\ql \li340\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin340\itap0\pararsid9635109\contextualspace {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid3683098\charrsid3683098 \hich\af39\dbch\af31505\loch\f39 The input mode depends on the selected input }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8350123\charrsid3683098 \hich\af39\dbch\af31505\loch\f39 behavior}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid3683098\charrsid3683098 \hich\af39\dbch\af31505\loch\f39 
-\hich\f39 . If \'84}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid3683098\charrsid8350123 \hich\af39\dbch\af31505\loch\f39 Zoom/Rotate}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8350123 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid3683098\charrsid3683098 \hich\af39\dbch\af31505\loch\f39 is }{
-\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \b\f39\fs20\lang1033\langfe1031\langnp1033\insrsid3683098\charrsid8350123 \hich\af39\dbch\af31505\loch\f39 NOT}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid3683098\charrsid3683098 
-\hich\af39\dbch\af31505\loch\f39  selected the following scheme applies:}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109 
-\par }\pard \ltrpar\s15\ql \fi368\li340\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin340\itap0\pararsid9635109\contextualspace {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid9635109 \loch\af39\dbch\af31505\hich\f39 \lquote }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8745149 \hich\af39\dbch\af31505\loch\f39 Arrow up}{
-\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid9635109 \loch\af39\dbch\af31505\hich\f39 \rquote \loch\f39  }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109 
-\tab }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid9635109 \hich\af39\dbch\af31505\loch\f39 = Move forward}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109 
-\hich\af39\dbch\af31505\loch\f39 s
-\par }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid9635109 \loch\af39\dbch\af31505\hich\f39 \lquote }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid74094 \hich\af39\dbch\af31505\loch\f39 A}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8745149 \hich\af39\dbch\af31505\loch\f39 rrow left}{
-\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid74094 \loch\af39\dbch\af31505\hich\f39 \rquote }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid9635109 \hich\af39\dbch\af31505\loch\f39  }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109 \tab }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid9635109 \hich\af39\dbch\af31505\loch\f39 = Move }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109 \hich\af39\dbch\af31505\loch\f39 to the left
+\par \tab }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Feedback}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 
+\hich\af39\dbch\af31505\loch\f39 ": Opens a p\hich\af39\dbch\af31505\loch\f39 opup menu with two options:
+\par }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556 \tab }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 * "}{
+\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 Report bug}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 ": Report a bug in AssimpView or in Assimp
+\par }\pard \ltrpar\qj \fi-360\li720\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin720\itap0\pararsid13463017 {\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556 \tab }{\rtlch\fcs1 \af39\afs16 
+\ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 
+\hich\af39\dbch\af31505\loch\f39 Feature request}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 \hich\af39\dbch\af31505\loch\f39 ": Tell us what}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid9465848 \hich\af39\dbch\af31505\loch\f39  you'd like us to support. Any }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid13463017 
+\hich\af39\dbch\af31505\loch\f39 exotic file formats? 
+\par }\pard \ltrpar\qj \li340\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin340\itap0\pararsid13463017 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 \hich\f39 
+The side panel \'93}{\rtlch\fcs1 \ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 Statistics}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 
+\loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  displays rendering statistics. The meanings of the fi\hich\af39\dbch\af31505\loch\f39 elds change if you change between normal and texture/material mode.
+\par }\pard \ltrpar\qj \li340\ri1474\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin1474\lin340\itap0\pararsid13463017 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 
+Normal view mode:
+\par }\pard \ltrpar\qj \li340\ri1208\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin1208\lin340\itap0\pararsid5053873 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \tab }{\rtlch\fcs1 \af39\afs16 
+\ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 
+\hich\af39\dbch\af31505\loch\f39 Verts}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 ": Number of unique vertices in the asset
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 Faces}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid6912689 \hich\af39\dbch\af31505\loch\f39 ": Numb}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 
+er of faces (= triangles) in the asset
+\par \tab \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 Nodes}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 ": Number of nodes in the scenegraph, including the root node
+\par }\pard \ltrpar\qj \fi-368\li708\ri1208\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin1208\lin708\itap0\pararsid5053873 {\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 \tab 
+\hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 Mats:}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 " Number of different materials found in the mesh. Most loaders \tab remove unreferenced materials.
+\par }\pard \ltrpar\qj \li700\ri1208\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin1208\lin700\itap0\pararsid5053873 {\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 
+\hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 Mesh}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 ": Number of }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid6912689\charrsid5053873 
+\hich\af39\dbch\af31505\loch\f39 sub meshes}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 . Each mesh has only one material \tab assigned, so thi
+\hich\af39\dbch\af31505\loch\f39 s number is in most cases equal to or higher than the \tab number of materials.
+\par \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 Shd}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 ": Number of unique shaders created}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5053873 
+\hich\af39\dbch\af31505\loch\f39  for this asset. If AssimpView }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 
+detects that two materials can be rendered using }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5053873 \hich\af39\dbch\af31505\loch\f39 the same }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid6912689 \hich\af39\dbch\af31505\loch\f39 Shader}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5053873 \hich\af39\dbch\af31505\loch\f39  code, 
+\hich\af39\dbch\af31505\loch\f39 but \hich\af39\dbch\af31505\loch\f39 with }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid6912689\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 different}{\rtlch\fcs1 \af39\afs16 
+\ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 \hich\af39\dbch\af31505\loch\f39  }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid6912689\charrsid5053873 
+\hich\af39\dbch\af31505\loch\f39 parameterizations}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 , it do}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid5053873 \hich\af39\dbch\af31505\loch\f39 esn't create the }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid6912689 \hich\af39\dbch\af31505\loch\f39 Shader}{\rtlch\fcs1 
+\af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5053873 \hich\af39\dbch\af31505\loch\f39  twice. }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 
+\hich\af39\dbch\af31505\loch\f39 Most engines do so, too. 
+\par \hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 Time}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 ": Time required for loading, in seco}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5053873 
+\hich\af39\dbch\af31505\loch\f39 nds. This time is the raw time }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 the process spent in Assimp loading the mod}{
+\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5053873 \hich\af39\dbch\af31505\loch\f39 el itself, it does not include }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 texture loading, }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid6912689\charrsid5053873 
+\hich\af39\dbch\af31505\loch\f39 Shader}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 \hich\af39\dbch\af31505\loch\f39  compilation ...
+\par }\pard \ltrpar\qj \li700\ri1208\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin1208\lin700\itap0\pararsid9465848 {\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 
+\hich\af39\dbch\af31505\loch\f39 * "}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \b\i\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 FPS}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 ": Current frame rate, in frames per se}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5053873 
+\hich\af39\dbch\af31505\loch\f39 cond. Note that this number }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid13463017\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 is }{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 
+\f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid5053873 \hich\af39\dbch\af31505\loch\f39 not really exact.}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid5053873 \hich\af39\dbch\af31505\loch\f39 
+ It is only an approximation to the real frame rate. The maximum frame rate \hich\af39\dbch\af31505\loch\f39 will\hich\af39\dbch\af31505\loch\f39  \hich\af39\dbch\af31505\loch\f39 never be reached since there is a 10 ms blocker included (
+\hich\af39\dbch\af31505\loch\f39 to work around good old AMD timing bug\hich\af39\dbch\af31505\loch\f39 )}{\rtlch\fcs1 \af39\afs16 \ltrch\fcs0 \f39\fs16\lang1033\langfe1031\langnp1033\insrsid8068556\charrsid9465848 
+\par }\pard \ltrpar\ql \li340\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin340\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 \hich\f39 The \'93}{
+\rtlch\fcs1 \ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 Rendering}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 
+\loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  panel provides rendering-related options, such as wireframe/normal visualization.}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9465848 
+\par }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 \hich\f39  \'93}{\rtlch\fcs1 \ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 
+\hich\af39\dbch\af31505\loch\f39 Interaction}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  bundles all input related options.
+\par \hich\af39\dbch\af31505\loch\f39 The main \hich\af39\dbch\af31505\loch\f39 component is the large viewer panel where the assets are displayed. Status messages (e.g. if a texture could not be loaded)}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 
+\f39\fs20\lang1033\langfe1031\langnp1033\insrsid9465848 \hich\af39\dbch\af31505\loch\f39  \hich\af39\dbch\af31505\loch\f39 are displayed in the upper-right}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 
+\hich\af39\dbch\af31505\loch\f39  edge.}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9465848 \hich\af39\dbch\af31505\loch\f39 
+ Yellow messages are simple information messages, red messages are error messages. Green messages\hich\af39\dbch\af31505\loch\f39 , however, are coming from heart ;-)}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 
+\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 
+\par }{\rtlch\fcs1 \af39\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid8068556 
+\par }\pard \ltrpar\ql \fi-360\li340\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin340\itap0 {\rtlch\fcs1 \af39\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 III.\tab Input
+\par }\pard \ltrpar\ql \li340\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin340\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 \hich\f39 
+The input mode depends on the selected input behavior. If \'84}{\rtlch\fcs1 \ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 Zoom/Rotate}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 
+\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  is }{\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 NOT}{
+\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39  selected the following scheme applies:
+\par }\pard \ltrpar\ql \fi368\li340\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin340\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \loch\af39\dbch\af31505\hich\f39 \lquote }{\rtlch\fcs1 
+\ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 Arrow up}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \loch\af39\dbch\af31505\hich\f39 
+\rquote \loch\f39  \tab = Move forwards
+\par \loch\af39\dbch\af31505\hich\f39 \lquote }{\rtlch\fcs1 \ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 Arrow left\hich\f39 \rquote }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 
+\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39  \tab = Move to the left
+\par \loch\af39\dbch\af31505\hich\f39 \lquote }{\rtlch\fcs1 \ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 Arrow down}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 
+\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \loch\af39\dbch\af31505\hich\f39 \rquote \loch\f39  \tab = Move backwards
+\par \loch\af39\dbch\af31505\hich\f39 \lquote }{\rtlch\fcs1 \ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 Arrow right}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 
+\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \loch\af39\dbch\af31505\hich\f39 \rquote \loch\f39  \tab = Move to the right
+\par }\pard \ltrpar\ql \fi340\li0\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 
+The mouse specifies the view direction. This is the typical FPS input behavior.
+\par }{\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 Otherwise\hich\af39\dbch\af31505\loch\f39 \hich\f39 , if \'84}{\rtlch\fcs1 \ab\ai\af39\afs20 \ltrch\fcs0 
+\b\i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 Zoom/Rotate}{\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39 
+ is enabled:
+\par }\pard \ltrpar\ql \li340\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin340\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \loch\af39\dbch\af31505\hich\f39 \'93}{\rtlch\fcs1 
+\ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 Left Mouse Button}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 
+\loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  = Keep pressed and move the mouse to rotate the asset around its local axes. Inside the yellow circle: x/y-axis, outside: Z-axis. To rotate around one axis only use the axis snap-ins (yellow squares with a
+\hich\af39\dbch\af31505\loch\f39  cross inside).
+\par \loch\af39\dbch\af31505\hich\f39 \'93}{\rtlch\fcs1 \ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 Right Mouse Button}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 
+\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  = Keep pressed and move the mouse to rotate the light source(s) around their x and y axes.
+\par \loch\af39\dbch\af31505\hich\f39 \'93}{\rtlch\fcs1 \ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 Middle Mouse Button}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 
+\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  = Keep pressed and move the mouse from the left to the right or the other way round to increase/decrease t\hich\af39\dbch\af31505\loch\f39 
+he intensity of the light source(s)
+\par \loch\af39\dbch\af31505\hich\f39 \'93}{\rtlch\fcs1 \ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 Right }{\rtlch\fcs1 \ab\ai\af39\afs20 \ltrch\fcs0 
+\b\i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 AND}{\rtlch\fcs1 \ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39  Left Mouse Button}{
+\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  = Keep pressed and move the mouse to rotate skybox (if existing) around the global x/y axes.
+\par \loch\af39\dbch\af31505\hich\f39 \'93}{\rtlch\fcs1 \ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 Mouse wheel}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 
+\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  = Zoom in/out
+\par }\pard \ltrpar\ql \fi-360\li340\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin340\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 IV.\tab }{\rtlch\fcs1 
+\af39\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 Rendering
+\par }\pard \ltrpar\ql \li340\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin340\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 
+Enabling MultiSampling improves rendering\hich\af39\dbch\af31505\loch\f39  quality. MultiSampling is activated by default. The highest quality MultiSampling mode supported by the video card is used.
+\par \hich\af39\dbch\af31505\loch\f39 MultiSampling is especially useful to remove line artifacts in wireframe/normals mode. Note that the transition between normal and \hich\af39\dbch\af31505\loch\f39 multisampled rendering may take a few seconds.
+\par \hich\af39\dbch\af31505\loch\f39 \hich\f39 Rendering is done via Direct3D\'99\loch\f39 \hich\f39  9.0c. Note that the \'93}{\rtlch\fcs1 \ai\af39\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 
+Low-quality lighting}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39 -Option is not available for PS 2.0 cards. Lighting on PS 2.0 cards is always low quality.
 
-\par }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid9635109 \loch\af39\dbch\af31505\hich\f39 \lquote }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8745149 
-\hich\af39\dbch\af31505\loch\f39 Arrow down}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid9635109 \loch\af39\dbch\af31505\hich\f39 \rquote \loch\f39  }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109 \tab }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid9635109 \hich\af39\dbch\af31505\loch\f39 = }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109 \hich\af39\dbch\af31505\loch\f39 Move backwards
-\par }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid9635109 \loch\af39\dbch\af31505\hich\f39 \lquote }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid8745149 
-\hich\af39\dbch\af31505\loch\f39 Arrow right}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid9635109 \loch\af39\dbch\af31505\hich\f39 \rquote \loch\f39  }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109 \tab }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid9635109 \hich\af39\dbch\af31505\loch\f39 = }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109 \hich\af39\dbch\af31505\loch\f39 Move to the right
-\par }\pard\plain \ltrpar\ql \fi340\li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid9635109 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 
-\fs22\lang1031\langfe1031\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid9635109 \hich\af39\dbch\af31505\loch\f39 The}{\rtlch\fcs1 
-\af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid9635109 \hich\af39\dbch\af31505\loch\f39  mouse specifies the view direction. This is the typical FPS input behavior.
-\par }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \b\f39\fs20\lang1033\langfe1031\langnp1033\insrsid14293319\charrsid67262 \hich\af39\dbch\af31505\loch\f39 \hich\f39 Otherwise, if \'84}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\b\i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid14293319\charrsid67262 \hich\af39\dbch\af31505\loch\f39 Zoom/Rotate}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \b\f39\fs20\lang1033\langfe1031\langnp1033\insrsid14293319\charrsid67262 
-\loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  is enabled:
-\par }\pard \ltrpar\ql \li340\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin340\itap0\pararsid14293319 {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid14293319 
-\loch\af39\dbch\af31505\hich\f39 \'93}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid14293319\charrsid74094 \hich\af39\dbch\af31505\loch\f39 Left Mouse Button}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid14293319 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  = Keep pressed and move the mouse to rotate the asset around its local axes. Inside the yellow circle: x/y-axis, outside: Z-axis}{\rtlch\fcs1 
-\af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid11029790 \hich\af39\dbch\af31505\loch\f39 . To rotate around one axis only use the axis snap-ins (yellow squar\hich\af39\dbch\af31505\loch\f39 es with a cross inside).}{\rtlch\fcs1 
-\af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid14293319 
-\par \loch\af39\dbch\af31505\hich\f39 \'93}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid14293319\charrsid74094 \hich\af39\dbch\af31505\loch\f39 Right Mouse Button}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid14293319 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  = Keep pressed and move the mouse to rotate the light source(s) around their x and y axes.
-\par \loch\af39\dbch\af31505\hich\f39 \'93}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid14293319\charrsid74094 \hich\af39\dbch\af31505\loch\f39 Middle Mouse Button}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid14293319 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  = Keep pressed and move the mouse }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid1405492 
-\hich\af39\dbch\af31505\loch\f39 from the left to the right or the other way round to increase/decrease the intensity of the light source(s)}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid14293319 
-\par }\pard \ltrpar\ql \li340\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin340\itap0\pararsid7677524 {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid7677524 
-\loch\af39\dbch\af31505\hich\f39 \'93}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid7677524\charrsid74094 \hich\af39\dbch\af31505\loch\f39 Right }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\b\i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid7677524\charrsid7677524 \hich\af39\dbch\af31505\loch\f39 AND}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid7677524 \hich\af39\dbch\af31505\loch\f39  Left }{
-\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid7677524\charrsid74094 \hich\af39\dbch\af31505\loch\f39 Mouse Button}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid7677524 
-\loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  = Keep pressed and move the mouse to rotate \hich\af39\dbch\af31505\loch\f39 skybox (\hich\af39\dbch\af31505\loch\f39 if existing\hich\af39\dbch\af31505\loch\f39 )\hich\af39\dbch\af31505\loch\f39 
- around the global x/y axes.
-\par }\pard \ltrpar\ql \li340\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin340\itap0\pararsid14293319 {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid7360491 
-\loch\af39\dbch\af31505\hich\f39 \'93}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid7360491 \hich\af39\dbch\af31505\loch\f39 Mouse wheel}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid7360491 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39  = Zoom in/out
-\par {\listtext\pard\plain\ltrpar \s15 \rtlch\fcs1 \af0 \ltrch\fcs0 \f39\lang1033\langfe1031\langnp1033\insrsid10752424 \hich\af39\dbch\af31505\loch\f39 IV.\tab}}\pard\plain \ltrpar\s15\ql \fi-360\li340\ri0\sa200\sl276\slmult1
-\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls2\adjustright\rin0\lin340\itap0\pararsid10752424\contextualspace \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 
-\fs22\lang1031\langfe1031\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid10752424 \hich\af39\dbch\af31505\loch\f39 Rendering
-\par }\pard \ltrpar\s15\ql \li340\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin340\itap0\pararsid10752424\contextualspace {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid10752424 
-\hich\af39\dbch\af31505\loch\f39 Enabling MultiSampling improves rendering quality. MultiSampling is activated by default. The highest qual\hich\af39\dbch\af31505\loch\f39 ity MultiSampling mode supported by the video card is used.
-\par }\pard \ltrpar\s15\ql \li340\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin340\itap0\pararsid2961835\contextualspace {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid10752424 
-\hich\af39\dbch\af31505\loch\f39 MultiSampling is especially useful to remove line artifacts in wireframe/normals mode. Note that the transition between normal and multisampled rendering may take a few seconds.}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid14187505\charrsid2961835 
-\par }\pard \ltrpar\s15\ql \li340\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin340\itap0\pararsid10752424\contextualspace {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid14187505 
-\hich\af39\dbch\af31505\loch\f39 Rendering is done \hich\af39\dbch\af31505\loch\f39 via Direct3D}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid14187505\charrsid14187505 \loch\af39\dbch\af31505\hich\f39 \'99}{
-\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid5860386 \hich\af39\dbch\af31505\loch\f39  9.0c.}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid14187505 
-\hich\af39\dbch\af31505\loch\f39 \hich\f39  Note that the \'93}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \i\f39\fs20\lang1033\langfe1031\langnp1033\insrsid14187505\charrsid14187505 \hich\af39\dbch\af31505\loch\f39 Low-quality lighting}{\rtlch\fcs1 \af0\afs20 
-\ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid14187505 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39 -Option is not available for PS 2.0 cards. Lighting on PS 2.0 cards is always low quality.
-\par }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid14115297 
-\par {\listtext\pard\plain\ltrpar \s15 \rtlch\fcs1 \af0 \ltrch\fcs0 \f39\lang1033\langfe1031\langnp1033\insrsid14115297 \hich\af39\dbch\af31505\loch\f39 V.\tab}}\pard \ltrpar\s15\ql \fi-360\li340\ri0\sa200\sl276\slmult1
-\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls2\adjustright\rin0\lin340\itap0\pararsid14115297\contextualspace {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid14115297 \hich\af39\dbch\af31505\loch\f39 Known issues}{
-\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid14115297\charrsid3683098 \hich\af39\dbch\af31505\loch\f39  }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid14115297 
-\par {\listtext\pard\plain\ltrpar \s15 \rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid14115297 \hich\af39\dbch\af31505\loch\f39 -\tab}}\pard \ltrpar\s15\ql \fi-360\li700\ri0\sa200\sl276\slmult1
-\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls4\adjustright\rin0\lin700\itap0\pararsid2961835\contextualspace {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid14115297 \hich\af39\dbch\af31505\loch\f39 
-If a loading process is canceled it is not guaranteed that further loading processes will succeed. ASSIMP Viewer might even crash in this case. }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid14115297\charrsid2961835 
-
-\par {\listtext\pard\plain\ltrpar \s15 \rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid2961835 \hich\af39\dbch\af31505\loch\f39 -\tab}}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 
-\f39\fs20\lang1033\langfe1031\langnp1033\insrsid2961835 \hich\af39\dbch\af31505\loch\f39 Some very complex materials involving real time reflection/refraction are not displayed properly.}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
-\f39\fs24\lang1033\langfe1031\langnp1033\insrsid2961835\charrsid2961835 
-\par {\listtext\pard\plain\ltrpar \s15 \rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid2961835 \hich\af39\dbch\af31505\loch\f39 -\tab}}\pard \ltrpar\s15\ql \fi-360\li700\ri0\sa200\sl276\slmult1
-\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls4\adjustright\rin0\lin700\itap0\pararsid9635109\contextualspace {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid2961835 \hich\af39\dbch\af31505\loch\f39 When rend
-\hich\af39\dbch\af31505\loch\f39 ering non-opaque objects some triangle artifacts might occur}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid10617294 .}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
-\f39\fs24\lang1033\langfe1031\langnp1033\insrsid9635109\charrsid10617294 
+\par 
+\par }\pard \ltrpar\ql \fi-360\li340\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin340\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 V.\tab }{\rtlch\fcs1 
+\af39\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid8068556 \hich\af39\dbch\af31505\loch\f39 Known issues 
+\par }\pard \ltrpar\ql \fi-360\li700\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin700\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 -\tab \hich\af39\dbch\af31505\loch\f39 
+If a loading process is \hich\af39\dbch\af31505\loch\f39 canceled it is not guaranteed that further loading processes will succeed. ASSIMP Viewer might even crash in this case. }{\rtlch\fcs1 \af39\afs24 \ltrch\fcs0 
+\f39\fs24\lang1033\langfe1031\langnp1033\insrsid8068556 
+\par }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 -\tab \hich\af39\dbch\af31505\loch\f39 Some very complex materials involving real time reflection/refraction are not displayed properly.}{\rtlch\fcs1 
+\af39\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid8068556 
+\par }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\lang1033\langfe1031\langnp1033\insrsid8068556 -\tab \hich\af39\dbch\af31505\loch\f39 When rendering non-opaque objects\hich\af39\dbch\af31505\loch\f39  some triangle artifacts might occur.}{\rtlch\fcs1 
+\af39\afs24 \ltrch\fcs0 \f39\fs24\lang1033\langfe1031\langnp1033\insrsid8068556 
 \par }{\*\themedata 504b030414000600080000002100828abc13fa0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb6ac3301045f785fe83d0b6d8
 72ba28a5d8cea249777d2cd20f18e4b12d6a8f843409c9df77ecb850ba082d74231062ce997b55ae8fe3a00e1893f354e9555e6885647de3a8abf4fbee29bbd7
 2a3150038327acf409935ed7d757e5ee14302999a654e99e393c18936c8f23a4dc072479697d1c81e51a3b13c07e4087e6b628ee8cf5c4489cf1c4d075f92a0b
@@ -363,8 +366,8 @@ fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff
 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffffec69d9888b8b3d4c859eaf6cd158be0f00000000000000000000000060e3
-1310819dc801feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000
+ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffffec69d9888b8b3d4c859eaf6cd158be0f0000000000000000000000004091
+1ff3e2b4c801feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000
 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000
 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000
-0000000000000000000000000000000000000000000000000105000000000000}}
+0000000000000000000000000000000000000000000000000105000000000000}}

BIN
tools/assimp_view/txi.bmp


+ 8 - 4
workspaces/vc8/assimp.vcproj

@@ -38,7 +38,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="../../include"
+				AdditionalIncludeDirectories="../../include;../../code"
 				PreprocessorDefinitions="DEBUG, _SCL_SECURE_NO_WARNINGS, _CRT_SECURE_NO_WARNINGS,WIN32"
 				BasicRuntimeChecks="3"
 				SmallerTypeCheck="true"
@@ -102,7 +102,7 @@
 				InlineFunctionExpansion="2"
 				EnableIntrinsicFunctions="true"
 				FavorSizeOrSpeed="1"
-				AdditionalIncludeDirectories="../../include"
+				AdditionalIncludeDirectories="../../include;../../code"
 				PreprocessorDefinitions="NDEBUG, _SCL_SECURE_NO_WARNINGS, _CRT_SECURE_NO_WARNINGS,WIN32"
 				StringPooling="true"
 				BufferSecurityCheck="false"
@@ -164,7 +164,7 @@
 				InlineFunctionExpansion="2"
 				EnableIntrinsicFunctions="true"
 				FavorSizeOrSpeed="1"
-				AdditionalIncludeDirectories="../../include"
+				AdditionalIncludeDirectories="../../include;../../code"
 				PreprocessorDefinitions="NDEBUG, _SCL_SECURE_NO_WARNINGS, _CRT_SECURE_NO_WARNINGS,WIN32"
 				StringPooling="true"
 				BufferSecurityCheck="false"
@@ -233,7 +233,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="../../include"
+				AdditionalIncludeDirectories="../../include;../../code"
 				PreprocessorDefinitions="DEBUG, _SCL_SECURE_NO_WARNINGS, _CRT_SECURE_NO_WARNINGS,WIN32"
 				BasicRuntimeChecks="3"
 				SmallerTypeCheck="true"
@@ -399,6 +399,10 @@
 				RelativePath="..\..\code\BaseProcess.h"
 				>
 			</File>
+			<File
+				RelativePath="..\..\code\ByteSwap.h"
+				>
+			</File>
 			<File
 				RelativePath="..\..\code\CalcTangentsProcess.h"
 				>

+ 22 - 2
workspaces/vc8/assimp_view.vcproj

@@ -40,7 +40,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="&quot;$(DXSDK_DIR)include&quot;;..\..\include"
+				AdditionalIncludeDirectories="&quot;$(DXSDK_DIR)include&quot;;..\..\include;..\..\code"
 				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS"
 				MinimalRebuild="true"
 				BasicRuntimeChecks="3"
@@ -121,7 +121,7 @@
 			/>
 			<Tool
 				Name="VCCLCompilerTool"
-				AdditionalIncludeDirectories="&quot;$(DXSDK_DIR)include&quot;;..\..\include"
+				AdditionalIncludeDirectories="&quot;$(DXSDK_DIR)include&quot;;..\..\include;..\..\code"
 				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS"
 				RuntimeLibrary="0"
 				UsePrecompiledHeader="2"
@@ -218,6 +218,10 @@
 				RelativePath="..\..\tools\assimp_view\Material.cpp"
 				>
 			</File>
+			<File
+				RelativePath="..\..\tools\assimp_view\MeshRenderer.cpp"
+				>
+			</File>
 			<File
 				RelativePath="..\..\tools\assimp_view\MessageProc.cpp"
 				>
@@ -226,6 +230,10 @@
 				RelativePath="..\..\tools\assimp_view\no_materials.fx"
 				>
 			</File>
+			<File
+				RelativePath="..\..\tools\assimp_view\Normals.cpp"
+				>
+			</File>
 			<File
 				RelativePath="..\..\tools\assimp_view\Shaders.cpp"
 				>
@@ -284,6 +292,14 @@
 				RelativePath="..\..\tools\assimp_view\LogWindow.h"
 				>
 			</File>
+			<File
+				RelativePath="..\..\tools\assimp_view\MaterialManager.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\tools\assimp_view\MeshRenderer.h"
+				>
+			</File>
 			<File
 				RelativePath="..\..\tools\assimp_view\RenderOptions.h"
 				>
@@ -370,6 +386,10 @@
 				RelativePath="..\..\tools\assimp_view\tx.bmp"
 				>
 			</File>
+			<File
+				RelativePath="..\..\tools\assimp_view\txi.bmp"
+				>
+			</File>
 		</Filter>
 	</Files>
 	<Globals>

Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov