diff --git a/code/3DSHelper.h b/code/3DSHelper.h index 43989639e..d53bf9bc8 100644 --- a/code/3DSHelper.h +++ b/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; diff --git a/code/3DSLoader.cpp b/code/3DSLoader.cpp index e2c5eef40..f313bade8 100644 --- a/code/3DSLoader.cpp +++ b/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: diff --git a/code/BaseProcess.h b/code/BaseProcess.h index 8254d971f..79b79e04e 100644 --- a/code/BaseProcess.h +++ b/code/BaseProcess.h @@ -60,7 +60,7 @@ class BaseProcess { friend class Importer; -protected: +public: /** Constructor to be privately used by Importer */ BaseProcess(); diff --git a/code/ByteSwap.h b/code/ByteSwap.h new file mode 100644 index 000000000..153d117be --- /dev/null +++ b/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 diff --git a/code/CalcTangentsProcess.cpp b/code/CalcTangentsProcess.cpp index 874c2dfcf..74a88ccab 100644 --- a/code/CalcTangentsProcess.cpp +++ b/code/CalcTangentsProcess.cpp @@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#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"); } // ------------------------------------------------------------------------------------------------ diff --git a/code/CalcTangentsProcess.h b/code/CalcTangentsProcess.h index 97e61b017..fb37fd981 100644 --- a/code/CalcTangentsProcess.h +++ b/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(); diff --git a/code/ConvertToLHProcess.cpp b/code/ConvertToLHProcess.cpp index 22ff35596..a19e279e7 100644 --- a/code/ConvertToLHProcess.cpp +++ b/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"); } // ------------------------------------------------------------------------------------------------ diff --git a/code/DefaultLogger.cpp b/code/DefaultLogger.cpp index 725dd4ad3..b83dc0335 100644 --- a/code/DefaultLogger.cpp +++ b/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() ); } // --------------------------------------------------------------------------- diff --git a/code/DefaultLogger.h b/code/DefaultLogger.h index c88a3bbe5..98f94dffe 100644 --- a/code/DefaultLogger.h +++ b/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 diff --git a/code/GenFaceNormalsProcess.cpp b/code/GenFaceNormalsProcess.cpp index ac082a7b3..c6f1c999c 100644 --- a/code/GenFaceNormalsProcess.cpp +++ b/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; } \ No newline at end of file diff --git a/code/GenFaceNormalsProcess.h b/code/GenFaceNormalsProcess.h index 6fbec39bf..52c154148 100644 --- a/code/GenFaceNormalsProcess.h +++ b/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 diff --git a/code/GenVertexNormalsProcess.cpp b/code/GenVertexNormalsProcess.cpp index 3bb8b17fd..c61977c2f 100644 --- a/code/GenVertexNormalsProcess.cpp +++ b/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; } \ No newline at end of file diff --git a/code/GenVertexNormalsProcess.h b/code/GenVertexNormalsProcess.h index 10a03d4be..516bcc9c4 100644 --- a/code/GenVertexNormalsProcess.h +++ b/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. */ - class GenVertexNormalsProcess : public BaseProcess - { - friend class Importer; + bool IsActive( unsigned int pFlags) const; - protected: - /** Constructor to be privately used by Importer */ - GenVertexNormalsProcess(); - - /** Destructor, private as well */ - ~GenVertexNormalsProcess(); - - public: - // ------------------------------------------------------------------- - /** Returns whether the processing step is present in the given flag field. - * @param pFlags The processing flags the importer was called with. A bitwise - * combination of #aiPostProcessSteps. - * @return true if the process is present in this flag fields, false if not. - */ - bool IsActive( unsigned int pFlags) const; - - // ------------------------------------------------------------------- - /** Executes the post processing step on the given imported data. - * At the moment a process is not supposed to fail. - * @param pScene The imported data to work at. - */ - void Execute( aiScene* pScene); + // ------------------------------------------------------------------- + /** Executes the post processing step on the given imported data. + * At the moment a process is not supposed to fail. + * @param pScene The imported data to work at. + */ + void Execute( aiScene* pScene); - private: - void GenMeshVertexNormals (aiMesh* pcMesh); - }; +private: + bool GenMeshVertexNormals (aiMesh* pcMesh); +}; - } // end of namespace Assimp +}; // end of namespace Assimp #endif // !!AI_GENVERTEXNORMALPROCESS_H_INC \ No newline at end of file diff --git a/code/Importer.cpp b/code/Importer.cpp index b61d5679b..b5b634025 100644 --- a/code/Importer.cpp +++ b/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; } diff --git a/code/JoinVerticesProcess.cpp b/code/JoinVerticesProcess.cpp index 3d5e092dd..9afd28295 100644 --- a/code/JoinVerticesProcess.cpp +++ b/code/JoinVerticesProcess.cpp @@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #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 uniqueVertices; uniqueVertices.reserve( pMesh->mNumVertices); + unsigned int iOldVerts = pMesh->mNumVertices; + // For each vertex the index of the vertex it was replaced by. std::vector 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); } diff --git a/code/JoinVerticesProcess.h b/code/JoinVerticesProcess.h index ca1a8e87b..277f4b5cd 100644 --- a/code/JoinVerticesProcess.h +++ b/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; } }; diff --git a/code/KillNormalsProcess.cpp b/code/KillNormalsProcess.cpp index d28a5cdc6..342ad8fc7 100644 --- a/code/KillNormalsProcess.cpp +++ b/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; } \ No newline at end of file diff --git a/code/KillNormalsProcess.h b/code/KillNormalsProcess.h index 83a97dba1..698c0d92a 100644 --- a/code/KillNormalsProcess.h +++ b/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. */ - class KillNormalsProcess : public BaseProcess - { - friend class Importer; + bool IsActive( unsigned int pFlags) const; - protected: - /** Constructor to be privately used by Importer */ - KillNormalsProcess(); - - /** Destructor, private as well */ - ~KillNormalsProcess(); - - public: - // ------------------------------------------------------------------- - /** Returns whether the processing step is present in the given flag field. - * @param pFlags The processing flags the importer was called with. A bitwise - * combination of #aiPostProcessSteps. - * @return true if the process is present in this flag fields, false if not. - */ - bool IsActive( unsigned int pFlags) const; - - // ------------------------------------------------------------------- - /** Executes the post processing step on the given imported data. - * At the moment a process is not supposed to fail. - * @param pScene The imported data to work at. - */ - void Execute( aiScene* pScene); + // ------------------------------------------------------------------- + /** Executes the post processing step on the given imported data. + * At the moment a process is not supposed to fail. + * @param pScene The imported data to work at. + */ + void Execute( aiScene* pScene); - private: - void KillMeshNormals (aiMesh* pcMesh); - }; - - } // end of namespace Assimp +private: + bool KillMeshNormals (aiMesh* pcMesh); +}; +}; // end of namespace Assimp #endif // !!AI_KILLNORMALPROCESS_H_INC \ No newline at end of file diff --git a/code/MDLFileData.h b/code/MDLFileData.h index f15e4ab86..7a4d41f2d 100644 --- a/code/MDLFileData.h +++ b/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 // --------------------------------------------------------------------------- diff --git a/code/MDLLoader.cpp b/code/MDLLoader.cpp index d68ef81d5..606eb8471 100644 --- a/code/MDLLoader.cpp +++ b/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(&szFile,1,AI_MATKEY_TEXTURE_DIFFUSE(0)); + pcMatOut->AddProperty(&szFile,AI_MATKEY_TEXTURE_DIFFUSE(0)); } - else if (0 != iMasked) + else if (0 != iMasked || 0 == pcSkin->typ) { // ***** STANDARD COLOR TEXTURE ***** + pcNew = new aiTexture(); if (0 == pcSkin->height || 0 == pcSkin->width) { - // LOG + DefaultLogger::get()->warn("Found embedded texture, but its width " + "an height are both 0. Is this a joke?"); + + // generate an empty chess pattern + pcNew->mWidth = pcNew->mHeight = 8; + pcNew->pcData = new aiTexel[64]; + for (unsigned int x = 0; x < 8;++x) + { + for (unsigned int y = 0; y < 8;++y) + { + bool bSet = false; + if (0 == x % 2 && 0 != y % 2 || + 0 != x % 2 && 0 == y % 2)bSet = true; + + aiTexel* pc = &pcNew->pcData[y * 8 + x]; + if (bSet)pc->r = pc->b = pc->g = 0xFF; + else pc->r = pc->b = pc->g = 0; + pc->a = 0xFF; + } + } } + else + { + // it is a standard color texture. Fill in width and height + // and call the same function we used for loading MDL5 files - // it is a standard color texture. Fill in width and height - // and call the same function we used for loading MDL5 files + pcNew->mWidth = pcSkin->width; + pcNew->mHeight = pcSkin->height; - pcNew = new aiTexture(); - pcNew->mWidth = pcSkin->width; - pcNew->mHeight = pcSkin->height; + unsigned int iSkip = 0; + this->ParseTextureColorData(szCurrent,iMasked,&iSkip,pcNew); - unsigned int iSkip = 0; - this->ParseTextureColorData(szCurrent,iMasked,&iSkip,pcNew); - - // skip length of texture data - szCurrent += iSkip; + // skip length of texture data + szCurrent += iSkip; + } } // check whether a material definition is contained in the skin @@ -1169,6 +1196,17 @@ void MDLImporter::ParseSkinLump_GameStudioA7( delete[] pc; } + // place the name of the skin in the material + const size_t iLen = strlen(pcSkin->texture_name); + if (0 != iLen) + { + aiString szFile; + memcpy(szFile.data,pcSkin->texture_name,sizeof(pcSkin->texture_name)); + szFile.length = iLen; + + pcMatOut->AddProperty(&szFile,AI_MATKEY_NAME); + } + *szCurrentOut = szCurrent; return; } @@ -1243,7 +1281,8 @@ void MDLImporter::InternReadFile_GameStudioA7( ) if (1 != pcGroup->typ) { // Not a triangle-based mesh - // LOGWRITE("[3DGS MDL7] Mesh group is no basing in triangles. Continuing happily"); + DefaultLogger::get()->warn("[3DGS MDL7] Mesh group is not basing on" + "triangles. Continuing happily"); } // read all skins @@ -1315,6 +1354,8 @@ void MDLImporter::InternReadFile_GameStudioA7( ) { // LOG iIndex = pcGroup->numverts-1; + + DefaultLogger::get()->warn("Index overflow in MDL7 vertex list"); } unsigned int iOutIndex = iTriangle * 3 + c; @@ -1439,7 +1480,10 @@ void MDLImporter::InternReadFile_GameStudioA7( ) // use the last material instead aiSplit[iNumMaterials-1]->push_back(iFace); - // LOG + // sometimes MED writes -1, but normally only if there is only + // one skin assigned. No warning in this case + if(0xFFFFFFFF != pcFaces[iFace].iMatIndex[0]) + DefaultLogger::get()->warn("Index overflow in MDL7 material list [#0]"); } else aiSplit[pcFaces[iFace].iMatIndex[0]]->push_back(iFace); } @@ -1464,13 +1508,19 @@ void MDLImporter::InternReadFile_GameStudioA7( ) if (iMatIndex >= iNumMaterials) { iMatIndex = iNumMaterials-1; - // LOG + + // sometimes MED writes -1, but normally only if there is only + // one skin assigned. No warning in this case + if(0xFFFFFFFF != iMatIndex) + DefaultLogger::get()->warn("Index overflow in MDL7 material list [#1]"); } unsigned int iMatIndex2 = pcFaces[iFace].iMatIndex[1]; if (iMatIndex2 >= iNumMaterials) { - iMatIndex2 = iNumMaterials-1; - // LOG + // sometimes MED writes -1, but normally only if there is only + // one skin assigned. No warning in this case + if(0xFFFFFFFF != iMatIndex2) + DefaultLogger::get()->warn("Index overflow in MDL7 material list [#2]"); } // do a slow O(log(n)*n) seach in the list ... @@ -1563,7 +1613,7 @@ void MDLImporter::InternReadFile_GameStudioA7( ) if (((unsigned int)szCurrent - (unsigned int)pcHeader) + iAdd > (unsigned int)pcHeader->data_size) { - // LOG + DefaultLogger::get()->warn("Index overflow in frame area. Ignoring frames"); // don't parse more groups if we can't even read one goto __BREAK_OUT; } diff --git a/code/MaterialSystem.cpp b/code/MaterialSystem.cpp index 3217f3361..7eaa55fa9 100644 --- a/code/MaterialSystem.cpp +++ b/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) { diff --git a/code/MaterialSystem.h b/code/MaterialSystem.h index 37ab3eec4..a72d917ae 100644 --- a/code/MaterialSystem.h +++ b/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 diff --git a/code/ObjFileImporter.cpp b/code/ObjFileImporter.cpp index 0ea6f2dba..2c1c6d99f 100644 --- a/code/ObjFileImporter.cpp +++ b/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(); } // ------------------------------------------------------------------------------------------------ diff --git a/code/PlyLoader.cpp b/code/PlyLoader.cpp index 4eda0071b..23fd2cc37 100644 --- a/code/PlyLoader.cpp +++ b/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)"); } diff --git a/code/PlyParser.cpp b/code/PlyParser.cpp index 83d5577d0..cb2f3e287 100644 --- a/code/PlyParser.cpp +++ b/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::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::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::iterator i = p_pcOut->alProperties.begin(); std::vector::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::iterator i = p_pcOut->alProperties.begin(); std::vector::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(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(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; } diff --git a/code/PlyParser.h b/code/PlyParser.h index cc6dbf488..b8a35440f 100644 --- a/code/PlyParser.h +++ b/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); diff --git a/code/SplitLargeMeshes.cpp b/code/SplitLargeMeshes.cpp index d26b64720..977fda6e3 100644 --- a/code/SplitLargeMeshes.cpp +++ b/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 > 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 >& 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 > 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(pMesh,a)); + avList.push_back(std::pair(pMesh,a)); return; } diff --git a/code/TriangulateProcess.cpp b/code/TriangulateProcess.cpp index 21a146213..d4a54a5ab 100644 --- a/code/TriangulateProcess.cpp +++ b/code/TriangulateProcess.cpp @@ -4,6 +4,7 @@ #include #include #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 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; } diff --git a/code/TriangulateProcess.h b/code/TriangulateProcess.h index 04c59cf72..10cde2eb6 100644 --- a/code/TriangulateProcess.h +++ b/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 diff --git a/code/XFileImporter.cpp b/code/XFileImporter.cpp index af0f478d5..380de4db9 100644 --- a/code/XFileImporter.cpp +++ b/code/XFileImporter.cpp @@ -561,8 +561,13 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, const std::vectorAddProperty( &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( &shadeMode, 1, AI_MATKEY_SHADING_MODEL); // material colours mat->AddProperty( &oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE); diff --git a/include/aiMaterial.h b/include/aiMaterial.h index 8c1713b85..0387a8c2e 100644 --- a/include/aiMaterial.h +++ b/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 diff --git a/include/aiTypes.h b/include/aiTypes.h index 3518564c4..674615e0e 100644 --- a/include/aiTypes.h +++ b/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 diff --git a/include/aiVector3D.h b/include/aiVector3D.h index 1f7cc0df5..a60c02df2 100644 --- a/include/aiVector3D.h +++ b/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; diff --git a/tools/assimp_view/AssetHelper.h b/tools/assimp_view/AssetHelper.h index 76557570b..72c3a1a2d 100644 --- a/tools/assimp_view/AssetHelper.h +++ b/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 \ No newline at end of file diff --git a/tools/assimp_view/Background.cpp b/tools/assimp_view/Background.cpp index ff76d6d47..0d63453a5 100644 --- a/tools/assimp_view/Background.cpp +++ b/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"); } } + // 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"); + } +} }; \ No newline at end of file diff --git a/tools/assimp_view/Display.cpp b/tools/assimp_view/Display.cpp index 1577c4e3b..59c5fc9c9 100644 --- a/tools/assimp_view/Display.cpp +++ b/tools/assimp_view/Display.cpp @@ -1 +1,2086 @@ -#include "stdafx.h" \ No newline at end of file +/* +--------------------------------------------------------------------------- +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 ()",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::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::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::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::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::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 +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 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(clrOld.r * 255.0f), + clamp(clrOld.g * 255.0f), + clamp(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::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(&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(&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::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::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; +} +}; + diff --git a/tools/assimp_view/Display.h b/tools/assimp_view/Display.h index e69de29bb..44e4a1718 100644 --- a/tools/assimp_view/Display.h +++ b/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 m_asTextures; + + // current texture or NULL if no texture is active + TextureInfo* m_pcCurrentTexture; + + // List of all node in the display CB + std::vector m_asNodes; + + // current Node or NULL if no Node is active + NodeInfo* m_pcCurrentNode; + + // List of all materials in the display CB + std::vector 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 \ No newline at end of file diff --git a/tools/assimp_view/Input.cpp b/tools/assimp_view/Input.cpp index 71b9a6b25..d9da956b8 100644 --- a/tools/assimp_view/Input.cpp +++ b/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 ); } }; \ No newline at end of file diff --git a/tools/assimp_view/LogDisplay.h b/tools/assimp_view/LogDisplay.h index 953c17735..4fb947ecd 100644 --- a/tools/assimp_view/LogDisplay.h +++ b/tools/assimp_view/LogDisplay.h @@ -91,7 +91,6 @@ private: std::list asEntries; ID3DXFont* piFont; - }; #endif // AV_LOG_DISPLAY_H_INCLUDE \ No newline at end of file diff --git a/tools/assimp_view/LogWindow.cpp b/tools/assimp_view/LogWindow.cpp index f33bf5d83..d172ccdee 100644 --- a/tools/assimp_view/LogWindow.cpp +++ b/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 \ No newline at end of file diff --git a/tools/assimp_view/LogWindow.h b/tools/assimp_view/LogWindow.h index 0fef5a20d..da5a00a4f 100644 --- a/tools/assimp_view/LogWindow.h +++ b/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 \ No newline at end of file diff --git a/tools/assimp_view/Material.cpp b/tools/assimp_view/Material.cpp index fd1760913..8b2e0ab47 100644 --- a/tools/assimp_view/Material.cpp +++ b/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); + + // {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; } -}; \ No newline at end of file +//------------------------------------------------------------------------------- +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 \ No newline at end of file diff --git a/tools/assimp_view/MaterialManager.h b/tools/assimp_view/MaterialManager.h new file mode 100644 index 000000000..705e8cfe1 --- /dev/null +++ b/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 diff --git a/tools/assimp_view/MeshRenderer.cpp b/tools/assimp_view/MeshRenderer.cpp new file mode 100644 index 000000000..21c0145d1 --- /dev/null +++ b/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 + +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> 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(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>::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>::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; +} +}; \ No newline at end of file diff --git a/tools/assimp_view/MeshRenderer.h b/tools/assimp_view/MeshRenderer.h new file mode 100644 index 000000000..c153c6685 --- /dev/null +++ b/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 \ No newline at end of file diff --git a/tools/assimp_view/MessageProc.cpp b/tools/assimp_view/MessageProc.cpp index 80cf8483d..3ace5b73a 100644 --- a/tools/assimp_view/MessageProc.cpp +++ b/tools/assimp_view/MessageProc.cpp @@ -42,12 +42,26 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "stdafx.h" #include "assimp_view.h" - namespace AssimpView { // Static array to keep custom color values COLORREF g_aclCustomColors[16] = {0}; +// Global registry key +HKEY g_hRegistry = NULL; + +// list of previous files (always 5) +std::vector g_aPreviousFiles; + +// history menu item +HMENU g_hHistoryMenu = NULL; + +#define AI_VIEW_NUM_RECENT_FILES 0x8 +#define AI_VIEW_RECENT_FILE_ID(_n_) (5678 + _n_) + +void UpdateHistory(); +void SaveHistory(); + //------------------------------------------------------------------------------- // Setup file associations for all formats supported by the library // @@ -62,103 +76,100 @@ void MakeFileAssociations() GetModuleFileName(NULL,szTemp2,MAX_PATH); sprintf(szTemp,"%s %%1",szTemp2); - HKEY hTemp; + HKEY g_hRegistry; // ------------------------------------------------- // .3ds // ------------------------------------------------- - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.3ds",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); - RegCloseKey(hTemp); - + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.3ds",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &g_hRegistry,NULL); + RegSetValueEx(g_hRegistry,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); + RegCloseKey(g_hRegistry); // ------------------------------------------------- // .x // ------------------------------------------------- - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.x",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); - RegCloseKey(hTemp); + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.x",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &g_hRegistry,NULL); + RegSetValueEx(g_hRegistry,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); + RegCloseKey(g_hRegistry); // ------------------------------------------------- // .obj // ------------------------------------------------- - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.obj",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); - RegCloseKey(hTemp); + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.obj",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &g_hRegistry,NULL); + RegSetValueEx(g_hRegistry,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); + RegCloseKey(g_hRegistry); // ------------------------------------------------- // .ms3d // ------------------------------------------------- - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.ms3d",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); - RegCloseKey(hTemp); + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.ms3d",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &g_hRegistry,NULL); + RegSetValueEx(g_hRegistry,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); + RegCloseKey(g_hRegistry); // ------------------------------------------------- // .md3 // ------------------------------------------------- - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.md3",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); - RegCloseKey(hTemp); + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.md3",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &g_hRegistry,NULL); + RegSetValueEx(g_hRegistry,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); + RegCloseKey(g_hRegistry); // ------------------------------------------------- // .md2 // ------------------------------------------------- - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.md2",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); - RegCloseKey(hTemp); + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.md2",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &g_hRegistry,NULL); + RegSetValueEx(g_hRegistry,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); + RegCloseKey(g_hRegistry); // ------------------------------------------------- // .md4/mdr // ------------------------------------------------- - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.md4",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); - RegCloseKey(hTemp); + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.md4",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &g_hRegistry,NULL); + RegSetValueEx(g_hRegistry,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); + RegCloseKey(g_hRegistry); - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.mdr",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); - RegCloseKey(hTemp); + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.mdr",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &g_hRegistry,NULL); + RegSetValueEx(g_hRegistry,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); + RegCloseKey(g_hRegistry); // ------------------------------------------------- // .md5 // ------------------------------------------------- - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.md5",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); - RegCloseKey(hTemp); + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.md5",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &g_hRegistry,NULL); + RegSetValueEx(g_hRegistry,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); + RegCloseKey(g_hRegistry); // ------------------------------------------------- // .mdl // ------------------------------------------------- - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.mdl",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); - RegCloseKey(hTemp); + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.mdl",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &g_hRegistry,NULL); + RegSetValueEx(g_hRegistry,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); + RegCloseKey(g_hRegistry); // ------------------------------------------------- // .ply // ------------------------------------------------- - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.ply",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); - RegCloseKey(hTemp); + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.ply",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &g_hRegistry,NULL); + RegSetValueEx(g_hRegistry,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); + RegCloseKey(g_hRegistry); // ------------------------------------------------- // .ase/.ask // ------------------------------------------------- - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.ase",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); - RegCloseKey(hTemp); - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.ask",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); - RegCloseKey(hTemp); + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.ase",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &g_hRegistry,NULL); + RegSetValueEx(g_hRegistry,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); + RegCloseKey(g_hRegistry); + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.ask",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &g_hRegistry,NULL); + RegSetValueEx(g_hRegistry,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); + RegCloseKey(g_hRegistry); + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\ASSIMPVIEW_CLASS",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &g_hRegistry,NULL); + RegCloseKey(g_hRegistry); - - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\ASSIMPVIEW_CLASS",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegCloseKey(hTemp); - - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\ASSIMPVIEW_CLASS\\shell\\open\\command",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)szTemp,(DWORD)strlen(szTemp)+1); - RegCloseKey(hTemp); + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\ASSIMPVIEW_CLASS\\shell\\open\\command",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &g_hRegistry,NULL); + RegSetValueEx(g_hRegistry,"",0,REG_SZ,(const BYTE*)szTemp,(DWORD)strlen(szTemp)+1); + RegCloseKey(g_hRegistry); CLogDisplay::Instance().AddEntry("[OK] File assocations have been registered", D3DCOLOR_ARGB(0xFF,0,0xFF,0)); @@ -167,31 +178,10 @@ void MakeFileAssociations() aiGetExtensionList(&sz); CLogDisplay::Instance().AddEntry(sz.data, D3DCOLOR_ARGB(0xFF,0,0xFF,0)); + return; } - -//------------------------------------------------------------------------------- -// 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() - { - 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]); - } - } - } - } - //------------------------------------------------------------------------------- // Handle command line parameters // @@ -212,8 +202,950 @@ void HandleCommandLine(char* p_szCommand) } strcpy( g_szFileName, sz ); LoadAsset(); + + // update the history + UpdateHistory(); + + // Save the list of previous files to the registry + SaveHistory(); } + +//------------------------------------------------------------------------------- +// Load the light colors from the registry +//------------------------------------------------------------------------------- +void LoadLightColors() +{ + DWORD dwTemp = 4; + RegQueryValueEx(g_hRegistry,"LightColor0",NULL,NULL, + (BYTE*)&g_avLightColors[0],&dwTemp); + RegQueryValueEx(g_hRegistry,"LightColor1",NULL,NULL, + (BYTE*)&g_avLightColors[1],&dwTemp); + RegQueryValueEx(g_hRegistry,"LightColor2",NULL,NULL, + (BYTE*)&g_avLightColors[2],&dwTemp); + return; +} + + +//------------------------------------------------------------------------------- +// Save the light colors to the registry +//------------------------------------------------------------------------------- +void SaveLightColors() +{ + RegSetValueExA(g_hRegistry,"LightColor0",0,REG_DWORD,(const BYTE*)&g_avLightColors[0],4); + RegSetValueExA(g_hRegistry,"LightColor1",0,REG_DWORD,(const BYTE*)&g_avLightColors[1],4); + RegSetValueExA(g_hRegistry,"LightColor2",0,REG_DWORD,(const BYTE*)&g_avLightColors[2],4); +} + +//------------------------------------------------------------------------------- +// Toggle the "Display Normals" state +//------------------------------------------------------------------------------- +void ToggleNormals() +{ + g_sOptions.bRenderNormals = !g_sOptions.bRenderNormals; + + // store this in the registry, too + DWORD dwValue = 0; + if (g_sOptions.bRenderNormals)dwValue = 1; + RegSetValueExA(g_hRegistry,"RenderNormals",0,REG_DWORD,(const BYTE*)&dwValue,4); + UpdateWindow(g_hDlg); +} + +//------------------------------------------------------------------------------- +// Toggle the "AutoRotate" state +//------------------------------------------------------------------------------- +void ToggleAutoRotate() +{ + g_sOptions.bRotate = !g_sOptions.bRotate; + + // store this in the registry, too + DWORD dwValue = 0; + if (g_sOptions.bRotate)dwValue = 1; + RegSetValueExA(g_hRegistry,"AutoRotate",0,REG_DWORD,(const BYTE*)&dwValue,4); + UpdateWindow(g_hDlg); +} + +//------------------------------------------------------------------------------- +// Toggle the "FPS" state +//------------------------------------------------------------------------------- +void ToggleFPSView() +{ + g_bFPSView = !g_bFPSView; + SetupFPSView(); + + // store this in the registry, too + DWORD dwValue = 0; + if (g_bFPSView)dwValue = 1; + RegSetValueExA(g_hRegistry,"FPSView",0,REG_DWORD,(const BYTE*)&dwValue,4); + UpdateWindow(g_hDlg); +} + +//------------------------------------------------------------------------------- +// Toggle the "2 Light sources" state +//------------------------------------------------------------------------------- +void ToggleMultipleLights() +{ + g_sOptions.b3Lights = !g_sOptions.b3Lights; + + // store this in the registry, too + DWORD dwValue = 0; + if (g_sOptions.b3Lights)dwValue = 1; + RegSetValueExA(g_hRegistry,"MultipleLights",0,REG_DWORD,(const BYTE*)&dwValue,4); + UpdateWindow(g_hDlg); +} + +//------------------------------------------------------------------------------- +// Toggle the "LightRotate" state +//------------------------------------------------------------------------------- +void ToggleLightRotate() +{ + g_sOptions.bLightRotate = !g_sOptions.bLightRotate; + + // store this in the registry, too + DWORD dwValue = 0; + if (g_sOptions.bLightRotate)dwValue = 1; + RegSetValueExA(g_hRegistry,"LightRotate",0,REG_DWORD,(const BYTE*)&dwValue,4); + UpdateWindow(g_hDlg); +} + +//------------------------------------------------------------------------------- +// Toggle the "LowQuality" state +//------------------------------------------------------------------------------- +void ToggleLowQuality() +{ + g_sOptions.bLowQuality = !g_sOptions.bLowQuality; + + // store this in the registry, too + DWORD dwValue = 0; + if (g_sOptions.bLowQuality)dwValue = 1; + RegSetValueExA(g_hRegistry,"LowQuality",0,REG_DWORD,(const BYTE*)&dwValue,4); + UpdateWindow(g_hDlg); +} + +//------------------------------------------------------------------------------- +// Toggle the "Specular" state +//------------------------------------------------------------------------------- +void ToggleSpecular() +{ + g_sOptions.bNoSpecular = !g_sOptions.bNoSpecular; + + // store this in the registry, too + DWORD dwValue = 0; + if (g_sOptions.bNoSpecular)dwValue = 1; + RegSetValueExA(g_hRegistry,"NoSpecular",0,REG_DWORD,(const BYTE*)&dwValue,4); + + // update all specular materials + CMaterialManager::Instance().UpdateSpecularMaterials(); + UpdateWindow(g_hDlg); +} + +//------------------------------------------------------------------------------- +// Toggle the "RenderMats" state +//------------------------------------------------------------------------------- +void ToggleMats() +{ + g_sOptions.bRenderMats = !g_sOptions.bRenderMats; + + // store this in the registry, too + DWORD dwValue = 0; + if (g_sOptions.bRenderMats)dwValue = 1; + RegSetValueExA(g_hRegistry,"RenderMats",0,REG_DWORD,(const BYTE*)&dwValue,4); + + // update all specular materials + CMaterialManager::Instance().UpdateSpecularMaterials(); + UpdateWindow(g_hDlg); +} + + +//------------------------------------------------------------------------------- +// Toggle the "WireFrame" state +//------------------------------------------------------------------------------- +void ToggleWireFrame() +{ + if (g_sOptions.eDrawMode == RenderOptions::WIREFRAME) + g_sOptions.eDrawMode = RenderOptions::NORMAL; + else g_sOptions.eDrawMode = RenderOptions::WIREFRAME; + + // store this in the registry, too + DWORD dwValue = 0; + if (RenderOptions::WIREFRAME == g_sOptions.eDrawMode)dwValue = 1; + RegSetValueExA(g_hRegistry,"Wireframe",0,REG_DWORD,(const BYTE*)&dwValue,4); + UpdateWindow(g_hDlg); +} + + +//------------------------------------------------------------------------------- +// Toggle the "MultiSample" state +//------------------------------------------------------------------------------- +void ToggleMS() +{ + g_sOptions.bMultiSample = !g_sOptions.bMultiSample; + DeleteAssetData(); + ShutdownDevice(); + if (0 == CreateDevice()) + { + CLogDisplay::Instance().AddEntry( + "[ERROR] Failed to toggle MultiSampling mode"); + g_sOptions.bMultiSample = !g_sOptions.bMultiSample; + CreateDevice(); + } + CreateAssetData(); + + if (g_sOptions.bMultiSample) + { + CLogDisplay::Instance().AddEntry( + "[OK] Changed MultiSampling mode to the maximum value for this device"); + } + else + { + CLogDisplay::Instance().AddEntry( + "[OK] MultiSampling has been disabled"); + } + + // store this in the registry, too + DWORD dwValue = 0; + if (g_sOptions.bMultiSample)dwValue = 1; + RegSetValueExA(g_hRegistry,"MultiSampling",0,REG_DWORD,(const BYTE*)&dwValue,4); + UpdateWindow(g_hDlg); +} + +//------------------------------------------------------------------------------- +// Expand or collapse the UI +//------------------------------------------------------------------------------- +void ToggleUIState() +{ + // adjust the size + RECT sRect; + GetWindowRect(g_hDlg,&sRect); + sRect.right -= sRect.left; + sRect.bottom -= sRect.top; + + RECT sRect2; + GetWindowRect(GetDlgItem ( g_hDlg, IDC_BLUBB ),&sRect2); + sRect2.left -= sRect.left; + sRect2.top -= sRect.top; + + DWORD dwValue; + if (BST_UNCHECKED == IsDlgButtonChecked(g_hDlg,IDC_BLUBB)) + { + SetWindowPos(g_hDlg,NULL,0,0,sRect.right-188,sRect.bottom, + SWP_NOMOVE | SWP_NOZORDER); + + dwValue = 0; + SetWindowText(GetDlgItem(g_hDlg,IDC_BLUBB),">>"); + RegSetValueExA(g_hRegistry,"LastUIState",0,REG_DWORD,(const BYTE*)&dwValue,4); + } + else + { + SetWindowPos(g_hDlg,NULL,0,0,sRect.right+188,sRect.bottom, + SWP_NOMOVE | SWP_NOZORDER); + + dwValue = 1; + SetWindowText(GetDlgItem(g_hDlg,IDC_BLUBB),"<<"); + RegSetValueExA(g_hRegistry,"LastUIState",0,REG_DWORD,(const BYTE*)&dwValue,4); + } + UpdateWindow(g_hDlg); + return; +} + + +//------------------------------------------------------------------------------- +// Load the background texture for the cviewer +//------------------------------------------------------------------------------- +void LoadBGTexture() +{ + char szFileName[MAX_PATH]; + + DWORD dwTemp = MAX_PATH; + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"TextureSrc",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, + "Open texture as background", + OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR, + 0, 1, ".jpg", 0, NULL, NULL + }; + if(GetOpenFileName(&sFilename1) == 0) return; + + // Now store the file in the registry + RegSetValueExA(g_hRegistry,"TextureSrc",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH); + RegSetValueExA(g_hRegistry,"LastTextureSrc",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH); + RegSetValueExA(g_hRegistry,"LastSkyBoxSrc",0,REG_SZ,(const BYTE*)"",MAX_PATH); + + CBackgroundPainter::Instance().SetTextureBG(szFileName); + return; +} + +//------------------------------------------------------------------------------- +// Reset the background color to a smart and nice grey +//------------------------------------------------------------------------------- +void ClearBG() +{ + D3DCOLOR clrColor = D3DCOLOR_ARGB(0xFF,100,100,100); + CBackgroundPainter::Instance().SetColor(clrColor); + + RegSetValueExA(g_hRegistry,"LastSkyBoxSrc",0,REG_SZ,(const BYTE*)"",MAX_PATH); + RegSetValueExA(g_hRegistry,"LastTextureSrc",0,REG_SZ,(const BYTE*)"",MAX_PATH); + + RegSetValueExA(g_hRegistry,"Color",0,REG_DWORD,(const BYTE*)&clrColor,4); + return; +} + +//------------------------------------------------------------------------------- +// Let the user choose a color in a windows standard color dialog +//------------------------------------------------------------------------------- +void DisplayColorDialog(D3DCOLOR* pclrResult) +{ + CHOOSECOLOR clr; + clr.lStructSize = sizeof(CHOOSECOLOR); + clr.hwndOwner = g_hDlg; + clr.Flags = CC_RGBINIT | CC_FULLOPEN; + clr.rgbResult = RGB(100,100,100); + clr.lpCustColors = g_aclCustomColors; + clr.lpfnHook = NULL; + clr.lpTemplateName = NULL; + clr.lCustData = NULL; + + ChooseColor(&clr); + + *pclrResult = D3DCOLOR_ARGB(0xFF, + GetRValue(clr.rgbResult), + GetGValue(clr.rgbResult), + GetBValue(clr.rgbResult)); + return; +} + +//------------------------------------------------------------------------------- +// Let the user choose the baclground color for the viewer +//------------------------------------------------------------------------------- +void ChooseBGColor() +{ + RegSetValueExA(g_hRegistry,"LastSkyBoxSrc",0,REG_SZ,(const BYTE*)"",MAX_PATH); + RegSetValueExA(g_hRegistry,"LastTextureSrc",0,REG_SZ,(const BYTE*)"",MAX_PATH); + + D3DCOLOR clrColor; + DisplayColorDialog(&clrColor); + CBackgroundPainter::Instance().SetColor(clrColor); + + RegSetValueExA(g_hRegistry,"Color",0,REG_DWORD,(const BYTE*)&clrColor,4); + return; +} + +//------------------------------------------------------------------------------- +// Display the OpenFile dialog and let the user choose a new slybox as bg +//------------------------------------------------------------------------------- +void LoadSkybox() +{ + char szFileName[MAX_PATH]; + + DWORD dwTemp = MAX_PATH; + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"SkyBoxSrc",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), + "Skyboxes\0*.dds\0*.*\0", NULL, 0, 1, + szFileName, MAX_PATH, NULL, 0, NULL, + "Open skybox as background", + OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR, + 0, 1, ".dds", 0, NULL, NULL + }; + if(GetOpenFileName(&sFilename1) == 0) return; + + // Now store the file in the registry + RegSetValueExA(g_hRegistry,"SkyBoxSrc",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH); + RegSetValueExA(g_hRegistry,"LastSkyBoxSrc",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH); + RegSetValueExA(g_hRegistry,"LastTextureSrc",0,REG_SZ,(const BYTE*)"",MAX_PATH); + + CBackgroundPainter::Instance().SetCubeMapBG(szFileName); + return; +} + + +//------------------------------------------------------------------------------- +// Sace a screenshot to an user-defined file +//------------------------------------------------------------------------------- +void SaveScreenshot() +{ + char szFileName[MAX_PATH]; + + DWORD dwTemp = MAX_PATH; + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"ScreenShot",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), + "PNG Images\0*.png", NULL, 0, 1, + szFileName, MAX_PATH, NULL, 0, NULL, + "Save Screenshot to file", + OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR, + 0, 1, ".png", 0, NULL, NULL + }; + if(GetSaveFileName(&sFilename1) == 0) return; + + // Now store the file in the registry + RegSetValueExA(g_hRegistry,"ScreenShot",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH); + + IDirect3DSurface9* pi = NULL; + g_piDevice->GetRenderTarget(0,&pi); + if(!pi || FAILED(D3DXSaveSurfaceToFile(szFileName,D3DXIFF_PNG,pi,NULL,NULL))) + { + CLogDisplay::Instance().AddEntry("[ERROR] Unable to save screenshot", + D3DCOLOR_ARGB(0xFF,0xFF,0,0)); + } + else + { + CLogDisplay::Instance().AddEntry("[INFO] The screenshot has been saved", + D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0)); + } + if(pi)pi->Release(); + return; +} + +//------------------------------------------------------------------------------- +// Get the amount of memory required for textures +//------------------------------------------------------------------------------- +void AddTextureMem(IDirect3DTexture9* pcTex, unsigned int& out) +{ + if (!pcTex)return; + + D3DSURFACE_DESC sDesc; + pcTex->GetLevelDesc(0,&sDesc); + + out += (sDesc.Width * sDesc.Height) << 2; + return; +} + +//------------------------------------------------------------------------------- +// Display memory statistics +//------------------------------------------------------------------------------- +void DisplayMemoryConsumption() +{ + // first get the memory consumption for the aiScene + if (! g_pcAsset ||!g_pcAsset->pcScene) + { + MessageBox(g_hDlg,"No asset is loaded. Can you guess how much memory I need to store nothing?", + "Memory consumption",MB_OK); + return; + } + unsigned int iScene = sizeof(aiScene); + for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) + { + iScene += sizeof(aiMesh); + if (g_pcAsset->pcScene->mMeshes[i]->HasPositions()) + iScene += sizeof(aiVector3D) * g_pcAsset->pcScene->mMeshes[i]->mNumVertices; + + if (g_pcAsset->pcScene->mMeshes[i]->HasNormals()) + iScene += sizeof(aiVector3D) * g_pcAsset->pcScene->mMeshes[i]->mNumVertices; + + if (g_pcAsset->pcScene->mMeshes[i]->HasTangentsAndBitangents()) + iScene += sizeof(aiVector3D) * g_pcAsset->pcScene->mMeshes[i]->mNumVertices * 2; + + for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS;++a) + { + if (g_pcAsset->pcScene->mMeshes[i]->HasVertexColors(a)) + iScene += sizeof(aiColor4D) * g_pcAsset->pcScene->mMeshes[i]->mNumVertices; + else break; + } + for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a) + { + if (g_pcAsset->pcScene->mMeshes[i]->HasTextureCoords(a)) + iScene += sizeof(aiVector3D) * g_pcAsset->pcScene->mMeshes[i]->mNumVertices; + else break; + } + if (g_pcAsset->pcScene->mMeshes[i]->HasBones()) + { + for (unsigned int p = 0; p < g_pcAsset->pcScene->mMeshes[i]->mNumBones;++p) + { + iScene += sizeof(aiBone); + iScene += g_pcAsset->pcScene->mMeshes[i]->mBones[p]->mNumWeights * sizeof(aiVertexWeight); + } + } + iScene += (sizeof(aiFace) + 3 * sizeof(unsigned int))*g_pcAsset->pcScene->mMeshes[i]->mNumFaces; + } + // add all embedded textures + for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumTextures;++i) + { + const aiTexture* pc = g_pcAsset->pcScene->mTextures[i]; + if (0 != pc->mHeight) + { + iScene += 4 * pc->mHeight * pc->mWidth; + } + else iScene += pc->mWidth; + } + // add 30k for each material ... a string has 4k for example + iScene += g_pcAsset->pcScene->mNumMaterials * 30 * 1024; + + // now get the memory consumption required by D3D, first all textures + unsigned int iTexture = 0; + for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) + { + AssetHelper::MeshHelper* pc = g_pcAsset->apcMeshes[i]; + + AddTextureMem(pc->piDiffuseTexture,iTexture); + AddTextureMem(pc->piSpecularTexture,iTexture); + AddTextureMem(pc->piAmbientTexture,iTexture); + AddTextureMem(pc->piEmissiveTexture,iTexture); + AddTextureMem(pc->piOpacityTexture,iTexture); + AddTextureMem(pc->piNormalTexture,iTexture); + AddTextureMem(pc->piShininessTexture,iTexture); + } + unsigned int iVRAM = iTexture; + + // now get the memory consumption of all vertex/index buffers + unsigned int iVB = 0; + unsigned int iIB = 0; + for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) + { + AssetHelper:: MeshHelper* pc = g_pcAsset->apcMeshes[i]; + + union{ + D3DVERTEXBUFFER_DESC sDesc; + D3DINDEXBUFFER_DESC sDesc2; + }; + + if (pc->piVB) + { + pc->piVB->GetDesc(&sDesc); + iVB += sDesc.Size; + } + if (pc->piVBNormals) + { + pc->piVBNormals->GetDesc(&sDesc); + iVB += sDesc.Size; + } + if (pc->piIB) + { + pc->piIB->GetDesc(&sDesc2); + iIB += sDesc2.Size; + } + } + iVRAM += iVB + iIB; + // add the memory for the back buffer and depth stencil buffer + RECT sRect; + GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect); + sRect.bottom -= sRect.top; + sRect.right -= sRect.left; + iVRAM += sRect.bottom * sRect.right * 8; + + char szOut[2048]; + sprintf(szOut, + "(1 KB = 1024 Byte)\n\n" + "ASSIMP Import Data: \t%i KB\n" + "Texture data:\t\t%i KB\n" + "Vertex buffers:\t\t%i KB\n" + "Index buffers:\t\t%i KB\n" + "Video Memory:\t\t%i KB\n\n" + "Total: \t\t\t%i KB", + iScene / 1024,iTexture / 1024,iVB / 1024,iIB / 1024,iVRAM / 1024, + (iScene + iTexture + iVB + iIB + iVRAM) / 1024); + MessageBox(g_hDlg,szOut,"Memory consumption",MB_OK); + return; +} + +//------------------------------------------------------------------------------- +// Save the list of recent files to the registry +//------------------------------------------------------------------------------- +void SaveHistory() +{ + for (unsigned int i = 0; i < AI_VIEW_NUM_RECENT_FILES;++i) + { + char szName[66]; + sprintf(szName,"Recent%i",i+1); + + RegSetValueEx(g_hRegistry,szName,0,REG_SZ, + (const BYTE*)g_aPreviousFiles[i].c_str(),(DWORD)g_aPreviousFiles[i].length()); + } + return; +} + +//------------------------------------------------------------------------------- +// Recover the file history +//------------------------------------------------------------------------------- +void LoadHistory() +{ + g_aPreviousFiles.resize(AI_VIEW_NUM_RECENT_FILES); + + char szFileName[MAX_PATH]; + + for (unsigned int i = 0; i < AI_VIEW_NUM_RECENT_FILES;++i) + { + char szName[66]; + sprintf(szName,"Recent%i",i+1); + + DWORD dwTemp = MAX_PATH; + + szFileName[0] ='\0'; + if(ERROR_SUCCESS == RegQueryValueEx(g_hRegistry,szName,NULL,NULL, + (BYTE*)szFileName,&dwTemp)) + { + g_aPreviousFiles[i] = std::string(szFileName); + } + } + + // add sub items for all recent files + g_hHistoryMenu = CreateMenu(); + for (int i = AI_VIEW_NUM_RECENT_FILES-1; i >= 0;--i) + { + const char* szText = g_aPreviousFiles[i].c_str(); + UINT iFlags = 0; + if ('\0' == *szText) + { + szText = ""; + iFlags = MF_GRAYED | MF_DISABLED; + } + AppendMenu(g_hHistoryMenu,MF_STRING | iFlags,AI_VIEW_RECENT_FILE_ID(i),szText); + } + + ModifyMenu(GetMenu(g_hDlg),ID_VIEWER_RECENTFILES,MF_BYCOMMAND | MF_POPUP, + (UINT_PTR)g_hHistoryMenu,"Recent files"); + return; +} + +//------------------------------------------------------------------------------- +// Clear the file history +//------------------------------------------------------------------------------- +void ClearHistory() +{ + for(unsigned int i = 0; i < AI_VIEW_NUM_RECENT_FILES;++i) + g_aPreviousFiles[i] = std::string(""); + + for (int i = AI_VIEW_NUM_RECENT_FILES-1; i >= 0;--i) + { + ModifyMenu(g_hHistoryMenu,AI_VIEW_RECENT_FILE_ID(i), + MF_STRING | MF_BYCOMMAND | MF_GRAYED | MF_DISABLED,AI_VIEW_RECENT_FILE_ID(i),""); + } + + SaveHistory(); +} + +//------------------------------------------------------------------------------- +// Update the file history +//------------------------------------------------------------------------------- +void UpdateHistory() +{ + if(!g_hHistoryMenu)return; + + std::string sz = std::string(g_szFileName); + if (g_aPreviousFiles[AI_VIEW_NUM_RECENT_FILES-1] == sz)return; + + // add the new asset to the list of recent files + for (unsigned int i = 0; i < AI_VIEW_NUM_RECENT_FILES-1;++i) + { + g_aPreviousFiles[i] = g_aPreviousFiles[i+1]; + } + g_aPreviousFiles[AI_VIEW_NUM_RECENT_FILES-1] = sz; + for (int i = AI_VIEW_NUM_RECENT_FILES-1; i >= 0;--i) + { + const char* szText = g_aPreviousFiles[i].c_str(); + UINT iFlags = 0; + if ('\0' == *szText) + { + szText = ""; + iFlags = MF_GRAYED | MF_DISABLED; + } + ModifyMenu(g_hHistoryMenu,AI_VIEW_RECENT_FILE_ID(i), + MF_STRING | MF_BYCOMMAND | iFlags,AI_VIEW_RECENT_FILE_ID(i),szText); + } + return; +} + +//------------------------------------------------------------------------------- +// Open a new asset +//------------------------------------------------------------------------------- +void OpenAsset() +{ + char szFileName[MAX_PATH]; + + DWORD dwTemp = MAX_PATH; + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"CurrentApp",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; + } + + // get a list of all file extensions supported by ASSIMP + aiString sz; + aiGetExtensionList(&sz); + + char szList[MAXLEN + 100]; + strcpy(szList,"ASSIMP assets"); + char* szCur = szList + 14; + strcpy(szCur,sz.data); + szCur += sz.length+1; + strcpy(szCur,"All files"); + szCur += 10; + strcpy(szCur,"*.*"); + szCur[4] = 0; + + OPENFILENAME sFilename1 = { + sizeof(OPENFILENAME), + g_hDlg,GetModuleHandle(NULL), szList, NULL, 0, 1, + szFileName, MAX_PATH, NULL, 0, NULL, + "Import Asset into ASSIMP", + OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR, + 0, 1, ".x", 0, NULL, NULL + }; + if(GetOpenFileName(&sFilename1) == 0) return; + + // Now store the file in the registry + RegSetValueExA(g_hRegistry,"CurrentApp",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH); + + if (0 != strcmp(g_szFileName,szFileName)) + { + strcpy(g_szFileName, szFileName); + DeleteAssetData(); + DeleteAsset(); + LoadAsset(); + + // update the history + UpdateHistory(); + + // Save the list of previous files to the registry + SaveHistory(); + } + return; +} + +//------------------------------------------------------------------------------- +// Initialize the user interface +//------------------------------------------------------------------------------- +void InitUI() +{ + SetDlgItemText(g_hDlg,IDC_EVERT,"0"); + SetDlgItemText(g_hDlg,IDC_EFACE,"0"); + SetDlgItemText(g_hDlg,IDC_EMAT,"0"); + SetDlgItemText(g_hDlg,IDC_ESHADER,"0"); + SetDlgItemText(g_hDlg,IDC_ENODE,"0"); + SetDlgItemText(g_hDlg,IDC_ETEX,"0"); + SetDlgItemText(g_hDlg,IDC_EMESH,"0"); + + // setup the default window title + SetWindowText(g_hDlg,AI_VIEW_CAPTION_BASE); + + // read some UI properties from the registry and apply them + DWORD dwValue; + DWORD dwTemp = sizeof( DWORD ); + + // store the key in a global variable for later use + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\ASSIMP\\Viewer", + NULL,NULL,0,KEY_ALL_ACCESS, NULL, &g_hRegistry,NULL); + + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"LastUIState",NULL,NULL, + (BYTE*)&dwValue,&dwTemp)) + { + dwValue = 1; + } + if (0 == dwValue) + { + // collapse the viewer + // adjust the size + RECT sRect; + GetWindowRect(g_hDlg,&sRect); + sRect.right -= sRect.left; + sRect.bottom -= sRect.top; + + RECT sRect2; + GetWindowRect(GetDlgItem ( g_hDlg, IDC_BLUBB ),&sRect2); + sRect2.left -= sRect.left; + sRect2.top -= sRect.top; + + SetWindowPos(g_hDlg,NULL,0,0,sRect.right-188,sRect.bottom, + SWP_NOMOVE | SWP_NOZORDER); + SetWindowText(GetDlgItem(g_hDlg,IDC_BLUBB),">>"); + } + else + { + CheckDlgButton(g_hDlg,IDC_BLUBB,BST_CHECKED); + } + + // AutoRotate + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"AutoRotate",NULL,NULL, + (BYTE*)&dwValue,&dwTemp))dwValue = 0; + if (0 == dwValue) + { + g_sOptions.bRotate = false; + CheckDlgButton(g_hDlg,IDC_AUTOROTATE,BST_UNCHECKED); + } + else + { + g_sOptions.bRotate = true; + CheckDlgButton(g_hDlg,IDC_AUTOROTATE,BST_CHECKED); + } + + // MultipleLights + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"MultipleLights",NULL,NULL, + (BYTE*)&dwValue,&dwTemp))dwValue = 0; + if (0 == dwValue) + { + g_sOptions.b3Lights = false; + CheckDlgButton(g_hDlg,IDC_3LIGHTS,BST_UNCHECKED); + } + else + { + g_sOptions.b3Lights = true; + CheckDlgButton(g_hDlg,IDC_3LIGHTS,BST_CHECKED); + } + + // Light rotate + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"LightRotate",NULL,NULL, + (BYTE*)&dwValue,&dwTemp))dwValue = 0; + if (0 == dwValue) + { + g_sOptions.bLightRotate = false; + CheckDlgButton(g_hDlg,IDC_LIGHTROTATE,BST_UNCHECKED); + } + else + { + g_sOptions.bLightRotate = true; + CheckDlgButton(g_hDlg,IDC_LIGHTROTATE,BST_CHECKED); + } + + // NoSpecular + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"NoSpecular",NULL,NULL, + (BYTE*)&dwValue,&dwTemp))dwValue = 0; + if (0 == dwValue) + { + g_sOptions.bNoSpecular = false; + CheckDlgButton(g_hDlg,IDC_NOSPECULAR,BST_UNCHECKED); + } + else + { + g_sOptions.bNoSpecular = true; + CheckDlgButton(g_hDlg,IDC_NOSPECULAR,BST_CHECKED); + } + + // LowQuality + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"LowQuality",NULL,NULL, + (BYTE*)&dwValue,&dwTemp))dwValue = 0; + if (0 == dwValue) + { + g_sOptions.bLowQuality = false; + CheckDlgButton(g_hDlg,IDC_LOWQUALITY,BST_UNCHECKED); + } + else + { + g_sOptions.bLowQuality = true; + CheckDlgButton(g_hDlg,IDC_LOWQUALITY,BST_CHECKED); + } + + // DisplayNormals + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"RenderNormals",NULL,NULL, + (BYTE*)&dwValue,&dwTemp))dwValue = 0; + if (0 == dwValue) + { + g_sOptions.bRenderNormals = false; + CheckDlgButton(g_hDlg,IDC_TOGGLENORMALS,BST_UNCHECKED); + } + else + { + g_sOptions.bRenderNormals = true; + CheckDlgButton(g_hDlg,IDC_TOGGLENORMALS,BST_CHECKED); + } + + // NoMaterials + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"RenderMats",NULL,NULL, + (BYTE*)&dwValue,&dwTemp))dwValue = 1; + if (0 == dwValue) + { + g_sOptions.bRenderMats = false; + CheckDlgButton(g_hDlg,IDC_TOGGLEMAT,BST_CHECKED); + } + else + { + g_sOptions.bRenderMats = true; + CheckDlgButton(g_hDlg,IDC_TOGGLEMAT,BST_UNCHECKED); + } + + // MultiSampling + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"MultiSampling",NULL,NULL, + (BYTE*)&dwValue,&dwTemp))dwValue = 1; + if (0 == dwValue) + { + g_sOptions.bMultiSample = false; + CheckDlgButton(g_hDlg,IDC_TOGGLEMS,BST_UNCHECKED); + } + else + { + g_sOptions.bMultiSample = true; + CheckDlgButton(g_hDlg,IDC_TOGGLEMS,BST_CHECKED); + } + + // FPS Mode + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"FPSView",NULL,NULL, + (BYTE*)&dwValue,&dwTemp))dwValue = 0; + if (0 == dwValue) + { + g_bFPSView = false; + CheckDlgButton(g_hDlg,IDC_ZOOM,BST_CHECKED); + } + else + { + g_bFPSView = true; + CheckDlgButton(g_hDlg,IDC_ZOOM,BST_UNCHECKED); + } + + // WireFrame + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"Wireframe",NULL,NULL, + (BYTE*)&dwValue,&dwTemp))dwValue = 0; + if (0 == dwValue) + { + g_sOptions.eDrawMode = RenderOptions::NORMAL; + CheckDlgButton(g_hDlg,IDC_TOGGLEWIRE,BST_UNCHECKED); + } + else + { + g_sOptions.eDrawMode = RenderOptions::WIREFRAME; + CheckDlgButton(g_hDlg,IDC_TOGGLEWIRE,BST_CHECKED); + } + return; +} + //------------------------------------------------------------------------------- // Main message procedure of the application // @@ -238,68 +1170,36 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, { case WM_INITDIALOG: - CheckDlgButton(hwndDlg,IDC_TOGGLEMS,BST_CHECKED); - CheckDlgButton(hwndDlg,IDC_ZOOM,BST_CHECKED); - CheckDlgButton(hwndDlg,IDC_AUTOROTATE,BST_CHECKED); + g_hDlg = hwndDlg; - SetDlgItemText(hwndDlg,IDC_EVERT,"0"); - SetDlgItemText(hwndDlg,IDC_EFACE,"0"); - SetDlgItemText(hwndDlg,IDC_EMAT,"0"); - SetDlgItemText(hwndDlg,IDC_ESHADER,"0"); - SetDlgItemText(hwndDlg,IDC_ENODE,"0"); - SetDlgItemText(hwndDlg,IDC_ETEX,"0"); + // load the state of the usr interface + InitUI(); - // setup the default window title - SetWindowText(hwndDlg,AI_VIEW_CAPTION_BASE); - { - // read some UI properties from the registry and apply them - DWORD dwValue; - DWORD dwTemp = sizeof( DWORD ); - HKEY hTemp; - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\ASSIMP\\Viewer", - NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); + // load the file history + LoadHistory(); - if(ERROR_SUCCESS != RegQueryValueEx(hTemp,"LastUIState",NULL,NULL, - (BYTE*)&dwValue,&dwTemp)) - { - dwValue = 1; - } - if (0 == dwValue) - { - // collapse the viewer - // adjust the size - RECT sRect; - GetWindowRect(hwndDlg,&sRect); - sRect.right -= sRect.left; - sRect.bottom -= sRect.top; - - RECT sRect2; - GetWindowRect(GetDlgItem ( hwndDlg, IDC_BLUBB ),&sRect2); - sRect2.left -= sRect.left; - sRect2.top -= sRect.top; - - SetWindowPos(hwndDlg,NULL,0,0,sRect.right-188,sRect.bottom, - SWP_NOMOVE | SWP_NOZORDER); - SetWindowText(GetDlgItem(hwndDlg,IDC_BLUBB),">>"); - } - else - { - CheckDlgButton(hwndDlg,IDC_BLUBB,BST_CHECKED); - } - RegCloseKey(hTemp);} + // load the current color of the lights + LoadLightColors(); return TRUE; case WM_MOUSEWHEEL: - if (!g_bFPSView) - { - g_sCamera.vPos.z += GET_WHEEL_DELTA_WPARAM(wParam) / 50.0f; - } + if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode()) + { + CDisplay::Instance().SetTextureViewZoom ( GET_WHEEL_DELTA_WPARAM(wParam) / 50.0f ); + } else - { - g_sCamera.vPos += (GET_WHEEL_DELTA_WPARAM(wParam) / 50.0f) * - g_sCamera.vLookAt.Normalize(); - } + { + if (!g_bFPSView) + { + g_sCamera.vPos.z += GET_WHEEL_DELTA_WPARAM(wParam) / 50.0f; + } + else + { + g_sCamera.vPos += (GET_WHEEL_DELTA_WPARAM(wParam) / 50.0f) * + g_sCamera.vLookAt.Normalize(); + } + } return TRUE; case WM_MOUSELEAVE: @@ -316,7 +1216,7 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, IsDlgButtonChecked(hwndDlg,IDC_AUTOROTATE) == BST_CHECKED ? BST_UNCHECKED : BST_CHECKED); - g_sOptions.bRotate = !g_sOptions.bRotate; + ToggleAutoRotate(); return TRUE; @@ -325,6 +1225,103 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, DestroyWindow(hwndDlg); return TRUE; + case WM_NOTIFY: + + if (IDC_TREE1 == wParam) + { + NMTREEVIEW* pnmtv = (LPNMTREEVIEW) lParam; + + if (TVN_SELCHANGED == pnmtv->hdr.code) + CDisplay::Instance().OnSetup( pnmtv->itemNew.hItem ); + else if (NM_RCLICK == pnmtv->hdr.code) + { + // determine in which item the click was ... + POINT sPoint; + GetCursorPos(&sPoint); + ScreenToClient(GetDlgItem(g_hDlg,IDC_TREE1),&sPoint); + + TVHITTESTINFO sHit; + sHit.pt = sPoint; + TreeView_HitTest(GetDlgItem(g_hDlg,IDC_TREE1),&sHit); + CDisplay::Instance().ShowTreeViewContextMenu(sHit.hItem); + } + } + return TRUE; + + case WM_DRAWITEM: + { + // draw the two light colors + DRAWITEMSTRUCT* pcStruct = (DRAWITEMSTRUCT*)lParam; + + RECT sRect; + GetWindowRect(GetDlgItem(g_hDlg,IDC_LCOLOR1),&sRect); + sRect.right -= sRect.left; + sRect.bottom -= sRect.top; + sRect.left = sRect.top = 0; + + bool bDraw = false; + + if(IDC_LCOLOR1 == pcStruct->CtlID) + { + unsigned char r = unsigned char((g_avLightColors[0] >> 16) & 0xFF); + unsigned char g = unsigned char((g_avLightColors[0] >> 8) & 0xFF); + unsigned char b = unsigned char((g_avLightColors[0]) & 0xFF); + HBRUSH hbr = CreateSolidBrush(RGB(r,g,b)); + + FillRect(pcStruct->hDC,&sRect,hbr); + + + SetTextColor(pcStruct->hDC,RGB(0xFF-r,0xFF-g,0xFF-b)); + SetBkMode(pcStruct->hDC,TRANSPARENT); + TextOut(pcStruct->hDC,4,1,"L0",2); + bDraw = true; + } + else if(IDC_LCOLOR2 == pcStruct->CtlID) + { + unsigned char r = unsigned char((g_avLightColors[1] >> 16) & 0xFF); + unsigned char g = unsigned char((g_avLightColors[1] >> 8) & 0xFF); + unsigned char b = unsigned char((g_avLightColors[1]) & 0xFF); + HBRUSH hbr = CreateSolidBrush(RGB(r,g,b)); + FillRect(pcStruct->hDC,&sRect,hbr); + + SetTextColor(pcStruct->hDC,RGB(0xFF-r,0xFF-g,0xFF-b)); + SetBkMode(pcStruct->hDC,TRANSPARENT); + TextOut(pcStruct->hDC,4,1,"L1",2); + bDraw = true; + } + else if(IDC_LCOLOR3 == pcStruct->CtlID) + { + unsigned char r = unsigned char((g_avLightColors[2] >> 16) & 0xFF); + unsigned char g = unsigned char((g_avLightColors[2] >> 8) & 0xFF); + unsigned char b = unsigned char((g_avLightColors[2]) & 0xFF); + HBRUSH hbr = CreateSolidBrush(RGB(r,g,b)); + + FillRect(pcStruct->hDC,&sRect,hbr); + + SetTextColor(pcStruct->hDC,RGB(0xFF-r,0xFF-g,0xFF-b)); + SetBkMode(pcStruct->hDC,TRANSPARENT); + TextOut(pcStruct->hDC,4,1,"A0",2); + bDraw = true; + } + // draw the black border around the rects + if (bDraw) + { + SetBkColor(pcStruct->hDC,RGB(0,0,0)); + MoveToEx(pcStruct->hDC,0,0,NULL); + LineTo(pcStruct->hDC,sRect.right-1,0); + LineTo(pcStruct->hDC,sRect.right-1,sRect.bottom-1); + LineTo(pcStruct->hDC,0,sRect.bottom-1); + LineTo(pcStruct->hDC,0,0); + } + } + return TRUE; + + case WM_DESTROY: + + // close the open registry key + RegCloseKey(g_hRegistry); + return TRUE; + case WM_LBUTTONDOWN: g_bMousePressed = true; @@ -346,12 +1343,19 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, // need to determine the position of the mouse and the // distance from the center - xPos = (int)(short)LOWORD(lParam); - yPos = (int)(short)HIWORD(lParam); - xPos -= 10; + //xPos = (int)(short)LOWORD(lParam); + //yPos = (int)(short)HIWORD(lParam); + + POINT sPoint; + GetCursorPos(&sPoint); + ScreenToClient(GetDlgItem(g_hDlg,IDC_RT),&sPoint); + xPos = xPos2 = sPoint.x; + yPos = yPos2 = sPoint.y; + + /* xPos -= 10; yPos -= 10; xPos2 = xPos-3; - yPos2 = yPos-5; + yPos2 = yPos-5;*/ RECT sRect; GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect); @@ -426,6 +1430,7 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, case WM_MBUTTONDOWN: + g_bMousePressedM = true; sEvent.cbSize = sizeof(TRACKMOUSEEVENT); @@ -449,6 +1454,97 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, g_bMousePressedM = false; return TRUE; + case WM_DROPFILES: + { + HDROP hDrop = (HDROP)wParam; + + char szFile[MAX_PATH]; + DragQueryFile(hDrop,0,szFile,sizeof(szFile)); + if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode()) + { + // replace the selected texture with the new one ... + CDisplay::Instance().ReplaceCurrentTexture(szFile); + } + else + { + const char* sz = strrchr(szFile,'.'); + if (sz && 0 != aiIsExtensionSupported(sz)) + { + strcpy(g_szFileName,szFile); + + DeleteAsset(); + LoadAsset(); + UpdateHistory(); + SaveHistory(); + } + else + { + if (!sz) goto __DRUNKEN_ALIEN_FROM_MARS; + + // check whether it is a typical texture file format ... + ++sz; + if (0 == Assimp::ASSIMP_stricmp(sz,"png") || + 0 == Assimp::ASSIMP_stricmp(sz,"bmp") || + 0 == Assimp::ASSIMP_stricmp(sz,"jpg") || + 0 == Assimp::ASSIMP_stricmp(sz,"tga") || + 0 == Assimp::ASSIMP_stricmp(sz,"tif") || + 0 == Assimp::ASSIMP_stricmp(sz,"hdr") || + 0 == Assimp::ASSIMP_stricmp(sz,"ppm") || + 0 == Assimp::ASSIMP_stricmp(sz,"pfm")) + { + CBackgroundPainter::Instance().SetTextureBG(szFile); + } + else if (0 == Assimp::ASSIMP_stricmp(sz,"dds")) + { + // DDS files could contain skyboxes, but they could also + // contain normal 2D textures. The easiest way to find this + // out is to open the file and check the header ... + FILE* pFile = fopen(szFile,"rb"); + if (!pFile)goto __DRUNKEN_ALIEN_FROM_MARS; + + // header of a dds file (begin) + /* + DWORD dwMagic + DWORD dwSize + DWORD dwFlags + DWORD dwHeight + DWORD dwWidth + DWORD dwPitchOrLinearSize + DWORD dwDepth + DWORD dwMipMapCount -> total with this: 32 + DWORD dwReserved1[11] -> total with this: 76 + DDPIXELFORMAT ddpfPixelFormat -> total with this: 108 + DWORD dwCaps1; -> total with this: 112 + DWORD dwCaps2; ---< here we are! + */ + DWORD dwCaps = 0; + fseek(pFile,112,SEEK_SET); + fread(&dwCaps,4,1,pFile); + + if (dwCaps & 0x00000400L /* DDSCAPS2_CUBEMAP_POSITIVEX */) + { + CLogDisplay::Instance().AddEntry( + "[INFO] Assuming this dds file is a skybox ...", + D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0)); + + CBackgroundPainter::Instance().SetCubeMapBG(szFile); + } + else CBackgroundPainter::Instance().SetTextureBG(szFile); + fclose(pFile); + } + else + { +__DRUNKEN_ALIEN_FROM_MARS: + CLogDisplay::Instance().AddEntry( + "[ERROR] File extension is not supported. E.T. can read this.", + D3DCOLOR_ARGB(0xFF,0xFF,0,0)); + } + } + } + DragFinish(hDrop); + } + return TRUE; + case WM_COMMAND: if (ID_VIEWER_QUIT == LOWORD(wParam)) @@ -482,233 +1578,123 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, { CLogWindow::Instance().Show(); } + else if (ID_TOOLS_CLEARLOG == LOWORD(wParam)) + { + CLogWindow::Instance().Clear(); + } + else if (ID_TOOLS_SAVELOGTOFILE == LOWORD(wParam)) + { + CLogWindow::Instance().Save(); + } + else if (ID_VIEWER_MEMORYCONSUMATION == LOWORD(wParam)) + { + DisplayMemoryConsumption(); + } else if (ID_VIEWER_H == LOWORD(wParam)) { MakeFileAssociations(); } else if (ID_BACKGROUND_CLEAR == LOWORD(wParam)) { - D3DCOLOR clrColor = D3DCOLOR_ARGB(0xFF,100,100,100); - CBackgroundPainter::Instance().SetColor(clrColor); - - HKEY hTemp; - RegCreateKeyEx(HKEY_CURRENT_USER, - "Software\\ASSIMP\\Viewer",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueExA(hTemp,"LastSkyBoxSrc",0,REG_SZ,(const BYTE*)"",MAX_PATH); - RegSetValueExA(hTemp,"LastTextureSrc",0,REG_SZ,(const BYTE*)"",MAX_PATH); - - RegSetValueExA(hTemp,"Color",0,REG_DWORD,(const BYTE*)&clrColor,4); - RegCloseKey(hTemp); + ClearBG(); } else if (ID_BACKGROUND_SETCOLOR == LOWORD(wParam)) { - HKEY hTemp; - RegCreateKeyEx(HKEY_CURRENT_USER, - "Software\\ASSIMP\\Viewer",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueExA(hTemp,"LastSkyBoxSrc",0,REG_SZ,(const BYTE*)"",MAX_PATH); - RegSetValueExA(hTemp,"LastTextureSrc",0,REG_SZ,(const BYTE*)"",MAX_PATH); - - CHOOSECOLOR clr; - clr.lStructSize = sizeof(CHOOSECOLOR); - clr.hwndOwner = hwndDlg; - clr.Flags = CC_RGBINIT | CC_FULLOPEN; - clr.rgbResult = RGB(100,100,100); - clr.lpCustColors = g_aclCustomColors; - clr.lpfnHook = NULL; - clr.lpTemplateName = NULL; - clr.lCustData = NULL; - - ChooseColor(&clr); - - D3DCOLOR clrColor = D3DCOLOR_ARGB(0xFF, - GetRValue(clr.rgbResult), - GetGValue(clr.rgbResult), - GetBValue(clr.rgbResult)); - CBackgroundPainter::Instance().SetColor(clrColor); - - RegSetValueExA(hTemp,"Color",0,REG_DWORD,(const BYTE*)&clrColor,4); - RegCloseKey(hTemp); + ChooseBGColor(); } else if (ID_BACKGROUND_LOADTEXTURE == LOWORD(wParam)) { - char szFileName[MAX_PATH]; - - DWORD dwTemp = MAX_PATH; - HKEY hTemp; - RegCreateKeyEx(HKEY_CURRENT_USER, - "Software\\ASSIMP\\Viewer",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - if(ERROR_SUCCESS != RegQueryValueEx(hTemp,"TextureSrc",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, - "Open texture as background", - OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR, - 0, 1, ".jpg", 0, NULL, NULL - }; - if(GetOpenFileName(&sFilename1) == 0) return TRUE; - - // Now store the file in the registry - RegSetValueExA(hTemp,"TextureSrc",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH); - RegSetValueExA(hTemp,"LastTextureSrc",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH); - RegSetValueExA(hTemp,"LastSkyBoxSrc",0,REG_SZ,(const BYTE*)"",MAX_PATH); - RegCloseKey(hTemp); - - CBackgroundPainter::Instance().SetTextureBG(szFileName); + LoadBGTexture(); } else if (ID_BACKGROUND_LOADSKYBOX == LOWORD(wParam)) { - char szFileName[MAX_PATH]; - - DWORD dwTemp = MAX_PATH; - HKEY hTemp; - RegCreateKeyEx(HKEY_CURRENT_USER, - "Software\\ASSIMP\\Viewer",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - if(ERROR_SUCCESS != RegQueryValueEx(hTemp,"SkyBoxSrc",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), - "Skyboxes\0*.dds\0*.*\0", NULL, 0, 1, - szFileName, MAX_PATH, NULL, 0, NULL, - "Open skybox as background", - OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR, - 0, 1, ".dds", 0, NULL, NULL - }; - if(GetOpenFileName(&sFilename1) == 0) return TRUE; - - // Now store the file in the registry - RegSetValueExA(hTemp,"SkyBoxSrc",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH); - RegSetValueExA(hTemp,"LastSkyBoxSrc",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH); - RegSetValueExA(hTemp,"LastTextureSrc",0,REG_SZ,(const BYTE*)"",MAX_PATH); - RegCloseKey(hTemp); - - CBackgroundPainter::Instance().SetCubeMapBG(szFileName); + LoadSkybox(); } else if (ID_VIEWER_SAVESCREENSHOTTOFILE == LOWORD(wParam)) { - char szFileName[MAX_PATH]; - - DWORD dwTemp = MAX_PATH; - HKEY hTemp; - RegCreateKeyEx(HKEY_CURRENT_USER, - "Software\\ASSIMP\\Viewer",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - if(ERROR_SUCCESS != RegQueryValueEx(hTemp,"ScreenShot",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), - "PNG Images\0*.png", NULL, 0, 1, - szFileName, MAX_PATH, NULL, 0, NULL, - "Save Screenshot to file", - OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR, - 0, 1, ".png", 0, NULL, NULL - }; - if(GetSaveFileName(&sFilename1) == 0) return TRUE; - - // Now store the file in the registry - RegSetValueExA(hTemp,"ScreenShot",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH); - RegCloseKey(hTemp); - - IDirect3DSurface9* pi; - g_piDevice->GetRenderTarget(0,&pi); - D3DXSaveSurfaceToFile(szFileName,D3DXIFF_PNG, - pi,NULL,NULL); - pi->Release(); + SaveScreenshot(); } else if (ID_VIEWER_OPEN == LOWORD(wParam)) { - char szFileName[MAX_PATH]; - - DWORD dwTemp = MAX_PATH; - HKEY hTemp; - RegCreateKeyEx(HKEY_CURRENT_USER, - "Software\\ASSIMP\\Viewer",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - if(ERROR_SUCCESS != RegQueryValueEx(hTemp,"CurrentApp",NULL,NULL, - (BYTE*)szFileName,&dwTemp)) + OpenAsset(); + } + else if (ID_TOOLS_FLIPNORMALS == LOWORD(wParam)) + { + if (g_pcAsset && g_pcAsset->pcScene) { - // Key was not found. Use C: - strcpy(szFileName,""); + g_pcAsset->FlipNormals(); } - else + } + else if (ID_TOOLS_ORIGINALNORMALS == LOWORD(wParam)) + { + if (g_pcAsset && g_pcAsset->pcScene) { - // need to remove the file name - char* sz = strrchr(szFileName,'\\'); - if (!sz)sz = strrchr(szFileName,'/'); - if (!sz)*sz = 0; + g_pcAsset->SetNormalSet(AssimpView::AssetHelper::ORIGINAL); + + HMENU hMenu = GetMenu(g_hDlg); + ModifyMenu(hMenu,ID_TOOLS_ORIGINALNORMALS, + MF_BYCOMMAND | MF_CHECKED | MF_STRING,ID_TOOLS_ORIGINALNORMALS,"Original normals"); + ModifyMenu(hMenu,ID_TOOLS_HARDNORMALS, + MF_BYCOMMAND | MF_UNCHECKED | MF_STRING,ID_TOOLS_HARDNORMALS,"Hard normals"); + ModifyMenu(hMenu,ID_TOOLS_SMOOTHNORMALS, + MF_BYCOMMAND | MF_UNCHECKED | MF_STRING,ID_TOOLS_SMOOTHNORMALS,"Smooth normals"); } - - // get a list of all file extensions supported by ASSIMP - aiString sz; - aiGetExtensionList(&sz); - - char szList[MAXLEN + 100]; - strcpy(szList,"ASSIMP assets"); - char* szCur = szList + 14; - strcpy(szCur,sz.data); - szCur += sz.length+1; - strcpy(szCur,"All files"); - szCur += 10; - strcpy(szCur,"*.*"); - szCur[4] = 0; - - OPENFILENAME sFilename1 = { - sizeof(OPENFILENAME), - g_hDlg,GetModuleHandle(NULL), szList, NULL, 0, 1, - szFileName, MAX_PATH, NULL, 0, NULL, - "Import Asset into ASSIMP", - OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR, - 0, 1, ".x", 0, NULL, NULL - }; - if(GetOpenFileName(&sFilename1) == 0) return TRUE; - - // Now store the file in the registry - RegSetValueExA(hTemp,"CurrentApp",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH); - RegCloseKey(hTemp); - - if (0 != strcmp(g_szFileName,szFileName)) + } + else if (ID_TOOLS_SMOOTHNORMALS == LOWORD(wParam)) + { + if (g_pcAsset && g_pcAsset->pcScene) { - strcpy(g_szFileName, szFileName); - DeleteAssetData(); - DeleteAsset(); - LoadAsset(); - } + g_pcAsset->SetNormalSet(AssimpView::AssetHelper::SMOOTH); + HMENU hMenu = GetMenu(g_hDlg); + ModifyMenu(hMenu,ID_TOOLS_SMOOTHNORMALS, + MF_BYCOMMAND | MF_CHECKED | MF_STRING,ID_TOOLS_SMOOTHNORMALS,"Smooth normals"); + ModifyMenu(hMenu,ID_TOOLS_HARDNORMALS, + MF_BYCOMMAND | MF_UNCHECKED | MF_STRING,ID_TOOLS_HARDNORMALS,"Hard normals"); + ModifyMenu(hMenu,ID_TOOLS_ORIGINALNORMALS, + MF_BYCOMMAND | MF_UNCHECKED | MF_STRING,ID_TOOLS_ORIGINALNORMALS,"Original normals"); + } + } + else if (ID_TOOLS_HARDNORMALS == LOWORD(wParam)) + { + if (g_pcAsset && g_pcAsset->pcScene) + { + g_pcAsset->SetNormalSet(AssimpView::AssetHelper::HARD); + + HMENU hMenu = GetMenu(g_hDlg); + ModifyMenu(hMenu,ID_TOOLS_HARDNORMALS, + MF_BYCOMMAND | MF_CHECKED | MF_STRING,ID_TOOLS_HARDNORMALS,"Hard normals"); + ModifyMenu(hMenu,ID_TOOLS_ORIGINALNORMALS, + MF_BYCOMMAND | MF_UNCHECKED | MF_STRING,ID_TOOLS_ORIGINALNORMALS,"Original normals"); + ModifyMenu(hMenu,ID_TOOLS_SMOOTHNORMALS, + MF_BYCOMMAND | MF_UNCHECKED | MF_STRING,ID_TOOLS_SMOOTHNORMALS,"Smooth normals"); + } + } + else if (ID_TOOLS_STEREOVIEW == LOWORD(wParam)) + { + g_sOptions.bStereoView =! g_sOptions.bStereoView; + + HMENU hMenu = GetMenu(g_hDlg); + if (g_sOptions.bStereoView) + { + ModifyMenu(hMenu,ID_TOOLS_STEREOVIEW, + MF_BYCOMMAND | MF_CHECKED | MF_STRING,ID_TOOLS_STEREOVIEW,"Stereo view"); + + CLogDisplay::Instance().AddEntry("[INFO] Switched to stereo mode", + D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0)); + } + else + { + ModifyMenu(hMenu,ID_TOOLS_STEREOVIEW, + MF_BYCOMMAND | MF_UNCHECKED | MF_STRING,ID_TOOLS_STEREOVIEW,"Stereo view"); + + CLogDisplay::Instance().AddEntry("[INFO] Switched to mono mode", + D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0)); + } + } + else if (ID_VIEWER_CLEARHISTORY == LOWORD(wParam)) + { + ClearHistory(); } else if (ID_VIEWER_CLOSEASSET == LOWORD(wParam)) { @@ -719,109 +1705,102 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, { if (IDC_TOGGLEMS == LOWORD(wParam)) { - g_sOptions.bMultiSample = !g_sOptions.bMultiSample; - DeleteAssetData(); - ShutdownDevice(); - if (0 == CreateDevice()) - { - CLogDisplay::Instance().AddEntry( - "[ERROR] Failed to toggle MultiSampling mode"); - g_sOptions.bMultiSample = !g_sOptions.bMultiSample; - CreateDevice(); - } - CreateAssetData(); - - if (g_sOptions.bMultiSample) - { - CLogDisplay::Instance().AddEntry( - "[OK] Changed MultiSampling mode to the maximum value for this device"); - } - else - { - CLogDisplay::Instance().AddEntry( - "[OK] MultiSampling has been disabled"); - } + ToggleMS(); } else if (IDC_TOGGLEMAT == LOWORD(wParam)) { - g_sOptions.bRenderMats = !g_sOptions.bRenderMats; + ToggleMats(); + } + else if (IDC_LCOLOR1 == LOWORD(wParam)) + { + DisplayColorDialog(&g_avLightColors[0]); + InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR1),NULL,TRUE); + UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR1)); + SaveLightColors(); + } + else if (IDC_LCOLOR2 == LOWORD(wParam)) + { + DisplayColorDialog(&g_avLightColors[1]); + InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR2),NULL,TRUE); + UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR2)); + SaveLightColors(); + } + else if (IDC_LCOLOR3 == LOWORD(wParam)) + { + DisplayColorDialog(&g_avLightColors[2]); + InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR3),NULL,TRUE); + UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR3)); + SaveLightColors(); + } + else if (IDC_LRESET == LOWORD(wParam)) + { + g_avLightColors[0] = D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0xFF); + g_avLightColors[1] = D3DCOLOR_ARGB(0xFF,0xFF,0x00,0x00); + g_avLightColors[2] = D3DCOLOR_ARGB(0xFF,0x05,0x05,0x05); + + InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR1),NULL,TRUE); + UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR1)); + InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR2),NULL,TRUE); + UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR2)); + InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR3),NULL,TRUE); + UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR3)); + SaveLightColors(); } else if (IDC_NOSPECULAR == LOWORD(wParam)) { - g_sOptions.bNoSpecular = !g_sOptions.bNoSpecular; - UpdateSpecularMaterials(); + ToggleSpecular(); } else if (IDC_ZOOM == LOWORD(wParam)) { - g_bFPSView = !g_bFPSView; - - SetupFPSView(); + ToggleFPSView(); } else if (IDC_BLUBB == LOWORD(wParam)) { - // adjust the size - RECT sRect; - GetWindowRect(hwndDlg,&sRect); - sRect.right -= sRect.left; - sRect.bottom -= sRect.top; - - RECT sRect2; - GetWindowRect(GetDlgItem ( hwndDlg, IDC_BLUBB ),&sRect2); - sRect2.left -= sRect.left; - sRect2.top -= sRect.top; - - HKEY hTemp; - DWORD dwValue; - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\ASSIMP\\Viewer", - NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - - if (BST_UNCHECKED == IsDlgButtonChecked(hwndDlg,IDC_BLUBB)) - { - SetWindowPos(hwndDlg,NULL,0,0,sRect.right-188,sRect.bottom, - SWP_NOMOVE | SWP_NOZORDER); - - dwValue = 0; - SetWindowText(GetDlgItem(hwndDlg,IDC_BLUBB),">>"); - RegSetValueExA(hTemp,"LastUIState",0,REG_DWORD,(const BYTE*)&dwValue,4); - } - else - { - SetWindowPos(hwndDlg,NULL,0,0,sRect.right+188,sRect.bottom, - SWP_NOMOVE | SWP_NOZORDER); - - dwValue = 1; - SetWindowText(GetDlgItem(hwndDlg,IDC_BLUBB),"<<"); - RegSetValueExA(hTemp,"LastUIState",0,REG_DWORD,(const BYTE*)&dwValue,4); - } - RegCloseKey(hTemp); + ToggleUIState(); } else if (IDC_TOGGLENORMALS == LOWORD(wParam)) { - g_sOptions.bRenderNormals = !g_sOptions.bRenderNormals; + ToggleNormals(); } else if (IDC_LOWQUALITY == LOWORD(wParam)) { - g_sOptions.bLowQuality = !g_sOptions.bLowQuality; + ToggleLowQuality(); } else if (IDC_3LIGHTS == LOWORD(wParam)) { - g_sOptions.b3Lights = !g_sOptions.b3Lights; + ToggleMultipleLights(); } else if (IDC_LIGHTROTATE == LOWORD(wParam)) { - g_sOptions.bLightRotate = !g_sOptions.bLightRotate; + ToggleLightRotate(); } else if (IDC_AUTOROTATE == LOWORD(wParam)) { - g_sOptions.bRotate = !g_sOptions.bRotate; + ToggleAutoRotate(); } else if (IDC_TOGGLEWIRE == LOWORD(wParam)) { - if (g_sOptions.eDrawMode == RenderOptions::WIREFRAME) - g_sOptions.eDrawMode = RenderOptions::NORMAL; - else g_sOptions.eDrawMode = RenderOptions::WIREFRAME; + ToggleWireFrame(); } } + // check the file history + for (unsigned int i = 0; i < AI_VIEW_NUM_RECENT_FILES;++i) + { + if (AI_VIEW_RECENT_FILE_ID(i) == LOWORD(wParam)) + { + strcpy(g_szFileName,g_aPreviousFiles[i].c_str()); + DeleteAssetData(); + DeleteAsset(); + LoadAsset(); + + // update and safe the history + UpdateHistory(); + SaveHistory(); + } + } + + // handle popup menus for the tree window + CDisplay::Instance().HandleTreeViewPopup(wParam,lParam); return TRUE; }; @@ -928,8 +1907,10 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, // needed for the RichEdit control in the about/help dialog LoadLibrary( "riched20.dll" ); + // load windows common controls library to get XP style InitCommonControls(); + // intiailize the IDirect3D9 interface g_hInstance = hInstance; if (0 == InitD3D()) { @@ -938,9 +1919,16 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, return -6; } + // create the main dialog HWND hDlg = CreateDialog(hInstance,MAKEINTRESOURCE(IDD_DIALOGMAIN), NULL,&MessageProc); + // initialise the default logger if neccessary + Assimp::DefaultLogger::create("",Assimp::Logger::VERBOSE); + Assimp::DefaultLogger::get()->attachStream((Assimp::LogStream*)&CLogWindow::Instance().pcStream, + Assimp::DefaultLogger::DEBUGGING | Assimp::DefaultLogger::INFO | + Assimp::DefaultLogger::ERR | Assimp::DefaultLogger::WARN); + if (NULL == hDlg) { MessageBox(NULL,"Failed to create dialog from resource", @@ -948,20 +1936,23 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, return -5; } + // display the window g_hDlg = hDlg; - MSG uMsg; memset(&uMsg,0,sizeof( MSG)); - ShowWindow( hDlg, nCmdShow ); UpdateWindow( hDlg ); - if (0 == CreateDevice(true,false,true)) + // create the D3D device object + if (0 == CreateDevice(g_sOptions.bMultiSample,false,true)) { MessageBox(NULL,"Failed to initialize Direct3D 9 (2)", "ASSIMP ModelViewer",MB_OK); return -4; } + // setup ASSIMP standard limits for the SplitLargeMeshes-process + aiSetTriangleSplitLimit(g_sCaps.MaxPrimitiveCount-1); + aiSetVertexSplitLimit(0xFFFFFFFF); CLogDisplay::Instance().AddEntry("[OK] The viewer has been initialized successfully"); @@ -971,7 +1962,7 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, SetFocus(g_hDlg); // recover background skyboxes/textures from the last session - HKEY hTemp; + HKEY g_hRegistry; union { char szFileName[MAX_PATH]; @@ -979,23 +1970,23 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, }; DWORD dwTemp = MAX_PATH; RegCreateKeyEx(HKEY_CURRENT_USER, - "Software\\ASSIMP\\Viewer",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - if(ERROR_SUCCESS == RegQueryValueEx(hTemp,"LastSkyBoxSrc",NULL,NULL, + "Software\\ASSIMP\\Viewer",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &g_hRegistry,NULL); + if(ERROR_SUCCESS == RegQueryValueEx(g_hRegistry,"LastSkyBoxSrc",NULL,NULL, (BYTE*)szFileName,&dwTemp) && '\0' != szFileName[0]) { CBackgroundPainter::Instance().SetCubeMapBG(szFileName); } - else if(ERROR_SUCCESS == RegQueryValueEx(hTemp,"LastTextureSrc",NULL,NULL, + else if(ERROR_SUCCESS == RegQueryValueEx(g_hRegistry,"LastTextureSrc",NULL,NULL, (BYTE*)szFileName,&dwTemp) && '\0' != szFileName[0]) { CBackgroundPainter::Instance().SetTextureBG(szFileName); } - else if(ERROR_SUCCESS == RegQueryValueEx(hTemp,"Color",NULL,NULL, + else if(ERROR_SUCCESS == RegQueryValueEx(g_hRegistry,"Color",NULL,NULL, (BYTE*)&clrColor,&dwTemp)) { CBackgroundPainter::Instance().SetColor(clrColor); } - RegCloseKey(hTemp); + RegCloseKey(g_hRegistry); // now handle command line arguments HandleCommandLine(lpCmdLine); @@ -1026,28 +2017,7 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, IsDlgButtonChecked(g_hDlg,IDC_TOGGLEMS) == BST_CHECKED ? BST_UNCHECKED : BST_CHECKED); - g_sOptions.bMultiSample = !g_sOptions.bMultiSample; - DeleteAssetData(); - ShutdownDevice(); - if (0 == CreateDevice()) - { - CLogDisplay::Instance().AddEntry( - "[ERROR] Failed to toggle MultiSampling mode"); - g_sOptions.bMultiSample = !g_sOptions.bMultiSample; - CreateDevice(); - } - CreateAssetData(); - - if (g_sOptions.bMultiSample) - { - CLogDisplay::Instance().AddEntry( - "[OK] Changed MultiSampling mode to the maximum value for this device"); - } - else - { - CLogDisplay::Instance().AddEntry( - "[OK] MultiSampling has been disabled"); - } + ToggleMS(); break; case 'L': @@ -1057,8 +2027,7 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, IsDlgButtonChecked(g_hDlg,IDC_3LIGHTS) == BST_CHECKED ? BST_UNCHECKED : BST_CHECKED); - g_sOptions.b3Lights = !g_sOptions.b3Lights; - + ToggleMultipleLights(); break; case 'P': @@ -1068,8 +2037,7 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, IsDlgButtonChecked(g_hDlg,IDC_LOWQUALITY) == BST_CHECKED ? BST_UNCHECKED : BST_CHECKED); - g_sOptions.bLowQuality = !g_sOptions.bLowQuality; - + ToggleLowQuality(); break; case 'D': @@ -1079,8 +2047,7 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, IsDlgButtonChecked(g_hDlg,IDC_TOGGLEMAT) == BST_CHECKED ? BST_UNCHECKED : BST_CHECKED); - g_sOptions.bRenderMats = !g_sOptions.bRenderMats; - + ToggleMats(); break; @@ -1090,9 +2057,7 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, CheckDlgButton(g_hDlg,IDC_TOGGLENORMALS, IsDlgButtonChecked(g_hDlg,IDC_TOGGLENORMALS) == BST_CHECKED ? BST_UNCHECKED : BST_CHECKED); - - g_sOptions.bRenderNormals = !g_sOptions.bRenderNormals; - + ToggleNormals(); break; @@ -1103,9 +2068,7 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, IsDlgButtonChecked(g_hDlg,IDC_NOSPECULAR) == BST_CHECKED ? BST_UNCHECKED : BST_CHECKED); - g_sOptions.bNoSpecular = !g_sOptions.bNoSpecular; - UpdateSpecularMaterials(); - + ToggleSpecular(); break; case 'A': @@ -1115,8 +2078,7 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, IsDlgButtonChecked(g_hDlg,IDC_AUTOROTATE) == BST_CHECKED ? BST_UNCHECKED : BST_CHECKED); - g_sOptions.bRotate = !g_sOptions.bRotate; - + ToggleAutoRotate(); break; @@ -1127,8 +2089,7 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, IsDlgButtonChecked(g_hDlg,IDC_LIGHTROTATE) == BST_CHECKED ? BST_UNCHECKED : BST_CHECKED); - g_sOptions.bLightRotate = !g_sOptions.bLightRotate; - + ToggleLightRotate(); break; case 'Z': @@ -1138,8 +2099,7 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, IsDlgButtonChecked(g_hDlg,IDC_ZOOM) == BST_CHECKED ? BST_UNCHECKED : BST_CHECKED); - g_bFPSView = !g_bFPSView; - SetupFPSView(); + ToggleFPSView(); break; @@ -1150,17 +2110,14 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, IsDlgButtonChecked(g_hDlg,IDC_TOGGLEWIRE) == BST_CHECKED ? BST_UNCHECKED : BST_CHECKED); - if (g_sOptions.eDrawMode == RenderOptions::NORMAL) - g_sOptions.eDrawMode = RenderOptions::WIREFRAME; - else g_sOptions.eDrawMode = RenderOptions::NORMAL; - + ToggleWireFrame(); break; } } } // render the scene - Render(); + CDisplay::Instance().OnRender(); g_dCurTime = timeGetTime(); g_fElpasedTime = (float)((g_dCurTime - g_dLastTime) * 0.001); @@ -1187,6 +2144,7 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, } } DeleteAsset(); + Assimp::DefaultLogger::kill(); ShutdownDevice(); ShutdownD3D(); return 0; diff --git a/tools/assimp_view/Normals.cpp b/tools/assimp_view/Normals.cpp new file mode 100644 index 000000000..190f3ad6d --- /dev/null +++ b/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; +} + +}; \ No newline at end of file diff --git a/tools/assimp_view/RenderOptions.h b/tools/assimp_view/RenderOptions.h index 37a66a8d0..8b8d6aa3a 100644 --- a/tools/assimp_view/RenderOptions.h +++ b/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; }; diff --git a/tools/assimp_view/Shaders.cpp b/tools/assimp_view/Shaders.cpp index 22bab2fc8..64e21ca42 100644 --- a/tools/assimp_view/Shaders.cpp +++ b/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" ); diff --git a/tools/assimp_view/Shaders.h b/tools/assimp_view/Shaders.h index 7ceec5ede..b27eea361 100644 --- a/tools/assimp_view/Shaders.h +++ b/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 diff --git a/tools/assimp_view/assimp_view.aps b/tools/assimp_view/assimp_view.aps index 35f202b8a..0620bea84 100644 Binary files a/tools/assimp_view/assimp_view.aps and b/tools/assimp_view/assimp_view.aps differ diff --git a/tools/assimp_view/assimp_view.cpp b/tools/assimp_view/assimp_view.cpp index 32eb57fde..5672e3e22 100644 --- a/tools/assimp_view/assimp_view.cpp +++ b/tools/assimp_view/assimp_view.cpp @@ -1,17 +1,49 @@ +/* +--------------------------------------------------------------------------- +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. +--------------------------------------------------------------------------- +*/ -//------------------------------------------------------------------------------- -/** - * This program is distributed under the terms of the GNU Lesser General - * Public License (LGPL). - * - * ASSIMP Viewer Utility - * - */ -//------------------------------------------------------------------------------- #include "stdafx.h" #include "assimp_view.h" - +#include +using namespace std; namespace AssimpView { @@ -28,6 +60,7 @@ char g_szFileName[MAX_PATH]; ID3DXEffect* g_piDefaultEffect = NULL; ID3DXEffect* g_piNormalsEffect = NULL; ID3DXEffect* g_piPassThroughEffect = NULL; +ID3DXEffect* g_piPatternEffect = NULL; bool g_bMousePressed = false; bool g_bMousePressedR = false; bool g_bMousePressedM = false; @@ -40,12 +73,23 @@ float g_fWheelPos = -10.0f; bool g_bLoadingCanceled = false; IDirect3DTexture9* g_pcTexture = NULL; +extern bool g_bWasFlipped /*= false*/; + aiMatrix4x4 g_mWorld; aiMatrix4x4 g_mWorldRotate; aiVector3D g_vRotateSpeed = aiVector3D(0.5f,0.5f,0.5f); -aiVector3D g_avLightDirs[1] = { aiVector3D(-0.5f,0.6f,0.2f) /*, - aiVector3D(-0.5f,0.5f,0.5f)*/}; +// NOTE: The second light direction is no computed from the first +aiVector3D g_avLightDirs[1] = +{ aiVector3D(-0.5f,0.6f,0.2f) }; + +extern D3DCOLOR g_avLightColors[3] = +{ + D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0xFF), + D3DCOLOR_ARGB(0xFF,0xFF,0x00,0x00), + D3DCOLOR_ARGB(0xFF,0x05,0x05,0x05), +}; + POINT g_mousePos; POINT g_LastmousePos; bool g_bFPSView = false; @@ -66,31 +110,7 @@ AssetHelper *g_pcAsset = NULL; // unsigned char* g_szImageMask = NULL; -//------------------------------------------------------------------------------- -// 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 - }; +float g_fLoadTime = 0.0f; //------------------------------------------------------------------------------- @@ -99,14 +119,14 @@ D3DXVECTOR4 g_aclNormalColors[14] = // smart progress bar //------------------------------------------------------------------------------- DWORD WINAPI LoadThreadProc(LPVOID lpParameter) - { +{ UNREFERENCED_PARAMETER(lpParameter); // get current time double fCur = (double)timeGetTime(); // call ASSIMPs C-API to load the file - g_pcAsset->pcScene = aiImportFile(g_szFileName, + g_pcAsset->pcScene = (aiScene*)aiImportFile(g_szFileName, aiProcess_CalcTangentSpace | // calculate tangents and bitangents aiProcess_JoinIdenticalVertices | // join identical vertices aiProcess_Triangulate | // triangulate n-polygons @@ -116,15 +136,13 @@ DWORD WINAPI LoadThreadProc(LPVOID lpParameter) // get the end time of zje operation, calculate delta t double fEnd = (double)timeGetTime(); - double dTime = (fEnd - fCur) / 1000; - char szTemp[128]; - sprintf(szTemp,"%.5f",(float)dTime); - SetDlgItemText(g_hDlg,IDC_ELOAD,szTemp); + g_fLoadTime = (float)((fEnd - fCur) / 1000); +// char szTemp[128]; g_bLoadingFinished = true; // check whether the loading process has failed ... if (NULL == g_pcAsset->pcScene) - { + { CLogDisplay::Instance().AddEntry("[ERROR] Unable to load this asset:", D3DCOLOR_ARGB(0xFF,0xFF,0,0)); @@ -132,19 +150,8 @@ DWORD WINAPI LoadThreadProc(LPVOID lpParameter) CLogDisplay::Instance().AddEntry(aiGetErrorString(), D3DCOLOR_ARGB(0xFF,0xFF,0,0)); return 1; - } - return 0; } - -//------------------------------------------------------------------------------- -// 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); + return 0; } //------------------------------------------------------------------------------- @@ -157,6 +164,15 @@ int LoadAsset(void) g_mWorldRotate = aiMatrix4x4(); g_mWorld = aiMatrix4x4(); + char szTemp[MAX_PATH+64]; + sprintf(szTemp,"Starting to load %s",g_szFileName); + CLogWindow::Instance().WriteLine( + "****************************************************************************"); + CLogWindow::Instance().WriteLine(szTemp); + CLogWindow::Instance().WriteLine( + "****************************************************************************"); + CLogWindow::Instance().SetAutoUpdate(false); + // create a helper thread to load the asset DWORD dwID; g_bLoadingCanceled = false; @@ -175,6 +191,10 @@ int LoadAsset(void) DialogBox(g_hInstance,MAKEINTRESOURCE(IDD_LOADDIALOG), g_hDlg,&ProgressMessageProc); + // update the log window + CLogWindow::Instance().SetAutoUpdate(true); + CLogWindow::Instance().Update(); + // now we should have loaded the asset. Check this ... g_bLoadingFinished = false; if (!g_pcAsset || !g_pcAsset->pcScene) @@ -189,34 +209,14 @@ int LoadAsset(void) // allocate a new MeshHelper array and build a new instance // for each mesh in the original asset - g_pcAsset->apcMeshes = new AssetHelper::MeshHelper*[ - g_pcAsset->pcScene->mNumMeshes](); - - // get the number of vertices/faces in the model - unsigned int iNumVert = 0; - unsigned int iNumFaces = 0; + g_pcAsset->apcMeshes = new AssetHelper::MeshHelper*[g_pcAsset->pcScene->mNumMeshes](); 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; + { g_pcAsset->apcMeshes[i] = new AssetHelper::MeshHelper(); } - // 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); - - // need to get the number of nodes - iNumVert = 0; - GetNodeCount(g_pcAsset->pcScene->mRootNode,&iNumVert); - sprintf(szOut,"%i",(int)iNumVert); - SetDlgItemText(g_hDlg,IDC_ENODE,szOut); // build a new caption string for the viewer + char szOut[MAX_PATH + 10]; sprintf(szOut,AI_VIEW_CAPTION_BASE " [%s]",g_szFileName); SetWindowText(g_hDlg,szOut); @@ -230,26 +230,39 @@ int LoadAsset(void) g_sCamera.vRight = aiVector3D(0.0f,1.0f,0.0f); // build native D3D vertex/index buffers, textures, materials - return CreateAssetData(); + if( 1 != CreateAssetData())return 0; + + CLogDisplay::Instance().AddEntry("[OK] The asset has been loaded successfully"); + CDisplay::Instance().FillDisplayList(); + CDisplay::Instance().FillAnimList(); + + CDisplay::Instance().FillDefaultStatistics(); + + // just make sure the alpha blend ordering is done in the first frame + CMeshRenderer::Instance().Reset(); + g_pcAsset->iNormalSet = AssetHelper::ORIGINAL; + g_bWasFlipped = false; + return 1; } //------------------------------------------------------------------------------- // Delete the loaded asset +// The function does nothing is no asset is loaded //------------------------------------------------------------------------------- int DeleteAsset(void) - { +{ if (!g_pcAsset)return 0; // don't anymore know why this was necessary ... - Render(); + CDisplay::Instance().OnRender(); // delete everything DeleteAssetData(); for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) - { + { delete g_pcAsset->apcMeshes[i]; - } + } aiReleaseImport(g_pcAsset->pcScene); delete[] g_pcAsset->apcMeshes; delete g_pcAsset; @@ -265,26 +278,39 @@ int DeleteAsset(void) // reset the caption of the viewer window SetWindowText(g_hDlg,AI_VIEW_CAPTION_BASE); + + // clear UI + CDisplay::Instance().ClearAnimList(); + CDisplay::Instance().ClearDisplayList(); + + CMaterialManager::Instance().Reset(); return 1; - } +} //------------------------------------------------------------------------------- +// Calculate the boundaries of a given node and all of its children +// The boundaries are in Worldspace (AABB) +// piNode Input node +// p_avOut Receives the min/max boundaries. Must point to 2 vec3s +// piMatrix Transformation matrix of the graph at this position //------------------------------------------------------------------------------- int CalculateBounds(aiNode* piNode, aiVector3D* p_avOut, const aiMatrix4x4& piMatrix) - { +{ + ai_assert(NULL != piNode); + ai_assert(NULL != p_avOut); + aiMatrix4x4 mTemp = piNode->mTransformation; mTemp.Transpose(); aiMatrix4x4 aiMe = mTemp * piMatrix; for (unsigned int i = 0; i < piNode->mNumMeshes;++i) - { + { for( unsigned int a = 0; a < g_pcAsset->pcScene->mMeshes[ piNode->mMeshes[i]]->mNumVertices;++a) - { - aiVector3D pc =g_pcAsset->pcScene->mMeshes[ - piNode->mMeshes[i]]->mVertices[a]; + { + aiVector3D pc =g_pcAsset->pcScene->mMeshes[piNode->mMeshes[i]]->mVertices[a]; aiVector3D pc1; D3DXVec3TransformCoord((D3DXVECTOR3*)&pc1,(D3DXVECTOR3*)&pc, @@ -296,89 +322,58 @@ int CalculateBounds(aiNode* piNode, aiVector3D* p_avOut, p_avOut[1].x = std::max( p_avOut[1].x, pc1.x); p_avOut[1].y = std::max( p_avOut[1].y, pc1.y); p_avOut[1].z = std::max( p_avOut[1].z, pc1.z); - } } - for (unsigned int i = 0; i < piNode->mNumChildren;++i) - { - CalculateBounds( piNode->mChildren[i], p_avOut, aiMe ); - } - return 1; } - - + for (unsigned int i = 0; i < piNode->mNumChildren;++i) + { + CalculateBounds( piNode->mChildren[i], p_avOut, aiMe ); + } + return 1; +} //------------------------------------------------------------------------------- +// Scale the asset that it fits perfectly into the viewer window +// The function calculates the boundaries of the mesh and modifies the +// global world transformation matrix according to the aset AABB //------------------------------------------------------------------------------- int ScaleAsset(void) - { +{ aiVector3D aiVecs[2] = {aiVector3D( 1e10f, 1e10f, 1e10f), aiVector3D( -1e10f, -1e10f, -1e10f) }; if (g_pcAsset->pcScene->mRootNode) - { + { aiMatrix4x4 m; CalculateBounds(g_pcAsset->pcScene->mRootNode,aiVecs,m); - } - + } + aiVector3D vDelta = aiVecs[1]-aiVecs[0]; aiVector3D vHalf = aiVecs[0] + (vDelta / 2.0f); float fScale = 10.0f / vDelta.Length(); - + g_mWorld = aiMatrix4x4( - 1.0f,0.0f,0.0f,0.0f, - 0.0f,1.0f,0.0f,0.0f, - 0.0f,0.0f,1.0f,0.0f, - -vHalf.x,-vHalf.y,-vHalf.z,1.0f) * + 1.0f,0.0f,0.0f,0.0f, + 0.0f,1.0f,0.0f,0.0f, + 0.0f,0.0f,1.0f,0.0f, + -vHalf.x,-vHalf.y,-vHalf.z,1.0f) * aiMatrix4x4( - fScale,0.0f,0.0f,0.0f, - 0.0f,fScale,0.0f,0.0f, - 0.0f,0.0f,fScale,0.0f, - 0.0f,0.0f,0.0f,1.0f); -#if 0 - // now handle the fact that the asset might have its - // own transformation matrix (handle scaling and translation) - if (NULL != g_pcAsset->pcScene->mRootNode) - { - if (0.0f != g_pcAsset->pcScene->mRootNode->mTransformation[0][0] && - 0.0f != g_pcAsset->pcScene->mRootNode->mTransformation[1][1] && - 0.0f != g_pcAsset->pcScene->mRootNode->mTransformation[2][2] && - 0.0f != g_pcAsset->pcScene->mRootNode->mTransformation[3][3]) - { - g_mWorld[0][0] /= g_pcAsset->pcScene->mRootNode->mTransformation[0][0]; - g_mWorld[1][1] /= g_pcAsset->pcScene->mRootNode->mTransformation[1][1]; - g_mWorld[2][2] /= g_pcAsset->pcScene->mRootNode->mTransformation[2][2]; - g_mWorld[3][3] /= g_pcAsset->pcScene->mRootNode->mTransformation[3][3]; - } - g_mWorld[3][0] -= g_pcAsset->pcScene->mRootNode->mTransformation[3][0]; - g_mWorld[3][1] -= g_pcAsset->pcScene->mRootNode->mTransformation[3][1]; - g_mWorld[3][2] -= g_pcAsset->pcScene->mRootNode->mTransformation[3][2]; - - aiMatrix4x4 m; - if ( 0 == memcmp(&m,&g_pcAsset->pcScene->mRootNode->mTransformation,sizeof(aiMatrix4x4)) && - 1 <= g_pcAsset->pcScene->mRootNode->mNumChildren) - { - if (0.0f != g_pcAsset->pcScene->mRootNode->mChildren[0]->mTransformation[0][0] && - 0.0f != g_pcAsset->pcScene->mRootNode->mChildren[0]->mTransformation[1][1] && - 0.0f != g_pcAsset->pcScene->mRootNode->mChildren[0]->mTransformation[2][2] && - 0.0f != g_pcAsset->pcScene->mRootNode->mChildren[0]->mTransformation[3][3]) - { - g_mWorld[0][0] /= g_pcAsset->pcScene->mRootNode->mChildren[0]->mTransformation[0][0]; - g_mWorld[1][1] /= g_pcAsset->pcScene->mRootNode->mChildren[0]->mTransformation[1][1]; - g_mWorld[2][2] /= g_pcAsset->pcScene->mRootNode->mChildren[0]->mTransformation[2][2]; - g_mWorld[3][3] /= g_pcAsset->pcScene->mRootNode->mChildren[0]->mTransformation[3][3]; - } - g_mWorld[3][0] -= g_pcAsset->pcScene->mRootNode->mChildren[0]->mTransformation[3][0]; - g_mWorld[3][1] -= g_pcAsset->pcScene->mRootNode->mChildren[0]->mTransformation[3][1]; - g_mWorld[3][2] -= g_pcAsset->pcScene->mRootNode->mChildren[0]->mTransformation[3][2]; - } - } -#endif + fScale,0.0f,0.0f,0.0f, + 0.0f,fScale,0.0f,0.0f, + 0.0f,0.0f,fScale,0.0f, + 0.0f,0.0f,0.0f,1.0f); return 1; - } +} //------------------------------------------------------------------------------- +// Generate a vertex buffer which holds the normals of the asset as +// a list of unconnected lines +// pcMesh Input mesh +// pcSource Source mesh from ASSIMP //------------------------------------------------------------------------------- int GenerateNormalsAsLineList(AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSource) - { +{ + ai_assert(NULL != pcMesh); + ai_assert(NULL != pcSource); + if (!pcSource->mNormals)return 0; // create vertex buffer @@ -387,17 +382,17 @@ int GenerateNormalsAsLineList(AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSo D3DUSAGE_WRITEONLY, AssetHelper::LineVertex::GetFVF(), D3DPOOL_DEFAULT, &pcMesh->piVBNormals,NULL))) - { - MessageBox(g_hDlg,"Failed to create vertex buffer for the normal list", - "ASSIMP Viewer Utility",MB_OK); + { + CLogDisplay::Instance().AddEntry("Failed to create vertex buffer for the normal list", + D3DCOLOR_ARGB(0xFF,0xFF,0,0)); return 2; - } + } - // now fill the vertex buffer + // now fill the vertex buffer with data AssetHelper::LineVertex* pbData2; pcMesh->piVBNormals->Lock(0,0,(void**)&pbData2,0); for (unsigned int x = 0; x < pcSource->mNumVertices;++x) - { + { pbData2->vPosition = pcSource->mVertices[x]; ++pbData2; @@ -405,358 +400,70 @@ int GenerateNormalsAsLineList(AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSo aiVector3D vNormal = pcSource->mNormals[x]; vNormal.Normalize(); + // scalo with the inverse of the world scaling to make sure + // the normals have equal length in each case + // TODO: Check whether this works in every case, I don't think so vNormal.x /= g_mWorld.a1*4; vNormal.y /= g_mWorld.b2*4; vNormal.z /= g_mWorld.c3*4; pbData2->vPosition = pcSource->mVertices[x] + vNormal; - + ++pbData2; - } + } pcMesh->piVBNormals->Unlock(); return 1; - } - - -//------------------------------------------------------------------------------- -// Fill the UI combobox with a list of all supported animations -// -// The animations are added in order -//------------------------------------------------------------------------------- -int FillAnimList(void) -{ - // clear the combo box - SendDlgItemMessage(g_hDlg,IDC_COMBO1,CB_RESETCONTENT,0,0); - - 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; -} - - -//------------------------------------------------------------------------------- -// Add a node to the display list -// Recusrivly add all subnodes -// iNode - Index of the node image in the tree view's image lust -// 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 iNode, - unsigned int iIndex, - unsigned int iDepth, - const aiNode* pcNode, - HTREEITEM hRoot) -{ - ai_assert(NULL != pcNode); - - char chTemp[512]; - - if(0 == pcNode->mName.length) - { - if (iNode >= 100) - { - iNode += iDepth * 1000; - } - else if (iNode >= 10) - { - iNode += iDepth * 100; - } - else iNode += iDepth * 10; - sprintf(chTemp,"Node %i",iNode); - } - 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; - tvi.iImage = iNode; - tvi.iSelectedImage = iNode; - tvi.lParam = (LPARAM)0; - - 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(iNode,i,iDepth,pcNode->mChildren[i],hTexture); - } - return 1; -} - - -//------------------------------------------------------------------------------- -// Add a texture to the display list -// pcMat - material containing the texture -// hTexture - Handle to the material tree item -// iTexture - Index of the texture image in the image list of the tree view -// 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, - const aiMaterial* pcMat, - unsigned int iTexture = 0, - unsigned int iUVIndex = 0, - const float fBlendFactor = 0.0f, - aiTextureOp eTextureOp = aiTextureOp_Multiply) -{ - char chTemp[512]; - const char* sz = strrchr(szPath->data,'\\'); - if (!sz)sz = strrchr(szPath->data,'/'); - if (!sz)sz = szPath->data; - - const char* szType; - switch (iType) - { - case AI_TEXTYPE_DIFFUSE: - szType = "Diffuse";break; - case AI_TEXTYPE_SPECULAR: - szType = "Specular";break; - case AI_TEXTYPE_AMBIENT: - szType = "Ambient";break; - case AI_TEXTYPE_EMISSIVE: - szType = "Emissive";break; - case AI_TEXTYPE_HEIGHT: - szType = "HeightMap";break; - case AI_TEXTYPE_NORMALS: - szType = "NormalMap";break; - case AI_TEXTYPE_SHININESS: - szType = "Shininess";break; - }; - 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; - tvi.iImage = iTexture; - tvi.iSelectedImage = iTexture; - tvi.lParam = (LPARAM)0; - - 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); - return 1; -} - - -//------------------------------------------------------------------------------- -// Add a material and all sub textures to the display mode list -// pcMat - material to be added -// hRoot - Handle to the root of the tree view -// iFX - Index of the material image in the image list of the tree view -// iTexture - Index of the texture image in the image list of the tree view -// iIndex - Material index -//------------------------------------------------------------------------------- -int AddMaterialToDisplayList(HTREEITEM hRoot, const aiMaterial* pcMat, - unsigned int iFX, unsigned int iTexture, unsigned int iIndex) -{ - // 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_STATE; - tvi.iImage = iFX; - tvi.iSelectedImage = iFX; - tvi.lParam = (LPARAM)0; - 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 - unsigned int iUV; - float fBlend; - aiTextureOp eOp; - aiString szPath; - for (unsigned int i = 0; i < 7;++i) - { - unsigned int iNum = 0; - while (true) - { - if (AI_SUCCESS != aiGetMaterialTexture(pcMat,iNum,i, - &szPath,&iUV,&fBlend,&eOp)) - { - break; - } - AddTextureToDisplayList(i,iNum,&szPath,hTexture, - pcMat,iTexture,iUV,fBlend,eOp); - ++iNum; - } - } - return 1; } //------------------------------------------------------------------------------- -// Fill the UI combobox with a list of all supported view modi -// -// The display modes are added in order +// Create the native D3D representation of the asset: vertex buffers, +// index buffers, materials ... //------------------------------------------------------------------------------- -int FillDisplayList(void) +int CreateAssetData() { - // Initialize the tree view window. - - // First, create the image list we will need. -#define NUM_BITMAPS 4 - HIMAGELIST hIml = ImageList_Create( 16,16,ILC_COLOR24, NUM_BITMAPS, 0 ); - - - // Load the bitmaps and add them to the image lists. - HBITMAP hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BFX)); - int iFX = ImageList_Add(hIml, hBmp, NULL); - DeleteObject(hBmp); - - hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BNODE)); - int iNode = ImageList_Add(hIml, hBmp, NULL); - DeleteObject(hBmp); - - hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BTX)); - int iTexture = ImageList_Add(hIml, hBmp, NULL); - DeleteObject(hBmp); - - hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BROOT)); - int iRoot = ImageList_Add(hIml, hBmp, NULL); - DeleteObject(hBmp); - - // Associate the image list with the tree. - TreeView_SetImageList(GetDlgItem(g_hDlg,IDC_TREE1), hIml, TVSIL_NORMAL); - - // 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 = iRoot; - tvi.iSelectedImage = iRoot; - tvi.lParam = (LPARAM)0; - - sNew.itemex = tvi; - sNew.hInsertAfter = TVI_ROOT; - sNew.hParent = 0; - - HTREEITEM hRoot = (HTREEITEM)SendMessage(GetDlgItem(g_hDlg,IDC_TREE1), - TVM_INSERTITEM, - 0, - (LPARAM)(LPTVINSERTSTRUCT)&sNew); - - - // add each loaded material - for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMaterials;++i) - { - AddMaterialToDisplayList(hRoot,g_pcAsset->pcScene->mMaterials[i], - iFX,iTexture,i); - } - - // now add all loaded nodes recursively - AddNodeToDisplayList(iNode,0,0,g_pcAsset->pcScene->mRootNode,hRoot); - return 1; -} - -//------------------------------------------------------------------------------- -//------------------------------------------------------------------------------- -int CreateAssetData(void) - { if (!g_pcAsset)return 0; - g_iShaderCount = 0; + // reset all subsystems + CMaterialManager::Instance().Reset(); + CMeshRenderer::Instance().Reset(); + CDisplay::Instance().Reset(); for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) + { + // create the material for the mesh + if (!g_pcAsset->apcMeshes[i]->piEffect) { + CMaterialManager::Instance().CreateMaterial( + g_pcAsset->apcMeshes[i],g_pcAsset->pcScene->mMeshes[i]); + } + // create vertex buffer if(FAILED( g_piDevice->CreateVertexBuffer(sizeof(AssetHelper::Vertex) * g_pcAsset->pcScene->mMeshes[i]->mNumVertices, D3DUSAGE_WRITEONLY, AssetHelper::Vertex::GetFVF(), D3DPOOL_DEFAULT, &g_pcAsset->apcMeshes[i]->piVB,NULL))) - { + { MessageBox(g_hDlg,"Failed to create vertex buffer", "ASSIMP Viewer Utility",MB_OK); return 2; } + DWORD dwUsage = 0; + if (g_pcAsset->apcMeshes[i]->piOpacityTexture || 1.0f != g_pcAsset->apcMeshes[i]->fOpacity) + dwUsage |= D3DUSAGE_DYNAMIC; + // check whether we can use 16 bit indices if (g_pcAsset->pcScene->mMeshes[i]->mNumFaces * 3 >= 65536) { // create 32 bit index buffer if(FAILED( g_piDevice->CreateIndexBuffer( 4 * g_pcAsset->pcScene->mMeshes[i]->mNumFaces * 3, - D3DUSAGE_WRITEONLY, + D3DUSAGE_WRITEONLY | dwUsage, D3DFMT_INDEX32, - D3DPOOL_DEFAULT, &g_pcAsset->apcMeshes[i]->piIB,NULL))) + D3DPOOL_DEFAULT, + &g_pcAsset->apcMeshes[i]->piIB, + NULL))) { MessageBox(g_hDlg,"Failed to create 32 Bit index buffer", "ASSIMP Viewer Utility",MB_OK); @@ -779,9 +486,11 @@ int CreateAssetData(void) // create 16 bit index buffer if(FAILED( g_piDevice->CreateIndexBuffer( 2 * g_pcAsset->pcScene->mMeshes[i]->mNumFaces * 3, - D3DUSAGE_WRITEONLY, + D3DUSAGE_WRITEONLY | dwUsage, D3DFMT_INDEX16, - D3DPOOL_DEFAULT, &g_pcAsset->apcMeshes[i]->piIB,NULL))) + D3DPOOL_DEFAULT, + &g_pcAsset->apcMeshes[i]->piIB, + NULL))) { MessageBox(g_hDlg,"Failed to create 16 Bit index buffer", "ASSIMP Viewer Utility",MB_OK); @@ -805,7 +514,7 @@ int CreateAssetData(void) AssetHelper::Vertex* pbData2; g_pcAsset->apcMeshes[i]->piVB->Lock(0,0,(void**)&pbData2,0); for (unsigned int x = 0; x < g_pcAsset->pcScene->mMeshes[i]->mNumVertices;++x) - { + { pbData2->vPosition = g_pcAsset->pcScene->mMeshes[i]->mVertices[x]; if (NULL == g_pcAsset->pcScene->mMeshes[i]->mNormals) @@ -813,210 +522,235 @@ int CreateAssetData(void) else pbData2->vNormal = g_pcAsset->pcScene->mMeshes[i]->mNormals[x]; if (NULL == g_pcAsset->pcScene->mMeshes[i]->mTangents) - { + { pbData2->vTangent = aiVector3D(0.0f,0.0f,0.0f); pbData2->vBitangent = aiVector3D(0.0f,0.0f,0.0f); - } + } else - { + { pbData2->vTangent = g_pcAsset->pcScene->mMeshes[i]->mTangents[x]; pbData2->vBitangent = g_pcAsset->pcScene->mMeshes[i]->mBitangents[x]; - } + } if (g_pcAsset->pcScene->mMeshes[i]->HasVertexColors( 0)) - { + { pbData2->dColorDiffuse = D3DCOLOR_ARGB( - ((unsigned char)std::max( std::min( g_pcAsset->pcScene-> - mMeshes[i]->mColors[0][x].a * 255.0f, 255.0f),0.0f)), - ((unsigned char)std::max( std::min( g_pcAsset->pcScene-> - mMeshes[i]->mColors[0][x].r * 255.0f, 255.0f),0.0f)), - ((unsigned char)std::max( std::min( g_pcAsset->pcScene-> - mMeshes[i]->mColors[0][x].g * 255.0f, 255.0f),0.0f)), - ((unsigned char)std::max( std::min( g_pcAsset->pcScene-> - mMeshes[i]->mColors[0][x].b * 255.0f, 255.0f),0.0f))); - } + ((unsigned char)std::max( std::min( g_pcAsset->pcScene->mMeshes[i]->mColors[0][x].a * 255.0f, 255.0f),0.0f)), + ((unsigned char)std::max( std::min( g_pcAsset->pcScene->mMeshes[i]->mColors[0][x].r * 255.0f, 255.0f),0.0f)), + ((unsigned char)std::max( std::min( g_pcAsset->pcScene->mMeshes[i]->mColors[0][x].g * 255.0f, 255.0f),0.0f)), + ((unsigned char)std::max( std::min( g_pcAsset->pcScene->mMeshes[i]->mColors[0][x].b * 255.0f, 255.0f),0.0f))); + } else pbData2->dColorDiffuse = D3DCOLOR_ARGB(0xFF,0,0,0); // ignore a third texture coordinate component if (g_pcAsset->pcScene->mMeshes[i]->HasTextureCoords( 0)) - { + { pbData2->vTextureUV = aiVector2D( g_pcAsset->pcScene->mMeshes[i]->mTextureCoords[0][x].x, g_pcAsset->pcScene->mMeshes[i]->mTextureCoords[0][x].y); - } + } else pbData2->vTextureUV = aiVector2D(0.0f,0.0f); ++pbData2; - } + } g_pcAsset->apcMeshes[i]->piVB->Unlock(); // now generate the second vertex buffer, holding all normals - GenerateNormalsAsLineList(g_pcAsset->apcMeshes[i],g_pcAsset->pcScene->mMeshes[i]); - - // create the material for the mesh - CreateMaterial(g_pcAsset->apcMeshes[i],g_pcAsset->pcScene->mMeshes[i]); + if (!g_pcAsset->apcMeshes[i]->piVBNormals) + { + GenerateNormalsAsLineList(g_pcAsset->apcMeshes[i],g_pcAsset->pcScene->mMeshes[i]); } - CLogDisplay::Instance().AddEntry("[OK] The asset has been loaded successfully"); - - - // now get the number of unique shaders generated for the asset - // (even if the environment changes this number won't change) - char szTemp[32]; - sprintf(szTemp,"%i", g_iShaderCount); - SetDlgItemText(g_hDlg,IDC_ESHADER,szTemp); - - FillDisplayList(); - return FillAnimList(); } + return 1; +} //------------------------------------------------------------------------------- +// Delete all effects, textures, vertex buffers ... associated with +// an asset //------------------------------------------------------------------------------- -int DeleteAssetData(void) - { +int DeleteAssetData(bool bNoMaterials) +{ if (!g_pcAsset)return 0; // TODO: Move this to a proper destructor for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) - { + { if(g_pcAsset->apcMeshes[i]->piVB) - { + { g_pcAsset->apcMeshes[i]->piVB->Release(); g_pcAsset->apcMeshes[i]->piVB = NULL; - } + } if(g_pcAsset->apcMeshes[i]->piVBNormals) - { + { g_pcAsset->apcMeshes[i]->piVBNormals->Release(); g_pcAsset->apcMeshes[i]->piVBNormals = NULL; - } + } if(g_pcAsset->apcMeshes[i]->piIB) - { + { g_pcAsset->apcMeshes[i]->piIB->Release(); g_pcAsset->apcMeshes[i]->piIB = NULL; - } - if(g_pcAsset->apcMeshes[i]->piEffect) + } + + //// delete storage eventually allocated to hold a copy + //// of the original vertex normals + //if (AssetHelper::ORIGINAL != g_pcAsset->iNormalSet) + //{ + // delete[] g_pcAsset->apcMeshes[i]->pvOriginalNormals; + //} + + if (!bNoMaterials) + { + if(g_pcAsset->apcMeshes[i]->piEffect) { - g_pcAsset->apcMeshes[i]->piEffect->Release(); - g_pcAsset->apcMeshes[i]->piEffect = NULL; + g_pcAsset->apcMeshes[i]->piEffect->Release(); + g_pcAsset->apcMeshes[i]->piEffect = NULL; } - if(g_pcAsset->apcMeshes[i]->piDiffuseTexture) + if(g_pcAsset->apcMeshes[i]->piDiffuseTexture) { - g_pcAsset->apcMeshes[i]->piDiffuseTexture->Release(); - g_pcAsset->apcMeshes[i]->piDiffuseTexture = NULL; + g_pcAsset->apcMeshes[i]->piDiffuseTexture->Release(); + g_pcAsset->apcMeshes[i]->piDiffuseTexture = NULL; } - if(g_pcAsset->apcMeshes[i]->piNormalTexture) + if(g_pcAsset->apcMeshes[i]->piNormalTexture) { - g_pcAsset->apcMeshes[i]->piNormalTexture->Release(); - g_pcAsset->apcMeshes[i]->piNormalTexture = NULL; + g_pcAsset->apcMeshes[i]->piNormalTexture->Release(); + g_pcAsset->apcMeshes[i]->piNormalTexture = NULL; } - if(g_pcAsset->apcMeshes[i]->piSpecularTexture) + if(g_pcAsset->apcMeshes[i]->piSpecularTexture) { - g_pcAsset->apcMeshes[i]->piSpecularTexture->Release(); - g_pcAsset->apcMeshes[i]->piSpecularTexture = NULL; + g_pcAsset->apcMeshes[i]->piSpecularTexture->Release(); + g_pcAsset->apcMeshes[i]->piSpecularTexture = NULL; } - if(g_pcAsset->apcMeshes[i]->piAmbientTexture) + if(g_pcAsset->apcMeshes[i]->piAmbientTexture) { - g_pcAsset->apcMeshes[i]->piAmbientTexture->Release(); - g_pcAsset->apcMeshes[i]->piAmbientTexture = NULL; + g_pcAsset->apcMeshes[i]->piAmbientTexture->Release(); + g_pcAsset->apcMeshes[i]->piAmbientTexture = NULL; } - if(g_pcAsset->apcMeshes[i]->piEmissiveTexture) + if(g_pcAsset->apcMeshes[i]->piEmissiveTexture) { - g_pcAsset->apcMeshes[i]->piEmissiveTexture->Release(); - g_pcAsset->apcMeshes[i]->piEmissiveTexture = NULL; + g_pcAsset->apcMeshes[i]->piEmissiveTexture->Release(); + g_pcAsset->apcMeshes[i]->piEmissiveTexture = NULL; + } + if(g_pcAsset->apcMeshes[i]->piShininessTexture) + { + g_pcAsset->apcMeshes[i]->piShininessTexture->Release(); + g_pcAsset->apcMeshes[i]->piShininessTexture = NULL; } } - return 1; } + return 1; +} //------------------------------------------------------------------------------- +// Switch beetween zoom/rotate view and the standatd FPS view +// g_bFPSView specifies the view mode to setup //------------------------------------------------------------------------------- int SetupFPSView() - { +{ if (!g_bFPSView) - { + { g_sCamera.vPos = aiVector3D(0.0f,0.0f,g_fWheelPos); g_sCamera.vLookAt = aiVector3D(0.0f,0.0f,1.0f); g_sCamera.vUp = aiVector3D(0.0f,1.0f,0.0f); g_sCamera.vRight = aiVector3D(0.0f,1.0f,0.0f); - } + } else - { + { g_fWheelPos = g_sCamera.vPos.z; g_sCamera.vPos = aiVector3D(0.0f,0.0f,-10.0f); g_sCamera.vLookAt = aiVector3D(0.0f,0.0f,1.0f); g_sCamera.vUp = aiVector3D(0.0f,1.0f,0.0f); g_sCamera.vRight = aiVector3D(0.0f,1.0f,0.0f); - } - return 1; } + return 1; +} //------------------------------------------------------------------------------- +// Initialize the IDIrect3D interface +// Called by the WinMain //------------------------------------------------------------------------------- int InitD3D(void) - { +{ if (NULL == g_piD3D) - { + { g_piD3D = Direct3DCreate9(D3D_SDK_VERSION); if (NULL == g_piD3D)return 0; - } - return 1; } + return 1; +} //------------------------------------------------------------------------------- +// Release the IDirect3D interface. +// NOTE: Assumes that the device has already been deleted //------------------------------------------------------------------------------- int ShutdownD3D(void) - { +{ ShutdownDevice(); if (NULL != g_piD3D) - { + { g_piD3D->Release(); g_piD3D = NULL; - } - return 1; } + return 1; +} //------------------------------------------------------------------------------- +// Shutdown the D3D devie object and all resources associated with it +// NOTE: Assumes that the asset has already been deleted //------------------------------------------------------------------------------- int ShutdownDevice(void) - { - if (NULL != g_piDevice) - { - g_piDevice->Release(); - g_piDevice = NULL; - } - if (NULL != g_piDefaultEffect) - { - g_piDefaultEffect->Release(); - g_piDefaultEffect = NULL; - } - if (NULL != g_piNormalsEffect) - { - g_piNormalsEffect->Release(); - g_piNormalsEffect = NULL; - } - if (NULL != g_piPassThroughEffect) - { - g_piPassThroughEffect->Release(); - g_piPassThroughEffect = NULL; - } - if (NULL != g_pcTexture) - { - g_pcTexture->Release(); - g_pcTexture = NULL; - } - delete[] g_szImageMask; - g_szImageMask = NULL; +{ + // release other subsystems CBackgroundPainter::Instance().ReleaseNativeResource(); CLogDisplay::Instance().ReleaseNativeResource(); - return 1; + + // release global shaders that have been allocazed + if (NULL != g_piDefaultEffect) + { + g_piDefaultEffect->Release(); + g_piDefaultEffect = NULL; } + if (NULL != g_piNormalsEffect) + { + g_piNormalsEffect->Release(); + g_piNormalsEffect = NULL; + } + if (NULL != g_piPassThroughEffect) + { + g_piPassThroughEffect->Release(); + g_piPassThroughEffect = NULL; + } + if (NULL != g_piPatternEffect) + { + g_piPatternEffect->Release(); + g_piPatternEffect = NULL; + } + if (NULL != g_pcTexture) + { + g_pcTexture->Release(); + g_pcTexture = NULL; + } + + // delete the main D3D device object + if (NULL != g_piDevice) + { + g_piDevice->Release(); + g_piDevice = NULL; + } + + // deleted the one channel image allocated to hold the HUD mask + delete[] g_szImageMask; + g_szImageMask = NULL; + + return 1; +} //------------------------------------------------------------------------------- //------------------------------------------------------------------------------- int CreateHUDTexture() - { +{ // lock the memory resource ourselves HRSRC res = FindResource(NULL,MAKEINTRESOURCE(IDR_HUD),RT_RCDATA); HGLOBAL hg = LoadResource(NULL,res); @@ -1036,7 +770,7 @@ int CreateHUDTexture() NULL, NULL, &g_pcTexture))) - { + { CLogDisplay::Instance().AddEntry("[ERROR] Unable to load HUD texture", D3DCOLOR_ARGB(0xFF,0xFF,0,0)); @@ -1046,7 +780,7 @@ int CreateHUDTexture() UnlockResource(hg); FreeResource(hg); return 0; - } + } UnlockResource(hg); FreeResource(hg); @@ -1075,7 +809,7 @@ int CreateHUDTexture() NULL, NULL, &pcTex))) - { + { CLogDisplay::Instance().AddEntry("[ERROR] Unable to load HUD mask texture", D3DCOLOR_ARGB(0xFF,0xFF,0,0)); g_szImageMask = NULL; @@ -1083,7 +817,7 @@ int CreateHUDTexture() UnlockResource(hg); FreeResource(hg); return 0; - } + } UnlockResource(hg); FreeResource(hg); @@ -1097,23 +831,23 @@ int CreateHUDTexture() unsigned char* szCur = (unsigned char*) sRect.pBits; for (unsigned int y = 0; y < sDesc.Height;++y) - { + { memcpy(_szOut,szCur,sDesc.Width); - + szCur += sRect.Pitch; _szOut += sDesc.Width; - } + } pcTex->UnlockRect(0); pcTex->Release(); g_szImageMask = szOut; return 1; - } +} //------------------------------------------------------------------------------- //------------------------------------------------------------------------------- int CreateDevice (bool p_bMultiSample,bool p_bSuperSample,bool bHW /*= true*/) - { +{ D3DDEVTYPE eType = bHW ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF; // get the client rectangle of the window. @@ -1151,35 +885,35 @@ int CreateDevice (bool p_bMultiSample,bool p_bSuperSample,bool bHW /*= true*/) D3DMULTISAMPLE_TYPE sMSOut = D3DMULTISAMPLE_NONE; DWORD dwQuality = 0; if (p_bMultiSample) - { + { while ((D3DMULTISAMPLE_TYPE)(D3DMULTISAMPLE_16_SAMPLES + 1) != - (sMS = (D3DMULTISAMPLE_TYPE)(sMS + 1))) - { + (sMS = (D3DMULTISAMPLE_TYPE)(sMS + 1))) + { if(SUCCEEDED( g_piD3D->CheckDeviceMultiSampleType(0,eType, sMode.Format,TRUE,sMS,&dwQuality))) - { + { sMSOut = sMS; - } } + } if (0 != dwQuality)dwQuality -= 1; - + sParams.MultiSampleQuality = dwQuality; sParams.MultiSampleType = sMSOut; - } + } // create the D3D9 device object if(FAILED(g_piD3D->CreateDevice(0,eType, g_hDlg,D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED,&sParams,&g_piDevice))) - { + { if(FAILED(g_piD3D->CreateDevice(0,eType, g_hDlg,D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED,&sParams,&g_piDevice))) - { + { // if hardware fails use software rendering instead if (bHW)return CreateDevice(p_bMultiSample,p_bSuperSample,false); return 0; - } } + } g_piDevice->SetFVF(AssetHelper::Vertex::GetFVF()); // compile the default material shader (gray gouraud/phong) @@ -1192,64 +926,64 @@ int CreateDevice (bool p_bMultiSample,bool p_bSuperSample,bool bHW /*= true*/) D3DXSHADER_USE_LEGACY_D3DX9_31_DLL, NULL, &g_piDefaultEffect,&piBuffer))) - { + { if( piBuffer) - { + { MessageBox(g_hDlg,(LPCSTR)piBuffer->GetBufferPointer(),"HLSL",MB_OK); piBuffer->Release(); - } - return 0; } + return 0; + } if( piBuffer) - { + { piBuffer->Release(); piBuffer = NULL; - } + } // create the shader used to draw the HUD if(FAILED( D3DXCreateEffect(g_piDevice, g_szPassThroughShader.c_str(),(UINT)g_szPassThroughShader.length(), NULL,NULL,D3DXSHADER_USE_LEGACY_D3DX9_31_DLL,NULL,&g_piPassThroughEffect,&piBuffer))) - { + { if( piBuffer) - { + { MessageBox(g_hDlg,(LPCSTR )piBuffer->GetBufferPointer(),"HLSL",MB_OK); piBuffer->Release(); - } - return 0; } + return 0; + } if( piBuffer) - { + { piBuffer->Release(); piBuffer = NULL; - } + } // create the shader used to visualize normal vectors if(FAILED( D3DXCreateEffect(g_piDevice, g_szNormalsShader.c_str(),(UINT)g_szNormalsShader.length(), NULL,NULL,D3DXSHADER_USE_LEGACY_D3DX9_31_DLL,NULL,&g_piNormalsEffect, &piBuffer))) - { + { if( piBuffer) - { + { MessageBox(g_hDlg,(LPCSTR )piBuffer->GetBufferPointer(),"HLSL",MB_OK); piBuffer->Release(); - } - return 0; } + return 0; + } if( piBuffer) - { + { piBuffer->Release(); piBuffer = NULL; - } + } // get the capabilities of the device object g_piDevice->GetDeviceCaps(&g_sCaps); if(g_sCaps.PixelShaderVersion < D3DPS_VERSION(3,0)) - { + { EnableWindow(GetDlgItem(g_hDlg,IDC_LOWQUALITY),FALSE); - } + } // create the texture for the HUD CreateHUDTexture(); @@ -1258,48 +992,48 @@ int CreateDevice (bool p_bMultiSample,bool p_bSuperSample,bool bHW /*= true*/) g_piPassThroughEffect->SetTexture("TEXTURE_2D",g_pcTexture); return 1; - } +} //------------------------------------------------------------------------------- //------------------------------------------------------------------------------- int CreateDevice (void) - { +{ return CreateDevice(g_sOptions.bMultiSample, g_sOptions.bSuperSample); - } +} //------------------------------------------------------------------------------- //------------------------------------------------------------------------------- int GetProjectionMatrix (aiMatrix4x4& p_mOut) - { +{ const float fFarPlane = 100.0f; const float fNearPlane = 0.1f; const float fFOV = (float)(45.0 * 0.0174532925); const float s = 1.0f / tanf(fFOV * 0.5f); - const float Q = fFarPlane / (fFarPlane - fNearPlane); - + const float Q = fFarPlane / (fFarPlane - fNearPlane); + RECT sRect; GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect); sRect.right -= sRect.left; sRect.bottom -= sRect.top; const float fAspect = (float)sRect.right / (float)sRect.bottom; - p_mOut = aiMatrix4x4( + p_mOut = aiMatrix4x4( s / fAspect, 0.0f, 0.0f, 0.0f, - 0.0f, s, 0.0f, 0.0f, - 0.0f, 0.0f, Q, 1.0f, - 0.0f, 0.0f, -Q * fNearPlane, 0.0f); + 0.0f, s, 0.0f, 0.0f, + 0.0f, 0.0f, Q, 1.0f, + 0.0f, 0.0f, -Q * fNearPlane, 0.0f); return 1; - } +} //------------------------------------------------------------------------------- //------------------------------------------------------------------------------- aiVector3D GetCameraMatrix (aiMatrix4x4& p_mOut) - { +{ D3DXMATRIX view; D3DXMatrixIdentity( &view ); @@ -1332,525 +1066,8 @@ aiVector3D GetCameraMatrix (aiMatrix4x4& p_mOut) memcpy(&p_mOut,&view,sizeof(aiMatrix4x4)); return g_sCamera.vPos; - } +} -//------------------------------------------------------------------------------- -//------------------------------------------------------------------------------- -int SetupMaterial (AssetHelper::MeshHelper* pcMesh, - const aiMatrix4x4& pcProj, - const aiMatrix4x4& aiMe, - const aiMatrix4x4& pcCam, - const aiVector3D& vPos) - { - 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); - - if(g_sOptions.b3Lights) - { - apcVec[0].x = 1.0f; - apcVec[0].y = 1.0f; - apcVec[0].z = 1.0f; - apcVec[0].w = 1.0f; - - apcVec[1].x = 0.1f; - apcVec[1].y = 1.0f; - apcVec[1].z = 0.1f; - apcVec[1].w = 1.0f; - } - else - { - apcVec[0].x = 1.0f; - apcVec[0].y = 1.0f; - apcVec[0].z = 1.0f; - apcVec[0].w = 1.0f; - - apcVec[1].x = 0.0f; - apcVec[1].y = 0.0f; - apcVec[1].z = 0.0f; - apcVec[1].w = 0.0f; - } - apcVec[0] *= g_fLightIntensity; - apcVec[1] *= g_fLightIntensity; - piEnd->SetVectorArray("afLightColor",apcVec,5); - - if(g_sOptions.b3Lights) - { - apcVec[0].x = 0.05f; - apcVec[0].y = 0.05f; - apcVec[0].z = 0.05f; - apcVec[0].w = 1.0f; - - apcVec[1].x = 0.05f; - apcVec[1].y = 0.05f; - apcVec[1].z = 0.05f; - apcVec[1].w = 1.0f; - } - else - { - apcVec[0].x = 0.05f; - apcVec[0].y = 0.05f; - apcVec[0].z = 0.05f; - apcVec[0].w = 1.0f; - - apcVec[1].x = 0.0f; - apcVec[1].y = 0.0f; - apcVec[1].z = 0.0f; - apcVec[1].w = 0.0f; - } - 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 (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 (CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode()) - { - piEnd->SetTexture("lw_tex_envmap",CBackgroundPainter::Instance().GetTexture()); - } - } - - 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"); - } - - UINT dwPasses = 0; - piEnd->Begin(&dwPasses,0); - piEnd->BeginPass(0); - return 1; - } - - -//------------------------------------------------------------------------------- -//------------------------------------------------------------------------------- -int EndMaterial (AssetHelper::MeshHelper* pcMesh) - { - if (!pcMesh->piEffect)return 0; - - pcMesh->piEffect->EndPass(); - pcMesh->piEffect->End(); - - return 1; - } - -//------------------------------------------------------------------------------- -//------------------------------------------------------------------------------- -int RenderNode (aiNode* piNode,const aiMatrix4x4& piMatrix, bool bAlpha = false) - { - aiMatrix4x4 mTemp = piNode->mTransformation; - mTemp.Transpose(); - aiMatrix4x4 aiMe = mTemp * piMatrix; - - 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; - - 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); - } - - 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); - - if(g_sOptions.b3Lights) - { - apcVec[0].x = 0.6f; - apcVec[0].y = 0.6f; - apcVec[0].z = 0.6f; - apcVec[0].w = 1.0f; - - apcVec[1].x = 0.3f; - apcVec[1].y = 0.0f; - apcVec[1].z = 0.0f; - apcVec[1].w = 1.0f; - } - else - { - apcVec[0].x = 1.0f; - apcVec[0].y = 1.0f; - apcVec[0].z = 1.0f; - apcVec[0].w = 1.0f; - - apcVec[1].x = 0.0f; - apcVec[1].y = 0.0f; - apcVec[1].z = 0.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]); - - 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"); - } - - 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; - - // set vertex and index buffer and the material ... - g_piDevice->SetStreamSource(0, - g_pcAsset->apcMeshes[piNode->mMeshes[i]]->piVB,0, - sizeof(AssetHelper::Vertex)); - - // now setup the material - if (g_sOptions.bRenderMats) - SetupMaterial(g_pcAsset->apcMeshes[piNode->mMeshes[i]],pcProj,aiMe,pcCam,vPos); - - g_piDevice->SetIndices(g_pcAsset->apcMeshes[piNode->mMeshes[i]]->piIB); - g_piDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, - 0,0, - g_pcAsset->pcScene->mMeshes[piNode->mMeshes[i]]->mNumVertices,0, - g_pcAsset->pcScene->mMeshes[piNode->mMeshes[i]]->mNumFaces); - - // now end the material - if (g_sOptions.bRenderMats) - 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(); - } - } - if (!g_sOptions.bRenderMats) - { - g_piDefaultEffect->EndPass(); - g_piDefaultEffect->End(); - } - } - for (unsigned int i = 0; i < piNode->mNumChildren;++i) - { - RenderNode(piNode->mChildren[i],aiMe,bAlpha ); - } - return 1; - } - - -//------------------------------------------------------------------------------- -//------------------------------------------------------------------------------- -int Render (void) - { - g_iCurrentColor = 0; - - // 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); - - g_piDevice->BeginScene(); - - // draw the scene background (clear and texture 2d) - CBackgroundPainter::Instance().OnPreRender(); - - // draw all opaque objects in the scene - aiMatrix4x4 m; - if (NULL != g_pcAsset && NULL != g_pcAsset->pcScene->mRootNode) - { - 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 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(); - } - - 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 - else 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; - } - } - - // draw the scene background - CBackgroundPainter::Instance().OnPostRender(); - - // draw all non-opaque objects in the scene - if (NULL != g_pcAsset && NULL != g_pcAsset->pcScene->mRootNode) - { - RenderNode(g_pcAsset->pcScene->mRootNode,m,true); - } - - // draw the HUD texture on top of the rendered scene using - // pre-projected vertices - if (!g_bFPSView && g_pcAsset && g_pcTexture) - { - 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; - 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; - - DWORD dw2;g_piDevice->GetFVF(&dw2); - g_piDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1); - g_piDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2, - &as,sizeof(SVertex)); - - g_piPassThroughEffect->EndPass(); - g_piPassThroughEffect->End(); - - g_piDevice->SetFVF(dw2); - } - - // 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; - } }; diff --git a/tools/assimp_view/assimp_view.h b/tools/assimp_view/assimp_view.h index 72f7eecbf..3f9d1e2fc 100644 --- a/tools/assimp_view/assimp_view.h +++ b/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 \ No newline at end of file diff --git a/tools/assimp_view/assimp_view.rc b/tools/assimp_view/assimp_view.rc index dec9b4741..cacb93841 100644 --- a/tools/assimp_view/assimp_view.rc +++ b/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,11 +326,58 @@ 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 + ///////////////////////////////////////////////////////////////////////////// // diff --git a/tools/assimp_view/help.rtf b/tools/assimp_view/help.rtf index aae67e0d9..2eb49bd58 100644 --- a/tools/assimp_view/help.rtf +++ b/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}} \ No newline at end of file diff --git a/tools/assimp_view/resource.h b/tools/assimp_view/resource.h index 7de873532..b2bf9354f 100644 --- a/tools/assimp_view/resource.h +++ b/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 diff --git a/tools/assimp_view/text1.bin b/tools/assimp_view/text1.bin index 82d87095a..c606841b3 100644 --- a/tools/assimp_view/text1.bin +++ b/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}} \ No newline at end of file +0000000000000000000000000000000000000000000000000105000000000000}} \ No newline at end of file diff --git a/tools/assimp_view/txi.bmp b/tools/assimp_view/txi.bmp new file mode 100644 index 000000000..541243bb6 Binary files /dev/null and b/tools/assimp_view/txi.bmp differ diff --git a/workspaces/vc8/assimp.vcproj b/workspaces/vc8/assimp.vcproj index 000a09da4..6cb628a59 100644 --- a/workspaces/vc8/assimp.vcproj +++ b/workspaces/vc8/assimp.vcproj @@ -38,7 +38,7 @@ + + diff --git a/workspaces/vc8/assimp_view.vcproj b/workspaces/vc8/assimp_view.vcproj index 7d465339b..adf241a7c 100644 --- a/workspaces/vc8/assimp_view.vcproj +++ b/workspaces/vc8/assimp_view.vcproj @@ -40,7 +40,7 @@ + + @@ -226,6 +230,10 @@ RelativePath="..\..\tools\assimp_view\no_materials.fx" > + + @@ -284,6 +292,14 @@ RelativePath="..\..\tools\assimp_view\LogWindow.h" > + + + + @@ -370,6 +386,10 @@ RelativePath="..\..\tools\assimp_view\tx.bmp" > + +