From 5ae1c28881508152a092443c314dc7c8a5216bd7 Mon Sep 17 00:00:00 2001 From: Richard <legalize@xmission.com> Date: Mon, 29 Jun 2015 20:54:59 -0600 Subject: [PATCH] Refactor: Apply editor config rules to tools --- tools/assimp_cmd/CompareDump.cpp | 1854 +++++----- tools/assimp_view/AnimEvaluator.cpp | 338 +- tools/assimp_view/AnimEvaluator.h | 182 +- tools/assimp_view/AssetHelper.h | 492 +-- tools/assimp_view/Background.cpp | 938 ++--- tools/assimp_view/Background.h | 256 +- tools/assimp_view/Camera.h | 168 +- tools/assimp_view/Display.cpp | 4584 +++++++++++------------ tools/assimp_view/Display.h | 1082 +++--- tools/assimp_view/HelpDialog.cpp | 214 +- tools/assimp_view/Input.cpp | 742 ++-- tools/assimp_view/LogDisplay.cpp | 464 +-- tools/assimp_view/LogDisplay.h | 198 +- tools/assimp_view/LogWindow.cpp | 508 +-- tools/assimp_view/LogWindow.h | 264 +- tools/assimp_view/Material.cpp | 2988 +++++++-------- tools/assimp_view/MaterialManager.h | 416 +-- tools/assimp_view/MeshRenderer.cpp | 330 +- tools/assimp_view/MeshRenderer.h | 196 +- tools/assimp_view/MessageProc.cpp | 5288 +++++++++++++-------------- tools/assimp_view/NOTE@help.rtf.txt | 2 +- tools/assimp_view/Normals.cpp | 348 +- tools/assimp_view/RenderOptions.h | 224 +- tools/assimp_view/SceneAnimator.cpp | 490 +-- tools/assimp_view/SceneAnimator.h | 484 +-- tools/assimp_view/Shaders.h | 126 +- tools/assimp_view/assimp_view.h | 570 +-- tools/assimp_view/stdafx.h | 148 +- 28 files changed, 11947 insertions(+), 11947 deletions(-) diff --git a/tools/assimp_cmd/CompareDump.cpp b/tools/assimp_cmd/CompareDump.cpp index 762a58358..26f2cd3ce 100644 --- a/tools/assimp_cmd/CompareDump.cpp +++ b/tools/assimp_cmd/CompareDump.cpp @@ -1,927 +1,927 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2015, assimp 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 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 CompareDump.cpp - * @brief Implementation of the 'assimp cmpdmp', which compares - * two model dumps for equality. It plays an important role - * in the regression test suite. - */ - -#include "Main.h" -const char* AICMD_MSG_CMPDUMP_HELP = -"assimp cmpdump <actual> <expected>\n" -"\tCompare two short dumps produced with \'assimp dump <..> -s\' for equality.\n" -; - -#include "../../code/assbin_chunks.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// -#include "generic_inserter.hpp" -#include <map> -#include <deque> -#include <stack> -#include <sstream> -#include <iostream> -#include "../../include/assimp/ai_assert.h" - -// get << for aiString -template <typename char_t, typename traits_t> -void mysprint(std::basic_ostream<char_t, traits_t>& os, const aiString& vec) { - os << "[length: \'" << std::dec << vec.length << "\' content: \'" << vec.data << "\']"; -} - -template <typename char_t, typename traits_t> -std::basic_ostream<char_t, traits_t>& operator<< (std::basic_ostream<char_t, traits_t>& os, const aiString& vec) { - return generic_inserter(mysprint<char_t,traits_t>, os, vec); -} - -class sliced_chunk_iterator; -//////////////////////////////////////////////////////////////////////////////////////////////////// -/// @class compare_fails_exception -/// -/// @brief Sentinel exception to return quickly from deeply nested control paths -//////////////////////////////////////////////////////////////////////////////////////////////////// -class compare_fails_exception : public virtual std::exception { -public: - - enum {MAX_ERR_LEN = 4096}; - - /* public c'tors */ - compare_fails_exception(const char* msg) { - strncpy(mywhat,msg,MAX_ERR_LEN-1); - strcat(mywhat,"\n"); - } - - /* public member functions */ - const char* what() const throw() { - return mywhat; - } - -private: - - char mywhat[MAX_ERR_LEN+1]; -}; - - -#define MY_FLT_EPSILON 1e-1f -#define MY_DBL_EPSILON 1e-1 -//////////////////////////////////////////////////////////////////////////////////////////////////// -/// @class comparer_context -/// -/// @brief Record our way through the files to be compared and dump useful information if we fail. -//////////////////////////////////////////////////////////////////////////////////////////////////// -class comparer_context { - friend class sliced_chunk_iterator; - -public: - - /* construct given two file handles to compare */ - comparer_context(FILE* actual,FILE* expect) - : actual(actual) - , expect(expect) - , cnt_chunks(0) - { - ai_assert(actual); - ai_assert(expect); - - fseek(actual,0,SEEK_END); - lengths.push(std::make_pair(static_cast<uint32_t>(ftell(actual)),0)); - fseek(actual,0,SEEK_SET); - - history.push_back(HistoryEntry("---",PerChunkCounter())); - } - -public: - - - /* set new scope */ - void push_elem(const char* msg) { - const std::string s = msg; - - PerChunkCounter::const_iterator it = history.back().second.find(s); - if(it != history.back().second.end()) { - ++history.back().second[s]; - } - else history.back().second[s] = 0; - - history.push_back(HistoryEntry(s,PerChunkCounter())); - debug_trace.push_back("PUSH " + s); - } - - /* leave current scope */ - void pop_elem() { - ai_assert(history.size()); - debug_trace.push_back("POP "+ history.back().first); - history.pop_back(); - } - - - /* push current chunk length and start offset on top of stack */ - void push_length(uint32_t nl, uint32_t start) { - lengths.push(std::make_pair(nl,start)); - ++cnt_chunks; - } - - /* pop the chunk length stack */ - void pop_length() { - ai_assert(lengths.size()); - lengths.pop(); - } - - /* access the current chunk length */ - uint32_t get_latest_chunk_length() { - ai_assert(lengths.size()); - return lengths.top().first; - } - - /* access the current chunk start offset */ - uint32_t get_latest_chunk_start() { - ai_assert(lengths.size()); - return lengths.top().second; - } - - /* total number of chunk headers passed so far*/ - uint32_t get_num_chunks() { - return cnt_chunks; - } - - - /* get ACTUAL file desc. != NULL */ - FILE* get_actual() const { - return actual; - } - - /* get EXPECT file desc. != NULL */ - FILE* get_expect() const { - return expect; - } - - - /* compare next T from both streams, name occurs in error messages */ - template<typename T> T cmp(const std::string& name) { - T a,e; - read(a,e); - - if(a != e) { - std::stringstream ss; - failure((ss<< "Expected " << e << ", but actual is " << a, - ss.str()),name); - } - // std::cout << name << " " << std::hex << a << std::endl; - return a; - } - - /* compare next num T's from both streams, name occurs in error messages */ - template<typename T> void cmp(size_t num,const std::string& name) { - for(size_t n = 0; n < num; ++n) { - std::stringstream ss; - cmp<T>((ss<<name<<"["<<n<<"]",ss.str())); - // std::cout << name << " " << std::hex << a << std::endl; - } - } - - /* Bounds of an aiVector3D array (separate function - * because partial specializations of member functions are illegal--)*/ - template<typename T> void cmp_bounds(const std::string& name) { - cmp<T> (name+".<minimum-value>"); - cmp<T> (name+".<maximum-value>"); - } - -private: - - /* Report failure */ - AI_WONT_RETURN void failure(const std::string& err, const std::string& name) AI_WONT_RETURN_SUFFIX { - std::stringstream ss; - throw compare_fails_exception((ss - << "Files are different at " - << history.back().first - << "." - << name - << ".\nError is: " - << err - << ".\nCurrent position in scene hierarchy is " - << print_hierarchy(),ss.str().c_str() - )); - } - - /** print our 'stack' */ - std::string print_hierarchy() { - std::stringstream ss; - ss << std::endl; - - const char* last = history.back().first.c_str(); - std::string pad; - - for(ChunkHistory::reverse_iterator rev = history.rbegin(), - end = history.rend(); rev != end; ++rev, pad += " ") - { - ss << pad << (*rev).first << "(Index: " << (*rev).second[last] << ")" << std::endl; - last = (*rev).first.c_str(); - } - - ss << std::endl << "Debug trace: "<< std::endl; - for (std::vector<std::string>::const_iterator it = debug_trace.begin(); it != debug_trace.end(); ++it) { - ss << *it << std::endl; - } - return ss.str(); - } - - - /* read from both streams at the same time */ - template <typename T> void read(T& filla,T& fille) { - if(1 != fread(&filla,sizeof(T),1,actual)) { - EOFActual(); - } - if(1 != fread(&fille,sizeof(T),1,expect)) { - EOFExpect(); - } - } - -private: - - void EOFActual() { - std::stringstream ss; - throw compare_fails_exception((ss - << "Unexpected EOF reading ACTUAL.\nCurrent position in scene hierarchy is " - << print_hierarchy(),ss.str().c_str() - )); - } - - void EOFExpect() { - std::stringstream ss; - throw compare_fails_exception((ss - << "Unexpected EOF reading EXPECT.\nCurrent position in scene hierarchy is " - << print_hierarchy(),ss.str().c_str() - )); - } - - - FILE *const actual, *const expect; - - typedef std::map<std::string,unsigned int> PerChunkCounter; - typedef std::pair<std::string,PerChunkCounter> HistoryEntry; - - typedef std::deque<HistoryEntry> ChunkHistory; - ChunkHistory history; - - std::vector<std::string> debug_trace; - - typedef std::stack<std::pair<uint32_t,uint32_t> > LengthStack; - LengthStack lengths; - - uint32_t cnt_chunks; -}; - - -//////////////////////////////////////////////////////////////////////////////////////////////////// -/* specialization for aiString (it needs separate handling because its on-disk representation - * differs from its binary representation in memory and can't be treated as an array of n T's.*/ -template <> void comparer_context :: read<aiString>(aiString& filla,aiString& fille) { - uint32_t lena,lene; - read(lena,lene); - - if(lena && 1 != fread(&filla.data,lena,1,actual)) { - EOFActual(); - } - if(lene && 1 != fread(&fille.data,lene,1,expect)) { - EOFExpect(); - } - - fille.data[fille.length=static_cast<unsigned int>(lene)] = '\0'; - filla.data[filla.length=static_cast<unsigned int>(lena)] = '\0'; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -/* Specialization for float, uses epsilon for comparisons*/ -template<> float comparer_context :: cmp<float>(const std::string& name) -{ - float a,e,t; - read(a,e); - - if((t=fabs(a-e)) > MY_FLT_EPSILON) { - std::stringstream ss; - failure((ss<< "Expected " << e << ", but actual is " - << a << " (delta is " << t << ")", ss.str()),name); - } - return a; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -/* Specialization for double, uses epsilon for comparisons*/ -template<> double comparer_context :: cmp<double>(const std::string& name) -{ - double a,e,t; - read(a,e); - - if((t=fabs(a-e)) > MY_DBL_EPSILON) { - std::stringstream ss; - failure((ss<< "Expected " << e << ", but actual is " - << a << " (delta is " << t << ")", ss.str()),name); - } - return a; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -/* Specialization for aiVector3D */ -template<> aiVector3D comparer_context :: cmp<aiVector3D >(const std::string& name) -{ - const float x = cmp<float>(name+".x"); - const float y = cmp<float>(name+".y"); - const float z = cmp<float>(name+".z"); - - return aiVector3D(x,y,z); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -/* Specialization for aiColor4D */ -template<> aiColor4D comparer_context :: cmp<aiColor4D >(const std::string& name) -{ - const float r = cmp<float>(name+".r"); - const float g = cmp<float>(name+".g"); - const float b = cmp<float>(name+".b"); - const float a = cmp<float>(name+".a"); - - return aiColor4D(r,g,b,a); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -/* Specialization for aiQuaternion */ -template<> aiQuaternion comparer_context :: cmp<aiQuaternion >(const std::string& name) -{ - const float w = cmp<float>(name+".w"); - const float x = cmp<float>(name+".x"); - const float y = cmp<float>(name+".y"); - const float z = cmp<float>(name+".z"); - - return aiQuaternion(w,x,y,z); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -/* Specialization for aiQuatKey */ -template<> aiQuatKey comparer_context :: cmp<aiQuatKey >(const std::string& name) -{ - const double mTime = cmp<double>(name+".mTime"); - const aiQuaternion mValue = cmp<aiQuaternion>(name+".mValue"); - - return aiQuatKey(mTime,mValue); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -/* Specialization for aiVectorKey */ -template<> aiVectorKey comparer_context :: cmp<aiVectorKey >(const std::string& name) -{ - const double mTime = cmp<double>(name+".mTime"); - const aiVector3D mValue = cmp<aiVector3D>(name+".mValue"); - - return aiVectorKey(mTime,mValue); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -/* Specialization for aiMatrix4x4 */ -template<> aiMatrix4x4 comparer_context :: cmp<aiMatrix4x4 >(const std::string& name) -{ - aiMatrix4x4 res; - for(unsigned int i = 0; i < 4; ++i) { - for(unsigned int j = 0; j < 4; ++j) { - std::stringstream ss; - res[i][j] = cmp<float>(name+(ss<<".m"<<i<<j,ss.str())); - } - } - - return res; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -/* Specialization for aiVertexWeight */ -template<> aiVertexWeight comparer_context :: cmp<aiVertexWeight >(const std::string& name) -{ - const unsigned int mVertexId = cmp<unsigned int>(name+".mVertexId"); - const float mWeight = cmp<float>(name+".mWeight"); - - return aiVertexWeight(mVertexId,mWeight); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -/// @class sliced_chunk_iterator -/// -/// @brief Helper to iterate easily through corresponding chunks of two dumps simultaneously. -/// -/// Not a *real* iterator, doesn't fully conform to the isocpp iterator spec -//////////////////////////////////////////////////////////////////////////////////////////////////// -class sliced_chunk_iterator { - - friend class sliced_chunk_reader; - sliced_chunk_iterator(comparer_context& ctx, long end) - : ctx(ctx) - , endit(false) - , next(std::numeric_limits<long>::max()) - , end(end) - { - load_next(); - } - -public: - - ~sliced_chunk_iterator() { - fseek(ctx.get_actual(),end,SEEK_SET); - fseek(ctx.get_expect(),end,SEEK_SET); - } - -public: - - /* get current chunk head */ - typedef std::pair<uint32_t,uint32_t> Chunk; - const Chunk& operator*() { - return current; - } - - /* get to next chunk head */ - const sliced_chunk_iterator& operator++() { - cleanup(); - load_next(); - return *this; - } - - /* */ - bool is_end() const { - return endit; - } - -private: - - /* get to the end of *this* chunk */ - void cleanup() { - if(next != std::numeric_limits<long>::max()) { - fseek(ctx.get_actual(),next,SEEK_SET); - fseek(ctx.get_expect(),next,SEEK_SET); - - ctx.pop_length(); - } - } - - /* advance to the next chunk */ - void load_next() { - - Chunk actual; - size_t res=0; - - const long cur = ftell(ctx.get_expect()); - if(end-cur<8) { - current = std::make_pair(0u,0u); - endit = true; - return; - } - - res|=fread(¤t.first,4,1,ctx.get_expect()); - res|=fread(¤t.second,4,1,ctx.get_expect()) <<1u; - res|=fread(&actual.first,4,1,ctx.get_actual()) <<2u; - res|=fread(&actual.second,4,1,ctx.get_actual()) <<3u; - - if(res!=0xf) { - ctx.failure("IO Error reading chunk head, dumps are malformed","<ChunkHead>"); - } - - if (current.first != actual.first) { - std::stringstream ss; - ctx.failure((ss - <<"Chunk headers do not match. EXPECT: " - << std::hex << current.first - <<" ACTUAL: " - << /*std::hex */actual.first, - ss.str()), - "<ChunkHead>"); - } - - if (current.first != actual.first) { - std::stringstream ss; - ctx.failure((ss - <<"Chunk lengths do not match. EXPECT: " - <<current.second - <<" ACTUAL: " - << actual.second, - ss.str()), - "<ChunkHead>"); - } - - next = cur+current.second+8; - ctx.push_length(current.second,cur+8); - } - - comparer_context& ctx; - Chunk current; - bool endit; - long next,end; -}; - -//////////////////////////////////////////////////////////////////////////////////////////////////// -/// @class sliced_chunk_reader -/// -/// @brief Helper to iterate easily through corresponding chunks of two dumps simultaneously. -//////////////////////////////////////////////////////////////////////////////////////////////////// -class sliced_chunk_reader { -public: - - // - sliced_chunk_reader(comparer_context& ctx) - : ctx(ctx) - {} - - // - ~sliced_chunk_reader() { - } - -public: - - sliced_chunk_iterator begin() const { - return sliced_chunk_iterator(ctx,ctx.get_latest_chunk_length()+ - ctx.get_latest_chunk_start()); - } - -private: - - comparer_context& ctx; -}; - -//////////////////////////////////////////////////////////////////////////////////////////////////// -/// @class scoped_chunk -/// -/// @brief Utility to simplify usage of comparer_context.push_elem/pop_elem -//////////////////////////////////////////////////////////////////////////////////////////////////// -class scoped_chunk { -public: - - // - scoped_chunk(comparer_context& ctx,const char* msg) - : ctx(ctx) - { - ctx.push_elem(msg); - } - - // - ~scoped_chunk() - { - ctx.pop_elem(); - } - -private: - - comparer_context& ctx; -}; - -//////////////////////////////////////////////////////////////////////////////////////////////////// -void CompareOnTheFlyMaterialProperty(comparer_context& comp) { - scoped_chunk chunk(comp,"aiMaterialProperty"); - - comp.cmp<aiString>("mKey"); - comp.cmp<uint32_t>("mSemantic"); - comp.cmp<uint32_t>("mIndex"); - const uint32_t length = comp.cmp<uint32_t>("mDataLength"); - const aiPropertyTypeInfo type = static_cast<aiPropertyTypeInfo>( - comp.cmp<uint32_t>("mType")); - - switch (type) - { - case aiPTI_Float: - comp.cmp<float>(length/4,"mData"); - break; - - case aiPTI_String: - comp.cmp<aiString>("mData"); - break; - - case aiPTI_Integer: - comp.cmp<uint32_t>(length/4,"mData"); - break; - - case aiPTI_Buffer: - comp.cmp<uint8_t>(length,"mData"); - break; - - default: - break; - }; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -void CompareOnTheFlyMaterial(comparer_context& comp) { - scoped_chunk chunk(comp,"aiMaterial"); - - comp.cmp<uint32_t>("aiMaterial::mNumProperties"); - sliced_chunk_reader reader(comp); - for(sliced_chunk_iterator it = reader.begin(); !it.is_end(); ++it) { - if ((*it).first == ASSBIN_CHUNK_AIMATERIALPROPERTY) { - CompareOnTheFlyMaterialProperty(comp); - } - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -void CompareOnTheFlyBone(comparer_context& comp) { - scoped_chunk chunk(comp,"aiBone"); - comp.cmp<aiString>("mName"); - comp.cmp<uint32_t>("mNumWeights"); - comp.cmp<aiMatrix4x4>("mOffsetMatrix"); - - comp.cmp_bounds<aiVertexWeight>("mWeights"); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -void CompareOnTheFlyNodeAnim(comparer_context& comp) { - scoped_chunk chunk(comp,"aiNodeAnim"); - - comp.cmp<aiString>("mNodeName"); - comp.cmp<uint32_t>("mNumPositionKeys"); - comp.cmp<uint32_t>("mNumRotationKeys"); - comp.cmp<uint32_t>("mNumScalingKeys"); - comp.cmp<uint32_t>("mPreState"); - comp.cmp<uint32_t>("mPostState"); - - comp.cmp_bounds<aiVectorKey>("mPositionKeys"); - comp.cmp_bounds<aiQuatKey>("mRotationKeys"); - comp.cmp_bounds<aiVectorKey>("mScalingKeys"); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -void CompareOnTheFlyMesh(comparer_context& comp) { - scoped_chunk chunk(comp,"aiMesh"); - - comp.cmp<uint32_t>("mPrimitiveTypes"); - comp.cmp<uint32_t>("mNumVertices"); - const uint32_t nf = comp.cmp<uint32_t>("mNumFaces"); - comp.cmp<uint32_t>("mNumBones"); - comp.cmp<uint32_t>("mMaterialIndex"); - - const uint32_t present = comp.cmp<uint32_t>("<vertex-components-present>"); - if(present & ASSBIN_MESH_HAS_POSITIONS) { - comp.cmp_bounds<aiVector3D>("mVertices"); - } - - if(present & ASSBIN_MESH_HAS_NORMALS) { - comp.cmp_bounds<aiVector3D>("mNormals"); - } - - if(present & ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS) { - comp.cmp_bounds<aiVector3D>("mTangents"); - comp.cmp_bounds<aiVector3D>("mBitangents"); - } - - for(unsigned int i = 0; present & ASSBIN_MESH_HAS_COLOR(i); ++i) { - std::stringstream ss; - comp.cmp_bounds<aiColor4D>((ss<<"mColors["<<i<<"]",ss.str())); - } - - for(unsigned int i = 0; present & ASSBIN_MESH_HAS_TEXCOORD(i); ++i) { - std::stringstream ss; - comp.cmp<uint32_t>((ss<<"mNumUVComponents["<<i<<"]",ss.str())); - comp.cmp_bounds<aiVector3D>((ss.clear(),ss<<"mTextureCoords["<<i<<"]",ss.str())); - } - - for(unsigned int i = 0; i< ((nf+511)/512); ++i) { - std::stringstream ss; - comp.cmp<uint32_t>((ss<<"mFaces["<<i*512<<"-"<<std::min(static_cast< - uint32_t>((i+1)*512),nf)<<"]",ss.str())); - } - - sliced_chunk_reader reader(comp); - for(sliced_chunk_iterator it = reader.begin(); !it.is_end(); ++it) { - if ((*it).first == ASSBIN_CHUNK_AIBONE) { - CompareOnTheFlyBone(comp); - } - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -void CompareOnTheFlyCamera(comparer_context& comp) { - scoped_chunk chunk(comp,"aiCamera"); - - comp.cmp<aiString>("mName"); - - comp.cmp<aiVector3D>("mPosition"); - comp.cmp<aiVector3D>("mLookAt"); - comp.cmp<aiVector3D>("mUp"); - - comp.cmp<float>("mHorizontalFOV"); - comp.cmp<float>("mClipPlaneNear"); - comp.cmp<float>("mClipPlaneFar"); - comp.cmp<float>("mAspect"); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -void CompareOnTheFlyLight(comparer_context& comp) { - scoped_chunk chunk(comp,"aiLight"); - - comp.cmp<aiString>("mName"); - const aiLightSourceType type = static_cast<aiLightSourceType>( - comp.cmp<uint32_t>("mType")); - - if(type!=aiLightSource_DIRECTIONAL) { - comp.cmp<float>("mAttenuationConstant"); - comp.cmp<float>("mAttenuationLinear"); - comp.cmp<float>("mAttenuationQuadratic"); - } - - comp.cmp<aiVector3D>("mColorDiffuse"); - comp.cmp<aiVector3D>("mColorSpecular"); - comp.cmp<aiVector3D>("mColorAmbient"); - - if(type==aiLightSource_SPOT) { - comp.cmp<float>("mAngleInnerCone"); - comp.cmp<float>("mAngleOuterCone"); - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -void CompareOnTheFlyAnimation(comparer_context& comp) { - scoped_chunk chunk(comp,"aiAnimation"); - - comp.cmp<aiString>("mName"); - comp.cmp<double>("mDuration"); - comp.cmp<double>("mTicksPerSecond"); - comp.cmp<uint32_t>("mNumChannels"); - - sliced_chunk_reader reader(comp); - for(sliced_chunk_iterator it = reader.begin(); !it.is_end(); ++it) { - if ((*it).first == ASSBIN_CHUNK_AINODEANIM) { - CompareOnTheFlyNodeAnim(comp); - } - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -void CompareOnTheFlyTexture(comparer_context& comp) { - scoped_chunk chunk(comp,"aiTexture"); - - const uint32_t w = comp.cmp<uint32_t>("mWidth"); - const uint32_t h = comp.cmp<uint32_t>("mHeight"); - (void)w; (void)h; - comp.cmp<char>("achFormatHint[0]"); - comp.cmp<char>("achFormatHint[1]"); - comp.cmp<char>("achFormatHint[2]"); - comp.cmp<char>("achFormatHint[3]"); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -void CompareOnTheFlyNode(comparer_context& comp) { - scoped_chunk chunk(comp,"aiNode"); - comp.cmp<aiString>("mName"); - comp.cmp<aiMatrix4x4>("mTransformation"); - comp.cmp<uint32_t>("mNumChildren"); - comp.cmp<uint32_t>(comp.cmp<uint32_t>("mNumMeshes"),"mMeshes"); - - sliced_chunk_reader reader(comp); - for(sliced_chunk_iterator it = reader.begin(); !it.is_end(); ++it) { - if ((*it).first == ASSBIN_CHUNK_AINODE) { - CompareOnTheFlyNode(comp); - } - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -void CompareOnTheFlyScene(comparer_context& comp) { - scoped_chunk chunk(comp,"aiScene"); - - comp.cmp<uint32_t>("mFlags"); - comp.cmp<uint32_t>("mNumMeshes"); - comp.cmp<uint32_t>("mNumMaterials"); - comp.cmp<uint32_t>("mNumAnimations"); - comp.cmp<uint32_t>("mNumTextures"); - comp.cmp<uint32_t>("mNumLights"); - comp.cmp<uint32_t>("mNumCameras"); - - sliced_chunk_reader reader(comp); - for(sliced_chunk_iterator it = reader.begin(); !it.is_end(); ++it) { - if ((*it).first == ASSBIN_CHUNK_AIMATERIAL) { - CompareOnTheFlyMaterial(comp); - } - else if ((*it).first == ASSBIN_CHUNK_AITEXTURE) { - CompareOnTheFlyTexture(comp); - } - else if ((*it).first == ASSBIN_CHUNK_AIMESH) { - CompareOnTheFlyMesh(comp); - } - else if ((*it).first == ASSBIN_CHUNK_AIANIMATION) { - CompareOnTheFlyAnimation(comp); - } - else if ((*it).first == ASSBIN_CHUNK_AICAMERA) { - CompareOnTheFlyCamera(comp); - } - else if ((*it).first == ASSBIN_CHUNK_AILIGHT) { - CompareOnTheFlyLight(comp); - } - else if ((*it).first == ASSBIN_CHUNK_AINODE) { - CompareOnTheFlyNode(comp); - } - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -void CompareOnTheFly(comparer_context& comp) -{ - sliced_chunk_reader reader(comp); - for(sliced_chunk_iterator it = reader.begin(); !it.is_end(); ++it) { - if ((*it).first == ASSBIN_CHUNK_AISCENE) { - CompareOnTheFlyScene(comp); - break; - } - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -void CheckHeader(comparer_context& comp) -{ - fseek(comp.get_actual(),ASSBIN_HEADER_LENGTH,SEEK_CUR); - fseek(comp.get_expect(),ASSBIN_HEADER_LENGTH,SEEK_CUR); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -int Assimp_CompareDump (const char* const* params, unsigned int num) -{ - // --help - if ((num == 1 && !strcmp( params[0], "-h")) || !strcmp( params[0], "--help") || !strcmp( params[0], "-?") ) { - printf("%s",AICMD_MSG_CMPDUMP_HELP); - return 0; - } - - // assimp cmpdump actual expected - if (num < 1) { - std::cout << "assimp cmpdump: Invalid number of arguments. " - "See \'assimp cmpdump --help\'\r\n" << std::endl; - return 1; - } - - if(!strcmp(params[0],params[1])) { - std::cout << "assimp cmpdump: same file, same content." << std::endl; - return 0; - } - - FILE* actual = fopen(params[0],"rb"), *expected = fopen(params[1],"rb"); - if (!actual) { - std::cout << "assimp cmpdump: Failure reading ACTUAL data from " << - params[0] << std::endl; - return -5; - } - if (!expected) { - std::cout << "assimp cmpdump: Failure reading EXPECT data from " << - params[1] << std::endl; - return -6; - } - - comparer_context comp(actual,expected); - try { - CheckHeader(comp); - CompareOnTheFly(comp); - } - catch(const compare_fails_exception& ex) { - printf("%s",ex.what()); - return -1; - } - catch(...) { - // we don't bother checking too rigourously here, so - // we might end up here ... - std::cout << "Unknown failure, are the input files well-defined?"; - return -3; - } - - std::cout << "Success (totally " << std::dec << comp.get_num_chunks() << - " chunks)" << std::endl; - - return 0; -} +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2015, assimp 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 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 CompareDump.cpp + * @brief Implementation of the 'assimp cmpdmp', which compares + * two model dumps for equality. It plays an important role + * in the regression test suite. + */ + +#include "Main.h" +const char* AICMD_MSG_CMPDUMP_HELP = +"assimp cmpdump <actual> <expected>\n" +"\tCompare two short dumps produced with \'assimp dump <..> -s\' for equality.\n" +; + +#include "../../code/assbin_chunks.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// +#include "generic_inserter.hpp" +#include <map> +#include <deque> +#include <stack> +#include <sstream> +#include <iostream> +#include "../../include/assimp/ai_assert.h" + +// get << for aiString +template <typename char_t, typename traits_t> +void mysprint(std::basic_ostream<char_t, traits_t>& os, const aiString& vec) { + os << "[length: \'" << std::dec << vec.length << "\' content: \'" << vec.data << "\']"; +} + +template <typename char_t, typename traits_t> +std::basic_ostream<char_t, traits_t>& operator<< (std::basic_ostream<char_t, traits_t>& os, const aiString& vec) { + return generic_inserter(mysprint<char_t,traits_t>, os, vec); +} + +class sliced_chunk_iterator; +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// @class compare_fails_exception +/// +/// @brief Sentinel exception to return quickly from deeply nested control paths +//////////////////////////////////////////////////////////////////////////////////////////////////// +class compare_fails_exception : public virtual std::exception { +public: + + enum {MAX_ERR_LEN = 4096}; + + /* public c'tors */ + compare_fails_exception(const char* msg) { + strncpy(mywhat,msg,MAX_ERR_LEN-1); + strcat(mywhat,"\n"); + } + + /* public member functions */ + const char* what() const throw() { + return mywhat; + } + +private: + + char mywhat[MAX_ERR_LEN+1]; +}; + + +#define MY_FLT_EPSILON 1e-1f +#define MY_DBL_EPSILON 1e-1 +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// @class comparer_context +/// +/// @brief Record our way through the files to be compared and dump useful information if we fail. +//////////////////////////////////////////////////////////////////////////////////////////////////// +class comparer_context { + friend class sliced_chunk_iterator; + +public: + + /* construct given two file handles to compare */ + comparer_context(FILE* actual,FILE* expect) + : actual(actual) + , expect(expect) + , cnt_chunks(0) + { + ai_assert(actual); + ai_assert(expect); + + fseek(actual,0,SEEK_END); + lengths.push(std::make_pair(static_cast<uint32_t>(ftell(actual)),0)); + fseek(actual,0,SEEK_SET); + + history.push_back(HistoryEntry("---",PerChunkCounter())); + } + +public: + + + /* set new scope */ + void push_elem(const char* msg) { + const std::string s = msg; + + PerChunkCounter::const_iterator it = history.back().second.find(s); + if(it != history.back().second.end()) { + ++history.back().second[s]; + } + else history.back().second[s] = 0; + + history.push_back(HistoryEntry(s,PerChunkCounter())); + debug_trace.push_back("PUSH " + s); + } + + /* leave current scope */ + void pop_elem() { + ai_assert(history.size()); + debug_trace.push_back("POP "+ history.back().first); + history.pop_back(); + } + + + /* push current chunk length and start offset on top of stack */ + void push_length(uint32_t nl, uint32_t start) { + lengths.push(std::make_pair(nl,start)); + ++cnt_chunks; + } + + /* pop the chunk length stack */ + void pop_length() { + ai_assert(lengths.size()); + lengths.pop(); + } + + /* access the current chunk length */ + uint32_t get_latest_chunk_length() { + ai_assert(lengths.size()); + return lengths.top().first; + } + + /* access the current chunk start offset */ + uint32_t get_latest_chunk_start() { + ai_assert(lengths.size()); + return lengths.top().second; + } + + /* total number of chunk headers passed so far*/ + uint32_t get_num_chunks() { + return cnt_chunks; + } + + + /* get ACTUAL file desc. != NULL */ + FILE* get_actual() const { + return actual; + } + + /* get EXPECT file desc. != NULL */ + FILE* get_expect() const { + return expect; + } + + + /* compare next T from both streams, name occurs in error messages */ + template<typename T> T cmp(const std::string& name) { + T a,e; + read(a,e); + + if(a != e) { + std::stringstream ss; + failure((ss<< "Expected " << e << ", but actual is " << a, + ss.str()),name); + } + // std::cout << name << " " << std::hex << a << std::endl; + return a; + } + + /* compare next num T's from both streams, name occurs in error messages */ + template<typename T> void cmp(size_t num,const std::string& name) { + for(size_t n = 0; n < num; ++n) { + std::stringstream ss; + cmp<T>((ss<<name<<"["<<n<<"]",ss.str())); + // std::cout << name << " " << std::hex << a << std::endl; + } + } + + /* Bounds of an aiVector3D array (separate function + * because partial specializations of member functions are illegal--)*/ + template<typename T> void cmp_bounds(const std::string& name) { + cmp<T> (name+".<minimum-value>"); + cmp<T> (name+".<maximum-value>"); + } + +private: + + /* Report failure */ + AI_WONT_RETURN void failure(const std::string& err, const std::string& name) AI_WONT_RETURN_SUFFIX { + std::stringstream ss; + throw compare_fails_exception((ss + << "Files are different at " + << history.back().first + << "." + << name + << ".\nError is: " + << err + << ".\nCurrent position in scene hierarchy is " + << print_hierarchy(),ss.str().c_str() + )); + } + + /** print our 'stack' */ + std::string print_hierarchy() { + std::stringstream ss; + ss << std::endl; + + const char* last = history.back().first.c_str(); + std::string pad; + + for(ChunkHistory::reverse_iterator rev = history.rbegin(), + end = history.rend(); rev != end; ++rev, pad += " ") + { + ss << pad << (*rev).first << "(Index: " << (*rev).second[last] << ")" << std::endl; + last = (*rev).first.c_str(); + } + + ss << std::endl << "Debug trace: "<< std::endl; + for (std::vector<std::string>::const_iterator it = debug_trace.begin(); it != debug_trace.end(); ++it) { + ss << *it << std::endl; + } + return ss.str(); + } + + + /* read from both streams at the same time */ + template <typename T> void read(T& filla,T& fille) { + if(1 != fread(&filla,sizeof(T),1,actual)) { + EOFActual(); + } + if(1 != fread(&fille,sizeof(T),1,expect)) { + EOFExpect(); + } + } + +private: + + void EOFActual() { + std::stringstream ss; + throw compare_fails_exception((ss + << "Unexpected EOF reading ACTUAL.\nCurrent position in scene hierarchy is " + << print_hierarchy(),ss.str().c_str() + )); + } + + void EOFExpect() { + std::stringstream ss; + throw compare_fails_exception((ss + << "Unexpected EOF reading EXPECT.\nCurrent position in scene hierarchy is " + << print_hierarchy(),ss.str().c_str() + )); + } + + + FILE *const actual, *const expect; + + typedef std::map<std::string,unsigned int> PerChunkCounter; + typedef std::pair<std::string,PerChunkCounter> HistoryEntry; + + typedef std::deque<HistoryEntry> ChunkHistory; + ChunkHistory history; + + std::vector<std::string> debug_trace; + + typedef std::stack<std::pair<uint32_t,uint32_t> > LengthStack; + LengthStack lengths; + + uint32_t cnt_chunks; +}; + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +/* specialization for aiString (it needs separate handling because its on-disk representation + * differs from its binary representation in memory and can't be treated as an array of n T's.*/ +template <> void comparer_context :: read<aiString>(aiString& filla,aiString& fille) { + uint32_t lena,lene; + read(lena,lene); + + if(lena && 1 != fread(&filla.data,lena,1,actual)) { + EOFActual(); + } + if(lene && 1 != fread(&fille.data,lene,1,expect)) { + EOFExpect(); + } + + fille.data[fille.length=static_cast<unsigned int>(lene)] = '\0'; + filla.data[filla.length=static_cast<unsigned int>(lena)] = '\0'; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +/* Specialization for float, uses epsilon for comparisons*/ +template<> float comparer_context :: cmp<float>(const std::string& name) +{ + float a,e,t; + read(a,e); + + if((t=fabs(a-e)) > MY_FLT_EPSILON) { + std::stringstream ss; + failure((ss<< "Expected " << e << ", but actual is " + << a << " (delta is " << t << ")", ss.str()),name); + } + return a; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +/* Specialization for double, uses epsilon for comparisons*/ +template<> double comparer_context :: cmp<double>(const std::string& name) +{ + double a,e,t; + read(a,e); + + if((t=fabs(a-e)) > MY_DBL_EPSILON) { + std::stringstream ss; + failure((ss<< "Expected " << e << ", but actual is " + << a << " (delta is " << t << ")", ss.str()),name); + } + return a; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +/* Specialization for aiVector3D */ +template<> aiVector3D comparer_context :: cmp<aiVector3D >(const std::string& name) +{ + const float x = cmp<float>(name+".x"); + const float y = cmp<float>(name+".y"); + const float z = cmp<float>(name+".z"); + + return aiVector3D(x,y,z); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +/* Specialization for aiColor4D */ +template<> aiColor4D comparer_context :: cmp<aiColor4D >(const std::string& name) +{ + const float r = cmp<float>(name+".r"); + const float g = cmp<float>(name+".g"); + const float b = cmp<float>(name+".b"); + const float a = cmp<float>(name+".a"); + + return aiColor4D(r,g,b,a); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +/* Specialization for aiQuaternion */ +template<> aiQuaternion comparer_context :: cmp<aiQuaternion >(const std::string& name) +{ + const float w = cmp<float>(name+".w"); + const float x = cmp<float>(name+".x"); + const float y = cmp<float>(name+".y"); + const float z = cmp<float>(name+".z"); + + return aiQuaternion(w,x,y,z); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +/* Specialization for aiQuatKey */ +template<> aiQuatKey comparer_context :: cmp<aiQuatKey >(const std::string& name) +{ + const double mTime = cmp<double>(name+".mTime"); + const aiQuaternion mValue = cmp<aiQuaternion>(name+".mValue"); + + return aiQuatKey(mTime,mValue); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +/* Specialization for aiVectorKey */ +template<> aiVectorKey comparer_context :: cmp<aiVectorKey >(const std::string& name) +{ + const double mTime = cmp<double>(name+".mTime"); + const aiVector3D mValue = cmp<aiVector3D>(name+".mValue"); + + return aiVectorKey(mTime,mValue); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +/* Specialization for aiMatrix4x4 */ +template<> aiMatrix4x4 comparer_context :: cmp<aiMatrix4x4 >(const std::string& name) +{ + aiMatrix4x4 res; + for(unsigned int i = 0; i < 4; ++i) { + for(unsigned int j = 0; j < 4; ++j) { + std::stringstream ss; + res[i][j] = cmp<float>(name+(ss<<".m"<<i<<j,ss.str())); + } + } + + return res; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +/* Specialization for aiVertexWeight */ +template<> aiVertexWeight comparer_context :: cmp<aiVertexWeight >(const std::string& name) +{ + const unsigned int mVertexId = cmp<unsigned int>(name+".mVertexId"); + const float mWeight = cmp<float>(name+".mWeight"); + + return aiVertexWeight(mVertexId,mWeight); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// @class sliced_chunk_iterator +/// +/// @brief Helper to iterate easily through corresponding chunks of two dumps simultaneously. +/// +/// Not a *real* iterator, doesn't fully conform to the isocpp iterator spec +//////////////////////////////////////////////////////////////////////////////////////////////////// +class sliced_chunk_iterator { + + friend class sliced_chunk_reader; + sliced_chunk_iterator(comparer_context& ctx, long end) + : ctx(ctx) + , endit(false) + , next(std::numeric_limits<long>::max()) + , end(end) + { + load_next(); + } + +public: + + ~sliced_chunk_iterator() { + fseek(ctx.get_actual(),end,SEEK_SET); + fseek(ctx.get_expect(),end,SEEK_SET); + } + +public: + + /* get current chunk head */ + typedef std::pair<uint32_t,uint32_t> Chunk; + const Chunk& operator*() { + return current; + } + + /* get to next chunk head */ + const sliced_chunk_iterator& operator++() { + cleanup(); + load_next(); + return *this; + } + + /* */ + bool is_end() const { + return endit; + } + +private: + + /* get to the end of *this* chunk */ + void cleanup() { + if(next != std::numeric_limits<long>::max()) { + fseek(ctx.get_actual(),next,SEEK_SET); + fseek(ctx.get_expect(),next,SEEK_SET); + + ctx.pop_length(); + } + } + + /* advance to the next chunk */ + void load_next() { + + Chunk actual; + size_t res=0; + + const long cur = ftell(ctx.get_expect()); + if(end-cur<8) { + current = std::make_pair(0u,0u); + endit = true; + return; + } + + res|=fread(¤t.first,4,1,ctx.get_expect()); + res|=fread(¤t.second,4,1,ctx.get_expect()) <<1u; + res|=fread(&actual.first,4,1,ctx.get_actual()) <<2u; + res|=fread(&actual.second,4,1,ctx.get_actual()) <<3u; + + if(res!=0xf) { + ctx.failure("IO Error reading chunk head, dumps are malformed","<ChunkHead>"); + } + + if (current.first != actual.first) { + std::stringstream ss; + ctx.failure((ss + <<"Chunk headers do not match. EXPECT: " + << std::hex << current.first + <<" ACTUAL: " + << /*std::hex */actual.first, + ss.str()), + "<ChunkHead>"); + } + + if (current.first != actual.first) { + std::stringstream ss; + ctx.failure((ss + <<"Chunk lengths do not match. EXPECT: " + <<current.second + <<" ACTUAL: " + << actual.second, + ss.str()), + "<ChunkHead>"); + } + + next = cur+current.second+8; + ctx.push_length(current.second,cur+8); + } + + comparer_context& ctx; + Chunk current; + bool endit; + long next,end; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// @class sliced_chunk_reader +/// +/// @brief Helper to iterate easily through corresponding chunks of two dumps simultaneously. +//////////////////////////////////////////////////////////////////////////////////////////////////// +class sliced_chunk_reader { +public: + + // + sliced_chunk_reader(comparer_context& ctx) + : ctx(ctx) + {} + + // + ~sliced_chunk_reader() { + } + +public: + + sliced_chunk_iterator begin() const { + return sliced_chunk_iterator(ctx,ctx.get_latest_chunk_length()+ + ctx.get_latest_chunk_start()); + } + +private: + + comparer_context& ctx; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// @class scoped_chunk +/// +/// @brief Utility to simplify usage of comparer_context.push_elem/pop_elem +//////////////////////////////////////////////////////////////////////////////////////////////////// +class scoped_chunk { +public: + + // + scoped_chunk(comparer_context& ctx,const char* msg) + : ctx(ctx) + { + ctx.push_elem(msg); + } + + // + ~scoped_chunk() + { + ctx.pop_elem(); + } + +private: + + comparer_context& ctx; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +void CompareOnTheFlyMaterialProperty(comparer_context& comp) { + scoped_chunk chunk(comp,"aiMaterialProperty"); + + comp.cmp<aiString>("mKey"); + comp.cmp<uint32_t>("mSemantic"); + comp.cmp<uint32_t>("mIndex"); + const uint32_t length = comp.cmp<uint32_t>("mDataLength"); + const aiPropertyTypeInfo type = static_cast<aiPropertyTypeInfo>( + comp.cmp<uint32_t>("mType")); + + switch (type) + { + case aiPTI_Float: + comp.cmp<float>(length/4,"mData"); + break; + + case aiPTI_String: + comp.cmp<aiString>("mData"); + break; + + case aiPTI_Integer: + comp.cmp<uint32_t>(length/4,"mData"); + break; + + case aiPTI_Buffer: + comp.cmp<uint8_t>(length,"mData"); + break; + + default: + break; + }; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +void CompareOnTheFlyMaterial(comparer_context& comp) { + scoped_chunk chunk(comp,"aiMaterial"); + + comp.cmp<uint32_t>("aiMaterial::mNumProperties"); + sliced_chunk_reader reader(comp); + for(sliced_chunk_iterator it = reader.begin(); !it.is_end(); ++it) { + if ((*it).first == ASSBIN_CHUNK_AIMATERIALPROPERTY) { + CompareOnTheFlyMaterialProperty(comp); + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +void CompareOnTheFlyBone(comparer_context& comp) { + scoped_chunk chunk(comp,"aiBone"); + comp.cmp<aiString>("mName"); + comp.cmp<uint32_t>("mNumWeights"); + comp.cmp<aiMatrix4x4>("mOffsetMatrix"); + + comp.cmp_bounds<aiVertexWeight>("mWeights"); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +void CompareOnTheFlyNodeAnim(comparer_context& comp) { + scoped_chunk chunk(comp,"aiNodeAnim"); + + comp.cmp<aiString>("mNodeName"); + comp.cmp<uint32_t>("mNumPositionKeys"); + comp.cmp<uint32_t>("mNumRotationKeys"); + comp.cmp<uint32_t>("mNumScalingKeys"); + comp.cmp<uint32_t>("mPreState"); + comp.cmp<uint32_t>("mPostState"); + + comp.cmp_bounds<aiVectorKey>("mPositionKeys"); + comp.cmp_bounds<aiQuatKey>("mRotationKeys"); + comp.cmp_bounds<aiVectorKey>("mScalingKeys"); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +void CompareOnTheFlyMesh(comparer_context& comp) { + scoped_chunk chunk(comp,"aiMesh"); + + comp.cmp<uint32_t>("mPrimitiveTypes"); + comp.cmp<uint32_t>("mNumVertices"); + const uint32_t nf = comp.cmp<uint32_t>("mNumFaces"); + comp.cmp<uint32_t>("mNumBones"); + comp.cmp<uint32_t>("mMaterialIndex"); + + const uint32_t present = comp.cmp<uint32_t>("<vertex-components-present>"); + if(present & ASSBIN_MESH_HAS_POSITIONS) { + comp.cmp_bounds<aiVector3D>("mVertices"); + } + + if(present & ASSBIN_MESH_HAS_NORMALS) { + comp.cmp_bounds<aiVector3D>("mNormals"); + } + + if(present & ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS) { + comp.cmp_bounds<aiVector3D>("mTangents"); + comp.cmp_bounds<aiVector3D>("mBitangents"); + } + + for(unsigned int i = 0; present & ASSBIN_MESH_HAS_COLOR(i); ++i) { + std::stringstream ss; + comp.cmp_bounds<aiColor4D>((ss<<"mColors["<<i<<"]",ss.str())); + } + + for(unsigned int i = 0; present & ASSBIN_MESH_HAS_TEXCOORD(i); ++i) { + std::stringstream ss; + comp.cmp<uint32_t>((ss<<"mNumUVComponents["<<i<<"]",ss.str())); + comp.cmp_bounds<aiVector3D>((ss.clear(),ss<<"mTextureCoords["<<i<<"]",ss.str())); + } + + for(unsigned int i = 0; i< ((nf+511)/512); ++i) { + std::stringstream ss; + comp.cmp<uint32_t>((ss<<"mFaces["<<i*512<<"-"<<std::min(static_cast< + uint32_t>((i+1)*512),nf)<<"]",ss.str())); + } + + sliced_chunk_reader reader(comp); + for(sliced_chunk_iterator it = reader.begin(); !it.is_end(); ++it) { + if ((*it).first == ASSBIN_CHUNK_AIBONE) { + CompareOnTheFlyBone(comp); + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +void CompareOnTheFlyCamera(comparer_context& comp) { + scoped_chunk chunk(comp,"aiCamera"); + + comp.cmp<aiString>("mName"); + + comp.cmp<aiVector3D>("mPosition"); + comp.cmp<aiVector3D>("mLookAt"); + comp.cmp<aiVector3D>("mUp"); + + comp.cmp<float>("mHorizontalFOV"); + comp.cmp<float>("mClipPlaneNear"); + comp.cmp<float>("mClipPlaneFar"); + comp.cmp<float>("mAspect"); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +void CompareOnTheFlyLight(comparer_context& comp) { + scoped_chunk chunk(comp,"aiLight"); + + comp.cmp<aiString>("mName"); + const aiLightSourceType type = static_cast<aiLightSourceType>( + comp.cmp<uint32_t>("mType")); + + if(type!=aiLightSource_DIRECTIONAL) { + comp.cmp<float>("mAttenuationConstant"); + comp.cmp<float>("mAttenuationLinear"); + comp.cmp<float>("mAttenuationQuadratic"); + } + + comp.cmp<aiVector3D>("mColorDiffuse"); + comp.cmp<aiVector3D>("mColorSpecular"); + comp.cmp<aiVector3D>("mColorAmbient"); + + if(type==aiLightSource_SPOT) { + comp.cmp<float>("mAngleInnerCone"); + comp.cmp<float>("mAngleOuterCone"); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +void CompareOnTheFlyAnimation(comparer_context& comp) { + scoped_chunk chunk(comp,"aiAnimation"); + + comp.cmp<aiString>("mName"); + comp.cmp<double>("mDuration"); + comp.cmp<double>("mTicksPerSecond"); + comp.cmp<uint32_t>("mNumChannels"); + + sliced_chunk_reader reader(comp); + for(sliced_chunk_iterator it = reader.begin(); !it.is_end(); ++it) { + if ((*it).first == ASSBIN_CHUNK_AINODEANIM) { + CompareOnTheFlyNodeAnim(comp); + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +void CompareOnTheFlyTexture(comparer_context& comp) { + scoped_chunk chunk(comp,"aiTexture"); + + const uint32_t w = comp.cmp<uint32_t>("mWidth"); + const uint32_t h = comp.cmp<uint32_t>("mHeight"); + (void)w; (void)h; + comp.cmp<char>("achFormatHint[0]"); + comp.cmp<char>("achFormatHint[1]"); + comp.cmp<char>("achFormatHint[2]"); + comp.cmp<char>("achFormatHint[3]"); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +void CompareOnTheFlyNode(comparer_context& comp) { + scoped_chunk chunk(comp,"aiNode"); + comp.cmp<aiString>("mName"); + comp.cmp<aiMatrix4x4>("mTransformation"); + comp.cmp<uint32_t>("mNumChildren"); + comp.cmp<uint32_t>(comp.cmp<uint32_t>("mNumMeshes"),"mMeshes"); + + sliced_chunk_reader reader(comp); + for(sliced_chunk_iterator it = reader.begin(); !it.is_end(); ++it) { + if ((*it).first == ASSBIN_CHUNK_AINODE) { + CompareOnTheFlyNode(comp); + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +void CompareOnTheFlyScene(comparer_context& comp) { + scoped_chunk chunk(comp,"aiScene"); + + comp.cmp<uint32_t>("mFlags"); + comp.cmp<uint32_t>("mNumMeshes"); + comp.cmp<uint32_t>("mNumMaterials"); + comp.cmp<uint32_t>("mNumAnimations"); + comp.cmp<uint32_t>("mNumTextures"); + comp.cmp<uint32_t>("mNumLights"); + comp.cmp<uint32_t>("mNumCameras"); + + sliced_chunk_reader reader(comp); + for(sliced_chunk_iterator it = reader.begin(); !it.is_end(); ++it) { + if ((*it).first == ASSBIN_CHUNK_AIMATERIAL) { + CompareOnTheFlyMaterial(comp); + } + else if ((*it).first == ASSBIN_CHUNK_AITEXTURE) { + CompareOnTheFlyTexture(comp); + } + else if ((*it).first == ASSBIN_CHUNK_AIMESH) { + CompareOnTheFlyMesh(comp); + } + else if ((*it).first == ASSBIN_CHUNK_AIANIMATION) { + CompareOnTheFlyAnimation(comp); + } + else if ((*it).first == ASSBIN_CHUNK_AICAMERA) { + CompareOnTheFlyCamera(comp); + } + else if ((*it).first == ASSBIN_CHUNK_AILIGHT) { + CompareOnTheFlyLight(comp); + } + else if ((*it).first == ASSBIN_CHUNK_AINODE) { + CompareOnTheFlyNode(comp); + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +void CompareOnTheFly(comparer_context& comp) +{ + sliced_chunk_reader reader(comp); + for(sliced_chunk_iterator it = reader.begin(); !it.is_end(); ++it) { + if ((*it).first == ASSBIN_CHUNK_AISCENE) { + CompareOnTheFlyScene(comp); + break; + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +void CheckHeader(comparer_context& comp) +{ + fseek(comp.get_actual(),ASSBIN_HEADER_LENGTH,SEEK_CUR); + fseek(comp.get_expect(),ASSBIN_HEADER_LENGTH,SEEK_CUR); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +int Assimp_CompareDump (const char* const* params, unsigned int num) +{ + // --help + if ((num == 1 && !strcmp( params[0], "-h")) || !strcmp( params[0], "--help") || !strcmp( params[0], "-?") ) { + printf("%s",AICMD_MSG_CMPDUMP_HELP); + return 0; + } + + // assimp cmpdump actual expected + if (num < 1) { + std::cout << "assimp cmpdump: Invalid number of arguments. " + "See \'assimp cmpdump --help\'\r\n" << std::endl; + return 1; + } + + if(!strcmp(params[0],params[1])) { + std::cout << "assimp cmpdump: same file, same content." << std::endl; + return 0; + } + + FILE* actual = fopen(params[0],"rb"), *expected = fopen(params[1],"rb"); + if (!actual) { + std::cout << "assimp cmpdump: Failure reading ACTUAL data from " << + params[0] << std::endl; + return -5; + } + if (!expected) { + std::cout << "assimp cmpdump: Failure reading EXPECT data from " << + params[1] << std::endl; + return -6; + } + + comparer_context comp(actual,expected); + try { + CheckHeader(comp); + CompareOnTheFly(comp); + } + catch(const compare_fails_exception& ex) { + printf("%s",ex.what()); + return -1; + } + catch(...) { + // we don't bother checking too rigourously here, so + // we might end up here ... + std::cout << "Unknown failure, are the input files well-defined?"; + return -3; + } + + std::cout << "Success (totally " << std::dec << comp.get_num_chunks() << + " chunks)" << std::endl; + + return 0; +} diff --git a/tools/assimp_view/AnimEvaluator.cpp b/tools/assimp_view/AnimEvaluator.cpp index 5a78426c9..c3baee9d5 100644 --- a/tools/assimp_view/AnimEvaluator.cpp +++ b/tools/assimp_view/AnimEvaluator.cpp @@ -1,169 +1,169 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2015, assimp 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 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 "assimp_view.h" - -using namespace AssimpView; - -// ------------------------------------------------------------------------------------------------ -// Constructor on a given animation. -AnimEvaluator::AnimEvaluator( const aiAnimation* pAnim) -{ - mAnim = pAnim; - mLastTime = 0.0; - mLastPositions.resize( pAnim->mNumChannels, boost::make_tuple( 0, 0, 0)); -} - -// ------------------------------------------------------------------------------------------------ -// Evaluates the animation tracks for a given time stamp. -void AnimEvaluator::Evaluate( double pTime) -{ - // extract ticks per second. Assume default value if not given - double ticksPerSecond = mAnim->mTicksPerSecond != 0.0 ? mAnim->mTicksPerSecond : 25.0; - // every following time calculation happens in ticks - pTime *= ticksPerSecond; - - // map into anim's duration - double time = 0.0f; - if( mAnim->mDuration > 0.0) - time = fmod( pTime, mAnim->mDuration); - - if( mTransforms.size() != mAnim->mNumChannels) - mTransforms.resize( mAnim->mNumChannels); - - // calculate the transformations for each animation channel - for( unsigned int a = 0; a < mAnim->mNumChannels; a++) - { - const aiNodeAnim* channel = mAnim->mChannels[a]; - - // ******** Position ***** - aiVector3D presentPosition( 0, 0, 0); - if( channel->mNumPositionKeys > 0) - { - // Look for present frame number. Search from last position if time is after the last time, else from beginning - // Should be much quicker than always looking from start for the average use case. - unsigned int frame = (time >= mLastTime) ? mLastPositions[a].get<0>() : 0; - while( frame < channel->mNumPositionKeys - 1) - { - if( time < channel->mPositionKeys[frame+1].mTime) - break; - frame++; - } - - // interpolate between this frame's value and next frame's value - unsigned int nextFrame = (frame + 1) % channel->mNumPositionKeys; - const aiVectorKey& key = channel->mPositionKeys[frame]; - const aiVectorKey& nextKey = channel->mPositionKeys[nextFrame]; - double diffTime = nextKey.mTime - key.mTime; - if( diffTime < 0.0) - diffTime += mAnim->mDuration; - if( diffTime > 0) - { - float factor = float( (time - key.mTime) / diffTime); - presentPosition = key.mValue + (nextKey.mValue - key.mValue) * factor; - } else - { - presentPosition = key.mValue; - } - - mLastPositions[a].get<0>() = frame; - } - - // ******** Rotation ********* - aiQuaternion presentRotation( 1, 0, 0, 0); - if( channel->mNumRotationKeys > 0) - { - unsigned int frame = (time >= mLastTime) ? mLastPositions[a].get<1>() : 0; - while( frame < channel->mNumRotationKeys - 1) - { - if( time < channel->mRotationKeys[frame+1].mTime) - break; - frame++; - } - - // interpolate between this frame's value and next frame's value - unsigned int nextFrame = (frame + 1) % channel->mNumRotationKeys; - const aiQuatKey& key = channel->mRotationKeys[frame]; - const aiQuatKey& nextKey = channel->mRotationKeys[nextFrame]; - double diffTime = nextKey.mTime - key.mTime; - if( diffTime < 0.0) - diffTime += mAnim->mDuration; - if( diffTime > 0) - { - float factor = float( (time - key.mTime) / diffTime); - aiQuaternion::Interpolate( presentRotation, key.mValue, nextKey.mValue, factor); - } else - { - presentRotation = key.mValue; - } - - mLastPositions[a].get<1>() = frame; - } - - // ******** Scaling ********** - aiVector3D presentScaling( 1, 1, 1); - if( channel->mNumScalingKeys > 0) - { - unsigned int frame = (time >= mLastTime) ? mLastPositions[a].get<2>() : 0; - while( frame < channel->mNumScalingKeys - 1) - { - if( time < channel->mScalingKeys[frame+1].mTime) - break; - frame++; - } - - // TODO: (thom) interpolation maybe? This time maybe even logarithmic, not linear - presentScaling = channel->mScalingKeys[frame].mValue; - mLastPositions[a].get<2>() = frame; - } - - // build a transformation matrix from it - aiMatrix4x4& mat = mTransforms[a]; - mat = aiMatrix4x4( presentRotation.GetMatrix()); - mat.a1 *= presentScaling.x; mat.b1 *= presentScaling.x; mat.c1 *= presentScaling.x; - mat.a2 *= presentScaling.y; mat.b2 *= presentScaling.y; mat.c2 *= presentScaling.y; - mat.a3 *= presentScaling.z; mat.b3 *= presentScaling.z; mat.c3 *= presentScaling.z; - mat.a4 = presentPosition.x; mat.b4 = presentPosition.y; mat.c4 = presentPosition.z; - //mat.Transpose(); - } - - mLastTime = time; -} +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2015, assimp 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 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 "assimp_view.h" + +using namespace AssimpView; + +// ------------------------------------------------------------------------------------------------ +// Constructor on a given animation. +AnimEvaluator::AnimEvaluator( const aiAnimation* pAnim) +{ + mAnim = pAnim; + mLastTime = 0.0; + mLastPositions.resize( pAnim->mNumChannels, boost::make_tuple( 0, 0, 0)); +} + +// ------------------------------------------------------------------------------------------------ +// Evaluates the animation tracks for a given time stamp. +void AnimEvaluator::Evaluate( double pTime) +{ + // extract ticks per second. Assume default value if not given + double ticksPerSecond = mAnim->mTicksPerSecond != 0.0 ? mAnim->mTicksPerSecond : 25.0; + // every following time calculation happens in ticks + pTime *= ticksPerSecond; + + // map into anim's duration + double time = 0.0f; + if( mAnim->mDuration > 0.0) + time = fmod( pTime, mAnim->mDuration); + + if( mTransforms.size() != mAnim->mNumChannels) + mTransforms.resize( mAnim->mNumChannels); + + // calculate the transformations for each animation channel + for( unsigned int a = 0; a < mAnim->mNumChannels; a++) + { + const aiNodeAnim* channel = mAnim->mChannels[a]; + + // ******** Position ***** + aiVector3D presentPosition( 0, 0, 0); + if( channel->mNumPositionKeys > 0) + { + // Look for present frame number. Search from last position if time is after the last time, else from beginning + // Should be much quicker than always looking from start for the average use case. + unsigned int frame = (time >= mLastTime) ? mLastPositions[a].get<0>() : 0; + while( frame < channel->mNumPositionKeys - 1) + { + if( time < channel->mPositionKeys[frame+1].mTime) + break; + frame++; + } + + // interpolate between this frame's value and next frame's value + unsigned int nextFrame = (frame + 1) % channel->mNumPositionKeys; + const aiVectorKey& key = channel->mPositionKeys[frame]; + const aiVectorKey& nextKey = channel->mPositionKeys[nextFrame]; + double diffTime = nextKey.mTime - key.mTime; + if( diffTime < 0.0) + diffTime += mAnim->mDuration; + if( diffTime > 0) + { + float factor = float( (time - key.mTime) / diffTime); + presentPosition = key.mValue + (nextKey.mValue - key.mValue) * factor; + } else + { + presentPosition = key.mValue; + } + + mLastPositions[a].get<0>() = frame; + } + + // ******** Rotation ********* + aiQuaternion presentRotation( 1, 0, 0, 0); + if( channel->mNumRotationKeys > 0) + { + unsigned int frame = (time >= mLastTime) ? mLastPositions[a].get<1>() : 0; + while( frame < channel->mNumRotationKeys - 1) + { + if( time < channel->mRotationKeys[frame+1].mTime) + break; + frame++; + } + + // interpolate between this frame's value and next frame's value + unsigned int nextFrame = (frame + 1) % channel->mNumRotationKeys; + const aiQuatKey& key = channel->mRotationKeys[frame]; + const aiQuatKey& nextKey = channel->mRotationKeys[nextFrame]; + double diffTime = nextKey.mTime - key.mTime; + if( diffTime < 0.0) + diffTime += mAnim->mDuration; + if( diffTime > 0) + { + float factor = float( (time - key.mTime) / diffTime); + aiQuaternion::Interpolate( presentRotation, key.mValue, nextKey.mValue, factor); + } else + { + presentRotation = key.mValue; + } + + mLastPositions[a].get<1>() = frame; + } + + // ******** Scaling ********** + aiVector3D presentScaling( 1, 1, 1); + if( channel->mNumScalingKeys > 0) + { + unsigned int frame = (time >= mLastTime) ? mLastPositions[a].get<2>() : 0; + while( frame < channel->mNumScalingKeys - 1) + { + if( time < channel->mScalingKeys[frame+1].mTime) + break; + frame++; + } + + // TODO: (thom) interpolation maybe? This time maybe even logarithmic, not linear + presentScaling = channel->mScalingKeys[frame].mValue; + mLastPositions[a].get<2>() = frame; + } + + // build a transformation matrix from it + aiMatrix4x4& mat = mTransforms[a]; + mat = aiMatrix4x4( presentRotation.GetMatrix()); + mat.a1 *= presentScaling.x; mat.b1 *= presentScaling.x; mat.c1 *= presentScaling.x; + mat.a2 *= presentScaling.y; mat.b2 *= presentScaling.y; mat.c2 *= presentScaling.y; + mat.a3 *= presentScaling.z; mat.b3 *= presentScaling.z; mat.c3 *= presentScaling.z; + mat.a4 = presentPosition.x; mat.b4 = presentPosition.y; mat.c4 = presentPosition.z; + //mat.Transpose(); + } + + mLastTime = time; +} diff --git a/tools/assimp_view/AnimEvaluator.h b/tools/assimp_view/AnimEvaluator.h index 825bb7c0f..8e61f07f4 100644 --- a/tools/assimp_view/AnimEvaluator.h +++ b/tools/assimp_view/AnimEvaluator.h @@ -1,91 +1,91 @@ -/** Calculates a pose for a given time of an animation */ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2012, assimp 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 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. ---------------------------------------------------------------------------- -*/ - -#ifndef AV_ANIMEVALUATOR_H_INCLUDED -#define AV_ANIMEVALUATOR_H_INCLUDED - -#include <boost/tuple/tuple.hpp> - -namespace AssimpView -{ - -/** Calculates transformations for a given timestamp from a set of animation tracks. Not directly useful, - * better use the AnimPlayer class. - */ -class AnimEvaluator -{ -public: - /** Constructor on a given animation. The animation is fixed throughout the lifetime of - * the object. - * @param pAnim The animation to calculate poses for. Ownership of the animation object stays - * at the caller, the evaluator just keeps a reference to it as long as it persists. - */ - AnimEvaluator( const aiAnimation* pAnim); - - /** Evaluates the animation tracks for a given time stamp. The calculated pose can be retrieved as a - * array of transformation matrices afterwards by calling GetTransformations(). - * @param pTime The time for which you want to evaluate the animation, in seconds. Will be mapped into the animation cycle, so - * it can be an arbitrary value. Best use with ever-increasing time stamps. - */ - void Evaluate( double pTime); - - /** Returns the transform matrices calculated at the last Evaluate() call. The array matches the mChannels array of - * the aiAnimation. */ - const std::vector<aiMatrix4x4>& GetTransformations() const { return mTransforms; } - -protected: - /** The animation we're working on */ - const aiAnimation* mAnim; - - /** At which frame the last evaluation happened for each channel. - * Useful to quickly find the corresponding frame for slightly increased time stamps - */ - double mLastTime; - std::vector<boost::tuple<unsigned int, unsigned int, unsigned int> > mLastPositions; - - /** The array to store the transformations results of the evaluation */ - std::vector<aiMatrix4x4> mTransforms; -}; - -} // end of namespace AssimpView - -#endif // AV_ANIMEVALUATOR_H_INCLUDED +/** Calculates a pose for a given time of an animation */ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2012, assimp 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 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. +--------------------------------------------------------------------------- +*/ + +#ifndef AV_ANIMEVALUATOR_H_INCLUDED +#define AV_ANIMEVALUATOR_H_INCLUDED + +#include <boost/tuple/tuple.hpp> + +namespace AssimpView +{ + +/** Calculates transformations for a given timestamp from a set of animation tracks. Not directly useful, + * better use the AnimPlayer class. + */ +class AnimEvaluator +{ +public: + /** Constructor on a given animation. The animation is fixed throughout the lifetime of + * the object. + * @param pAnim The animation to calculate poses for. Ownership of the animation object stays + * at the caller, the evaluator just keeps a reference to it as long as it persists. + */ + AnimEvaluator( const aiAnimation* pAnim); + + /** Evaluates the animation tracks for a given time stamp. The calculated pose can be retrieved as a + * array of transformation matrices afterwards by calling GetTransformations(). + * @param pTime The time for which you want to evaluate the animation, in seconds. Will be mapped into the animation cycle, so + * it can be an arbitrary value. Best use with ever-increasing time stamps. + */ + void Evaluate( double pTime); + + /** Returns the transform matrices calculated at the last Evaluate() call. The array matches the mChannels array of + * the aiAnimation. */ + const std::vector<aiMatrix4x4>& GetTransformations() const { return mTransforms; } + +protected: + /** The animation we're working on */ + const aiAnimation* mAnim; + + /** At which frame the last evaluation happened for each channel. + * Useful to quickly find the corresponding frame for slightly increased time stamps + */ + double mLastTime; + std::vector<boost::tuple<unsigned int, unsigned int, unsigned int> > mLastPositions; + + /** The array to store the transformations results of the evaluation */ + std::vector<aiMatrix4x4> mTransforms; +}; + +} // end of namespace AssimpView + +#endif // AV_ANIMEVALUATOR_H_INCLUDED diff --git a/tools/assimp_view/AssetHelper.h b/tools/assimp_view/AssetHelper.h index 94a453ece..390f0c6b9 100644 --- a/tools/assimp_view/AssetHelper.h +++ b/tools/assimp_view/AssetHelper.h @@ -1,246 +1,246 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2012, assimp 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 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 - -#include <d3d9.h> -#include <d3dx9.h> -#include <d3dx9mesh.h> - -#include <assimp/scene.h> - -namespace AssimpView { - - class SceneAnimator; - - //------------------------------------------------------------------------------- - /** \brief Class to wrap ASSIMP's asset output structures - */ - //------------------------------------------------------------------------------- - 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 ) - { - mAnimator = NULL; - apcMeshes = NULL; - pcScene = NULL; - } - - //--------------------------------------------------------------- - // default vertex data structure - // (even if tangents, bitangents or normals aren't - // required by the shader they will be committed to the GPU) - //--------------------------------------------------------------- - struct Vertex - { - aiVector3D vPosition; - aiVector3D vNormal; - - D3DCOLOR dColorDiffuse; - aiVector3D vTangent; - aiVector3D vBitangent; - aiVector2D vTextureUV; - aiVector2D vTextureUV2; - unsigned char mBoneIndices[ 4 ]; - unsigned char mBoneWeights[ 4 ]; // last Weight not used, calculated inside the vertex shader - - /** Returns the vertex declaration elements to create a declaration from. */ - static D3DVERTEXELEMENT9* GetDeclarationElements() - { - static D3DVERTEXELEMENT9 decl[] = - { - { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, - { 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 }, - { 0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 }, - { 0, 28, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0 }, - { 0, 40, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL, 0 }, - { 0, 52, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, - { 0, 60, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 }, - { 0, 68, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDINDICES, 0 }, - { 0, 72, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0 }, - D3DDECL_END() - }; - - return decl; - } - }; - - //--------------------------------------------------------------- - // FVF vertex structure used for normals - //--------------------------------------------------------------- - struct LineVertex - { - aiVector3D vPosition; - DWORD dColorDiffuse; - - // retrieves the FVF code of the vertex type - static DWORD GetFVF() - { - return D3DFVF_DIFFUSE | D3DFVF_XYZ; - } - }; - - //--------------------------------------------------------------- - // Helper class to store GPU related resources created for - // a given aiMesh - //--------------------------------------------------------------- - class MeshHelper - { - public: - - MeshHelper() - : - piVB( NULL ), - piIB( NULL ), - piVBNormals( NULL ), - piEffect( NULL ), - bSharedFX( false ), - piDiffuseTexture( NULL ), - piSpecularTexture( NULL ), - piAmbientTexture( NULL ), - piEmissiveTexture( NULL ), - piNormalTexture( NULL ), - piOpacityTexture( NULL ), - piShininessTexture( NULL ), - piLightmapTexture( NULL ), - twosided( false ), - pvOriginalNormals( NULL ) - {} - - ~MeshHelper() - { - // NOTE: This is done in DeleteAssetData() - // TODO: Make this a proper d'tor - } - - // shading mode to use. Either Lambert or otherwise phong - // will be used in every case - aiShadingMode eShadingMode; - - // vertex buffer - IDirect3DVertexBuffer9* piVB; - - // 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 - // (vertex normals are generated in every case) - IDirect3DVertexBuffer9* piVBNormals; - - // shader to be used - ID3DXEffect* piEffect; - bool bSharedFX; - - // material textures - IDirect3DTexture9* piDiffuseTexture; - IDirect3DTexture9* piSpecularTexture; - IDirect3DTexture9* piAmbientTexture; - IDirect3DTexture9* piEmissiveTexture; - IDirect3DTexture9* piNormalTexture; - IDirect3DTexture9* piOpacityTexture; - IDirect3DTexture9* piShininessTexture; - IDirect3DTexture9* piLightmapTexture; - - // material colors - D3DXVECTOR4 vDiffuseColor; - D3DXVECTOR4 vSpecularColor; - D3DXVECTOR4 vAmbientColor; - D3DXVECTOR4 vEmissiveColor; - - // opacity for the material - float fOpacity; - - // shininess for the material - float fShininess; - - // strength of the specular highlight - float fSpecularStrength; - - // two-sided? - bool twosided; - - // 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 - aiScene* pcScene; - - // Animation player to animate the scene if necessary - SceneAnimator* mAnimator; - - // 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(); - void FlipNormalsInt(); - }; -} - -#endif // !! IG +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2012, assimp 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 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 + +#include <d3d9.h> +#include <d3dx9.h> +#include <d3dx9mesh.h> + +#include <assimp/scene.h> + +namespace AssimpView { + + class SceneAnimator; + + //------------------------------------------------------------------------------- + /** \brief Class to wrap ASSIMP's asset output structures + */ + //------------------------------------------------------------------------------- + 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 ) + { + mAnimator = NULL; + apcMeshes = NULL; + pcScene = NULL; + } + + //--------------------------------------------------------------- + // default vertex data structure + // (even if tangents, bitangents or normals aren't + // required by the shader they will be committed to the GPU) + //--------------------------------------------------------------- + struct Vertex + { + aiVector3D vPosition; + aiVector3D vNormal; + + D3DCOLOR dColorDiffuse; + aiVector3D vTangent; + aiVector3D vBitangent; + aiVector2D vTextureUV; + aiVector2D vTextureUV2; + unsigned char mBoneIndices[ 4 ]; + unsigned char mBoneWeights[ 4 ]; // last Weight not used, calculated inside the vertex shader + + /** Returns the vertex declaration elements to create a declaration from. */ + static D3DVERTEXELEMENT9* GetDeclarationElements() + { + static D3DVERTEXELEMENT9 decl[] = + { + { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, + { 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 }, + { 0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 }, + { 0, 28, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0 }, + { 0, 40, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL, 0 }, + { 0, 52, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, + { 0, 60, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 }, + { 0, 68, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDINDICES, 0 }, + { 0, 72, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0 }, + D3DDECL_END() + }; + + return decl; + } + }; + + //--------------------------------------------------------------- + // FVF vertex structure used for normals + //--------------------------------------------------------------- + struct LineVertex + { + aiVector3D vPosition; + DWORD dColorDiffuse; + + // retrieves the FVF code of the vertex type + static DWORD GetFVF() + { + return D3DFVF_DIFFUSE | D3DFVF_XYZ; + } + }; + + //--------------------------------------------------------------- + // Helper class to store GPU related resources created for + // a given aiMesh + //--------------------------------------------------------------- + class MeshHelper + { + public: + + MeshHelper() + : + piVB( NULL ), + piIB( NULL ), + piVBNormals( NULL ), + piEffect( NULL ), + bSharedFX( false ), + piDiffuseTexture( NULL ), + piSpecularTexture( NULL ), + piAmbientTexture( NULL ), + piEmissiveTexture( NULL ), + piNormalTexture( NULL ), + piOpacityTexture( NULL ), + piShininessTexture( NULL ), + piLightmapTexture( NULL ), + twosided( false ), + pvOriginalNormals( NULL ) + {} + + ~MeshHelper() + { + // NOTE: This is done in DeleteAssetData() + // TODO: Make this a proper d'tor + } + + // shading mode to use. Either Lambert or otherwise phong + // will be used in every case + aiShadingMode eShadingMode; + + // vertex buffer + IDirect3DVertexBuffer9* piVB; + + // 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 + // (vertex normals are generated in every case) + IDirect3DVertexBuffer9* piVBNormals; + + // shader to be used + ID3DXEffect* piEffect; + bool bSharedFX; + + // material textures + IDirect3DTexture9* piDiffuseTexture; + IDirect3DTexture9* piSpecularTexture; + IDirect3DTexture9* piAmbientTexture; + IDirect3DTexture9* piEmissiveTexture; + IDirect3DTexture9* piNormalTexture; + IDirect3DTexture9* piOpacityTexture; + IDirect3DTexture9* piShininessTexture; + IDirect3DTexture9* piLightmapTexture; + + // material colors + D3DXVECTOR4 vDiffuseColor; + D3DXVECTOR4 vSpecularColor; + D3DXVECTOR4 vAmbientColor; + D3DXVECTOR4 vEmissiveColor; + + // opacity for the material + float fOpacity; + + // shininess for the material + float fShininess; + + // strength of the specular highlight + float fSpecularStrength; + + // two-sided? + bool twosided; + + // 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 + aiScene* pcScene; + + // Animation player to animate the scene if necessary + SceneAnimator* mAnimator; + + // 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(); + void FlipNormalsInt(); + }; +} + +#endif // !! IG diff --git a/tools/assimp_view/Background.cpp b/tools/assimp_view/Background.cpp index a790460d2..27f2f1546 100644 --- a/tools/assimp_view/Background.cpp +++ b/tools/assimp_view/Background.cpp @@ -1,470 +1,470 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2015, assimp 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 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 "assimp_view.h" - -namespace AssimpView { - -extern std::string g_szSkyboxShader; - -// 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; -}; - - -// ------------------------------------------------------------------------------ -/** \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 - { 1.0f,-1.0f,-1.0f, 1.0f,-1.0f,-1.0f }, // 3 - {-1.0f, 1.0f, 1.0f, -1.0f,1.0f,1.0f }, // 4 - {-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 == eMode) - RemoveSBDeps(); - - clrColor = p_clrNew; - eMode = SIMPLE_COLOR; - - if (pcTexture) - { - pcTexture->Release(); - pcTexture = NULL; - } -} -//------------------------------------------------------------------------------- -void CBackgroundPainter::RemoveSBDeps() -{ - MODE e = eMode; - 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) - { - CMaterialManager::Instance().DeleteMaterial(g_pcAsset->apcMeshes[i]); - CMaterialManager::Instance().CreateMaterial( - g_pcAsset->apcMeshes[i],g_pcAsset->pcScene->mMeshes[i]); - } - } - } - eMode = e; -} -//------------------------------------------------------------------------------- -void CBackgroundPainter::ResetSB() -{ - mMatrix = aiMatrix4x4(); -} -//------------------------------------------------------------------------------- -void CBackgroundPainter::SetCubeMapBG (const char* p_szPath) -{ - bool bHad = false; - if (pcTexture) - { - pcTexture->Release(); - pcTexture = NULL; - if(TEXTURE_CUBE ==eMode)bHad = true; - } - - eMode = TEXTURE_CUBE; - - szPath = std::string( p_szPath ); - - // ARRRGHH... ugly. TODO: Rewrite this! - aiString sz; - sz.Set(szPath); - CMaterialManager::Instance().FindValidPath(&sz); - szPath = std::string( sz.data ); - - // now recreate all native resources - 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) - { - 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 = mMatrix * (*pm); -} -//------------------------------------------------------------------------------- -void CBackgroundPainter::SetTextureBG (const char* p_szPath) -{ - if (TEXTURE_CUBE == this->eMode)this->RemoveSBDeps(); - - if (pcTexture) - { - pcTexture->Release(); - pcTexture = NULL; - } - - eMode = TEXTURE_2D; - szPath = std::string( p_szPath ); - - // ARRRGHH... ugly. TODO: Rewrite this! - aiString sz; - sz.Set(szPath); - CMaterialManager::Instance().FindValidPath(&sz); - szPath = std::string( sz.data ); - - // now recreate all native resources - RecreateNativeResource(); -} -//------------------------------------------------------------------------------- -void CBackgroundPainter::OnPreRender() -{ - if (SIMPLE_COLOR != 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 == 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); - this->piSkyBoxEffect->BeginPass(0); - - SVertex as[4]; - as[1].x = 0.0f; - as[1].y = 0.0f; - 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; - as[3].y = 0.0f; - as[3].z = 0.2f; - as[3].w = 1.0f; - as[3].u = 1.0f; - as[3].v = 0.0f; - - as[0].x = 0.0f; - as[0].y = (float)sRect.bottom; - 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; - as[2].y = (float)sRect.bottom; - 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)); - - piSkyBoxEffect->EndPass(); - piSkyBoxEffect->End(); - - g_piDevice->SetFVF(dw2); - } - return; - } - // clear both the render target and the z-buffer - g_piDevice->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, - clrColor,1.0f,0); -} -//------------------------------------------------------------------------------- -void CBackgroundPainter::OnPostRender() -{ - if (TEXTURE_CUBE == eMode) - { - aiMatrix4x4 pcProj; - GetProjectionMatrix(pcProj); - - aiMatrix4x4 pcCam; - aiVector3D vPos = GetCameraMatrix(pcCam); - - aiMatrix4x4 aiMe; - aiMe[3][0] = vPos.x; - aiMe[3][1] = vPos.y; - aiMe[3][2] = vPos.z; - aiMe = mMatrix * aiMe; - - pcProj = (aiMe * pcCam) * pcProj; - - piSkyBoxEffect->SetMatrix("WorldViewProjection", - (const D3DXMATRIX*)&pcProj); - - UINT dwPasses; - piSkyBoxEffect->Begin(&dwPasses,0); - piSkyBoxEffect->BeginPass(0); - - DWORD dw2; - g_piDevice->GetFVF(&dw2); - g_piDevice->SetFVF(D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE3(0)); - - g_piDevice->DrawIndexedPrimitiveUP( - D3DPT_TRIANGLELIST,0,8,12,g_cubeIndices,D3DFMT_INDEX16, - g_cubeVertices_indexed,sizeof(SkyBoxVertex)); - - g_piDevice->SetFVF(dw2); - - piSkyBoxEffect->EndPass(); - piSkyBoxEffect->End(); - } -} -//------------------------------------------------------------------------------- -void CBackgroundPainter::ReleaseNativeResource() -{ - if ( piSkyBoxEffect) - { - piSkyBoxEffect->Release(); - piSkyBoxEffect = NULL; - } - if (pcTexture) - { - pcTexture->Release(); - pcTexture = NULL; - } -} -//------------------------------------------------------------------------------- -void CBackgroundPainter::RecreateNativeResource() -{ - if (SIMPLE_COLOR == eMode)return; - if (TEXTURE_CUBE == eMode) - { - - // many skyboxes are 16bit FP format which isn't supported - // with bilinear filtering on older cards - D3DFORMAT eFmt = D3DFMT_UNKNOWN; - if(FAILED(g_piD3D->CheckDeviceFormat(0,D3DDEVTYPE_HAL, - D3DFMT_X8R8G8B8,D3DUSAGE_QUERY_FILTER,D3DRTYPE_CUBETEXTURE,D3DFMT_A16B16G16R16F))) - { - eFmt = D3DFMT_A8R8G8B8; - } - - if (FAILED(D3DXCreateCubeTextureFromFileEx( - g_piDevice, - szPath.c_str(), - D3DX_DEFAULT, - 0, - 0, - eFmt, - D3DPOOL_MANAGED, - D3DX_DEFAULT, - D3DX_DEFAULT, - 0, - NULL, - NULL, - (IDirect3DCubeTexture9**)&pcTexture))) - { - const char* szEnd = strrchr(szPath.c_str(),'\\'); - if (!szEnd)szEnd = strrchr(szPath.c_str(),'/'); - if (!szEnd)szEnd = 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)); - - 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, - szPath.c_str(), - D3DX_DEFAULT, - D3DX_DEFAULT, - 0, - 0, - D3DFMT_A8R8G8B8, - D3DPOOL_MANAGED, - D3DX_DEFAULT, - D3DX_DEFAULT, - 0, - NULL, - NULL, - (IDirect3DTexture9**)&pcTexture))) - { - const char* szEnd = strrchr(szPath.c_str(),'\\'); - if (!szEnd)szEnd = strrchr(szPath.c_str(),'/'); - if (!szEnd)szEnd = 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)); - - eMode = SIMPLE_COLOR; - return; - } - else CLogDisplay::Instance().AddEntry("[OK] The background texture has been imported successfully", - D3DCOLOR_ARGB(0xFF,0,0xFF,0)); - } - if (!piSkyBoxEffect) - { - ID3DXBuffer* piBuffer = NULL; - if(FAILED( D3DXCreateEffect( - g_piDevice, - g_szSkyboxShader.c_str(), - (UINT)g_szSkyboxShader.length(), - NULL, - NULL, - AI_SHADER_COMPILE_FLAGS, - NULL, - &piSkyBoxEffect,&piBuffer))) - { - // failed to compile the shader - if( piBuffer) { - MessageBox(g_hDlg,(LPCSTR)piBuffer->GetBufferPointer(),"HLSL",MB_OK); - piBuffer->Release(); - } - - CLogDisplay::Instance().AddEntry("[ERROR] Unable to compile skybox shader", - D3DCOLOR_ARGB(0xFF,0xFF,0,0)); - eMode = SIMPLE_COLOR; - return ; - } - } - // commit the correct textures to the shader - if (TEXTURE_CUBE == eMode) - { - piSkyBoxEffect->SetTexture("lw_tex_envmap",pcTexture); - piSkyBoxEffect->SetTechnique("RenderSkyBox"); - } - else if (TEXTURE_2D == eMode) - { - piSkyBoxEffect->SetTexture("TEXTURE_2D",pcTexture); - piSkyBoxEffect->SetTechnique("RenderImage2D"); - } -} +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2015, assimp 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 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 "assimp_view.h" + +namespace AssimpView { + +extern std::string g_szSkyboxShader; + +// 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; +}; + + +// ------------------------------------------------------------------------------ +/** \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 + { 1.0f,-1.0f,-1.0f, 1.0f,-1.0f,-1.0f }, // 3 + {-1.0f, 1.0f, 1.0f, -1.0f,1.0f,1.0f }, // 4 + {-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 == eMode) + RemoveSBDeps(); + + clrColor = p_clrNew; + eMode = SIMPLE_COLOR; + + if (pcTexture) + { + pcTexture->Release(); + pcTexture = NULL; + } +} +//------------------------------------------------------------------------------- +void CBackgroundPainter::RemoveSBDeps() +{ + MODE e = eMode; + 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) + { + CMaterialManager::Instance().DeleteMaterial(g_pcAsset->apcMeshes[i]); + CMaterialManager::Instance().CreateMaterial( + g_pcAsset->apcMeshes[i],g_pcAsset->pcScene->mMeshes[i]); + } + } + } + eMode = e; +} +//------------------------------------------------------------------------------- +void CBackgroundPainter::ResetSB() +{ + mMatrix = aiMatrix4x4(); +} +//------------------------------------------------------------------------------- +void CBackgroundPainter::SetCubeMapBG (const char* p_szPath) +{ + bool bHad = false; + if (pcTexture) + { + pcTexture->Release(); + pcTexture = NULL; + if(TEXTURE_CUBE ==eMode)bHad = true; + } + + eMode = TEXTURE_CUBE; + + szPath = std::string( p_szPath ); + + // ARRRGHH... ugly. TODO: Rewrite this! + aiString sz; + sz.Set(szPath); + CMaterialManager::Instance().FindValidPath(&sz); + szPath = std::string( sz.data ); + + // now recreate all native resources + 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) + { + 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 = mMatrix * (*pm); +} +//------------------------------------------------------------------------------- +void CBackgroundPainter::SetTextureBG (const char* p_szPath) +{ + if (TEXTURE_CUBE == this->eMode)this->RemoveSBDeps(); + + if (pcTexture) + { + pcTexture->Release(); + pcTexture = NULL; + } + + eMode = TEXTURE_2D; + szPath = std::string( p_szPath ); + + // ARRRGHH... ugly. TODO: Rewrite this! + aiString sz; + sz.Set(szPath); + CMaterialManager::Instance().FindValidPath(&sz); + szPath = std::string( sz.data ); + + // now recreate all native resources + RecreateNativeResource(); +} +//------------------------------------------------------------------------------- +void CBackgroundPainter::OnPreRender() +{ + if (SIMPLE_COLOR != 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 == 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); + this->piSkyBoxEffect->BeginPass(0); + + SVertex as[4]; + as[1].x = 0.0f; + as[1].y = 0.0f; + 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; + as[3].y = 0.0f; + as[3].z = 0.2f; + as[3].w = 1.0f; + as[3].u = 1.0f; + as[3].v = 0.0f; + + as[0].x = 0.0f; + as[0].y = (float)sRect.bottom; + 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; + as[2].y = (float)sRect.bottom; + 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)); + + piSkyBoxEffect->EndPass(); + piSkyBoxEffect->End(); + + g_piDevice->SetFVF(dw2); + } + return; + } + // clear both the render target and the z-buffer + g_piDevice->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, + clrColor,1.0f,0); +} +//------------------------------------------------------------------------------- +void CBackgroundPainter::OnPostRender() +{ + if (TEXTURE_CUBE == eMode) + { + aiMatrix4x4 pcProj; + GetProjectionMatrix(pcProj); + + aiMatrix4x4 pcCam; + aiVector3D vPos = GetCameraMatrix(pcCam); + + aiMatrix4x4 aiMe; + aiMe[3][0] = vPos.x; + aiMe[3][1] = vPos.y; + aiMe[3][2] = vPos.z; + aiMe = mMatrix * aiMe; + + pcProj = (aiMe * pcCam) * pcProj; + + piSkyBoxEffect->SetMatrix("WorldViewProjection", + (const D3DXMATRIX*)&pcProj); + + UINT dwPasses; + piSkyBoxEffect->Begin(&dwPasses,0); + piSkyBoxEffect->BeginPass(0); + + DWORD dw2; + g_piDevice->GetFVF(&dw2); + g_piDevice->SetFVF(D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE3(0)); + + g_piDevice->DrawIndexedPrimitiveUP( + D3DPT_TRIANGLELIST,0,8,12,g_cubeIndices,D3DFMT_INDEX16, + g_cubeVertices_indexed,sizeof(SkyBoxVertex)); + + g_piDevice->SetFVF(dw2); + + piSkyBoxEffect->EndPass(); + piSkyBoxEffect->End(); + } +} +//------------------------------------------------------------------------------- +void CBackgroundPainter::ReleaseNativeResource() +{ + if ( piSkyBoxEffect) + { + piSkyBoxEffect->Release(); + piSkyBoxEffect = NULL; + } + if (pcTexture) + { + pcTexture->Release(); + pcTexture = NULL; + } +} +//------------------------------------------------------------------------------- +void CBackgroundPainter::RecreateNativeResource() +{ + if (SIMPLE_COLOR == eMode)return; + if (TEXTURE_CUBE == eMode) + { + + // many skyboxes are 16bit FP format which isn't supported + // with bilinear filtering on older cards + D3DFORMAT eFmt = D3DFMT_UNKNOWN; + if(FAILED(g_piD3D->CheckDeviceFormat(0,D3DDEVTYPE_HAL, + D3DFMT_X8R8G8B8,D3DUSAGE_QUERY_FILTER,D3DRTYPE_CUBETEXTURE,D3DFMT_A16B16G16R16F))) + { + eFmt = D3DFMT_A8R8G8B8; + } + + if (FAILED(D3DXCreateCubeTextureFromFileEx( + g_piDevice, + szPath.c_str(), + D3DX_DEFAULT, + 0, + 0, + eFmt, + D3DPOOL_MANAGED, + D3DX_DEFAULT, + D3DX_DEFAULT, + 0, + NULL, + NULL, + (IDirect3DCubeTexture9**)&pcTexture))) + { + const char* szEnd = strrchr(szPath.c_str(),'\\'); + if (!szEnd)szEnd = strrchr(szPath.c_str(),'/'); + if (!szEnd)szEnd = 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)); + + 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, + szPath.c_str(), + D3DX_DEFAULT, + D3DX_DEFAULT, + 0, + 0, + D3DFMT_A8R8G8B8, + D3DPOOL_MANAGED, + D3DX_DEFAULT, + D3DX_DEFAULT, + 0, + NULL, + NULL, + (IDirect3DTexture9**)&pcTexture))) + { + const char* szEnd = strrchr(szPath.c_str(),'\\'); + if (!szEnd)szEnd = strrchr(szPath.c_str(),'/'); + if (!szEnd)szEnd = 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)); + + eMode = SIMPLE_COLOR; + return; + } + else CLogDisplay::Instance().AddEntry("[OK] The background texture has been imported successfully", + D3DCOLOR_ARGB(0xFF,0,0xFF,0)); + } + if (!piSkyBoxEffect) + { + ID3DXBuffer* piBuffer = NULL; + if(FAILED( D3DXCreateEffect( + g_piDevice, + g_szSkyboxShader.c_str(), + (UINT)g_szSkyboxShader.length(), + NULL, + NULL, + AI_SHADER_COMPILE_FLAGS, + NULL, + &piSkyBoxEffect,&piBuffer))) + { + // failed to compile the shader + if( piBuffer) { + MessageBox(g_hDlg,(LPCSTR)piBuffer->GetBufferPointer(),"HLSL",MB_OK); + piBuffer->Release(); + } + + CLogDisplay::Instance().AddEntry("[ERROR] Unable to compile skybox shader", + D3DCOLOR_ARGB(0xFF,0xFF,0,0)); + eMode = SIMPLE_COLOR; + return ; + } + } + // commit the correct textures to the shader + if (TEXTURE_CUBE == eMode) + { + piSkyBoxEffect->SetTexture("lw_tex_envmap",pcTexture); + piSkyBoxEffect->SetTechnique("RenderSkyBox"); + } + else if (TEXTURE_2D == eMode) + { + piSkyBoxEffect->SetTexture("TEXTURE_2D",pcTexture); + piSkyBoxEffect->SetTechnique("RenderImage2D"); + } +} }; \ No newline at end of file diff --git a/tools/assimp_view/Background.h b/tools/assimp_view/Background.h index 0edc240a2..54b21676f 100644 --- a/tools/assimp_view/Background.h +++ b/tools/assimp_view/Background.h @@ -1,128 +1,128 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2015, assimp 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 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. ---------------------------------------------------------------------------- -*/ -#pragma once - -namespace AssimpView -{ - - class CBackgroundPainter - { - CBackgroundPainter() - : - clrColor( D3DCOLOR_ARGB( 0xFF, 100, 100, 100 ) ), - pcTexture( NULL ), - piSkyBoxEffect( NULL ), - eMode( SIMPLE_COLOR ) - {} - - public: - - // Supported background draw modi - enum MODE { SIMPLE_COLOR, TEXTURE_2D, TEXTURE_CUBE }; - - // Singleton accessors - static CBackgroundPainter s_cInstance; - inline static CBackgroundPainter& Instance() - { - return s_cInstance; - } - - // set the current background color - // (this removes any textures loaded) - void SetColor( D3DCOLOR p_clrNew ); - - // Setup a cubemap/a 2d texture as background - void SetCubeMapBG( const char* p_szPath ); - void SetTextureBG( const char* p_szPath ); - - // Called by the render loop - void OnPreRender(); - void OnPostRender(); - - // Release any native resources associated with the instance - void ReleaseNativeResource(); - - // Recreate any native resources associated with the instance - void RecreateNativeResource(); - - // Rotate the skybox - void RotateSB( const aiMatrix4x4* pm ); - - // Reset the state of the skybox - void ResetSB(); - - inline MODE GetMode() const - { - return this->eMode; - } - - inline IDirect3DBaseTexture9* GetTexture() - { - return this->pcTexture; - } - - inline ID3DXBaseEffect* GetEffect() - { - return this->piSkyBoxEffect; - } - - private: - - void RemoveSBDeps(); - - // current background color - D3DCOLOR clrColor; - - // current background texture - IDirect3DBaseTexture9* pcTexture; - ID3DXEffect* piSkyBoxEffect; - - // current background mode - MODE eMode; - - // path to the texture - std::string szPath; - - // transformation matrix for the skybox - aiMatrix4x4 mMatrix; - }; - -} +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2015, assimp 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 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. +--------------------------------------------------------------------------- +*/ +#pragma once + +namespace AssimpView +{ + + class CBackgroundPainter + { + CBackgroundPainter() + : + clrColor( D3DCOLOR_ARGB( 0xFF, 100, 100, 100 ) ), + pcTexture( NULL ), + piSkyBoxEffect( NULL ), + eMode( SIMPLE_COLOR ) + {} + + public: + + // Supported background draw modi + enum MODE { SIMPLE_COLOR, TEXTURE_2D, TEXTURE_CUBE }; + + // Singleton accessors + static CBackgroundPainter s_cInstance; + inline static CBackgroundPainter& Instance() + { + return s_cInstance; + } + + // set the current background color + // (this removes any textures loaded) + void SetColor( D3DCOLOR p_clrNew ); + + // Setup a cubemap/a 2d texture as background + void SetCubeMapBG( const char* p_szPath ); + void SetTextureBG( const char* p_szPath ); + + // Called by the render loop + void OnPreRender(); + void OnPostRender(); + + // Release any native resources associated with the instance + void ReleaseNativeResource(); + + // Recreate any native resources associated with the instance + void RecreateNativeResource(); + + // Rotate the skybox + void RotateSB( const aiMatrix4x4* pm ); + + // Reset the state of the skybox + void ResetSB(); + + inline MODE GetMode() const + { + return this->eMode; + } + + inline IDirect3DBaseTexture9* GetTexture() + { + return this->pcTexture; + } + + inline ID3DXBaseEffect* GetEffect() + { + return this->piSkyBoxEffect; + } + + private: + + void RemoveSBDeps(); + + // current background color + D3DCOLOR clrColor; + + // current background texture + IDirect3DBaseTexture9* pcTexture; + ID3DXEffect* piSkyBoxEffect; + + // current background mode + MODE eMode; + + // path to the texture + std::string szPath; + + // transformation matrix for the skybox + aiMatrix4x4 mMatrix; + }; + +} diff --git a/tools/assimp_view/Camera.h b/tools/assimp_view/Camera.h index 264ab19cb..fa9308ed5 100644 --- a/tools/assimp_view/Camera.h +++ b/tools/assimp_view/Camera.h @@ -1,85 +1,85 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2012, assimp 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 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_CAMERA_H_INCLUDED) -#define AV_CAMERA_H_INCLUDED - -//------------------------------------------------------------------------------- -/** \brief Camera class -*/ -//------------------------------------------------------------------------------- -class Camera - { - public: - - - Camera () - : - - vPos(0.0f,0.0f,-10.0f), - vUp(0.0f,1.0f,0.0f), - vLookAt(0.0f,0.0f,1.0f), - vRight(0.0f,1.0f,0.0f) - { - - } - public: - - // position of the camera - aiVector3D vPos; - - // up-vector of the camera - aiVector3D vUp; - - // camera's looking point is vPos + vLookAt - aiVector3D vLookAt; - - // right vector of the camera - aiVector3D vRight; - - - // Equation - // (vRight ^ vUp) - vLookAt == 0 - // needn't apply - - } ; - +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2012, assimp 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 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_CAMERA_H_INCLUDED) +#define AV_CAMERA_H_INCLUDED + +//------------------------------------------------------------------------------- +/** \brief Camera class +*/ +//------------------------------------------------------------------------------- +class Camera + { + public: + + + Camera () + : + + vPos(0.0f,0.0f,-10.0f), + vUp(0.0f,1.0f,0.0f), + vLookAt(0.0f,0.0f,1.0f), + vRight(0.0f,1.0f,0.0f) + { + + } + public: + + // position of the camera + aiVector3D vPos; + + // up-vector of the camera + aiVector3D vUp; + + // camera's looking point is vPos + vLookAt + aiVector3D vLookAt; + + // right vector of the camera + aiVector3D vRight; + + + // Equation + // (vRight ^ vUp) - vLookAt == 0 + // needn't apply + + } ; + #endif // !!IG \ No newline at end of file diff --git a/tools/assimp_view/Display.cpp b/tools/assimp_view/Display.cpp index 9ea08819a..a1d113aea 100644 --- a/tools/assimp_view/Display.cpp +++ b/tools/assimp_view/Display.cpp @@ -1,2292 +1,2292 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2015, assimp 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 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 "assimp_view.h" -#include "AnimEvaluator.h" -#include "SceneAnimator.h" - -namespace AssimpView { - -using namespace Assimp; - -extern std::string g_szCheckerBackgroundShader; - -struct SVertex -{ - float x,y,z,w,u,v; -}; - -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::EnableAnimTools(BOOL hm) -{ - EnableWindow(GetDlgItem(g_hDlg,IDC_PLAY),hm); - EnableWindow(GetDlgItem(g_hDlg,IDC_SLIDERANIM),hm); - return 1; -} - -//------------------------------------------------------------------------------- -// Fill animation combo box -int CDisplay::FillAnimList(void) -{ - if (0 != g_pcAsset->pcScene->mNumAnimations) - { - // 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); - } - - // also add a dummy - 'none' - SendDlgItemMessage(g_hDlg,IDC_COMBO1,CB_ADDSTRING,0,(LPARAM)"none"); - - // select first - SendDlgItemMessage(g_hDlg,IDC_COMBO1,CB_SETCURSEL,0,0); - - EnableAnimTools(TRUE); - } - else // tools remain disabled - EnableAnimTools(FALSE); - - return 1; -} -//------------------------------------------------------------------------------- -// Clear the list of animations -int CDisplay::ClearAnimList(void) -{ - // clear the combo box - SendDlgItemMessage(g_hDlg,IDC_COMBO1,CB_RESETCONTENT,0,0); - return 1; -} -//------------------------------------------------------------------------------- -// Clear the tree view -int CDisplay::ClearDisplayList(void) -{ - // clear the combo box - TreeView_DeleteAllItems(GetDlgItem(g_hDlg,IDC_TREE1)); - this->Reset(); - return 1; -} -//------------------------------------------------------------------------------- -// Add a specific node to the display list -int CDisplay::AddNodeToDisplayList( - unsigned int iIndex, - unsigned int iDepth, - aiNode* pcNode, - HTREEITEM hRoot) -{ - ai_assert(NULL != pcNode); - ai_assert(NULL != hRoot); - - char chTemp[MAXLEN]; - - 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 { - sprintf(chTemp,"%s",pcNode->mName.data); - } - sprintf(chTemp+strlen(chTemp), iIndex ? " (%i)" : " (%i meshes)",pcNode->mNumMeshes); - - TVITEMEXW tvi; - TVINSERTSTRUCTW sNew; - - wchar_t tmp[512]; - int t = MultiByteToWideChar(CP_UTF8,0,chTemp,-1,tmp,512); - - tvi.pszText = tmp; - tvi.cchTextMax = (int)t; - - 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_INSERTITEMW, - 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::AddMeshToDisplayList(unsigned int iIndex, HTREEITEM hRoot) -{ - aiMesh* pcMesh = g_pcAsset->pcScene->mMeshes[iIndex]; - - char chTemp[MAXLEN]; - - if(0 == pcMesh->mName.length) { - sprintf(chTemp,"Mesh %i",iIndex); - } - else { - sprintf(chTemp,"%s",pcMesh->mName.data); - } - sprintf(chTemp+strlen(chTemp), iIndex ? " (%i)" : " (%i faces)",pcMesh->mNumFaces); - - TVITEMEXW tvi; - TVINSERTSTRUCTW sNew; - - wchar_t tmp[512]; - int t = MultiByteToWideChar(CP_UTF8,0,chTemp,-1,tmp,512); - - tvi.pszText = tmp; - tvi.cchTextMax = (int)t; - - 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_INSERTITEMW, - 0, - (LPARAM)(LPTVINSERTSTRUCT)&sNew); - - // add the mesh to the list of all mesh entries in the scene browser - MeshInfo info; - info.hTreeItem = hTexture; - info.psMesh = pcMesh; - AddMesh(info); - return 1; -} - -//------------------------------------------------------------------------------- -// Replace the currently selected texture by another one -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 = m_aiImageList[AI_VIEW_IMGLIST_MATERIAL]; - tvi.iSelectedImage = m_aiImageList[AI_VIEW_IMGLIST_MATERIAL]; - - TreeView_SetItem(GetDlgItem(g_hDlg,IDC_TREE1), - m_pcCurrentTexture->hTreeItem); - - // update all meshes referencing this material - 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]; - IDirect3DTexture9** tex = NULL; - const char* tex_string = NULL; - - switch (this->m_pcCurrentTexture->iType) - { - case aiTextureType_DIFFUSE: - tex = &pcMesh->piDiffuseTexture; - tex_string = "DIFFUSE_TEXTURE"; - break; - case aiTextureType_AMBIENT: - tex = &pcMesh->piAmbientTexture; - tex_string = "AMBIENT_TEXTURE"; - break; - case aiTextureType_SPECULAR: - tex = &pcMesh->piSpecularTexture; - tex_string = "SPECULAR_TEXTURE"; - break; - case aiTextureType_EMISSIVE: - tex = &pcMesh->piEmissiveTexture; - tex_string = "EMISSIVE_TEXTURE"; - break; - case aiTextureType_LIGHTMAP: - tex = &pcMesh->piLightmapTexture; - tex_string = "LIGHTMAP_TEXTURE"; - break; - case aiTextureType_DISPLACEMENT: - case aiTextureType_REFLECTION: - case aiTextureType_UNKNOWN: - break; - case aiTextureType_SHININESS: - tex = &pcMesh->piShininessTexture; - tex_string = "SHININESS_TEXTURE"; - break; - case aiTextureType_NORMALS: - case aiTextureType_HEIGHT: - - // special handling here - if (pcMesh->piNormalTexture && pcMesh->piNormalTexture != piTexture) { - piTexture->AddRef(); - pcMesh->piNormalTexture->Release(); - pcMesh->piNormalTexture = piTexture; - CMaterialManager::Instance().HMtoNMIfNecessary(pcMesh->piNormalTexture,&pcMesh->piNormalTexture,true); - m_pcCurrentTexture->piTexture = &pcMesh->piNormalTexture; - - if (!pcMesh->bSharedFX) { - pcMesh->piEffect->SetTexture("NORMAL_TEXTURE",piTexture); - } - } - break; - default: //case aiTextureType_OPACITY && case aiTextureType_OPACITY | 0x40000000: - - tex = &pcMesh->piOpacityTexture; - tex_string = "OPACITY_TEXTURE"; - break; - }; - if (tex && *tex && *tex != piTexture) - { - (**tex).Release(); - *tex = piTexture; - m_pcCurrentTexture->piTexture = tex; - - //if (!pcMesh->bSharedFX){ - pcMesh->piEffect->SetTexture(tex_string,piTexture); - //} - } - } - - 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); - - 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 aiTextureType_DIFFUSE: - piTexture = &g_pcAsset->apcMeshes[iMesh]->piDiffuseTexture; - szType = "Diffuse"; - break; - case aiTextureType_SPECULAR: - piTexture = &g_pcAsset->apcMeshes[iMesh]->piSpecularTexture; - szType = "Specular"; - break; - case aiTextureType_AMBIENT: - piTexture = &g_pcAsset->apcMeshes[iMesh]->piAmbientTexture; - szType = "Ambient"; - break; - case aiTextureType_EMISSIVE: - piTexture = &g_pcAsset->apcMeshes[iMesh]->piEmissiveTexture; - szType = "Emissive"; - break; - case aiTextureType_HEIGHT: - piTexture = &g_pcAsset->apcMeshes[iMesh]->piNormalTexture; - szType = "Heightmap"; - break; - case aiTextureType_NORMALS: - piTexture = &g_pcAsset->apcMeshes[iMesh]->piNormalTexture; - szType = "Normalmap"; - break; - case aiTextureType_SHININESS: - piTexture = &g_pcAsset->apcMeshes[iMesh]->piShininessTexture; - szType = "Shininess"; - break; - case aiTextureType_LIGHTMAP: - piTexture = &g_pcAsset->apcMeshes[iMesh]->piLightmapTexture; - szType = "Lightmap"; - break; - case aiTextureType_DISPLACEMENT: - piTexture = NULL; - szType = "Displacement"; - break; - case aiTextureType_REFLECTION: - piTexture = NULL; - szType = "Reflection"; - break; - case aiTextureType_UNKNOWN: - piTexture = NULL; - szType = "Unknown"; - break; - default: // opacity + opacity | mask - piTexture = &g_pcAsset->apcMeshes[iMesh]->piOpacityTexture; - szType = "Opacity"; - break; - }; - if (bIsExtraOpacity) { - sprintf(chTemp,"%s %i (<copy of diffuse #1>)",szType,iIndex+1); - } - else - sprintf(chTemp,"%s %i (%s)",szType,iIndex+1,sz); - - TVITEMEX tvi; - TVINSERTSTRUCT sNew; - tvi.pszText = chTemp; - tvi.cchTextMax = (int)strlen(chTemp); - tvi.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_HANDLE | TVIF_HANDLE; - tvi.lParam = (LPARAM)20; - - // find out whether this is the default texture or not - - if (piTexture && *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 = m_aiImageList[AI_VIEW_IMGLIST_TEXTURE_INVALID]; - tvi.iSelectedImage = m_aiImageList[AI_VIEW_IMGLIST_TEXTURE_INVALID]; - } - else - { - tvi.iImage = m_aiImageList[AI_VIEW_IMGLIST_TEXTURE]; - tvi.iSelectedImage = m_aiImageList[AI_VIEW_IMGLIST_TEXTURE]; - } - } - else - { - tvi.iImage = m_aiImageList[AI_VIEW_IMGLIST_TEXTURE_INVALID]; - tvi.iSelectedImage = 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; - 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); - } - TVITEMEXW tvi; - TVINSERTSTRUCTW sNew; - - wchar_t tmp[512]; - int t = MultiByteToWideChar(CP_UTF8,0,chTemp,-1,tmp,512); - - tvi.pszText = tmp; - tvi.cchTextMax = (int)t; - tvi.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_HANDLE | TVIF_PARAM ; - tvi.iImage = m_aiImageList[AI_VIEW_IMGLIST_MATERIAL]; - tvi.iSelectedImage = 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_INSERTITEMW, - 0, - (LPARAM)(LPTVINSERTSTRUCT)&sNew); - - // for each texture in the list ... add it - unsigned int iUV; - float fBlend; - aiTextureOp eOp; - aiString szPath; - bool bNoOpacity = true; - for (unsigned int i = 0; i <= AI_TEXTURE_TYPE_MAX;++i) - { - unsigned int iNum = 0; - while (true) - { - if (AI_SUCCESS != aiGetMaterialTexture(pcMat,(aiTextureType)i,iNum, - &szPath,NULL, &iUV,&fBlend,&eOp)) - { - break; - } - if (aiTextureType_OPACITY == i)bNoOpacity = false; - AddTextureToDisplayList(i,iNum,&szPath,hTexture,iUV,fBlend,eOp,iMesh); - ++iNum; - } - } - - AssetHelper::MeshHelper* pcMesh = g_pcAsset->apcMeshes[iMesh]; - - if (pcMesh->piDiffuseTexture && pcMesh->piDiffuseTexture == pcMesh->piOpacityTexture && bNoOpacity) - { - // check whether the diffuse texture is not a default texture - - // {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; - if(FAILED( pcMesh->piDiffuseTexture->GetPrivateData(guidPrivateData,&iData,&dwSize) || - 0xffffffff == iData)) - { - // seems the diffuse texture contains alpha, therefore it has been - // added to the opacity channel, too. Add a special value ... - AddTextureToDisplayList(aiTextureType_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; -} -//------------------------------------------------------------------------------- -// Expand all elements in the treeview -int CDisplay::ExpandTree() -{ - // expand all materials - for (std::vector< MaterialInfo >::iterator - i = m_asMaterials.begin(); - i != m_asMaterials.end();++i) - { - TreeView_Expand(GetDlgItem(g_hDlg,IDC_TREE1),(*i).hTreeItem,TVE_EXPAND); - } - // expand all nodes - for (std::vector< NodeInfo >::iterator - i = m_asNodes.begin(); - i != m_asNodes.end();++i) - { - TreeView_Expand(GetDlgItem(g_hDlg,IDC_TREE1),(*i).hTreeItem,TVE_EXPAND); - } - TreeView_Expand(GetDlgItem(g_hDlg,IDC_TREE1),m_hRoot,TVE_EXPAND); - return 1; -} -//------------------------------------------------------------------------------- -// Get image list for tree view -int CDisplay::LoadImageList(void) -{ - if (!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)); - m_aiImageList[AI_VIEW_IMGLIST_MATERIAL] = ImageList_Add(hIml, hBmp, NULL); - DeleteObject(hBmp); - - hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BNODE)); - m_aiImageList[AI_VIEW_IMGLIST_NODE] = ImageList_Add(hIml, hBmp, NULL); - DeleteObject(hBmp); - - hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BTX)); - m_aiImageList[AI_VIEW_IMGLIST_TEXTURE] = ImageList_Add(hIml, hBmp, NULL); - DeleteObject(hBmp); - - hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BTXI)); - m_aiImageList[AI_VIEW_IMGLIST_TEXTURE_INVALID] = ImageList_Add(hIml, hBmp, NULL); - DeleteObject(hBmp); - - hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BROOT)); - 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); - - m_hImageList = hIml; - } - return 1; -} -//------------------------------------------------------------------------------- -// Fill tree view -int CDisplay::FillDisplayList(void) -{ - LoadImageList(); - - // Initialize the tree view window. - // fill in the first entry - TVITEMEX tvi; - TVINSERTSTRUCT sNew; - tvi.pszText = (char*) "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 = m_aiImageList[AI_VIEW_IMGLIST_MODEL]; - tvi.iSelectedImage = 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 - 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(m_hRoot,i); - - // add each mesh to the tree - for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) - AddMeshToDisplayList(i,m_hRoot); - - // now add all loaded nodes recursively - AddNodeToDisplayList(0,0,g_pcAsset->pcScene->mRootNode,m_hRoot); - - // now expand all parent nodes in the tree - 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; -} -//------------------------------------------------------------------------------- -// Main render loop -int CDisplay::OnRender() -{ - // update possible animation - if( g_pcAsset) - { - static double lastPlaying = 0.; - - ai_assert( g_pcAsset->mAnimator); - if (g_bPlay) { - g_dCurrent += clock()/ double( CLOCKS_PER_SEC) -lastPlaying; - - double time = g_dCurrent; - aiAnimation* mAnim = g_pcAsset->mAnimator->CurrentAnim(); - if( mAnim && mAnim->mDuration > 0.0) { - double tps = mAnim->mTicksPerSecond ? mAnim->mTicksPerSecond : 25.f; - time = fmod( time, mAnim->mDuration/tps); - SendDlgItemMessage(g_hDlg,IDC_SLIDERANIM,TBM_SETPOS,TRUE,LPARAM(10000 * (time/(mAnim->mDuration/tps)))); - } - - g_pcAsset->mAnimator->Calculate( time ); - lastPlaying = g_dCurrent; - } - } - // begin the frame - g_piDevice->BeginScene(); - - switch (m_iViewMode) - { - case VIEWMODE_FULL: - case VIEWMODE_NODE: - RenderFullScene(); - break; - case VIEWMODE_MATERIAL: - RenderMaterialView(); - break; - case VIEWMODE_TEXTURE: - 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; -} -//------------------------------------------------------------------------------- -// Update UI -void UpdateColorFieldsInUI() -{ - InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR1),NULL,TRUE); - InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR2),NULL,TRUE); - InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR3),NULL,TRUE); - - UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR1)); - UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR2)); - UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR3)); -} -//------------------------------------------------------------------------------- -// FIll statistics UI -int CDisplay::FillDefaultStatistics(void) -{ - if (!g_pcAsset) - { - // clear all stats edit controls - SetDlgItemText(g_hDlg,IDC_EVERT,"0"); - SetDlgItemText(g_hDlg,IDC_EFACE,"0"); - SetDlgItemText(g_hDlg,IDC_EMAT,"0"); - SetDlgItemText(g_hDlg,IDC_ENODE,"0"); - SetDlgItemText(g_hDlg,IDC_ESHADER,"0"); - SetDlgItemText(g_hDlg,IDC_ETEX,"0"); - return 1; - } - - // 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); - - UpdateColorFieldsInUI(); - UpdateWindow(g_hDlg); - return 1; -} -//------------------------------------------------------------------------------- -// Reset UI -int CDisplay::Reset(void) -{ - // clear all lists - m_asMaterials.clear(); - m_asTextures.clear(); - m_asNodes.clear(); - m_asMeshes.clear(); - - m_hRoot = NULL; - - return OnSetupNormalView(); -} -//------------------------------------------------------------------------------- -// reset to standard statistics view -void ShowNormalUIComponents() -{ - ShowWindow(GetDlgItem(g_hDlg,IDC_NUMNODES),SW_SHOW); - ShowWindow(GetDlgItem(g_hDlg,IDC_ENODEWND),SW_SHOW); - ShowWindow(GetDlgItem(g_hDlg,IDC_NUMSHADERS),SW_SHOW); - ShowWindow(GetDlgItem(g_hDlg,IDC_LOADTIME),SW_SHOW); - ShowWindow(GetDlgItem(g_hDlg,IDC_ESHADER),SW_SHOW); - ShowWindow(GetDlgItem(g_hDlg,IDC_ELOAD),SW_SHOW); - ShowWindow(GetDlgItem(g_hDlg,IDC_VIEWMATRIX),SW_HIDE); -} -//------------------------------------------------------------------------------- -int CDisplay::OnSetupNormalView() -{ - if (VIEWMODE_NODE == m_iViewMode) - { - ShowNormalUIComponents(); - } - - // now ... change the meaning of the statistics fields back - SetWindowText(GetDlgItem(g_hDlg,IDC_NUMVERTS),"Vertices:"); - SetWindowText(GetDlgItem(g_hDlg,IDC_NUMNODES),"Nodes:"); - SetWindowText(GetDlgItem(g_hDlg,IDC_NUMFACES),"Faces:"); - SetWindowText(GetDlgItem(g_hDlg,IDC_NUMSHADERS),"Shaders:"); - SetWindowText(GetDlgItem(g_hDlg,IDC_NUMMATS),"Materials:"); - SetWindowText(GetDlgItem(g_hDlg,IDC_NUMMESHES),"Meshes:"); - SetWindowText(GetDlgItem(g_hDlg,IDC_LOADTIME),"Time:"); - - FillDefaultStatistics(); - SetViewMode(VIEWMODE_FULL); - - // for debugging - m_pcCurrentMaterial = NULL; - m_pcCurrentTexture = NULL; - m_pcCurrentNode = NULL; - - // redraw the color fields in the UI --- their purpose has possibly changed - UpdateColorFieldsInUI(); - UpdateWindow(g_hDlg); - return 1; -} -//------------------------------------------------------------------------------- -int CDisplay::OnSetupNodeView(NodeInfo* pcNew) -{ - ai_assert(NULL != pcNew); - - if (m_pcCurrentNode == pcNew)return 2; - - // now ... change the meaning of the statistics fields back - SetWindowText(GetDlgItem(g_hDlg,IDC_NUMVERTS),"Vertices:"); - SetWindowText(GetDlgItem(g_hDlg,IDC_NUMFACES),"Faces:"); - SetWindowText(GetDlgItem(g_hDlg,IDC_NUMMATS),"Materials:"); - SetWindowText(GetDlgItem(g_hDlg,IDC_NUMMESHES),"Meshes:"); - - ShowWindow(GetDlgItem(g_hDlg,IDC_NUMNODES),SW_HIDE); - ShowWindow(GetDlgItem(g_hDlg,IDC_ENODEWND),SW_HIDE); - ShowWindow(GetDlgItem(g_hDlg,IDC_NUMSHADERS),SW_HIDE); - ShowWindow(GetDlgItem(g_hDlg,IDC_LOADTIME),SW_HIDE); - ShowWindow(GetDlgItem(g_hDlg,IDC_ESHADER),SW_HIDE); - ShowWindow(GetDlgItem(g_hDlg,IDC_ELOAD),SW_HIDE); - ShowWindow(GetDlgItem(g_hDlg,IDC_VIEWMATRIX),SW_SHOW); - - char szTemp[1024]; - sprintf(szTemp, - "%.2f %.2f %.2f\r\n" - "%.2f %.2f %.2f\r\n" - "%.2f %.2f %.2f\r\n" - "%.2f %.2f %.2f\r\n", - pcNew->psNode->mTransformation.a1, - pcNew->psNode->mTransformation.b1, - pcNew->psNode->mTransformation.c1, - pcNew->psNode->mTransformation.a2, - pcNew->psNode->mTransformation.b2, - pcNew->psNode->mTransformation.c2, - pcNew->psNode->mTransformation.a3, - pcNew->psNode->mTransformation.b3, - pcNew->psNode->mTransformation.c3, - pcNew->psNode->mTransformation.a4, - pcNew->psNode->mTransformation.b4, - pcNew->psNode->mTransformation.c4); - SetWindowText(GetDlgItem(g_hDlg,IDC_VIEWMATRIX),szTemp); - - - m_pcCurrentNode = pcNew; - SetViewMode(VIEWMODE_NODE); - - return 1; -} -//------------------------------------------------------------------------------- -int CDisplay::OnSetupMaterialView(MaterialInfo* pcNew) -{ - ai_assert(NULL != pcNew); - - if (m_pcCurrentMaterial == pcNew)return 2; - - if (VIEWMODE_NODE == m_iViewMode) - ShowNormalUIComponents(); - - m_pcCurrentMaterial = pcNew; - SetViewMode(VIEWMODE_MATERIAL); - - // redraw the color fields in the UI --- their purpose has possibly changed - UpdateColorFieldsInUI(); - UpdateWindow(g_hDlg); - return 1; -} -//------------------------------------------------------------------------------- -int CDisplay::OnSetupTextureView(TextureInfo* pcNew) -{ - ai_assert(NULL != pcNew); - - if (this->m_pcCurrentTexture == pcNew)return 2; - - if (VIEWMODE_NODE == this->m_iViewMode) - { - ShowNormalUIComponents(); - } - - if ((aiTextureType_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)); - } - - // check whether the pattern background effect is supported - if (g_sCaps.PixelShaderVersion < D3DPS_VERSION(3,0)) - { - CLogDisplay::Instance().AddEntry("[WARN] The background shader won't work " - "on your system, it required PS 3.0 hardware. A default color is used ...", - D3DCOLOR_ARGB(0xFF,0xFF,0x00,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; - if (pcNew->piTexture && *pcNew->piTexture) { - (*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 - // converted 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; - } - } - } - // redraw the color fields in the UI --- their purpose has possibly changed - UpdateColorFieldsInUI(); - UpdateWindow(g_hDlg); - return 1; -} -//------------------------------------------------------------------------------- -int CDisplay::OnSetup(HTREEITEM p_hTreeItem) -{ - // search in our list for the item - union { - TextureInfo* pcNew; - NodeInfo* pcNew2; - MaterialInfo* pcNew3; - }; - - pcNew = NULL; - for (std::vector<TextureInfo>::iterator i = m_asTextures.begin();i != m_asTextures.end();++i){ - if (p_hTreeItem == (*i).hTreeItem) { - pcNew = &(*i); - break; - } - } - if (pcNew) { - return OnSetupTextureView(pcNew); - } - - // seach the node list - for (std::vector<NodeInfo>::iterator i = m_asNodes.begin(); i != m_asNodes.end();++i){ - if (p_hTreeItem == (*i).hTreeItem) { - pcNew2 = &(*i); - break; - } - } - if (pcNew2) { - return OnSetupNodeView(pcNew2); - } - - // seach the material list - for (std::vector<MaterialInfo>::iterator i = m_asMaterials.begin();i != m_asMaterials.end();++i){ - if (p_hTreeItem == (*i).hTreeItem){ - pcNew3 = &(*i); - break; - } - } - if (pcNew3) { - return OnSetupMaterialView(pcNew3); - } - return OnSetupNormalView(); -} -//------------------------------------------------------------------------------- -int CDisplay::ShowTreeViewContextMenu(HTREEITEM hItem) -{ - ai_assert(NULL != hItem); - - HMENU hDisplay = NULL; - - // search in our list for the item - TextureInfo* pcNew = NULL; - for (std::vector<TextureInfo>::iterator - i = m_asTextures.begin(); - i != 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); - } - - // search in the material list for the item - MaterialInfo* pcNew2 = NULL; - for (std::vector<MaterialInfo>::iterator - i = m_asMaterials.begin(); - i != 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); - } - 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 - OnRender(); - - POINT sPoint; - GetCursorPos(&sPoint); - TrackPopupMenu(hDisplay, TPM_LEFTALIGN, sPoint.x, sPoint.y, 0, - g_hDlg,NULL); - } - return 1; -} -//------------------------------------------------------------------------------- -int CDisplay::HandleTreeViewPopup(WPARAM wParam,LPARAM lParam) -{ - // get the current selected material - std::vector<Info> apclrOut; - const char* szMatKey = ""; - - switch (LOWORD(wParam)) - { - case ID_SOLONG_CLEARDIFFUSECOLOR: - for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) - { - if (this->m_pcCurrentMaterial->iIndex == g_pcAsset->pcScene->mMeshes[i]->mMaterialIndex) - { - apclrOut.push_back( Info( &g_pcAsset->apcMeshes[i]->vDiffuseColor, - g_pcAsset->apcMeshes[i],"DIFFUSE_COLOR")); - } - } - szMatKey = "$clr.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 = "$clr.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 = "$clr.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 = "$clr.emissive"; - break; - default: - - // let the next function do this ... no spaghetti code ;-) - HandleTreeViewPopup2(wParam,lParam); - }; - if (!apclrOut.empty()) - { - aiColor4D clrOld = *((aiColor4D*)(apclrOut.front().pclrColor)); - - CHOOSECOLOR clr; - clr.lStructSize = sizeof(CHOOSECOLOR); - clr.hwndOwner = g_hDlg; - clr.Flags = CC_RGBINIT | CC_FULLOPEN; - clr.rgbResult = RGB( - clamp<unsigned char>(clrOld.r * 255.0f), - clamp<unsigned char>(clrOld.g * 255.0f), - clamp<unsigned char>(clrOld.b * 255.0f)); - clr.lpCustColors = g_aclCustomColors; - clr.lpfnHook = NULL; - clr.lpTemplateName = NULL; - clr.lCustData = 0; - - ChooseColor(&clr); - - clrOld.r = (float)(((unsigned int)clr.rgbResult) & 0xFF) / 255.0f; - clrOld.g = (float)(((unsigned int)clr.rgbResult >> 8) & 0xFF) / 255.0f; - clrOld.b = (float)(((unsigned int)clr.rgbResult >> 16) & 0xFF) / 255.0f; - - // update the color values in the mesh instances and - // update all shaders ... - for (std::vector<Info>::iterator - i = apclrOut.begin(); - i != apclrOut.end();++i) - { - *((*i).pclrColor) = *((D3DXVECTOR4*)&clrOld); - if (!(*i).pMesh->bSharedFX) - { - (*i).pMesh->piEffect->SetVector((*i).szShaderParam,(*i).pclrColor); - } - } - - // change the material key ... - aiMaterial* pcMat = (aiMaterial*)g_pcAsset->pcScene->mMaterials[ - this->m_pcCurrentMaterial->iIndex]; - pcMat->AddProperty<aiColor4D>(&clrOld,1,szMatKey,0,0); - - 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; - } - - aiMaterial* pcMat = (aiMaterial*)g_pcAsset->pcScene->mMaterials[ - m_pcCurrentTexture->iMatIndex]; - - unsigned int s; - if (m_pcCurrentTexture->iType == (aiTextureType_OPACITY | 0x40000000)) - { - // set a special property to indicate that no alpha channel is required - int iVal = 1; - pcMat->AddProperty<int>(&iVal,1,"no_a_from_d",0,0); - s = aiTextureType_OPACITY; - } - else s = m_pcCurrentTexture->iType; - pcMat->RemoveProperty(AI_MATKEY_TEXTURE(m_pcCurrentTexture->iType,0)); - - // need to update all meshes associated with this material - for (unsigned int i = 0;i < g_pcAsset->pcScene->mNumMeshes;++i) - { - if (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 = m_pcCurrentTexture->iMatIndex; - for (std::vector<MaterialInfo>::iterator - a = m_asMaterials.begin(); - a != m_asMaterials.end();++a) - { - if (iMatIndex == (*a).iIndex) - { - // good news. we will also need to find all other textures - // associated with this item ... - for (std::vector<TextureInfo>::iterator - n = m_asTextures.begin(); - n != m_asTextures.end();++n) - { - if ((*n).iMatIndex == iMatIndex) - { - n = m_asTextures.erase(n); - if (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(m_hRoot,iMatIndex); - HTREEITEM hNewItem = 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 = 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),m_hRoot,TVGN_CARET); - return 1; - } - } - return 0; -} -//------------------------------------------------------------------------------- -// Setup stereo view -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; -} -//------------------------------------------------------------------------------- -// Do the actual rendering pass for the stereo view -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; -} -//------------------------------------------------------------------------------- -// Process input for the texture view -int CDisplay::HandleInputTextureView() -{ - HandleMouseInputTextureView(); - HandleKeyboardInputTextureView(); - return 1; -} -//------------------------------------------------------------------------------- -// Get input for the current state -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); - - g_avLightDirs[0].Normalize(); - } - return 1; -} -//------------------------------------------------------------------------------- -// Process input for an empty scen view to allow for skybox rotations -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; -} -//------------------------------------------------------------------------------- -// Draw the HUD on top of the scene -int CDisplay::DrawHUD() -{ - // HACK: (thom) can't get the effect to work on non-shader cards, therefore deactivated for the moment - if( g_sCaps.PixelShaderVersion < D3DPS_VERSION(2,0)) - return 1; - - // get the dimension of the back buffer - RECT sRect; - GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect); - sRect.right -= sRect.left; - sRect.bottom -= sRect.top; - - // 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 - if( g_sCaps.PixelShaderVersion < D3DPS_VERSION(2,0)) - g_piPassThroughEffect->SetTechnique( "PassThrough_FF"); - else - 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; - - g_piDevice->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR); - g_piDevice->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR); - - // 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; -} -//------------------------------------------------------------------------------- -// Render the full scene, all nodes -int CDisplay::RenderFullScene() -{ - // reset the color index used for drawing normals - g_iCurrentColor = 0; - - aiMatrix4x4 pcProj; - GetProjectionMatrix(pcProj); - - vPos = GetCameraMatrix(mViewProjection); - mViewProjection = mViewProjection * pcProj; - - // 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); - - if (g_sOptions.bCulling) - g_piDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_CCW); - else g_piDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE); - - // for high-quality mode, enable anisotropic texture filtering - if (g_sOptions.bLowQuality) { - for (DWORD d = 0; d < 8;++d) { - g_piDevice->SetSamplerState(d,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR); - g_piDevice->SetSamplerState(d,D3DSAMP_MINFILTER,D3DTEXF_LINEAR); - g_piDevice->SetSamplerState(d,D3DSAMP_MIPFILTER,D3DTEXF_LINEAR); - } - } - else { - for (DWORD d = 0; d < 8;++d) { - g_piDevice->SetSamplerState(d,D3DSAMP_MAGFILTER,D3DTEXF_ANISOTROPIC); - g_piDevice->SetSamplerState(d,D3DSAMP_MINFILTER,D3DTEXF_ANISOTROPIC); - g_piDevice->SetSamplerState(d,D3DSAMP_MIPFILTER,D3DTEXF_LINEAR); - - g_piDevice->SetSamplerState(d,D3DSAMP_MAXANISOTROPY,g_sCaps.MaxAnisotropy); - } - } - - // draw the scene background (clear and texture 2d) - CBackgroundPainter::Instance().OnPreRender(); - - // setup the stereo view if necessary - if (g_sOptions.bStereoView) - SetupStereoView(); - - - // draw all opaque objects in the scene - aiMatrix4x4 m; - if (NULL != g_pcAsset && NULL != g_pcAsset->pcScene->mRootNode) - { - 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 - 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 - if (!g_sOptions.bNoAlphaBlending) { - g_piDevice->SetRenderState(D3DRS_ZWRITEENABLE,FALSE); - } - RenderNode(g_pcAsset->pcScene->mRootNode,m,true); - - if (!g_sOptions.bNoAlphaBlending) { - g_piDevice->SetRenderState(D3DRS_ZWRITEENABLE,TRUE); - } - } - - // setup the stereo view if necessary - if (g_sOptions.bStereoView) - RenderStereoView(m); - - // render the skeleton if necessary - if (g_sOptions.bSkeleton && NULL != g_pcAsset && NULL != g_pcAsset->pcScene->mRootNode) { - // disable the z-buffer - g_piDevice->SetRenderState(D3DRS_ZWRITEENABLE,FALSE); - - if (g_sOptions.eDrawMode != RenderOptions::WIREFRAME) { - g_piDevice->SetRenderState(D3DRS_ZENABLE,FALSE); - } - - g_piDevice->SetVertexDeclaration( gDefaultVertexDecl); - // this is very similar to the code in SetupMaterial() - ID3DXEffect* piEnd = g_piNormalsEffect; - aiMatrix4x4 pcProj = m * mViewProjection; - - D3DXVECTOR4 vVector(1.f,0.f,0.f,1.f); - piEnd->SetVector("OUTPUT_COLOR",&vVector); - piEnd->SetMatrix("WorldViewProjection", (const D3DXMATRIX*)&pcProj); - - UINT dwPasses = 0; - piEnd->Begin(&dwPasses,0); - piEnd->BeginPass(0); - - RenderSkeleton(g_pcAsset->pcScene->mRootNode,m,m); - - piEnd->EndPass();piEnd->End(); - g_piDevice->SetRenderState(D3DRS_ZWRITEENABLE,TRUE); - g_piDevice->SetRenderState(D3DRS_ZENABLE,TRUE); - } - - // draw the HUD texture on top of the rendered scene using - // pre-projected vertices - if (!g_bFPSView && g_pcAsset && g_pcTexture) - DrawHUD(); - - return 1; -} -//------------------------------------------------------------------------------- -int CDisplay::RenderMaterialView() -{ - return 1; -} -//------------------------------------------------------------------------------- -// Render animation skeleton -int CDisplay::RenderSkeleton (aiNode* piNode,const aiMatrix4x4& piMatrix, const aiMatrix4x4& parent) -{ - aiMatrix4x4 me = g_pcAsset->mAnimator->GetGlobalTransform( piNode); - - me.Transpose(); - //me *= piMatrix; - - if (piNode->mParent) { - AssetHelper::LineVertex data[2]; - data[0].dColorDiffuse = data[1].dColorDiffuse = D3DCOLOR_ARGB(0xff,0xff,0,0); - - data[0].vPosition.x = parent.d1; - data[0].vPosition.y = parent.d2; - data[0].vPosition.z = parent.d3; - - data[1].vPosition.x = me.d1; - data[1].vPosition.y = me.d2; - data[1].vPosition.z = me.d3; - - g_piDevice->DrawPrimitiveUP(D3DPT_LINELIST,1,&data,sizeof(AssetHelper::LineVertex)); - } - - // render all child nodes - for (unsigned int i = 0; i < piNode->mNumChildren;++i) - RenderSkeleton(piNode->mChildren[i],piMatrix, me ); - - return 1; -} -//------------------------------------------------------------------------------- -// Render a single node -int CDisplay::RenderNode (aiNode* piNode,const aiMatrix4x4& piMatrix, - bool bAlpha /*= false*/) -{ - aiMatrix4x4 aiMe = g_pcAsset->mAnimator->GetGlobalTransform( piNode); - - aiMe.Transpose(); - aiMe *= piMatrix; - - bool bChangedVM = false; - if (VIEWMODE_NODE == m_iViewMode && m_pcCurrentNode) - { - if (piNode != m_pcCurrentNode->psNode) - { - // directly call our children - for (unsigned int i = 0; i < piNode->mNumChildren;++i) - RenderNode(piNode->mChildren[i],piMatrix,bAlpha ); - - return 1; - } - m_iViewMode = VIEWMODE_FULL; - bChangedVM = true; - } - - aiMatrix4x4 pcProj = aiMe * mViewProjection; - - aiMatrix4x4 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[0].w = 0.0f; - 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; - apcVec[1].w = 0.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; - - if( g_sOptions.b3Lights) - { - 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; - } else - { - 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]); - - // setup the best technique - if( g_sCaps.PixelShaderVersion < D3DPS_VERSION(2,0)) - { - g_piDefaultEffect->SetTechnique( "DefaultFXSpecular_FF"); - } else - 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) - { - const aiMesh* mesh = g_pcAsset->pcScene->mMeshes[piNode->mMeshes[i]]; - AssetHelper::MeshHelper* helper = g_pcAsset->apcMeshes[piNode->mMeshes[i]]; - - // don't render the mesh if the render pass is incorrect - if (g_sOptions.bRenderMats && (helper->piOpacityTexture || helper->fOpacity != 1.0f) && !mesh->HasBones()) - { - if (!bAlpha)continue; - } - else if (bAlpha)continue; - - // Upload bone matrices. This maybe is the wrong place to do it, but for the heck of it I don't understand this code flow - if( mesh->HasBones()) - { - if( helper->piEffect) - { - static float matrices[4*4*60]; - float* tempmat = matrices; - const std::vector<aiMatrix4x4>& boneMats = g_pcAsset->mAnimator->GetBoneMatrices( piNode, i); - ai_assert( boneMats.size() == mesh->mNumBones); - - for( unsigned int a = 0; a < mesh->mNumBones; a++) - { - const aiMatrix4x4& mat = boneMats[a]; - *tempmat++ = mat.a1; *tempmat++ = mat.a2; *tempmat++ = mat.a3; *tempmat++ = mat.a4; - *tempmat++ = mat.b1; *tempmat++ = mat.b2; *tempmat++ = mat.b3; *tempmat++ = mat.b4; - *tempmat++ = mat.c1; *tempmat++ = mat.c2; *tempmat++ = mat.c3; *tempmat++ = mat.c4; - *tempmat++ = mat.d1; *tempmat++ = mat.d2; *tempmat++ = mat.d3; *tempmat++ = mat.d4; - //tempmat += 4; - } - - if( g_sOptions.bRenderMats) - { - helper->piEffect->SetMatrixTransposeArray( "gBoneMatrix", (D3DXMATRIX*)matrices, 60); - } else - { - g_piDefaultEffect->SetMatrixTransposeArray( "gBoneMatrix", (D3DXMATRIX*)matrices, 60); - g_piDefaultEffect->CommitChanges(); - } - } - } else - { - // upload identity matrices instead. Only the first is ever going to be used in meshes without bones - if( !g_sOptions.bRenderMats) - { - D3DXMATRIX identity( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); - g_piDefaultEffect->SetMatrixTransposeArray( "gBoneMatrix", &identity, 1); - g_piDefaultEffect->CommitChanges(); - } - } - - // now setup the material - if (g_sOptions.bRenderMats) - { - CMaterialManager::Instance().SetupMaterial( helper, pcProj, aiMe, pcCam, vPos); - } - g_piDevice->SetVertexDeclaration( gDefaultVertexDecl); - - if (g_sOptions.bNoAlphaBlending) { - // manually disable alphablending - g_piDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,FALSE); - } - - 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( helper); - } - - // render normal vectors? - if (g_sOptions.bRenderNormals && helper->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, helper->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],piMatrix,bAlpha ); - - // need to reset the viewmode? - if (bChangedVM) - m_iViewMode = VIEWMODE_NODE; - return 1; -} -//------------------------------------------------------------------------------- -int CDisplay::RenderPatternBG() -{ - if (!g_piPatternEffect) - { - // the pattern effect won't work on ps_2_0 cards - if (g_sCaps.PixelShaderVersion >= D3DPS_VERSION(3,0)) - { - // 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; - } - } - else - { - // clear the color buffer in magenta - // (hopefully this is ugly enough that every ps_2_0 cards owner - // runs to the next shop to buy himself a new card ...) - g_piDevice->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, - D3DCOLOR_ARGB(0xFF,0xFF,0,0xFF), 1.0f,0 ); - return 1; - } - } - - // clear the depth buffer only - g_piDevice->Clear(0,NULL,D3DCLEAR_ZBUFFER, - D3DCOLOR_ARGB(0xFF,0xFF,0,0xFF), 1.0f,0 ); - - // setup the colors to be used ... - g_piPatternEffect->SetVector("COLOR_ONE",&m_avCheckerColors[0]); - g_piPatternEffect->SetVector("COLOR_TWO",&m_avCheckerColors[1]); - - // 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 - RenderPatternBG(); - - // it might be that there is no texture ... - if (!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",*m_pcCurrentTexture->piTexture); - - if (aiTextureType_OPACITY == m_pcCurrentTexture->iType) - { - g_piPassThroughEffect->SetTechnique("PassThroughAlphaFromR"); - } - else if ((aiTextureType_OPACITY | 0x40000000) == m_pcCurrentTexture->iType) - { - g_piPassThroughEffect->SetTechnique("PassThroughAlphaFromA"); - } - else if( g_sCaps.PixelShaderVersion < D3DPS_VERSION(2,0)) - g_piPassThroughEffect->SetTechnique( "PassThrough_FF"); - else - g_piPassThroughEffect->SetTechnique("PassThrough"); - - UINT dw; - g_piPassThroughEffect->Begin(&dw,0); - g_piPassThroughEffect->BeginPass(0); - - if (aiTextureType_HEIGHT == m_pcCurrentTexture->iType || - aiTextureType_NORMALS == m_pcCurrentTexture->iType || g_sOptions.bNoAlphaBlending) - { - // 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; - if ( m_pcCurrentTexture->piTexture && *m_pcCurrentTexture->piTexture) { /* just a dirty fix */ - (*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 = min((nx-30) / x,(ny-30) / y) * (m_fTextureZoom/1000.0f); - - float fHalfX = (nx - (f * x)) / 2.0f; - float fHalfY = (ny - (f * y)) / 2.0f; - as[1].x = fHalfX + m_vTextureOffset.x; - as[1].y = fHalfY + 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 + m_vTextureOffset.x; - as[3].y = fHalfY + 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 + m_vTextureOffset.x; - as[0].y = ny-fHalfY + 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 + m_vTextureOffset.x; - as[2].y = ny-fHalfY + 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; -} -}; - +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2015, assimp 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 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 "assimp_view.h" +#include "AnimEvaluator.h" +#include "SceneAnimator.h" + +namespace AssimpView { + +using namespace Assimp; + +extern std::string g_szCheckerBackgroundShader; + +struct SVertex +{ + float x,y,z,w,u,v; +}; + +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::EnableAnimTools(BOOL hm) +{ + EnableWindow(GetDlgItem(g_hDlg,IDC_PLAY),hm); + EnableWindow(GetDlgItem(g_hDlg,IDC_SLIDERANIM),hm); + return 1; +} + +//------------------------------------------------------------------------------- +// Fill animation combo box +int CDisplay::FillAnimList(void) +{ + if (0 != g_pcAsset->pcScene->mNumAnimations) + { + // 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); + } + + // also add a dummy - 'none' + SendDlgItemMessage(g_hDlg,IDC_COMBO1,CB_ADDSTRING,0,(LPARAM)"none"); + + // select first + SendDlgItemMessage(g_hDlg,IDC_COMBO1,CB_SETCURSEL,0,0); + + EnableAnimTools(TRUE); + } + else // tools remain disabled + EnableAnimTools(FALSE); + + return 1; +} +//------------------------------------------------------------------------------- +// Clear the list of animations +int CDisplay::ClearAnimList(void) +{ + // clear the combo box + SendDlgItemMessage(g_hDlg,IDC_COMBO1,CB_RESETCONTENT,0,0); + return 1; +} +//------------------------------------------------------------------------------- +// Clear the tree view +int CDisplay::ClearDisplayList(void) +{ + // clear the combo box + TreeView_DeleteAllItems(GetDlgItem(g_hDlg,IDC_TREE1)); + this->Reset(); + return 1; +} +//------------------------------------------------------------------------------- +// Add a specific node to the display list +int CDisplay::AddNodeToDisplayList( + unsigned int iIndex, + unsigned int iDepth, + aiNode* pcNode, + HTREEITEM hRoot) +{ + ai_assert(NULL != pcNode); + ai_assert(NULL != hRoot); + + char chTemp[MAXLEN]; + + 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 { + sprintf(chTemp,"%s",pcNode->mName.data); + } + sprintf(chTemp+strlen(chTemp), iIndex ? " (%i)" : " (%i meshes)",pcNode->mNumMeshes); + + TVITEMEXW tvi; + TVINSERTSTRUCTW sNew; + + wchar_t tmp[512]; + int t = MultiByteToWideChar(CP_UTF8,0,chTemp,-1,tmp,512); + + tvi.pszText = tmp; + tvi.cchTextMax = (int)t; + + 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_INSERTITEMW, + 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::AddMeshToDisplayList(unsigned int iIndex, HTREEITEM hRoot) +{ + aiMesh* pcMesh = g_pcAsset->pcScene->mMeshes[iIndex]; + + char chTemp[MAXLEN]; + + if(0 == pcMesh->mName.length) { + sprintf(chTemp,"Mesh %i",iIndex); + } + else { + sprintf(chTemp,"%s",pcMesh->mName.data); + } + sprintf(chTemp+strlen(chTemp), iIndex ? " (%i)" : " (%i faces)",pcMesh->mNumFaces); + + TVITEMEXW tvi; + TVINSERTSTRUCTW sNew; + + wchar_t tmp[512]; + int t = MultiByteToWideChar(CP_UTF8,0,chTemp,-1,tmp,512); + + tvi.pszText = tmp; + tvi.cchTextMax = (int)t; + + 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_INSERTITEMW, + 0, + (LPARAM)(LPTVINSERTSTRUCT)&sNew); + + // add the mesh to the list of all mesh entries in the scene browser + MeshInfo info; + info.hTreeItem = hTexture; + info.psMesh = pcMesh; + AddMesh(info); + return 1; +} + +//------------------------------------------------------------------------------- +// Replace the currently selected texture by another one +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 = m_aiImageList[AI_VIEW_IMGLIST_MATERIAL]; + tvi.iSelectedImage = m_aiImageList[AI_VIEW_IMGLIST_MATERIAL]; + + TreeView_SetItem(GetDlgItem(g_hDlg,IDC_TREE1), + m_pcCurrentTexture->hTreeItem); + + // update all meshes referencing this material + 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]; + IDirect3DTexture9** tex = NULL; + const char* tex_string = NULL; + + switch (this->m_pcCurrentTexture->iType) + { + case aiTextureType_DIFFUSE: + tex = &pcMesh->piDiffuseTexture; + tex_string = "DIFFUSE_TEXTURE"; + break; + case aiTextureType_AMBIENT: + tex = &pcMesh->piAmbientTexture; + tex_string = "AMBIENT_TEXTURE"; + break; + case aiTextureType_SPECULAR: + tex = &pcMesh->piSpecularTexture; + tex_string = "SPECULAR_TEXTURE"; + break; + case aiTextureType_EMISSIVE: + tex = &pcMesh->piEmissiveTexture; + tex_string = "EMISSIVE_TEXTURE"; + break; + case aiTextureType_LIGHTMAP: + tex = &pcMesh->piLightmapTexture; + tex_string = "LIGHTMAP_TEXTURE"; + break; + case aiTextureType_DISPLACEMENT: + case aiTextureType_REFLECTION: + case aiTextureType_UNKNOWN: + break; + case aiTextureType_SHININESS: + tex = &pcMesh->piShininessTexture; + tex_string = "SHININESS_TEXTURE"; + break; + case aiTextureType_NORMALS: + case aiTextureType_HEIGHT: + + // special handling here + if (pcMesh->piNormalTexture && pcMesh->piNormalTexture != piTexture) { + piTexture->AddRef(); + pcMesh->piNormalTexture->Release(); + pcMesh->piNormalTexture = piTexture; + CMaterialManager::Instance().HMtoNMIfNecessary(pcMesh->piNormalTexture,&pcMesh->piNormalTexture,true); + m_pcCurrentTexture->piTexture = &pcMesh->piNormalTexture; + + if (!pcMesh->bSharedFX) { + pcMesh->piEffect->SetTexture("NORMAL_TEXTURE",piTexture); + } + } + break; + default: //case aiTextureType_OPACITY && case aiTextureType_OPACITY | 0x40000000: + + tex = &pcMesh->piOpacityTexture; + tex_string = "OPACITY_TEXTURE"; + break; + }; + if (tex && *tex && *tex != piTexture) + { + (**tex).Release(); + *tex = piTexture; + m_pcCurrentTexture->piTexture = tex; + + //if (!pcMesh->bSharedFX){ + pcMesh->piEffect->SetTexture(tex_string,piTexture); + //} + } + } + + 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); + + 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 aiTextureType_DIFFUSE: + piTexture = &g_pcAsset->apcMeshes[iMesh]->piDiffuseTexture; + szType = "Diffuse"; + break; + case aiTextureType_SPECULAR: + piTexture = &g_pcAsset->apcMeshes[iMesh]->piSpecularTexture; + szType = "Specular"; + break; + case aiTextureType_AMBIENT: + piTexture = &g_pcAsset->apcMeshes[iMesh]->piAmbientTexture; + szType = "Ambient"; + break; + case aiTextureType_EMISSIVE: + piTexture = &g_pcAsset->apcMeshes[iMesh]->piEmissiveTexture; + szType = "Emissive"; + break; + case aiTextureType_HEIGHT: + piTexture = &g_pcAsset->apcMeshes[iMesh]->piNormalTexture; + szType = "Heightmap"; + break; + case aiTextureType_NORMALS: + piTexture = &g_pcAsset->apcMeshes[iMesh]->piNormalTexture; + szType = "Normalmap"; + break; + case aiTextureType_SHININESS: + piTexture = &g_pcAsset->apcMeshes[iMesh]->piShininessTexture; + szType = "Shininess"; + break; + case aiTextureType_LIGHTMAP: + piTexture = &g_pcAsset->apcMeshes[iMesh]->piLightmapTexture; + szType = "Lightmap"; + break; + case aiTextureType_DISPLACEMENT: + piTexture = NULL; + szType = "Displacement"; + break; + case aiTextureType_REFLECTION: + piTexture = NULL; + szType = "Reflection"; + break; + case aiTextureType_UNKNOWN: + piTexture = NULL; + szType = "Unknown"; + break; + default: // opacity + opacity | mask + piTexture = &g_pcAsset->apcMeshes[iMesh]->piOpacityTexture; + szType = "Opacity"; + break; + }; + if (bIsExtraOpacity) { + sprintf(chTemp,"%s %i (<copy of diffuse #1>)",szType,iIndex+1); + } + else + sprintf(chTemp,"%s %i (%s)",szType,iIndex+1,sz); + + TVITEMEX tvi; + TVINSERTSTRUCT sNew; + tvi.pszText = chTemp; + tvi.cchTextMax = (int)strlen(chTemp); + tvi.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_HANDLE | TVIF_HANDLE; + tvi.lParam = (LPARAM)20; + + // find out whether this is the default texture or not + + if (piTexture && *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 = m_aiImageList[AI_VIEW_IMGLIST_TEXTURE_INVALID]; + tvi.iSelectedImage = m_aiImageList[AI_VIEW_IMGLIST_TEXTURE_INVALID]; + } + else + { + tvi.iImage = m_aiImageList[AI_VIEW_IMGLIST_TEXTURE]; + tvi.iSelectedImage = m_aiImageList[AI_VIEW_IMGLIST_TEXTURE]; + } + } + else + { + tvi.iImage = m_aiImageList[AI_VIEW_IMGLIST_TEXTURE_INVALID]; + tvi.iSelectedImage = 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; + 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); + } + TVITEMEXW tvi; + TVINSERTSTRUCTW sNew; + + wchar_t tmp[512]; + int t = MultiByteToWideChar(CP_UTF8,0,chTemp,-1,tmp,512); + + tvi.pszText = tmp; + tvi.cchTextMax = (int)t; + tvi.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_HANDLE | TVIF_PARAM ; + tvi.iImage = m_aiImageList[AI_VIEW_IMGLIST_MATERIAL]; + tvi.iSelectedImage = 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_INSERTITEMW, + 0, + (LPARAM)(LPTVINSERTSTRUCT)&sNew); + + // for each texture in the list ... add it + unsigned int iUV; + float fBlend; + aiTextureOp eOp; + aiString szPath; + bool bNoOpacity = true; + for (unsigned int i = 0; i <= AI_TEXTURE_TYPE_MAX;++i) + { + unsigned int iNum = 0; + while (true) + { + if (AI_SUCCESS != aiGetMaterialTexture(pcMat,(aiTextureType)i,iNum, + &szPath,NULL, &iUV,&fBlend,&eOp)) + { + break; + } + if (aiTextureType_OPACITY == i)bNoOpacity = false; + AddTextureToDisplayList(i,iNum,&szPath,hTexture,iUV,fBlend,eOp,iMesh); + ++iNum; + } + } + + AssetHelper::MeshHelper* pcMesh = g_pcAsset->apcMeshes[iMesh]; + + if (pcMesh->piDiffuseTexture && pcMesh->piDiffuseTexture == pcMesh->piOpacityTexture && bNoOpacity) + { + // check whether the diffuse texture is not a default texture + + // {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; + if(FAILED( pcMesh->piDiffuseTexture->GetPrivateData(guidPrivateData,&iData,&dwSize) || + 0xffffffff == iData)) + { + // seems the diffuse texture contains alpha, therefore it has been + // added to the opacity channel, too. Add a special value ... + AddTextureToDisplayList(aiTextureType_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; +} +//------------------------------------------------------------------------------- +// Expand all elements in the treeview +int CDisplay::ExpandTree() +{ + // expand all materials + for (std::vector< MaterialInfo >::iterator + i = m_asMaterials.begin(); + i != m_asMaterials.end();++i) + { + TreeView_Expand(GetDlgItem(g_hDlg,IDC_TREE1),(*i).hTreeItem,TVE_EXPAND); + } + // expand all nodes + for (std::vector< NodeInfo >::iterator + i = m_asNodes.begin(); + i != m_asNodes.end();++i) + { + TreeView_Expand(GetDlgItem(g_hDlg,IDC_TREE1),(*i).hTreeItem,TVE_EXPAND); + } + TreeView_Expand(GetDlgItem(g_hDlg,IDC_TREE1),m_hRoot,TVE_EXPAND); + return 1; +} +//------------------------------------------------------------------------------- +// Get image list for tree view +int CDisplay::LoadImageList(void) +{ + if (!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)); + m_aiImageList[AI_VIEW_IMGLIST_MATERIAL] = ImageList_Add(hIml, hBmp, NULL); + DeleteObject(hBmp); + + hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BNODE)); + m_aiImageList[AI_VIEW_IMGLIST_NODE] = ImageList_Add(hIml, hBmp, NULL); + DeleteObject(hBmp); + + hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BTX)); + m_aiImageList[AI_VIEW_IMGLIST_TEXTURE] = ImageList_Add(hIml, hBmp, NULL); + DeleteObject(hBmp); + + hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BTXI)); + m_aiImageList[AI_VIEW_IMGLIST_TEXTURE_INVALID] = ImageList_Add(hIml, hBmp, NULL); + DeleteObject(hBmp); + + hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BROOT)); + 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); + + m_hImageList = hIml; + } + return 1; +} +//------------------------------------------------------------------------------- +// Fill tree view +int CDisplay::FillDisplayList(void) +{ + LoadImageList(); + + // Initialize the tree view window. + // fill in the first entry + TVITEMEX tvi; + TVINSERTSTRUCT sNew; + tvi.pszText = (char*) "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 = m_aiImageList[AI_VIEW_IMGLIST_MODEL]; + tvi.iSelectedImage = 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 + 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(m_hRoot,i); + + // add each mesh to the tree + for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) + AddMeshToDisplayList(i,m_hRoot); + + // now add all loaded nodes recursively + AddNodeToDisplayList(0,0,g_pcAsset->pcScene->mRootNode,m_hRoot); + + // now expand all parent nodes in the tree + 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; +} +//------------------------------------------------------------------------------- +// Main render loop +int CDisplay::OnRender() +{ + // update possible animation + if( g_pcAsset) + { + static double lastPlaying = 0.; + + ai_assert( g_pcAsset->mAnimator); + if (g_bPlay) { + g_dCurrent += clock()/ double( CLOCKS_PER_SEC) -lastPlaying; + + double time = g_dCurrent; + aiAnimation* mAnim = g_pcAsset->mAnimator->CurrentAnim(); + if( mAnim && mAnim->mDuration > 0.0) { + double tps = mAnim->mTicksPerSecond ? mAnim->mTicksPerSecond : 25.f; + time = fmod( time, mAnim->mDuration/tps); + SendDlgItemMessage(g_hDlg,IDC_SLIDERANIM,TBM_SETPOS,TRUE,LPARAM(10000 * (time/(mAnim->mDuration/tps)))); + } + + g_pcAsset->mAnimator->Calculate( time ); + lastPlaying = g_dCurrent; + } + } + // begin the frame + g_piDevice->BeginScene(); + + switch (m_iViewMode) + { + case VIEWMODE_FULL: + case VIEWMODE_NODE: + RenderFullScene(); + break; + case VIEWMODE_MATERIAL: + RenderMaterialView(); + break; + case VIEWMODE_TEXTURE: + 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; +} +//------------------------------------------------------------------------------- +// Update UI +void UpdateColorFieldsInUI() +{ + InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR1),NULL,TRUE); + InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR2),NULL,TRUE); + InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR3),NULL,TRUE); + + UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR1)); + UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR2)); + UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR3)); +} +//------------------------------------------------------------------------------- +// FIll statistics UI +int CDisplay::FillDefaultStatistics(void) +{ + if (!g_pcAsset) + { + // clear all stats edit controls + SetDlgItemText(g_hDlg,IDC_EVERT,"0"); + SetDlgItemText(g_hDlg,IDC_EFACE,"0"); + SetDlgItemText(g_hDlg,IDC_EMAT,"0"); + SetDlgItemText(g_hDlg,IDC_ENODE,"0"); + SetDlgItemText(g_hDlg,IDC_ESHADER,"0"); + SetDlgItemText(g_hDlg,IDC_ETEX,"0"); + return 1; + } + + // 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); + + UpdateColorFieldsInUI(); + UpdateWindow(g_hDlg); + return 1; +} +//------------------------------------------------------------------------------- +// Reset UI +int CDisplay::Reset(void) +{ + // clear all lists + m_asMaterials.clear(); + m_asTextures.clear(); + m_asNodes.clear(); + m_asMeshes.clear(); + + m_hRoot = NULL; + + return OnSetupNormalView(); +} +//------------------------------------------------------------------------------- +// reset to standard statistics view +void ShowNormalUIComponents() +{ + ShowWindow(GetDlgItem(g_hDlg,IDC_NUMNODES),SW_SHOW); + ShowWindow(GetDlgItem(g_hDlg,IDC_ENODEWND),SW_SHOW); + ShowWindow(GetDlgItem(g_hDlg,IDC_NUMSHADERS),SW_SHOW); + ShowWindow(GetDlgItem(g_hDlg,IDC_LOADTIME),SW_SHOW); + ShowWindow(GetDlgItem(g_hDlg,IDC_ESHADER),SW_SHOW); + ShowWindow(GetDlgItem(g_hDlg,IDC_ELOAD),SW_SHOW); + ShowWindow(GetDlgItem(g_hDlg,IDC_VIEWMATRIX),SW_HIDE); +} +//------------------------------------------------------------------------------- +int CDisplay::OnSetupNormalView() +{ + if (VIEWMODE_NODE == m_iViewMode) + { + ShowNormalUIComponents(); + } + + // now ... change the meaning of the statistics fields back + SetWindowText(GetDlgItem(g_hDlg,IDC_NUMVERTS),"Vertices:"); + SetWindowText(GetDlgItem(g_hDlg,IDC_NUMNODES),"Nodes:"); + SetWindowText(GetDlgItem(g_hDlg,IDC_NUMFACES),"Faces:"); + SetWindowText(GetDlgItem(g_hDlg,IDC_NUMSHADERS),"Shaders:"); + SetWindowText(GetDlgItem(g_hDlg,IDC_NUMMATS),"Materials:"); + SetWindowText(GetDlgItem(g_hDlg,IDC_NUMMESHES),"Meshes:"); + SetWindowText(GetDlgItem(g_hDlg,IDC_LOADTIME),"Time:"); + + FillDefaultStatistics(); + SetViewMode(VIEWMODE_FULL); + + // for debugging + m_pcCurrentMaterial = NULL; + m_pcCurrentTexture = NULL; + m_pcCurrentNode = NULL; + + // redraw the color fields in the UI --- their purpose has possibly changed + UpdateColorFieldsInUI(); + UpdateWindow(g_hDlg); + return 1; +} +//------------------------------------------------------------------------------- +int CDisplay::OnSetupNodeView(NodeInfo* pcNew) +{ + ai_assert(NULL != pcNew); + + if (m_pcCurrentNode == pcNew)return 2; + + // now ... change the meaning of the statistics fields back + SetWindowText(GetDlgItem(g_hDlg,IDC_NUMVERTS),"Vertices:"); + SetWindowText(GetDlgItem(g_hDlg,IDC_NUMFACES),"Faces:"); + SetWindowText(GetDlgItem(g_hDlg,IDC_NUMMATS),"Materials:"); + SetWindowText(GetDlgItem(g_hDlg,IDC_NUMMESHES),"Meshes:"); + + ShowWindow(GetDlgItem(g_hDlg,IDC_NUMNODES),SW_HIDE); + ShowWindow(GetDlgItem(g_hDlg,IDC_ENODEWND),SW_HIDE); + ShowWindow(GetDlgItem(g_hDlg,IDC_NUMSHADERS),SW_HIDE); + ShowWindow(GetDlgItem(g_hDlg,IDC_LOADTIME),SW_HIDE); + ShowWindow(GetDlgItem(g_hDlg,IDC_ESHADER),SW_HIDE); + ShowWindow(GetDlgItem(g_hDlg,IDC_ELOAD),SW_HIDE); + ShowWindow(GetDlgItem(g_hDlg,IDC_VIEWMATRIX),SW_SHOW); + + char szTemp[1024]; + sprintf(szTemp, + "%.2f %.2f %.2f\r\n" + "%.2f %.2f %.2f\r\n" + "%.2f %.2f %.2f\r\n" + "%.2f %.2f %.2f\r\n", + pcNew->psNode->mTransformation.a1, + pcNew->psNode->mTransformation.b1, + pcNew->psNode->mTransformation.c1, + pcNew->psNode->mTransformation.a2, + pcNew->psNode->mTransformation.b2, + pcNew->psNode->mTransformation.c2, + pcNew->psNode->mTransformation.a3, + pcNew->psNode->mTransformation.b3, + pcNew->psNode->mTransformation.c3, + pcNew->psNode->mTransformation.a4, + pcNew->psNode->mTransformation.b4, + pcNew->psNode->mTransformation.c4); + SetWindowText(GetDlgItem(g_hDlg,IDC_VIEWMATRIX),szTemp); + + + m_pcCurrentNode = pcNew; + SetViewMode(VIEWMODE_NODE); + + return 1; +} +//------------------------------------------------------------------------------- +int CDisplay::OnSetupMaterialView(MaterialInfo* pcNew) +{ + ai_assert(NULL != pcNew); + + if (m_pcCurrentMaterial == pcNew)return 2; + + if (VIEWMODE_NODE == m_iViewMode) + ShowNormalUIComponents(); + + m_pcCurrentMaterial = pcNew; + SetViewMode(VIEWMODE_MATERIAL); + + // redraw the color fields in the UI --- their purpose has possibly changed + UpdateColorFieldsInUI(); + UpdateWindow(g_hDlg); + return 1; +} +//------------------------------------------------------------------------------- +int CDisplay::OnSetupTextureView(TextureInfo* pcNew) +{ + ai_assert(NULL != pcNew); + + if (this->m_pcCurrentTexture == pcNew)return 2; + + if (VIEWMODE_NODE == this->m_iViewMode) + { + ShowNormalUIComponents(); + } + + if ((aiTextureType_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)); + } + + // check whether the pattern background effect is supported + if (g_sCaps.PixelShaderVersion < D3DPS_VERSION(3,0)) + { + CLogDisplay::Instance().AddEntry("[WARN] The background shader won't work " + "on your system, it required PS 3.0 hardware. A default color is used ...", + D3DCOLOR_ARGB(0xFF,0xFF,0x00,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; + if (pcNew->piTexture && *pcNew->piTexture) { + (*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 + // converted 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; + } + } + } + // redraw the color fields in the UI --- their purpose has possibly changed + UpdateColorFieldsInUI(); + UpdateWindow(g_hDlg); + return 1; +} +//------------------------------------------------------------------------------- +int CDisplay::OnSetup(HTREEITEM p_hTreeItem) +{ + // search in our list for the item + union { + TextureInfo* pcNew; + NodeInfo* pcNew2; + MaterialInfo* pcNew3; + }; + + pcNew = NULL; + for (std::vector<TextureInfo>::iterator i = m_asTextures.begin();i != m_asTextures.end();++i){ + if (p_hTreeItem == (*i).hTreeItem) { + pcNew = &(*i); + break; + } + } + if (pcNew) { + return OnSetupTextureView(pcNew); + } + + // seach the node list + for (std::vector<NodeInfo>::iterator i = m_asNodes.begin(); i != m_asNodes.end();++i){ + if (p_hTreeItem == (*i).hTreeItem) { + pcNew2 = &(*i); + break; + } + } + if (pcNew2) { + return OnSetupNodeView(pcNew2); + } + + // seach the material list + for (std::vector<MaterialInfo>::iterator i = m_asMaterials.begin();i != m_asMaterials.end();++i){ + if (p_hTreeItem == (*i).hTreeItem){ + pcNew3 = &(*i); + break; + } + } + if (pcNew3) { + return OnSetupMaterialView(pcNew3); + } + return OnSetupNormalView(); +} +//------------------------------------------------------------------------------- +int CDisplay::ShowTreeViewContextMenu(HTREEITEM hItem) +{ + ai_assert(NULL != hItem); + + HMENU hDisplay = NULL; + + // search in our list for the item + TextureInfo* pcNew = NULL; + for (std::vector<TextureInfo>::iterator + i = m_asTextures.begin(); + i != 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); + } + + // search in the material list for the item + MaterialInfo* pcNew2 = NULL; + for (std::vector<MaterialInfo>::iterator + i = m_asMaterials.begin(); + i != 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); + } + 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 + OnRender(); + + POINT sPoint; + GetCursorPos(&sPoint); + TrackPopupMenu(hDisplay, TPM_LEFTALIGN, sPoint.x, sPoint.y, 0, + g_hDlg,NULL); + } + return 1; +} +//------------------------------------------------------------------------------- +int CDisplay::HandleTreeViewPopup(WPARAM wParam,LPARAM lParam) +{ + // get the current selected material + std::vector<Info> apclrOut; + const char* szMatKey = ""; + + switch (LOWORD(wParam)) + { + case ID_SOLONG_CLEARDIFFUSECOLOR: + for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) + { + if (this->m_pcCurrentMaterial->iIndex == g_pcAsset->pcScene->mMeshes[i]->mMaterialIndex) + { + apclrOut.push_back( Info( &g_pcAsset->apcMeshes[i]->vDiffuseColor, + g_pcAsset->apcMeshes[i],"DIFFUSE_COLOR")); + } + } + szMatKey = "$clr.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 = "$clr.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 = "$clr.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 = "$clr.emissive"; + break; + default: + + // let the next function do this ... no spaghetti code ;-) + HandleTreeViewPopup2(wParam,lParam); + }; + if (!apclrOut.empty()) + { + aiColor4D clrOld = *((aiColor4D*)(apclrOut.front().pclrColor)); + + CHOOSECOLOR clr; + clr.lStructSize = sizeof(CHOOSECOLOR); + clr.hwndOwner = g_hDlg; + clr.Flags = CC_RGBINIT | CC_FULLOPEN; + clr.rgbResult = RGB( + clamp<unsigned char>(clrOld.r * 255.0f), + clamp<unsigned char>(clrOld.g * 255.0f), + clamp<unsigned char>(clrOld.b * 255.0f)); + clr.lpCustColors = g_aclCustomColors; + clr.lpfnHook = NULL; + clr.lpTemplateName = NULL; + clr.lCustData = 0; + + ChooseColor(&clr); + + clrOld.r = (float)(((unsigned int)clr.rgbResult) & 0xFF) / 255.0f; + clrOld.g = (float)(((unsigned int)clr.rgbResult >> 8) & 0xFF) / 255.0f; + clrOld.b = (float)(((unsigned int)clr.rgbResult >> 16) & 0xFF) / 255.0f; + + // update the color values in the mesh instances and + // update all shaders ... + for (std::vector<Info>::iterator + i = apclrOut.begin(); + i != apclrOut.end();++i) + { + *((*i).pclrColor) = *((D3DXVECTOR4*)&clrOld); + if (!(*i).pMesh->bSharedFX) + { + (*i).pMesh->piEffect->SetVector((*i).szShaderParam,(*i).pclrColor); + } + } + + // change the material key ... + aiMaterial* pcMat = (aiMaterial*)g_pcAsset->pcScene->mMaterials[ + this->m_pcCurrentMaterial->iIndex]; + pcMat->AddProperty<aiColor4D>(&clrOld,1,szMatKey,0,0); + + 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; + } + + aiMaterial* pcMat = (aiMaterial*)g_pcAsset->pcScene->mMaterials[ + m_pcCurrentTexture->iMatIndex]; + + unsigned int s; + if (m_pcCurrentTexture->iType == (aiTextureType_OPACITY | 0x40000000)) + { + // set a special property to indicate that no alpha channel is required + int iVal = 1; + pcMat->AddProperty<int>(&iVal,1,"no_a_from_d",0,0); + s = aiTextureType_OPACITY; + } + else s = m_pcCurrentTexture->iType; + pcMat->RemoveProperty(AI_MATKEY_TEXTURE(m_pcCurrentTexture->iType,0)); + + // need to update all meshes associated with this material + for (unsigned int i = 0;i < g_pcAsset->pcScene->mNumMeshes;++i) + { + if (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 = m_pcCurrentTexture->iMatIndex; + for (std::vector<MaterialInfo>::iterator + a = m_asMaterials.begin(); + a != m_asMaterials.end();++a) + { + if (iMatIndex == (*a).iIndex) + { + // good news. we will also need to find all other textures + // associated with this item ... + for (std::vector<TextureInfo>::iterator + n = m_asTextures.begin(); + n != m_asTextures.end();++n) + { + if ((*n).iMatIndex == iMatIndex) + { + n = m_asTextures.erase(n); + if (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(m_hRoot,iMatIndex); + HTREEITEM hNewItem = 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 = 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),m_hRoot,TVGN_CARET); + return 1; + } + } + return 0; +} +//------------------------------------------------------------------------------- +// Setup stereo view +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; +} +//------------------------------------------------------------------------------- +// Do the actual rendering pass for the stereo view +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; +} +//------------------------------------------------------------------------------- +// Process input for the texture view +int CDisplay::HandleInputTextureView() +{ + HandleMouseInputTextureView(); + HandleKeyboardInputTextureView(); + return 1; +} +//------------------------------------------------------------------------------- +// Get input for the current state +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); + + g_avLightDirs[0].Normalize(); + } + return 1; +} +//------------------------------------------------------------------------------- +// Process input for an empty scen view to allow for skybox rotations +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; +} +//------------------------------------------------------------------------------- +// Draw the HUD on top of the scene +int CDisplay::DrawHUD() +{ + // HACK: (thom) can't get the effect to work on non-shader cards, therefore deactivated for the moment + if( g_sCaps.PixelShaderVersion < D3DPS_VERSION(2,0)) + return 1; + + // get the dimension of the back buffer + RECT sRect; + GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect); + sRect.right -= sRect.left; + sRect.bottom -= sRect.top; + + // 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 + if( g_sCaps.PixelShaderVersion < D3DPS_VERSION(2,0)) + g_piPassThroughEffect->SetTechnique( "PassThrough_FF"); + else + 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; + + g_piDevice->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR); + g_piDevice->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR); + + // 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; +} +//------------------------------------------------------------------------------- +// Render the full scene, all nodes +int CDisplay::RenderFullScene() +{ + // reset the color index used for drawing normals + g_iCurrentColor = 0; + + aiMatrix4x4 pcProj; + GetProjectionMatrix(pcProj); + + vPos = GetCameraMatrix(mViewProjection); + mViewProjection = mViewProjection * pcProj; + + // 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); + + if (g_sOptions.bCulling) + g_piDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_CCW); + else g_piDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE); + + // for high-quality mode, enable anisotropic texture filtering + if (g_sOptions.bLowQuality) { + for (DWORD d = 0; d < 8;++d) { + g_piDevice->SetSamplerState(d,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR); + g_piDevice->SetSamplerState(d,D3DSAMP_MINFILTER,D3DTEXF_LINEAR); + g_piDevice->SetSamplerState(d,D3DSAMP_MIPFILTER,D3DTEXF_LINEAR); + } + } + else { + for (DWORD d = 0; d < 8;++d) { + g_piDevice->SetSamplerState(d,D3DSAMP_MAGFILTER,D3DTEXF_ANISOTROPIC); + g_piDevice->SetSamplerState(d,D3DSAMP_MINFILTER,D3DTEXF_ANISOTROPIC); + g_piDevice->SetSamplerState(d,D3DSAMP_MIPFILTER,D3DTEXF_LINEAR); + + g_piDevice->SetSamplerState(d,D3DSAMP_MAXANISOTROPY,g_sCaps.MaxAnisotropy); + } + } + + // draw the scene background (clear and texture 2d) + CBackgroundPainter::Instance().OnPreRender(); + + // setup the stereo view if necessary + if (g_sOptions.bStereoView) + SetupStereoView(); + + + // draw all opaque objects in the scene + aiMatrix4x4 m; + if (NULL != g_pcAsset && NULL != g_pcAsset->pcScene->mRootNode) + { + 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 + 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 + if (!g_sOptions.bNoAlphaBlending) { + g_piDevice->SetRenderState(D3DRS_ZWRITEENABLE,FALSE); + } + RenderNode(g_pcAsset->pcScene->mRootNode,m,true); + + if (!g_sOptions.bNoAlphaBlending) { + g_piDevice->SetRenderState(D3DRS_ZWRITEENABLE,TRUE); + } + } + + // setup the stereo view if necessary + if (g_sOptions.bStereoView) + RenderStereoView(m); + + // render the skeleton if necessary + if (g_sOptions.bSkeleton && NULL != g_pcAsset && NULL != g_pcAsset->pcScene->mRootNode) { + // disable the z-buffer + g_piDevice->SetRenderState(D3DRS_ZWRITEENABLE,FALSE); + + if (g_sOptions.eDrawMode != RenderOptions::WIREFRAME) { + g_piDevice->SetRenderState(D3DRS_ZENABLE,FALSE); + } + + g_piDevice->SetVertexDeclaration( gDefaultVertexDecl); + // this is very similar to the code in SetupMaterial() + ID3DXEffect* piEnd = g_piNormalsEffect; + aiMatrix4x4 pcProj = m * mViewProjection; + + D3DXVECTOR4 vVector(1.f,0.f,0.f,1.f); + piEnd->SetVector("OUTPUT_COLOR",&vVector); + piEnd->SetMatrix("WorldViewProjection", (const D3DXMATRIX*)&pcProj); + + UINT dwPasses = 0; + piEnd->Begin(&dwPasses,0); + piEnd->BeginPass(0); + + RenderSkeleton(g_pcAsset->pcScene->mRootNode,m,m); + + piEnd->EndPass();piEnd->End(); + g_piDevice->SetRenderState(D3DRS_ZWRITEENABLE,TRUE); + g_piDevice->SetRenderState(D3DRS_ZENABLE,TRUE); + } + + // draw the HUD texture on top of the rendered scene using + // pre-projected vertices + if (!g_bFPSView && g_pcAsset && g_pcTexture) + DrawHUD(); + + return 1; +} +//------------------------------------------------------------------------------- +int CDisplay::RenderMaterialView() +{ + return 1; +} +//------------------------------------------------------------------------------- +// Render animation skeleton +int CDisplay::RenderSkeleton (aiNode* piNode,const aiMatrix4x4& piMatrix, const aiMatrix4x4& parent) +{ + aiMatrix4x4 me = g_pcAsset->mAnimator->GetGlobalTransform( piNode); + + me.Transpose(); + //me *= piMatrix; + + if (piNode->mParent) { + AssetHelper::LineVertex data[2]; + data[0].dColorDiffuse = data[1].dColorDiffuse = D3DCOLOR_ARGB(0xff,0xff,0,0); + + data[0].vPosition.x = parent.d1; + data[0].vPosition.y = parent.d2; + data[0].vPosition.z = parent.d3; + + data[1].vPosition.x = me.d1; + data[1].vPosition.y = me.d2; + data[1].vPosition.z = me.d3; + + g_piDevice->DrawPrimitiveUP(D3DPT_LINELIST,1,&data,sizeof(AssetHelper::LineVertex)); + } + + // render all child nodes + for (unsigned int i = 0; i < piNode->mNumChildren;++i) + RenderSkeleton(piNode->mChildren[i],piMatrix, me ); + + return 1; +} +//------------------------------------------------------------------------------- +// Render a single node +int CDisplay::RenderNode (aiNode* piNode,const aiMatrix4x4& piMatrix, + bool bAlpha /*= false*/) +{ + aiMatrix4x4 aiMe = g_pcAsset->mAnimator->GetGlobalTransform( piNode); + + aiMe.Transpose(); + aiMe *= piMatrix; + + bool bChangedVM = false; + if (VIEWMODE_NODE == m_iViewMode && m_pcCurrentNode) + { + if (piNode != m_pcCurrentNode->psNode) + { + // directly call our children + for (unsigned int i = 0; i < piNode->mNumChildren;++i) + RenderNode(piNode->mChildren[i],piMatrix,bAlpha ); + + return 1; + } + m_iViewMode = VIEWMODE_FULL; + bChangedVM = true; + } + + aiMatrix4x4 pcProj = aiMe * mViewProjection; + + aiMatrix4x4 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[0].w = 0.0f; + 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; + apcVec[1].w = 0.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; + + if( g_sOptions.b3Lights) + { + 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; + } else + { + 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]); + + // setup the best technique + if( g_sCaps.PixelShaderVersion < D3DPS_VERSION(2,0)) + { + g_piDefaultEffect->SetTechnique( "DefaultFXSpecular_FF"); + } else + 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) + { + const aiMesh* mesh = g_pcAsset->pcScene->mMeshes[piNode->mMeshes[i]]; + AssetHelper::MeshHelper* helper = g_pcAsset->apcMeshes[piNode->mMeshes[i]]; + + // don't render the mesh if the render pass is incorrect + if (g_sOptions.bRenderMats && (helper->piOpacityTexture || helper->fOpacity != 1.0f) && !mesh->HasBones()) + { + if (!bAlpha)continue; + } + else if (bAlpha)continue; + + // Upload bone matrices. This maybe is the wrong place to do it, but for the heck of it I don't understand this code flow + if( mesh->HasBones()) + { + if( helper->piEffect) + { + static float matrices[4*4*60]; + float* tempmat = matrices; + const std::vector<aiMatrix4x4>& boneMats = g_pcAsset->mAnimator->GetBoneMatrices( piNode, i); + ai_assert( boneMats.size() == mesh->mNumBones); + + for( unsigned int a = 0; a < mesh->mNumBones; a++) + { + const aiMatrix4x4& mat = boneMats[a]; + *tempmat++ = mat.a1; *tempmat++ = mat.a2; *tempmat++ = mat.a3; *tempmat++ = mat.a4; + *tempmat++ = mat.b1; *tempmat++ = mat.b2; *tempmat++ = mat.b3; *tempmat++ = mat.b4; + *tempmat++ = mat.c1; *tempmat++ = mat.c2; *tempmat++ = mat.c3; *tempmat++ = mat.c4; + *tempmat++ = mat.d1; *tempmat++ = mat.d2; *tempmat++ = mat.d3; *tempmat++ = mat.d4; + //tempmat += 4; + } + + if( g_sOptions.bRenderMats) + { + helper->piEffect->SetMatrixTransposeArray( "gBoneMatrix", (D3DXMATRIX*)matrices, 60); + } else + { + g_piDefaultEffect->SetMatrixTransposeArray( "gBoneMatrix", (D3DXMATRIX*)matrices, 60); + g_piDefaultEffect->CommitChanges(); + } + } + } else + { + // upload identity matrices instead. Only the first is ever going to be used in meshes without bones + if( !g_sOptions.bRenderMats) + { + D3DXMATRIX identity( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); + g_piDefaultEffect->SetMatrixTransposeArray( "gBoneMatrix", &identity, 1); + g_piDefaultEffect->CommitChanges(); + } + } + + // now setup the material + if (g_sOptions.bRenderMats) + { + CMaterialManager::Instance().SetupMaterial( helper, pcProj, aiMe, pcCam, vPos); + } + g_piDevice->SetVertexDeclaration( gDefaultVertexDecl); + + if (g_sOptions.bNoAlphaBlending) { + // manually disable alphablending + g_piDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,FALSE); + } + + 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( helper); + } + + // render normal vectors? + if (g_sOptions.bRenderNormals && helper->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, helper->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],piMatrix,bAlpha ); + + // need to reset the viewmode? + if (bChangedVM) + m_iViewMode = VIEWMODE_NODE; + return 1; +} +//------------------------------------------------------------------------------- +int CDisplay::RenderPatternBG() +{ + if (!g_piPatternEffect) + { + // the pattern effect won't work on ps_2_0 cards + if (g_sCaps.PixelShaderVersion >= D3DPS_VERSION(3,0)) + { + // 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; + } + } + else + { + // clear the color buffer in magenta + // (hopefully this is ugly enough that every ps_2_0 cards owner + // runs to the next shop to buy himself a new card ...) + g_piDevice->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, + D3DCOLOR_ARGB(0xFF,0xFF,0,0xFF), 1.0f,0 ); + return 1; + } + } + + // clear the depth buffer only + g_piDevice->Clear(0,NULL,D3DCLEAR_ZBUFFER, + D3DCOLOR_ARGB(0xFF,0xFF,0,0xFF), 1.0f,0 ); + + // setup the colors to be used ... + g_piPatternEffect->SetVector("COLOR_ONE",&m_avCheckerColors[0]); + g_piPatternEffect->SetVector("COLOR_TWO",&m_avCheckerColors[1]); + + // 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 + RenderPatternBG(); + + // it might be that there is no texture ... + if (!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",*m_pcCurrentTexture->piTexture); + + if (aiTextureType_OPACITY == m_pcCurrentTexture->iType) + { + g_piPassThroughEffect->SetTechnique("PassThroughAlphaFromR"); + } + else if ((aiTextureType_OPACITY | 0x40000000) == m_pcCurrentTexture->iType) + { + g_piPassThroughEffect->SetTechnique("PassThroughAlphaFromA"); + } + else if( g_sCaps.PixelShaderVersion < D3DPS_VERSION(2,0)) + g_piPassThroughEffect->SetTechnique( "PassThrough_FF"); + else + g_piPassThroughEffect->SetTechnique("PassThrough"); + + UINT dw; + g_piPassThroughEffect->Begin(&dw,0); + g_piPassThroughEffect->BeginPass(0); + + if (aiTextureType_HEIGHT == m_pcCurrentTexture->iType || + aiTextureType_NORMALS == m_pcCurrentTexture->iType || g_sOptions.bNoAlphaBlending) + { + // 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; + if ( m_pcCurrentTexture->piTexture && *m_pcCurrentTexture->piTexture) { /* just a dirty fix */ + (*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 = min((nx-30) / x,(ny-30) / y) * (m_fTextureZoom/1000.0f); + + float fHalfX = (nx - (f * x)) / 2.0f; + float fHalfY = (ny - (f * y)) / 2.0f; + as[1].x = fHalfX + m_vTextureOffset.x; + as[1].y = fHalfY + 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 + m_vTextureOffset.x; + as[3].y = fHalfY + 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 + m_vTextureOffset.x; + as[0].y = ny-fHalfY + 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 + m_vTextureOffset.x; + as[2].y = ny-fHalfY + 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 5b282bbdf..3382d38bb 100644 --- a/tools/assimp_view/Display.h +++ b/tools/assimp_view/Display.h @@ -1,542 +1,542 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2012, assimp 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 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 - -#include <windows.h> -#include <shellapi.h> -#include <commctrl.h> - -// 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 - -namespace AssimpView -{ - - //------------------------------------------------------------------------------- - /* Corresponds to the "Display" combobox in the UI - */ - //------------------------------------------------------------------------------- - class CDisplay - { - private: - - // 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; - }; - - // 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; - - this->m_avCheckerColors[ 0 ].x = this->m_avCheckerColors[ 0 ].y = this->m_avCheckerColors[ 0 ].z = 0.4f; - this->m_avCheckerColors[ 1 ].x = this->m_avCheckerColors[ 1 ].y = this->m_avCheckerColors[ 1 ].z = 0.6f; - } - - 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 mesh in the tree view - struct MeshInfo - { - // the mesh object - aiMesh* psMesh; - - // 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 adds all subnodes as well - // 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 ); - - //------------------------------------------------------------------ - // Add a mesh to the display list - // iIndex - Index of the mesh in the scene's mesh list - // hRoot - Parent tree view node - int AddMeshToDisplayList( - unsigned int iIndex, - 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 ); - - //------------------------------------------------------------------ - // Enable animation-related parts of the UI - int EnableAnimTools( BOOL hm ); - - //------------------------------------------------------------------ - // 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 mesh to the list - inline void AddMesh( const MeshInfo& info ) - { - this->m_asMeshes.push_back( info ); - } - - //------------------------------------------------------------------ - // add a new material to the list - inline void AddMaterial( const MaterialInfo& info ) - { - this->m_asMaterials.push_back( info ); - } - - //------------------------------------------------------------------ - // set the primary color of the checker pattern background - inline void SetFirstCheckerColor( D3DXVECTOR4 c ) - { - this->m_avCheckerColors[ 0 ] = c; - } - - //------------------------------------------------------------------ - // set the secondary color of the checker pattern background - inline void SetSecondCheckerColor( D3DXVECTOR4 c ) - { - this->m_avCheckerColors[ 1 ] = c; - } - - //------------------------------------------------------------------ - // get the primary color of the checker pattern background - inline const D3DXVECTOR4* GetFirstCheckerColor() const - { - return &this->m_avCheckerColors[ 0 ]; - } - - //------------------------------------------------------------------ - // get the secondary color of the checker pattern background - inline const D3DXVECTOR4* GetSecondCheckerColor() const - { - return &this->m_avCheckerColors[ 1 ]; - } - - 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 ); - - //------------------------------------------------------------------ - // Render skeleton - int RenderSkeleton( aiNode* piNode, const aiMatrix4x4& piMatrix, - const aiMatrix4x4& parent ); - - - - private: - - // view mode - unsigned int m_iViewMode; - - // List of all textures in the display CB - std::vector<TextureInfo> m_asTextures; - - // current texture or NULL if no texture is active - TextureInfo* m_pcCurrentTexture; - - // List of all node in the display CB - std::vector<NodeInfo> m_asNodes; - - // List of all node in the display CB - std::vector<MeshInfo> m_asMeshes; - - // current Node or NULL if no Node is active - NodeInfo* m_pcCurrentNode; - - // List of all materials in the display CB - std::vector<MaterialInfo> m_asMaterials; - - // current material or NULL if no material is active - MaterialInfo* m_pcCurrentMaterial; - - // indices into the image list of the "display" tree view control - unsigned int m_aiImageList[ 5 ]; /* = {0,1,2,3,4};*/ - - // Image list - HIMAGELIST m_hImageList; - - // Root node of the tree, "Model" - HTREEITEM m_hRoot; - - // Current zoom factor of the texture viewer - float m_fTextureZoom; - - // Current offset (in pixels) of the texture viewer - aiVector2D m_vTextureOffset; - - // Colors used to draw the checker pattern (for the - // texture viewer as background ) - D3DXVECTOR4 m_avCheckerColors[ 2 ]; - - // View projection matrix - aiMatrix4x4 mViewProjection; - aiVector3D vPos; - }; - -} +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2012, assimp 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 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 + +#include <windows.h> +#include <shellapi.h> +#include <commctrl.h> + +// 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 + +namespace AssimpView +{ + + //------------------------------------------------------------------------------- + /* Corresponds to the "Display" combobox in the UI + */ + //------------------------------------------------------------------------------- + class CDisplay + { + private: + + // 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; + }; + + // 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; + + this->m_avCheckerColors[ 0 ].x = this->m_avCheckerColors[ 0 ].y = this->m_avCheckerColors[ 0 ].z = 0.4f; + this->m_avCheckerColors[ 1 ].x = this->m_avCheckerColors[ 1 ].y = this->m_avCheckerColors[ 1 ].z = 0.6f; + } + + 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 mesh in the tree view + struct MeshInfo + { + // the mesh object + aiMesh* psMesh; + + // 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 adds all subnodes as well + // 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 ); + + //------------------------------------------------------------------ + // Add a mesh to the display list + // iIndex - Index of the mesh in the scene's mesh list + // hRoot - Parent tree view node + int AddMeshToDisplayList( + unsigned int iIndex, + 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 ); + + //------------------------------------------------------------------ + // Enable animation-related parts of the UI + int EnableAnimTools( BOOL hm ); + + //------------------------------------------------------------------ + // 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 mesh to the list + inline void AddMesh( const MeshInfo& info ) + { + this->m_asMeshes.push_back( info ); + } + + //------------------------------------------------------------------ + // add a new material to the list + inline void AddMaterial( const MaterialInfo& info ) + { + this->m_asMaterials.push_back( info ); + } + + //------------------------------------------------------------------ + // set the primary color of the checker pattern background + inline void SetFirstCheckerColor( D3DXVECTOR4 c ) + { + this->m_avCheckerColors[ 0 ] = c; + } + + //------------------------------------------------------------------ + // set the secondary color of the checker pattern background + inline void SetSecondCheckerColor( D3DXVECTOR4 c ) + { + this->m_avCheckerColors[ 1 ] = c; + } + + //------------------------------------------------------------------ + // get the primary color of the checker pattern background + inline const D3DXVECTOR4* GetFirstCheckerColor() const + { + return &this->m_avCheckerColors[ 0 ]; + } + + //------------------------------------------------------------------ + // get the secondary color of the checker pattern background + inline const D3DXVECTOR4* GetSecondCheckerColor() const + { + return &this->m_avCheckerColors[ 1 ]; + } + + 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 ); + + //------------------------------------------------------------------ + // Render skeleton + int RenderSkeleton( aiNode* piNode, const aiMatrix4x4& piMatrix, + const aiMatrix4x4& parent ); + + + + private: + + // view mode + unsigned int m_iViewMode; + + // List of all textures in the display CB + std::vector<TextureInfo> m_asTextures; + + // current texture or NULL if no texture is active + TextureInfo* m_pcCurrentTexture; + + // List of all node in the display CB + std::vector<NodeInfo> m_asNodes; + + // List of all node in the display CB + std::vector<MeshInfo> m_asMeshes; + + // current Node or NULL if no Node is active + NodeInfo* m_pcCurrentNode; + + // List of all materials in the display CB + std::vector<MaterialInfo> m_asMaterials; + + // current material or NULL if no material is active + MaterialInfo* m_pcCurrentMaterial; + + // indices into the image list of the "display" tree view control + unsigned int m_aiImageList[ 5 ]; /* = {0,1,2,3,4};*/ + + // Image list + HIMAGELIST m_hImageList; + + // Root node of the tree, "Model" + HTREEITEM m_hRoot; + + // Current zoom factor of the texture viewer + float m_fTextureZoom; + + // Current offset (in pixels) of the texture viewer + aiVector2D m_vTextureOffset; + + // Colors used to draw the checker pattern (for the + // texture viewer as background ) + D3DXVECTOR4 m_avCheckerColors[ 2 ]; + + // View projection matrix + aiMatrix4x4 mViewProjection; + aiVector3D vPos; + }; + +} #endif // AV_DISPLAY_H_INCLUDE \ No newline at end of file diff --git a/tools/assimp_view/HelpDialog.cpp b/tools/assimp_view/HelpDialog.cpp index b639113b2..7b2ebf7b6 100644 --- a/tools/assimp_view/HelpDialog.cpp +++ b/tools/assimp_view/HelpDialog.cpp @@ -1,108 +1,108 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2015, assimp 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 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 "assimp_view.h" - -#include "richedit.h" - -namespace AssimpView { - -//------------------------------------------------------------------------------- -// Message procedure for the help dialog -//------------------------------------------------------------------------------- -INT_PTR CALLBACK HelpDialogProc(HWND hwndDlg,UINT uMsg, - WPARAM wParam,LPARAM lParam) - { - (void)lParam; - switch (uMsg) - { - case WM_INITDIALOG: - { - // load the help file ... - HRSRC res = FindResource(NULL,MAKEINTRESOURCE(IDR_TEXT1),"TEXT"); - HGLOBAL hg = LoadResource(NULL,res); - void* pData = LockResource(hg); - - SETTEXTEX sInfo; - sInfo.flags = ST_DEFAULT; - sInfo.codepage = CP_ACP; - - SendDlgItemMessage(hwndDlg,IDC_RICHEDIT21, - EM_SETTEXTEX,(WPARAM)&sInfo,( LPARAM) pData); - - FreeResource(hg); - return TRUE; - } - - case WM_CLOSE: - EndDialog(hwndDlg,0); - return TRUE; - - case WM_COMMAND: - - if (IDOK == LOWORD(wParam)) - { - EndDialog(hwndDlg,0); - return TRUE; - } - - case WM_PAINT: - { - PAINTSTRUCT sPaint; - HDC hdc = BeginPaint(hwndDlg,&sPaint); - - HBRUSH hBrush = CreateSolidBrush(RGB(0xFF,0xFF,0xFF)); - - RECT sRect; - sRect.left = 0; - sRect.top = 26; - sRect.right = 1000; - sRect.bottom = 507; - FillRect(hdc, &sRect, hBrush); - - EndPaint(hwndDlg,&sPaint); - return TRUE; - } - }; - return FALSE; - } - +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2015, assimp 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 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 "assimp_view.h" + +#include "richedit.h" + +namespace AssimpView { + +//------------------------------------------------------------------------------- +// Message procedure for the help dialog +//------------------------------------------------------------------------------- +INT_PTR CALLBACK HelpDialogProc(HWND hwndDlg,UINT uMsg, + WPARAM wParam,LPARAM lParam) + { + (void)lParam; + switch (uMsg) + { + case WM_INITDIALOG: + { + // load the help file ... + HRSRC res = FindResource(NULL,MAKEINTRESOURCE(IDR_TEXT1),"TEXT"); + HGLOBAL hg = LoadResource(NULL,res); + void* pData = LockResource(hg); + + SETTEXTEX sInfo; + sInfo.flags = ST_DEFAULT; + sInfo.codepage = CP_ACP; + + SendDlgItemMessage(hwndDlg,IDC_RICHEDIT21, + EM_SETTEXTEX,(WPARAM)&sInfo,( LPARAM) pData); + + FreeResource(hg); + return TRUE; + } + + case WM_CLOSE: + EndDialog(hwndDlg,0); + return TRUE; + + case WM_COMMAND: + + if (IDOK == LOWORD(wParam)) + { + EndDialog(hwndDlg,0); + return TRUE; + } + + case WM_PAINT: + { + PAINTSTRUCT sPaint; + HDC hdc = BeginPaint(hwndDlg,&sPaint); + + HBRUSH hBrush = CreateSolidBrush(RGB(0xFF,0xFF,0xFF)); + + RECT sRect; + sRect.left = 0; + sRect.top = 26; + sRect.right = 1000; + sRect.bottom = 507; + FillRect(hdc, &sRect, hBrush); + + EndPaint(hwndDlg,&sPaint); + return TRUE; + } + }; + return FALSE; + } + }; \ No newline at end of file diff --git a/tools/assimp_view/Input.cpp b/tools/assimp_view/Input.cpp index a947742a5..7a9582fb2 100644 --- a/tools/assimp_view/Input.cpp +++ b/tools/assimp_view/Input.cpp @@ -1,372 +1,372 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2015, assimp 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 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 "assimp_view.h" - -namespace AssimpView { - -//------------------------------------------------------------------------------- -// Handle mouse input for the FPS input behaviour -// -// Movement in x and y axis is possible -//------------------------------------------------------------------------------- -void HandleMouseInputFPS( 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) - { - int nXDiff = (g_mousePos.x - g_LastmousePos.x); - int nYDiff = (g_mousePos.y - g_LastmousePos.y); - - if( 0 != nYDiff) - { - D3DXMatrixRotationAxis( &matRotation, (D3DXVECTOR3*)& g_sCamera.vRight, D3DXToRadian((float)nYDiff / 6.0f)); - D3DXVec3TransformCoord( (D3DXVECTOR3*)&g_sCamera.vLookAt, (D3DXVECTOR3*)& g_sCamera.vLookAt, &matRotation ); - D3DXVec3TransformCoord( (D3DXVECTOR3*)&g_sCamera.vUp, (D3DXVECTOR3*)&g_sCamera.vUp, &matRotation ); - } - - if( 0 != nXDiff ) - { - D3DXVECTOR3 v(0,1,0); - D3DXMatrixRotationAxis( &matRotation, (D3DXVECTOR3*)&g_sCamera.vUp, D3DXToRadian((float)nXDiff / 6.0f) ); - D3DXVec3TransformCoord( (D3DXVECTOR3*)&g_sCamera.vLookAt, (D3DXVECTOR3*)&g_sCamera.vLookAt, &matRotation ); - D3DXVec3TransformCoord( (D3DXVECTOR3*)&g_sCamera.vRight,(D3DXVECTOR3*) &g_sCamera.vRight, &matRotation ); - } - } - - g_LastmousePos.x = g_mousePos.x; - g_LastmousePos.y = g_mousePos.y; - } - - -//------------------------------------------------------------------------------- -// 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 -// -// Axes: global x/y axis -//------------------------------------------------------------------------------- -void HandleMouseInputLightRotate( void ) - { - POINT mousePos; - GetCursorPos( &mousePos ); - ScreenToClient( GetDlgItem(g_hDlg,IDC_RT), &mousePos ); - - g_mousePos.x = mousePos.x; - g_mousePos.y = mousePos.y; - - if (g_bMousePressedR) - { - int nXDiff = -(g_mousePos.x - g_LastmousePos.x); - int nYDiff = -(g_mousePos.y - g_LastmousePos.y); - - aiVector3D v = aiVector3D(1.0f,0.0f,0.0f); - aiMatrix4x4 mTemp; - D3DXMatrixRotationAxis( (D3DXMATRIX*) &mTemp, (D3DXVECTOR3*)&v, D3DXToRadian((float)nYDiff / 2.0f)); - D3DXVec3TransformCoord((D3DXVECTOR3*)&g_avLightDirs[0], - (const D3DXVECTOR3*)&g_avLightDirs[0],(const D3DXMATRIX*)&mTemp); - - v = aiVector3D(0.0f,1.0f,0.0f); - D3DXMatrixRotationAxis( (D3DXMATRIX*) &mTemp, (D3DXVECTOR3*)&v, D3DXToRadian((float)nXDiff / 2.0f)); - D3DXVec3TransformCoord((D3DXVECTOR3*)&g_avLightDirs[0], - (const D3DXVECTOR3*)&g_avLightDirs[0],(const D3DXMATRIX*)&mTemp); - } - return; - } - - -//------------------------------------------------------------------------------- -// Handle mouse input for movements of the skybox -// -// The skybox can be moved by holding both the left and the right mouse button -// pressed. Rotation is possible in x and y direction. -//------------------------------------------------------------------------------- -void HandleMouseInputSkyBox( void ) - { - POINT mousePos; - GetCursorPos( &mousePos ); - ScreenToClient( GetDlgItem(g_hDlg,IDC_RT), &mousePos ); - - g_mousePos.x = mousePos.x; - g_mousePos.y = mousePos.y; - - aiMatrix4x4 matRotation; - - if (g_bMousePressedBoth ) - { - int nXDiff = -(g_mousePos.x - g_LastmousePos.x); - int nYDiff = -(g_mousePos.y - g_LastmousePos.y); - - aiMatrix4x4 matWorld; - - if( 0 != nYDiff) - { - aiVector3D v = aiVector3D(1.0f,0.0f,0.0f); - D3DXMatrixRotationAxis( (D3DXMATRIX*) &matWorld, (D3DXVECTOR3*)&v, D3DXToRadian((float)nYDiff / 2.0f)); - CBackgroundPainter::Instance().RotateSB(&matWorld); - } - - if( 0 != nXDiff) - { - aiMatrix4x4 matWorldOld; - if( 0 != nYDiff) - { - matWorldOld = matWorld; - } - - aiVector3D v = aiVector3D(0.0f,1.0f,0.0f); - D3DXMatrixRotationAxis( (D3DXMATRIX*)&matWorld, (D3DXVECTOR3*)&v, D3DXToRadian((float)nXDiff / 2.0f) ); - matWorld = matWorldOld * matWorld; - CBackgroundPainter::Instance().RotateSB(&matWorld); - } - } - } - -//------------------------------------------------------------------------------- -//------------------------------------------------------------------------------- -void HandleMouseInputLightIntensityAndColor( void ) - { - POINT mousePos; - GetCursorPos( &mousePos ); - ScreenToClient( GetDlgItem(g_hDlg,IDC_RT), &mousePos ); - - g_mousePos.x = mousePos.x; - g_mousePos.y = mousePos.y; - - if (g_bMousePressedM) - { - int nXDiff = -(g_mousePos.x - g_LastmousePos.x); - 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) - { - g_sCamera.vPos.z += nYDiff / 120.0f; - } - else - { - g_sCamera.vPos += (nYDiff / 120.0f) * g_sCamera.vLookAt.Normalize(); - } - } - } - return; - } - -//------------------------------------------------------------------------------- -//------------------------------------------------------------------------------- -void HandleMouseInputLocal( void ) - { - POINT mousePos; - GetCursorPos( &mousePos ); - ScreenToClient( GetDlgItem(g_hDlg,IDC_RT), &mousePos ); - - g_mousePos.x = mousePos.x; - g_mousePos.y = mousePos.y; - - aiMatrix4x4 matRotation; - - if (g_bMousePressed) - { - int nXDiff = -(g_mousePos.x - g_LastmousePos.x); - int nYDiff = -(g_mousePos.y - g_LastmousePos.y); - - aiMatrix4x4 matWorld; - if (g_eClick != EClickPos_Outside) - { - if( 0 != nYDiff && g_eClick != EClickPos_CircleHor) - { - aiVector3D v = aiVector3D(1.0f,0.0f,0.0f); - D3DXMatrixRotationAxis( (D3DXMATRIX*) &matWorld, (D3DXVECTOR3*)&v, D3DXToRadian((float)nYDiff / 2.0f)); - g_mWorldRotate = g_mWorldRotate * matWorld; - } - - if( 0 != nXDiff && g_eClick != EClickPos_CircleVert) - { - aiVector3D v = aiVector3D(0.0f,1.0f,0.0f); - D3DXMatrixRotationAxis( (D3DXMATRIX*)&matWorld, (D3DXVECTOR3*)&v, D3DXToRadian((float)nXDiff / 2.0f) ); - g_mWorldRotate = g_mWorldRotate * matWorld; - } - } - else - { - if(0 != nYDiff || 0 != nXDiff) - { - // rotate around the z-axis - RECT sRect; - GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect); - sRect.right -= sRect.left; - sRect.bottom -= sRect.top; - - int xPos = g_mousePos.x - sRect.right/2; - int yPos = g_mousePos.y - sRect.bottom/2; - float fXDist = (float)xPos; - float fYDist = (float)yPos / sqrtf((float)(yPos * yPos + xPos * xPos)); - - bool bSign1; - if (fXDist < 0.0f)bSign1 = false; - else bSign1 = true; - float fAngle = asin(fYDist); - - xPos = g_LastmousePos.x - sRect.right/2; - yPos = g_LastmousePos.y - sRect.bottom/2; - - fXDist = (float)xPos; - fYDist = (float)yPos / sqrtf((float)(yPos * yPos + xPos * xPos)); - - bool bSign2; - if (fXDist < 0.0f)bSign2 = false; - else bSign2 = true; - float fAngle2 = asin(fYDist); - fAngle -= fAngle2; - - if (bSign1 != bSign2) - { - g_bInvert = !g_bInvert; - } - if (g_bInvert)fAngle *= -1.0f; - - aiVector3D v = aiVector3D(0.0f,0.0f,1.0f); - D3DXMatrixRotationAxis( (D3DXMATRIX*)&matWorld, (D3DXVECTOR3*)&v, (float) (fAngle * 1.2) ); - g_mWorldRotate = g_mWorldRotate * matWorld; - } - } - } - - g_LastmousePos.x = g_mousePos.x; - g_LastmousePos.y = g_mousePos.y; - } - -//------------------------------------------------------------------------------- -//------------------------------------------------------------------------------- -void HandleKeyboardInputFPS( void ) - { - unsigned char keys[256]; - GetKeyboardState( keys ); - - 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; - - // Down Arrow Key - View moves backward - if( keys[VK_DOWN] & 0x80 ) - g_sCamera.vPos += (tmpLook*-MOVE_SPEED)*g_fElpasedTime; - - // Left Arrow Key - View side-steps or strafes to the left - if( keys[VK_LEFT] & 0x80 ) - g_sCamera.vPos -= (tmpRight*MOVE_SPEED)*g_fElpasedTime; - - // Right Arrow Key - View side-steps or strafes to the right - if( keys[VK_RIGHT] & 0x80 ) - g_sCamera.vPos += (tmpRight*MOVE_SPEED)*g_fElpasedTime; - - // Home Key - View elevates up - if( keys[VK_HOME] & 0x80 ) - g_sCamera.vPos .y += MOVE_SPEED*g_fElpasedTime; - - // End Key - View elevates down - if( keys[VK_END] & 0x80 ) - g_sCamera.vPos.y -= MOVE_SPEED*g_fElpasedTime; - } - - -//------------------------------------------------------------------------------- -//------------------------------------------------------------------------------- -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 ); - } +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2015, assimp 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 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 "assimp_view.h" + +namespace AssimpView { + +//------------------------------------------------------------------------------- +// Handle mouse input for the FPS input behaviour +// +// Movement in x and y axis is possible +//------------------------------------------------------------------------------- +void HandleMouseInputFPS( 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) + { + int nXDiff = (g_mousePos.x - g_LastmousePos.x); + int nYDiff = (g_mousePos.y - g_LastmousePos.y); + + if( 0 != nYDiff) + { + D3DXMatrixRotationAxis( &matRotation, (D3DXVECTOR3*)& g_sCamera.vRight, D3DXToRadian((float)nYDiff / 6.0f)); + D3DXVec3TransformCoord( (D3DXVECTOR3*)&g_sCamera.vLookAt, (D3DXVECTOR3*)& g_sCamera.vLookAt, &matRotation ); + D3DXVec3TransformCoord( (D3DXVECTOR3*)&g_sCamera.vUp, (D3DXVECTOR3*)&g_sCamera.vUp, &matRotation ); + } + + if( 0 != nXDiff ) + { + D3DXVECTOR3 v(0,1,0); + D3DXMatrixRotationAxis( &matRotation, (D3DXVECTOR3*)&g_sCamera.vUp, D3DXToRadian((float)nXDiff / 6.0f) ); + D3DXVec3TransformCoord( (D3DXVECTOR3*)&g_sCamera.vLookAt, (D3DXVECTOR3*)&g_sCamera.vLookAt, &matRotation ); + D3DXVec3TransformCoord( (D3DXVECTOR3*)&g_sCamera.vRight,(D3DXVECTOR3*) &g_sCamera.vRight, &matRotation ); + } + } + + g_LastmousePos.x = g_mousePos.x; + g_LastmousePos.y = g_mousePos.y; + } + + +//------------------------------------------------------------------------------- +// 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 +// +// Axes: global x/y axis +//------------------------------------------------------------------------------- +void HandleMouseInputLightRotate( void ) + { + POINT mousePos; + GetCursorPos( &mousePos ); + ScreenToClient( GetDlgItem(g_hDlg,IDC_RT), &mousePos ); + + g_mousePos.x = mousePos.x; + g_mousePos.y = mousePos.y; + + if (g_bMousePressedR) + { + int nXDiff = -(g_mousePos.x - g_LastmousePos.x); + int nYDiff = -(g_mousePos.y - g_LastmousePos.y); + + aiVector3D v = aiVector3D(1.0f,0.0f,0.0f); + aiMatrix4x4 mTemp; + D3DXMatrixRotationAxis( (D3DXMATRIX*) &mTemp, (D3DXVECTOR3*)&v, D3DXToRadian((float)nYDiff / 2.0f)); + D3DXVec3TransformCoord((D3DXVECTOR3*)&g_avLightDirs[0], + (const D3DXVECTOR3*)&g_avLightDirs[0],(const D3DXMATRIX*)&mTemp); + + v = aiVector3D(0.0f,1.0f,0.0f); + D3DXMatrixRotationAxis( (D3DXMATRIX*) &mTemp, (D3DXVECTOR3*)&v, D3DXToRadian((float)nXDiff / 2.0f)); + D3DXVec3TransformCoord((D3DXVECTOR3*)&g_avLightDirs[0], + (const D3DXVECTOR3*)&g_avLightDirs[0],(const D3DXMATRIX*)&mTemp); + } + return; + } + + +//------------------------------------------------------------------------------- +// Handle mouse input for movements of the skybox +// +// The skybox can be moved by holding both the left and the right mouse button +// pressed. Rotation is possible in x and y direction. +//------------------------------------------------------------------------------- +void HandleMouseInputSkyBox( void ) + { + POINT mousePos; + GetCursorPos( &mousePos ); + ScreenToClient( GetDlgItem(g_hDlg,IDC_RT), &mousePos ); + + g_mousePos.x = mousePos.x; + g_mousePos.y = mousePos.y; + + aiMatrix4x4 matRotation; + + if (g_bMousePressedBoth ) + { + int nXDiff = -(g_mousePos.x - g_LastmousePos.x); + int nYDiff = -(g_mousePos.y - g_LastmousePos.y); + + aiMatrix4x4 matWorld; + + if( 0 != nYDiff) + { + aiVector3D v = aiVector3D(1.0f,0.0f,0.0f); + D3DXMatrixRotationAxis( (D3DXMATRIX*) &matWorld, (D3DXVECTOR3*)&v, D3DXToRadian((float)nYDiff / 2.0f)); + CBackgroundPainter::Instance().RotateSB(&matWorld); + } + + if( 0 != nXDiff) + { + aiMatrix4x4 matWorldOld; + if( 0 != nYDiff) + { + matWorldOld = matWorld; + } + + aiVector3D v = aiVector3D(0.0f,1.0f,0.0f); + D3DXMatrixRotationAxis( (D3DXMATRIX*)&matWorld, (D3DXVECTOR3*)&v, D3DXToRadian((float)nXDiff / 2.0f) ); + matWorld = matWorldOld * matWorld; + CBackgroundPainter::Instance().RotateSB(&matWorld); + } + } + } + +//------------------------------------------------------------------------------- +//------------------------------------------------------------------------------- +void HandleMouseInputLightIntensityAndColor( void ) + { + POINT mousePos; + GetCursorPos( &mousePos ); + ScreenToClient( GetDlgItem(g_hDlg,IDC_RT), &mousePos ); + + g_mousePos.x = mousePos.x; + g_mousePos.y = mousePos.y; + + if (g_bMousePressedM) + { + int nXDiff = -(g_mousePos.x - g_LastmousePos.x); + 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) + { + g_sCamera.vPos.z += nYDiff / 120.0f; + } + else + { + g_sCamera.vPos += (nYDiff / 120.0f) * g_sCamera.vLookAt.Normalize(); + } + } + } + return; + } + +//------------------------------------------------------------------------------- +//------------------------------------------------------------------------------- +void HandleMouseInputLocal( void ) + { + POINT mousePos; + GetCursorPos( &mousePos ); + ScreenToClient( GetDlgItem(g_hDlg,IDC_RT), &mousePos ); + + g_mousePos.x = mousePos.x; + g_mousePos.y = mousePos.y; + + aiMatrix4x4 matRotation; + + if (g_bMousePressed) + { + int nXDiff = -(g_mousePos.x - g_LastmousePos.x); + int nYDiff = -(g_mousePos.y - g_LastmousePos.y); + + aiMatrix4x4 matWorld; + if (g_eClick != EClickPos_Outside) + { + if( 0 != nYDiff && g_eClick != EClickPos_CircleHor) + { + aiVector3D v = aiVector3D(1.0f,0.0f,0.0f); + D3DXMatrixRotationAxis( (D3DXMATRIX*) &matWorld, (D3DXVECTOR3*)&v, D3DXToRadian((float)nYDiff / 2.0f)); + g_mWorldRotate = g_mWorldRotate * matWorld; + } + + if( 0 != nXDiff && g_eClick != EClickPos_CircleVert) + { + aiVector3D v = aiVector3D(0.0f,1.0f,0.0f); + D3DXMatrixRotationAxis( (D3DXMATRIX*)&matWorld, (D3DXVECTOR3*)&v, D3DXToRadian((float)nXDiff / 2.0f) ); + g_mWorldRotate = g_mWorldRotate * matWorld; + } + } + else + { + if(0 != nYDiff || 0 != nXDiff) + { + // rotate around the z-axis + RECT sRect; + GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect); + sRect.right -= sRect.left; + sRect.bottom -= sRect.top; + + int xPos = g_mousePos.x - sRect.right/2; + int yPos = g_mousePos.y - sRect.bottom/2; + float fXDist = (float)xPos; + float fYDist = (float)yPos / sqrtf((float)(yPos * yPos + xPos * xPos)); + + bool bSign1; + if (fXDist < 0.0f)bSign1 = false; + else bSign1 = true; + float fAngle = asin(fYDist); + + xPos = g_LastmousePos.x - sRect.right/2; + yPos = g_LastmousePos.y - sRect.bottom/2; + + fXDist = (float)xPos; + fYDist = (float)yPos / sqrtf((float)(yPos * yPos + xPos * xPos)); + + bool bSign2; + if (fXDist < 0.0f)bSign2 = false; + else bSign2 = true; + float fAngle2 = asin(fYDist); + fAngle -= fAngle2; + + if (bSign1 != bSign2) + { + g_bInvert = !g_bInvert; + } + if (g_bInvert)fAngle *= -1.0f; + + aiVector3D v = aiVector3D(0.0f,0.0f,1.0f); + D3DXMatrixRotationAxis( (D3DXMATRIX*)&matWorld, (D3DXVECTOR3*)&v, (float) (fAngle * 1.2) ); + g_mWorldRotate = g_mWorldRotate * matWorld; + } + } + } + + g_LastmousePos.x = g_mousePos.x; + g_LastmousePos.y = g_mousePos.y; + } + +//------------------------------------------------------------------------------- +//------------------------------------------------------------------------------- +void HandleKeyboardInputFPS( void ) + { + unsigned char keys[256]; + GetKeyboardState( keys ); + + 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; + + // Down Arrow Key - View moves backward + if( keys[VK_DOWN] & 0x80 ) + g_sCamera.vPos += (tmpLook*-MOVE_SPEED)*g_fElpasedTime; + + // Left Arrow Key - View side-steps or strafes to the left + if( keys[VK_LEFT] & 0x80 ) + g_sCamera.vPos -= (tmpRight*MOVE_SPEED)*g_fElpasedTime; + + // Right Arrow Key - View side-steps or strafes to the right + if( keys[VK_RIGHT] & 0x80 ) + g_sCamera.vPos += (tmpRight*MOVE_SPEED)*g_fElpasedTime; + + // Home Key - View elevates up + if( keys[VK_HOME] & 0x80 ) + g_sCamera.vPos .y += MOVE_SPEED*g_fElpasedTime; + + // End Key - View elevates down + if( keys[VK_END] & 0x80 ) + g_sCamera.vPos.y -= MOVE_SPEED*g_fElpasedTime; + } + + +//------------------------------------------------------------------------------- +//------------------------------------------------------------------------------- +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.cpp b/tools/assimp_view/LogDisplay.cpp index d76cfa217..bf0c190b6 100644 --- a/tools/assimp_view/LogDisplay.cpp +++ b/tools/assimp_view/LogDisplay.cpp @@ -1,233 +1,233 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2015, assimp 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 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 "assimp_view.h" - -namespace AssimpView { - -CLogDisplay CLogDisplay::s_cInstance; - -//------------------------------------------------------------------------------- -void CLogDisplay::AddEntry(const std::string& szText, - const D3DCOLOR clrColor) - { - SEntry sNew; - sNew.clrColor = clrColor; - sNew.szText = szText; - sNew.dwStartTicks = (DWORD)GetTickCount(); - - this->asEntries.push_back(sNew); - } - -//------------------------------------------------------------------------------- -void CLogDisplay::ReleaseNativeResource() - { - if (this->piFont) - { - this->piFont->Release(); - this->piFont = NULL; - } - } - -//------------------------------------------------------------------------------- -void CLogDisplay::RecreateNativeResource() - { - if (!this->piFont) - { - if (FAILED(D3DXCreateFont(g_piDevice, - 16, //Font height - 0, //Font width - FW_BOLD, //Font Weight - 1, //MipLevels - false, //Italic - DEFAULT_CHARSET, //CharSet - OUT_DEFAULT_PRECIS, //OutputPrecision - //CLEARTYPE_QUALITY, //Quality - 5, //Quality - DEFAULT_PITCH|FF_DONTCARE, //PitchAndFamily - "Verdana", //pFacename, - &this->piFont))) - { - CLogDisplay::Instance().AddEntry("Unable to load font",D3DCOLOR_ARGB(0xFF,0xFF,0,0)); - - this->piFont = NULL; - return; - } - } - return; - } - -//------------------------------------------------------------------------------- -void CLogDisplay::OnRender() - { - DWORD dwTick = (DWORD) GetTickCount(); - DWORD dwLimit = dwTick - 8000; - DWORD dwLimit2 = dwLimit + 3000; - - unsigned int iCnt = 0; - RECT sRect; - sRect.left = 10; - sRect.top = 10; - - RECT sWndRect; - GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sWndRect); - sWndRect.right -= sWndRect.left; - sWndRect.bottom -= sWndRect.top; - sWndRect.left = sWndRect.top = 0; - - sRect.right = sWndRect.right - 30; - sRect.bottom = sWndRect.bottom; - - // if no asset is loaded draw a "no asset loaded" text in the center - if (!g_pcAsset) - { - const char* szText = "Nothing to display ... \r\nTry [Viewer | Open asset] to load an asset"; - - // shadow - RECT sCopy; - sCopy.left = sWndRect.left+1; - sCopy.top = sWndRect.top+1; - sCopy.bottom = sWndRect.bottom+1; - sCopy.right = sWndRect.right+1; - this->piFont->DrawText(NULL,szText , - -1,&sCopy,DT_CENTER | DT_VCENTER,D3DCOLOR_ARGB(100,0x0,0x0,0x0)); - sCopy.left = sWndRect.left+1; - sCopy.top = sWndRect.top+1; - sCopy.bottom = sWndRect.bottom-1; - sCopy.right = sWndRect.right-1; - this->piFont->DrawText(NULL,szText , - -1,&sCopy,DT_CENTER | DT_VCENTER,D3DCOLOR_ARGB(100,0x0,0x0,0x0)); - sCopy.left = sWndRect.left-1; - sCopy.top = sWndRect.top-1; - sCopy.bottom = sWndRect.bottom+1; - sCopy.right = sWndRect.right+1; - this->piFont->DrawText(NULL,szText , - -1,&sCopy,DT_CENTER | DT_VCENTER,D3DCOLOR_ARGB(100,0x0,0x0,0x0)); - sCopy.left = sWndRect.left-1; - sCopy.top = sWndRect.top-1; - sCopy.bottom = sWndRect.bottom-1; - sCopy.right = sWndRect.right-1; - this->piFont->DrawText(NULL,szText , - -1,&sCopy,DT_CENTER | DT_VCENTER,D3DCOLOR_ARGB(100,0x0,0x0,0x0)); - - // text - this->piFont->DrawText(NULL,szText , - -1,&sWndRect,DT_CENTER | DT_VCENTER,D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0xFF)); - } - - // update all elements in the queue and render them - for (std::list<SEntry>::iterator - i = this->asEntries.begin(); - i != this->asEntries.end();++i,++iCnt) - { - if ((*i).dwStartTicks < dwLimit) - { - i = this->asEntries.erase(i); - - if(i == this->asEntries.end())break; - } - else if (NULL != this->piFont) - { - float fAlpha = 1.0f; - if ((*i).dwStartTicks <= dwLimit2) - { - // linearly interpolate to create the fade out effect - fAlpha = 1.0f - (float)(dwLimit2 - (*i).dwStartTicks) / 3000.0f; - } - D3DCOLOR& clrColor = (*i).clrColor; - clrColor &= ~(0xFFu << 24); - clrColor |= (((unsigned char)(fAlpha * 255.0f)) & 0xFFu) << 24; - - const char* szText = (*i).szText.c_str(); - if (sRect.top + 30 > sWndRect.bottom) - { - // end of window. send a special message - szText = "... too many errors"; - clrColor = D3DCOLOR_ARGB(0xFF,0xFF,100,0x0); - } - - // draw the black shadow - RECT sCopy; - sCopy.left = sRect.left+1; - sCopy.top = sRect.top+1; - sCopy.bottom = sRect.bottom+1; - sCopy.right = sRect.right+1; - this->piFont->DrawText(NULL,szText, - -1,&sCopy,DT_RIGHT | DT_TOP,D3DCOLOR_ARGB( - (unsigned char)(fAlpha * 100.0f),0x0,0x0,0x0)); - - sCopy.left = sRect.left-1; - sCopy.top = sRect.top-1; - sCopy.bottom = sRect.bottom-1; - sCopy.right = sRect.right-1; - this->piFont->DrawText(NULL,szText, - -1,&sCopy,DT_RIGHT | DT_TOP,D3DCOLOR_ARGB( - (unsigned char)(fAlpha * 100.0f),0x0,0x0,0x0)); - - sCopy.left = sRect.left-1; - sCopy.top = sRect.top-1; - sCopy.bottom = sRect.bottom+1; - sCopy.right = sRect.right+1; - this->piFont->DrawText(NULL,szText, - -1,&sCopy,DT_RIGHT | DT_TOP,D3DCOLOR_ARGB( - (unsigned char)(fAlpha * 100.0f),0x0,0x0,0x0)); - - sCopy.left = sRect.left+1; - sCopy.top = sRect.top+1; - sCopy.bottom = sRect.bottom-1; - sCopy.right = sRect.right-1; - this->piFont->DrawText(NULL,szText, - -1,&sCopy,DT_RIGHT | DT_TOP,D3DCOLOR_ARGB( - (unsigned char)(fAlpha * 100.0f),0x0,0x0,0x0)); - - // draw the text itself - int iPX = this->piFont->DrawText(NULL,szText, - -1,&sRect,DT_RIGHT | DT_TOP,clrColor); - - sRect.top += iPX; - sRect.bottom += iPX; - - if (szText != (*i).szText.c_str())break; - } - } - return; - } +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2015, assimp 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 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 "assimp_view.h" + +namespace AssimpView { + +CLogDisplay CLogDisplay::s_cInstance; + +//------------------------------------------------------------------------------- +void CLogDisplay::AddEntry(const std::string& szText, + const D3DCOLOR clrColor) + { + SEntry sNew; + sNew.clrColor = clrColor; + sNew.szText = szText; + sNew.dwStartTicks = (DWORD)GetTickCount(); + + this->asEntries.push_back(sNew); + } + +//------------------------------------------------------------------------------- +void CLogDisplay::ReleaseNativeResource() + { + if (this->piFont) + { + this->piFont->Release(); + this->piFont = NULL; + } + } + +//------------------------------------------------------------------------------- +void CLogDisplay::RecreateNativeResource() + { + if (!this->piFont) + { + if (FAILED(D3DXCreateFont(g_piDevice, + 16, //Font height + 0, //Font width + FW_BOLD, //Font Weight + 1, //MipLevels + false, //Italic + DEFAULT_CHARSET, //CharSet + OUT_DEFAULT_PRECIS, //OutputPrecision + //CLEARTYPE_QUALITY, //Quality + 5, //Quality + DEFAULT_PITCH|FF_DONTCARE, //PitchAndFamily + "Verdana", //pFacename, + &this->piFont))) + { + CLogDisplay::Instance().AddEntry("Unable to load font",D3DCOLOR_ARGB(0xFF,0xFF,0,0)); + + this->piFont = NULL; + return; + } + } + return; + } + +//------------------------------------------------------------------------------- +void CLogDisplay::OnRender() + { + DWORD dwTick = (DWORD) GetTickCount(); + DWORD dwLimit = dwTick - 8000; + DWORD dwLimit2 = dwLimit + 3000; + + unsigned int iCnt = 0; + RECT sRect; + sRect.left = 10; + sRect.top = 10; + + RECT sWndRect; + GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sWndRect); + sWndRect.right -= sWndRect.left; + sWndRect.bottom -= sWndRect.top; + sWndRect.left = sWndRect.top = 0; + + sRect.right = sWndRect.right - 30; + sRect.bottom = sWndRect.bottom; + + // if no asset is loaded draw a "no asset loaded" text in the center + if (!g_pcAsset) + { + const char* szText = "Nothing to display ... \r\nTry [Viewer | Open asset] to load an asset"; + + // shadow + RECT sCopy; + sCopy.left = sWndRect.left+1; + sCopy.top = sWndRect.top+1; + sCopy.bottom = sWndRect.bottom+1; + sCopy.right = sWndRect.right+1; + this->piFont->DrawText(NULL,szText , + -1,&sCopy,DT_CENTER | DT_VCENTER,D3DCOLOR_ARGB(100,0x0,0x0,0x0)); + sCopy.left = sWndRect.left+1; + sCopy.top = sWndRect.top+1; + sCopy.bottom = sWndRect.bottom-1; + sCopy.right = sWndRect.right-1; + this->piFont->DrawText(NULL,szText , + -1,&sCopy,DT_CENTER | DT_VCENTER,D3DCOLOR_ARGB(100,0x0,0x0,0x0)); + sCopy.left = sWndRect.left-1; + sCopy.top = sWndRect.top-1; + sCopy.bottom = sWndRect.bottom+1; + sCopy.right = sWndRect.right+1; + this->piFont->DrawText(NULL,szText , + -1,&sCopy,DT_CENTER | DT_VCENTER,D3DCOLOR_ARGB(100,0x0,0x0,0x0)); + sCopy.left = sWndRect.left-1; + sCopy.top = sWndRect.top-1; + sCopy.bottom = sWndRect.bottom-1; + sCopy.right = sWndRect.right-1; + this->piFont->DrawText(NULL,szText , + -1,&sCopy,DT_CENTER | DT_VCENTER,D3DCOLOR_ARGB(100,0x0,0x0,0x0)); + + // text + this->piFont->DrawText(NULL,szText , + -1,&sWndRect,DT_CENTER | DT_VCENTER,D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0xFF)); + } + + // update all elements in the queue and render them + for (std::list<SEntry>::iterator + i = this->asEntries.begin(); + i != this->asEntries.end();++i,++iCnt) + { + if ((*i).dwStartTicks < dwLimit) + { + i = this->asEntries.erase(i); + + if(i == this->asEntries.end())break; + } + else if (NULL != this->piFont) + { + float fAlpha = 1.0f; + if ((*i).dwStartTicks <= dwLimit2) + { + // linearly interpolate to create the fade out effect + fAlpha = 1.0f - (float)(dwLimit2 - (*i).dwStartTicks) / 3000.0f; + } + D3DCOLOR& clrColor = (*i).clrColor; + clrColor &= ~(0xFFu << 24); + clrColor |= (((unsigned char)(fAlpha * 255.0f)) & 0xFFu) << 24; + + const char* szText = (*i).szText.c_str(); + if (sRect.top + 30 > sWndRect.bottom) + { + // end of window. send a special message + szText = "... too many errors"; + clrColor = D3DCOLOR_ARGB(0xFF,0xFF,100,0x0); + } + + // draw the black shadow + RECT sCopy; + sCopy.left = sRect.left+1; + sCopy.top = sRect.top+1; + sCopy.bottom = sRect.bottom+1; + sCopy.right = sRect.right+1; + this->piFont->DrawText(NULL,szText, + -1,&sCopy,DT_RIGHT | DT_TOP,D3DCOLOR_ARGB( + (unsigned char)(fAlpha * 100.0f),0x0,0x0,0x0)); + + sCopy.left = sRect.left-1; + sCopy.top = sRect.top-1; + sCopy.bottom = sRect.bottom-1; + sCopy.right = sRect.right-1; + this->piFont->DrawText(NULL,szText, + -1,&sCopy,DT_RIGHT | DT_TOP,D3DCOLOR_ARGB( + (unsigned char)(fAlpha * 100.0f),0x0,0x0,0x0)); + + sCopy.left = sRect.left-1; + sCopy.top = sRect.top-1; + sCopy.bottom = sRect.bottom+1; + sCopy.right = sRect.right+1; + this->piFont->DrawText(NULL,szText, + -1,&sCopy,DT_RIGHT | DT_TOP,D3DCOLOR_ARGB( + (unsigned char)(fAlpha * 100.0f),0x0,0x0,0x0)); + + sCopy.left = sRect.left+1; + sCopy.top = sRect.top+1; + sCopy.bottom = sRect.bottom-1; + sCopy.right = sRect.right-1; + this->piFont->DrawText(NULL,szText, + -1,&sCopy,DT_RIGHT | DT_TOP,D3DCOLOR_ARGB( + (unsigned char)(fAlpha * 100.0f),0x0,0x0,0x0)); + + // draw the text itself + int iPX = this->piFont->DrawText(NULL,szText, + -1,&sRect,DT_RIGHT | DT_TOP,clrColor); + + sRect.top += iPX; + sRect.bottom += iPX; + + if (szText != (*i).szText.c_str())break; + } + } + return; + } }; \ No newline at end of file diff --git a/tools/assimp_view/LogDisplay.h b/tools/assimp_view/LogDisplay.h index dc6724cf8..a6dd69fc2 100644 --- a/tools/assimp_view/LogDisplay.h +++ b/tools/assimp_view/LogDisplay.h @@ -1,99 +1,99 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2012, assimp 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 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. ---------------------------------------------------------------------------- -*/ -#pragma once - -#include <list> - -namespace AssimpView -{ - - //------------------------------------------------------------------------------- - /** \brief Class to display log strings in the upper right corner of the view - */ - //------------------------------------------------------------------------------- - class CLogDisplay - { - private: - - CLogDisplay() {} - - public: - - // data structure for an entry in the log queue - struct SEntry - { - SEntry() - : - clrColor( D3DCOLOR_ARGB( 0xFF, 0xFF, 0xFF, 0x00 ) ), dwStartTicks( 0 ) - {} - - std::string szText; - D3DCOLOR clrColor; - DWORD dwStartTicks; - }; - - // Singleton accessors - static CLogDisplay s_cInstance; - inline static CLogDisplay& Instance() - { - return s_cInstance; - } - - // Add an entry to the log queue - void AddEntry( const std::string& szText, - const D3DCOLOR clrColor = D3DCOLOR_ARGB( 0xFF, 0xFF, 0xFF, 0x00 ) ); - - // Release any native resources associated with the instance - void ReleaseNativeResource(); - - // Recreate any native resources associated with the instance - void RecreateNativeResource(); - - // Called during the render loop - void OnRender(); - - private: - - std::list<SEntry> asEntries; - ID3DXFont* piFont; - }; - -} +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2012, assimp 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 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. +--------------------------------------------------------------------------- +*/ +#pragma once + +#include <list> + +namespace AssimpView +{ + + //------------------------------------------------------------------------------- + /** \brief Class to display log strings in the upper right corner of the view + */ + //------------------------------------------------------------------------------- + class CLogDisplay + { + private: + + CLogDisplay() {} + + public: + + // data structure for an entry in the log queue + struct SEntry + { + SEntry() + : + clrColor( D3DCOLOR_ARGB( 0xFF, 0xFF, 0xFF, 0x00 ) ), dwStartTicks( 0 ) + {} + + std::string szText; + D3DCOLOR clrColor; + DWORD dwStartTicks; + }; + + // Singleton accessors + static CLogDisplay s_cInstance; + inline static CLogDisplay& Instance() + { + return s_cInstance; + } + + // Add an entry to the log queue + void AddEntry( const std::string& szText, + const D3DCOLOR clrColor = D3DCOLOR_ARGB( 0xFF, 0xFF, 0xFF, 0x00 ) ); + + // Release any native resources associated with the instance + void ReleaseNativeResource(); + + // Recreate any native resources associated with the instance + void RecreateNativeResource(); + + // Called during the render loop + void OnRender(); + + private: + + std::list<SEntry> asEntries; + ID3DXFont* piFont; + }; + +} diff --git a/tools/assimp_view/LogWindow.cpp b/tools/assimp_view/LogWindow.cpp index 7feb3b01b..c8e725c34 100644 --- a/tools/assimp_view/LogWindow.cpp +++ b/tools/assimp_view/LogWindow.cpp @@ -1,255 +1,255 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2015, assimp 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 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 "assimp_view.h" -#include "richedit.h" - -namespace AssimpView { - -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 -//------------------------------------------------------------------------------- -INT_PTR CALLBACK LogDialogProc(HWND hwndDlg,UINT uMsg, - WPARAM wParam,LPARAM lParam) - { - (void)lParam; - switch (uMsg) - { - case WM_INITDIALOG: - { - - return TRUE; - } - - case WM_SIZE: - { - int x = LOWORD(lParam); - int y = HIWORD(lParam); - - SetWindowPos(GetDlgItem(hwndDlg,IDC_EDIT1),NULL,0,0, - x-10,y-12,SWP_NOMOVE|SWP_NOZORDER); - - return TRUE; - } - case WM_CLOSE: - EndDialog(hwndDlg,0); - - CLogWindow::Instance().bIsVisible = false; - return TRUE; - }; - return FALSE; - } - -//------------------------------------------------------------------------------- -void CLogWindow::Init () -{ - this->hwnd = ::CreateDialog(g_hInstance,MAKEINTRESOURCE(IDD_LOGVIEW), - NULL,&LogDialogProc); - - if (!this->hwnd) - { - 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() -{ - 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 char* 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 char* message) -{ - this->szPlainText.append(message); - this->szPlainText.append("\r\n"); - - if (0 != this->szText.length()) - { - this->szText.resize(this->szText.length()-1); - } - - switch (message[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; -} - +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2015, assimp 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 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 "assimp_view.h" +#include "richedit.h" + +namespace AssimpView { + +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 +//------------------------------------------------------------------------------- +INT_PTR CALLBACK LogDialogProc(HWND hwndDlg,UINT uMsg, + WPARAM wParam,LPARAM lParam) + { + (void)lParam; + switch (uMsg) + { + case WM_INITDIALOG: + { + + return TRUE; + } + + case WM_SIZE: + { + int x = LOWORD(lParam); + int y = HIWORD(lParam); + + SetWindowPos(GetDlgItem(hwndDlg,IDC_EDIT1),NULL,0,0, + x-10,y-12,SWP_NOMOVE|SWP_NOZORDER); + + return TRUE; + } + case WM_CLOSE: + EndDialog(hwndDlg,0); + + CLogWindow::Instance().bIsVisible = false; + return TRUE; + }; + return FALSE; + } + +//------------------------------------------------------------------------------- +void CLogWindow::Init () +{ + this->hwnd = ::CreateDialog(g_hInstance,MAKEINTRESOURCE(IDD_LOGVIEW), + NULL,&LogDialogProc); + + if (!this->hwnd) + { + 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() +{ + 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 char* 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 char* message) +{ + this->szPlainText.append(message); + this->szPlainText.append("\r\n"); + + if (0 != this->szText.length()) + { + this->szText.resize(this->szText.length()-1); + } + + switch (message[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 49862cdee..5248139da 100644 --- a/tools/assimp_view/LogWindow.h +++ b/tools/assimp_view/LogWindow.h @@ -1,133 +1,133 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2012, assimp 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 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_LOG_WINDOW_H_INCLUDED) -#define AV_LOG_WINDOW_H_INCLUDE - -namespace AssimpView -{ - - - //------------------------------------------------------------------------------- - /** \brief Subclass of Assimp::LogStream used to add all log messages to the - * log window. - */ - //------------------------------------------------------------------------------- - class CMyLogStream : public Assimp::LogStream - { - public: - /** @brief Implementation of the abstract method */ - void write( const char* message ); - }; - - - //------------------------------------------------------------------------------- - /** \brief Class to display log strings in a separate window - */ - //------------------------------------------------------------------------------- - class CLogWindow - { - private: - - friend class CMyLogStream; - friend INT_PTR CALLBACK LogDialogProc( HWND hwndDlg, UINT uMsg, - WPARAM wParam, LPARAM lParam ); - - CLogWindow() : hwnd( NULL ), bIsVisible( false ), bUpdate( true ) {} - - public: - - - // Singleton accessors - static CLogWindow s_cInstance; - inline static CLogWindow& Instance() - { - return s_cInstance; - } - - // initializes the log window - void Init(); - - // 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 char* 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; - }; - -} - +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2012, assimp 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 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_LOG_WINDOW_H_INCLUDED) +#define AV_LOG_WINDOW_H_INCLUDE + +namespace AssimpView +{ + + + //------------------------------------------------------------------------------- + /** \brief Subclass of Assimp::LogStream used to add all log messages to the + * log window. + */ + //------------------------------------------------------------------------------- + class CMyLogStream : public Assimp::LogStream + { + public: + /** @brief Implementation of the abstract method */ + void write( const char* message ); + }; + + + //------------------------------------------------------------------------------- + /** \brief Class to display log strings in a separate window + */ + //------------------------------------------------------------------------------- + class CLogWindow + { + private: + + friend class CMyLogStream; + friend INT_PTR CALLBACK LogDialogProc( HWND hwndDlg, UINT uMsg, + WPARAM wParam, LPARAM lParam ); + + CLogWindow() : hwnd( NULL ), bIsVisible( false ), bUpdate( true ) {} + + public: + + + // Singleton accessors + static CLogWindow s_cInstance; + inline static CLogWindow& Instance() + { + return s_cInstance; + } + + // initializes the log window + void Init(); + + // 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 char* 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 159274da5..81e342c86 100644 --- a/tools/assimp_view/Material.cpp +++ b/tools/assimp_view/Material.cpp @@ -1,1494 +1,1494 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2015, assimp 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 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 "assimp_view.h" - -#include "MaterialManager.h" -#include "AssetHelper.h" - -#include <assimp/cimport.h> -#include <assimp/Importer.hpp> -#include <assimp/ai_assert.h> -#include <assimp/cfileio.h> -#include <assimp/postprocess.h> -#include <assimp/scene.h> -#include <assimp/IOSystem.hpp> -#include <assimp/IOStream.hpp> -#include <assimp/LogStream.hpp> -#include <assimp/DefaultLogger.hpp> -#include <../code/StringComparison.h> - -#include <vector> -#include <algorithm> - -namespace AssimpView { - -using namespace Assimp; - -extern std::string g_szMaterialShader; -extern HINSTANCE g_hInstance /*= NULL*/; -extern HWND g_hDlg /*= NULL*/; -extern IDirect3D9* g_piD3D /*= NULL*/; -extern IDirect3DDevice9* g_piDevice /*= NULL*/; -extern IDirect3DVertexDeclaration9* gDefaultVertexDecl /*= NULL*/; -extern double g_fFPS /*= 0.0f*/; -extern char g_szFileName[ MAX_PATH ]; -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*/; -extern bool g_bMousePressedBoth /*= false*/; -extern float g_fElpasedTime /*= 0.0f*/; -extern D3DCAPS9 g_sCaps; -extern bool g_bLoadingFinished /*= false*/; -extern HANDLE g_hThreadHandle /*= NULL*/; -extern float g_fWheelPos /*= -10.0f*/; -extern bool g_bLoadingCanceled /*= false*/; -extern IDirect3DTexture9* g_pcTexture /*= NULL*/; - -extern aiMatrix4x4 g_mWorld; -extern aiMatrix4x4 g_mWorldRotate; -extern aiVector3D g_vRotateSpeed /*= aiVector3D(0.5f,0.5f,0.5f)*/; - -extern aiVector3D g_avLightDirs[ 1 ] /* = - { aiVector3D(-0.5f,0.6f,0.2f) , - aiVector3D(-0.5f,0.5f,0.5f)} */; - - -extern POINT g_mousePos /*= {0,0};*/; -extern POINT g_LastmousePos /*= {0,0}*/; -extern bool g_bFPSView /*= false*/; -extern bool g_bInvert /*= false*/; -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 D3DCOLOR g_avLightColors[ 3 ]; - -extern RenderOptions g_sOptions; -extern Camera g_sCamera; -extern AssetHelper *g_pcAsset /*= NULL*/; - - -// -// Contains the mask image for the HUD -// (used to determine the position of a click) -// -// The size of the image is identical to the size of the main -// HUD texture -// -extern unsigned char* g_szImageMask /*= NULL*/; - - -extern float g_fACMR /*= 3.0f*/; -extern IDirect3DQuery9* g_piQuery; - -extern bool g_bPlay /*= false*/; - -extern double g_dCurrent; -extern float g_smoothAngle /*= 80.f*/; - -extern unsigned int ppsteps, ppstepsdefault; -extern bool nopointslines; - - -CMaterialManager CMaterialManager::s_cInstance; - -//------------------------------------------------------------------------------- -// D3DX callback function to fill a texture with a checkers pattern -// -// This pattern is used to mark textures which could not be loaded -//------------------------------------------------------------------------------- -VOID WINAPI FillFunc(D3DXVECTOR4* pOut, - CONST D3DXVECTOR2* pTexCoord, - CONST D3DXVECTOR2* pTexelSize, - LPVOID pData) -{ - UNREFERENCED_PARAMETER(pData); - UNREFERENCED_PARAMETER(pTexelSize); - - // generate a nice checker pattern (yellow/black) - // size of a square: 32 * 32 px - unsigned int iX = (unsigned int)(pTexCoord->x * 256.0f); - unsigned int iY = (unsigned int)(pTexCoord->y * 256.0f); - - bool bBlack = false; - if ((iX / 32) % 2 == 0) - { - if ((iY / 32) % 2 == 0)bBlack = true; - } - else - { - if ((iY / 32) % 2 != 0)bBlack = true; - } - pOut->w = 1.0f; - if (bBlack) - { - pOut->x = pOut->y = pOut->z = 0.0f; - } - else - { - pOut->x = pOut->y = 1.0f; - pOut->z = 0.0f; - } - return; -} - -//------------------------------------------------------------------------------- -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 CMaterialManager::SetDefaultTexture(IDirect3DTexture9** p_ppiOut) -{ - if (sDefaultTexture) { - sDefaultTexture->AddRef(); - *p_ppiOut = sDefaultTexture; - return 1; - } - if(FAILED(g_piDevice->CreateTexture( - 256, - 256, - 0, - 0, - D3DFMT_A8R8G8B8, - D3DPOOL_MANAGED, - p_ppiOut, - NULL))) - { - CLogDisplay::Instance().AddEntry("[ERROR] Unable to create default texture", - D3DCOLOR_ARGB(0xFF,0xFF,0,0)); - - *p_ppiOut = NULL; - return 0; - } - D3DXFillTexture(*p_ppiOut,&FillFunc,NULL); - sDefaultTexture = *p_ppiOut; - sDefaultTexture->AddRef(); - - // {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; -} -//------------------------------------------------------------------------------- -bool CMaterialManager::TryLongerPath(char* szTemp,aiString* p_szString) -{ - char szTempB[MAX_PATH]; - strcpy(szTempB,szTemp); - - // go to the beginning of the file name - char* szFile = strrchr(szTempB,'\\'); - if (!szFile)szFile = strrchr(szTempB,'/'); - - char* szFile2 = szTemp + (szFile - szTempB)+1; - szFile++; - char* szExt = strrchr(szFile,'.'); - if (!szExt)return false; - szExt++; - *szFile = 0; - - strcat(szTempB,"*.*"); - const unsigned int iSize = (const unsigned int) ( szExt - 1 - szFile ); - - HANDLE h; - WIN32_FIND_DATA info; - - // build a list of files - h = FindFirstFile(szTempB, &info); - if (h != INVALID_HANDLE_VALUE) - { - do - { - if (!(strcmp(info.cFileName, ".") == 0 || strcmp(info.cFileName, "..") == 0)) - { - char* szExtFound = strrchr(info.cFileName, '.'); - if (szExtFound) - { - ++szExtFound; - if (0 == ASSIMP_stricmp(szExtFound,szExt)) - { - const unsigned int iSizeFound = (const unsigned int) ( - szExtFound - 1 - info.cFileName); - - for (unsigned int i = 0; i < iSizeFound;++i) - info.cFileName[i] = (CHAR)tolower(info.cFileName[i]); - - if (0 == memcmp(info.cFileName,szFile2, min(iSizeFound,iSize))) - { - // we have it. Build the full path ... - char* sz = strrchr(szTempB,'*'); - *(sz-2) = 0x0; - - strcat(szTempB,info.cFileName); - - // copy the result string back to the aiString - const size_t iLen = strlen(szTempB); - size_t iLen2 = iLen+1; - iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2; - memcpy(p_szString->data,szTempB,iLen2); - p_szString->length = iLen; - return true; - } - } - // check whether the 8.3 DOS name is matching - if (0 == ASSIMP_stricmp(info.cAlternateFileName,p_szString->data)) - { - strcat(szTempB,info.cAlternateFileName); - - // copy the result string back to the aiString - const size_t iLen = strlen(szTempB); - size_t iLen2 = iLen+1; - iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2; - memcpy(p_szString->data,szTempB,iLen2); - p_szString->length = iLen; - return true; - } - } - } - } - while (FindNextFile(h, &info)); - - FindClose(h); - } - return false; -} -//------------------------------------------------------------------------------- -int CMaterialManager::FindValidPath(aiString* p_szString) -{ - ai_assert(NULL != p_szString); - aiString pcpy = *p_szString; - if ('*' == p_szString->data[0]) { - // '*' as first character indicates an embedded file - return 5; - } - - // first check whether we can directly load the file - FILE* pFile = fopen(p_szString->data,"rb"); - if (pFile)fclose(pFile); - else - { - // check whether we can use the directory of the asset as relative base - char szTemp[MAX_PATH*2], tmp2[MAX_PATH*2]; - strcpy(szTemp, g_szFileName); - strcpy(tmp2,szTemp); - - char* szData = p_szString->data; - if (*szData == '\\' || *szData == '/')++szData; - - char* szEnd = strrchr(szTemp,'\\'); - if (!szEnd) - { - szEnd = strrchr(szTemp,'/'); - if (!szEnd)szEnd = szTemp; - } - szEnd++; - *szEnd = 0; - strcat(szEnd,szData); - - - pFile = fopen(szTemp,"rb"); - if (!pFile) - { - // convert the string to lower case - for (unsigned int i = 0;;++i) - { - if ('\0' == szTemp[i])break; - szTemp[i] = (char)tolower(szTemp[i]); - } - - if(TryLongerPath(szTemp,p_szString))return 1; - *szEnd = 0; - - // search common sub directories - strcat(szEnd,"tex\\"); - strcat(szEnd,szData); - - pFile = fopen(szTemp,"rb"); - if (!pFile) - { - if(TryLongerPath(szTemp,p_szString))return 1; - - *szEnd = 0; - - strcat(szEnd,"textures\\"); - strcat(szEnd,szData); - - pFile = fopen(szTemp,"rb"); - if (!pFile) - { - if(TryLongerPath(szTemp, p_szString))return 1; - } - - // patch by mark sibly to look for textures files in the asset's base directory. - const char *path=pcpy.data; - const char *p=strrchr( path,'/' ); - if( !p ) p=strrchr( path,'\\' ); - if( p ){ - char *q=strrchr( tmp2,'/' ); - if( !q ) q=strrchr( tmp2,'\\' ); - if( q ){ - strcpy( q+1,p+1 ); - if((pFile=fopen( tmp2,"r" ))){ - fclose( pFile ); - strcpy(p_szString->data,tmp2); - p_szString->length = strlen(tmp2); - return 1; - } - } - } - return 0; - } - } - fclose(pFile); - - // copy the result string back to the aiString - const size_t iLen = strlen(szTemp); - size_t iLen2 = iLen+1; - iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2; - memcpy(p_szString->data,szTemp,iLen2); - p_szString->length = iLen; - - } - return 1; -} -//------------------------------------------------------------------------------- -int CMaterialManager::LoadTexture(IDirect3DTexture9** p_ppiOut,aiString* szPath) -{ - ai_assert(NULL != p_ppiOut); - ai_assert(NULL != szPath); - - *p_ppiOut = NULL; - - const std::string s = szPath->data; - TextureCache::iterator ff; - if ((ff = sCachedTextures.find(s)) != sCachedTextures.end()) { - *p_ppiOut = (*ff).second; - (*p_ppiOut)->AddRef(); - return 1; - } - - // first get a valid path to the texture - if( 5 == FindValidPath(szPath)) - { - // embedded file. Find its index - unsigned int iIndex = atoi(szPath->data+1); - if (iIndex < g_pcAsset->pcScene->mNumTextures) - { - if (0 == g_pcAsset->pcScene->mTextures[iIndex]->mHeight) - { - // it is an embedded file ... don't need the file format hint, - // simply let D3DX load the file - D3DXIMAGE_INFO info; - if (FAILED(D3DXCreateTextureFromFileInMemoryEx(g_piDevice, - g_pcAsset->pcScene->mTextures[iIndex]->pcData, - g_pcAsset->pcScene->mTextures[iIndex]->mWidth, - D3DX_DEFAULT, - D3DX_DEFAULT, - 1, - D3DUSAGE_AUTOGENMIPMAP, - D3DFMT_UNKNOWN, - D3DPOOL_MANAGED, - D3DX_DEFAULT, - D3DX_DEFAULT, - 0, - &info, - NULL, - p_ppiOut))) - { - std::string sz = "[ERROR] Unable to load embedded texture (#1): "; - sz.append(szPath->data); - CLogDisplay::Instance().AddEntry(sz,D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0)); - - this->SetDefaultTexture(p_ppiOut); - return 1; - } - } - else - { - // fill a new texture ... - if(FAILED(g_piDevice->CreateTexture( - g_pcAsset->pcScene->mTextures[iIndex]->mWidth, - g_pcAsset->pcScene->mTextures[iIndex]->mHeight, - 0,D3DUSAGE_AUTOGENMIPMAP,D3DFMT_A8R8G8B8,D3DPOOL_MANAGED,p_ppiOut,NULL))) - { - std::string sz = "[ERROR] Unable to load embedded texture (#2): "; - sz.append(szPath->data); - CLogDisplay::Instance().AddEntry(sz,D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0)); - - this->SetDefaultTexture(p_ppiOut); - return 1; - } - - // now copy the data to it ... (assume non pow2 to be supported) - D3DLOCKED_RECT sLock; - (*p_ppiOut)->LockRect(0,&sLock,NULL,0); - - const aiTexel* pcData = g_pcAsset->pcScene->mTextures[iIndex]->pcData; - - for (unsigned int y = 0; y < g_pcAsset->pcScene->mTextures[iIndex]->mHeight;++y) - { - memcpy(sLock.pBits,pcData,g_pcAsset->pcScene->mTextures[iIndex]-> - mWidth *sizeof(aiTexel)); - sLock.pBits = (char*)sLock.pBits + sLock.Pitch; - pcData += g_pcAsset->pcScene->mTextures[iIndex]->mWidth; - } - (*p_ppiOut)->UnlockRect(0); - (*p_ppiOut)->GenerateMipSubLevels(); - } - sCachedTextures[s] = *p_ppiOut; - (*p_ppiOut)->AddRef(); - return 1; - } - else - { - std::string sz = "[ERROR] Invalid index for embedded texture: "; - sz.append(szPath->data); - CLogDisplay::Instance().AddEntry(sz,D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0)); - - SetDefaultTexture(p_ppiOut); - return 1; - } - } - - // then call D3DX to load the texture - if (FAILED(D3DXCreateTextureFromFileEx( - g_piDevice, - szPath->data, - D3DX_DEFAULT, - D3DX_DEFAULT, - 0, - 0, - D3DFMT_A8R8G8B8, - D3DPOOL_MANAGED, - D3DX_DEFAULT, - D3DX_DEFAULT, - 0, - NULL, - NULL, - p_ppiOut))) - { - // error ... use the default texture instead - std::string sz = "[ERROR] Unable to load texture: "; - sz.append(szPath->data); - CLogDisplay::Instance().AddEntry(sz,D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0)); - - this->SetDefaultTexture(p_ppiOut); - } - sCachedTextures[s] = *p_ppiOut; - (*p_ppiOut)->AddRef(); - - return 1; -} -//------------------------------------------------------------------------------- -void CMaterialManager::DeleteMaterial(AssetHelper::MeshHelper* pcIn) -{ - if (!pcIn || !pcIn->piEffect)return; - pcIn->piEffect->Release(); - - // release all textures associated with the material - if (pcIn->piDiffuseTexture) - { - pcIn->piDiffuseTexture->Release(); - pcIn->piDiffuseTexture = NULL; - } - if (pcIn->piSpecularTexture) - { - pcIn->piSpecularTexture->Release(); - pcIn->piSpecularTexture = NULL; - } - if (pcIn->piEmissiveTexture) - { - pcIn->piEmissiveTexture->Release(); - pcIn->piEmissiveTexture = NULL; - } - if (pcIn->piAmbientTexture) - { - pcIn->piAmbientTexture->Release(); - pcIn->piAmbientTexture = NULL; - } - if (pcIn->piOpacityTexture) - { - pcIn->piOpacityTexture->Release(); - pcIn->piOpacityTexture = NULL; - } - if (pcIn->piNormalTexture) - { - pcIn->piNormalTexture->Release(); - pcIn->piNormalTexture = NULL; - } - if (pcIn->piShininessTexture) - { - pcIn->piShininessTexture->Release(); - pcIn->piShininessTexture = NULL; - } - if (pcIn->piLightmapTexture) - { - pcIn->piLightmapTexture->Release(); - pcIn->piLightmapTexture = NULL; - } - pcIn->piEffect = NULL; -} -//------------------------------------------------------------------------------- -void CMaterialManager::HMtoNMIfNecessary( - IDirect3DTexture9* piTexture, - IDirect3DTexture9** piTextureOut, - bool bWasOriginallyHM) -{ - ai_assert(NULL != piTexture); - ai_assert(NULL != piTextureOut); - - bool bMustConvert = false; - uintptr_t iElement = 3; - - *piTextureOut = piTexture; - - // Lock the input texture and try to determine its type. - // Criterias: - // - If r,g,b channel are identical it MUST be a height map - // - If one of the rgb channels is used and the others are empty it - // must be a height map, too. - // - If the average color of the whole image is something inside the - // purple range we can be sure it is a normal map - // - // - Otherwise we assume it is a normal map - // To increase performance we take not every pixel - - D3DLOCKED_RECT sRect; - D3DSURFACE_DESC sDesc; - piTexture->GetLevelDesc(0,&sDesc); - if (FAILED(piTexture->LockRect(0,&sRect,NULL,D3DLOCK_READONLY))) - { - return; - } - const int iPitchDiff = (int)sRect.Pitch - (int)(sDesc.Width * 4); - - struct SColor - { - union - { - struct {unsigned char b,g,r,a;}; - char _array[4]; - }; - }; - const SColor* pcData = (const SColor*)sRect.pBits; - - union - { - const SColor* pcPointer; - const unsigned char* pcCharPointer; - }; - pcPointer = pcData; - - // 1. If r,g,b channel are identical it MUST be a height map - bool bIsEqual = true; - for (unsigned int y = 0; y < sDesc.Height;++y) - { - for (unsigned int x = 0; x < sDesc.Width;++x) - { - if (pcPointer->b != pcPointer->r || pcPointer->b != pcPointer->g) - { - bIsEqual = false; - break; - } - pcPointer++; - } - pcCharPointer += iPitchDiff; - } - if (bIsEqual)bMustConvert = true; - else - { - // 2. If one of the rgb channels is used and the others are empty it - // must be a height map, too. - pcPointer = pcData; - while (*pcCharPointer == 0)pcCharPointer++; - - iElement = (uintptr_t)(pcCharPointer - (unsigned char*)pcData) % 4; - unsigned int aiIndex[3] = {0,1,2}; - if (3 != iElement)aiIndex[iElement] = 3; - - pcPointer = pcData; - - bIsEqual = true; - if (3 != iElement) - { - for (unsigned int y = 0; y < sDesc.Height;++y) - { - for (unsigned int x = 0; x < sDesc.Width;++x) - { - for (unsigned int ii = 0; ii < 3;++ii) - { - // don't take the alpha channel into account. - // if the texture was stored n RGB888 format D3DX has - // converted it to ARGB8888 format with a fixed alpha channel - if (aiIndex[ii] != 3 && pcPointer->_array[aiIndex[ii]] != 0) - { - bIsEqual = false; - break; - } - } - pcPointer++; - } - pcCharPointer += iPitchDiff; - } - if (bIsEqual)bMustConvert = true; - else - { - // If the average color of the whole image is something inside the - // purple range we can be sure it is a normal map - - // (calculate the average color line per line to prevent overflows!) - pcPointer = pcData; - aiColor3D clrColor; - for (unsigned int y = 0; y < sDesc.Height;++y) - { - aiColor3D clrColorLine; - for (unsigned int x = 0; x < sDesc.Width;++x) - { - clrColorLine.r += pcPointer->r; - clrColorLine.g += pcPointer->g; - clrColorLine.b += pcPointer->b; - pcPointer++; - } - clrColor.r += clrColorLine.r /= (float)sDesc.Width; - clrColor.g += clrColorLine.g /= (float)sDesc.Width; - clrColor.b += clrColorLine.b /= (float)sDesc.Width; - pcCharPointer += iPitchDiff; - } - clrColor.r /= (float)sDesc.Height; - clrColor.g /= (float)sDesc.Height; - clrColor.b /= (float)sDesc.Height; - - if (!(clrColor.b > 215 && - clrColor.r > 100 && clrColor.r < 140 && - clrColor.g > 100 && clrColor.g < 140)) - { - // Unable to detect. Believe the original value obtained from the loader - if (bWasOriginallyHM) - { - bMustConvert = true; - } - } - } - } - } - - piTexture->UnlockRect(0); - - // if the input data is assumed to be a height map we'll - // need to convert it NOW - if (bMustConvert) - { - D3DSURFACE_DESC sDesc; - piTexture->GetLevelDesc(0, &sDesc); - - IDirect3DTexture9* piTempTexture; - if(FAILED(g_piDevice->CreateTexture( - sDesc.Width, - sDesc.Height, - piTexture->GetLevelCount(), - sDesc.Usage, - sDesc.Format, - sDesc.Pool, &piTempTexture, NULL))) - { - CLogDisplay::Instance().AddEntry( - "[ERROR] Unable to create normal map texture", - D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0)); - return; - } - - DWORD dwFlags; - if (3 == iElement)dwFlags = D3DX_CHANNEL_LUMINANCE; - else if (2 == iElement)dwFlags = D3DX_CHANNEL_RED; - else if (1 == iElement)dwFlags = D3DX_CHANNEL_GREEN; - else /*if (0 == iElement)*/dwFlags = D3DX_CHANNEL_BLUE; - - if(FAILED(D3DXComputeNormalMap(piTempTexture, - piTexture,NULL,0,dwFlags,1.0f))) - { - CLogDisplay::Instance().AddEntry( - "[ERROR] Unable to compute normal map from height map", - D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0)); - - piTempTexture->Release(); - return; - } - *piTextureOut = piTempTexture; - piTexture->Release(); - } -} -//------------------------------------------------------------------------------- -bool CMaterialManager::HasAlphaPixels(IDirect3DTexture9* piTexture) -{ - ai_assert(NULL != piTexture); - - D3DLOCKED_RECT sRect; - D3DSURFACE_DESC sDesc; - piTexture->GetLevelDesc(0,&sDesc); - if (FAILED(piTexture->LockRect(0,&sRect,NULL,D3DLOCK_READONLY))) - { - return false; - } - const int iPitchDiff = (int)sRect.Pitch - (int)(sDesc.Width * 4); - - struct SColor - { - unsigned char b,g,r,a;; - }; - const SColor* pcData = (const SColor*)sRect.pBits; - - union - { - const SColor* pcPointer; - const unsigned char* pcCharPointer; - }; - pcPointer = pcData; - for (unsigned int y = 0; y < sDesc.Height;++y) - { - for (unsigned int x = 0; x < sDesc.Width;++x) - { - if (pcPointer->a != 0xFF) - { - piTexture->UnlockRect(0); - return true; - } - pcPointer++; - } - pcCharPointer += iPitchDiff; - } - piTexture->UnlockRect(0); - return false; -} -//------------------------------------------------------------------------------- -int CMaterialManager::CreateMaterial( - AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSource) -{ - ai_assert(NULL != pcMesh); - ai_assert(NULL != pcSource); - - ID3DXBuffer* piBuffer; - - D3DXMACRO sMacro[64]; - - // extract all properties from the ASSIMP material structure - const aiMaterial* pcMat = g_pcAsset->pcScene->mMaterials[pcSource->mMaterialIndex]; - - // - // DIFFUSE COLOR -------------------------------------------------- - // - if(AI_SUCCESS != aiGetMaterialColor(pcMat,AI_MATKEY_COLOR_DIFFUSE, - (aiColor4D*)&pcMesh->vDiffuseColor)) - { - pcMesh->vDiffuseColor.x = 1.0f; - pcMesh->vDiffuseColor.y = 1.0f; - pcMesh->vDiffuseColor.z = 1.0f; - pcMesh->vDiffuseColor.w = 1.0f; - } - // - // SPECULAR COLOR -------------------------------------------------- - // - if(AI_SUCCESS != aiGetMaterialColor(pcMat,AI_MATKEY_COLOR_SPECULAR, - (aiColor4D*)&pcMesh->vSpecularColor)) - { - pcMesh->vSpecularColor.x = 1.0f; - pcMesh->vSpecularColor.y = 1.0f; - pcMesh->vSpecularColor.z = 1.0f; - pcMesh->vSpecularColor.w = 1.0f; - } - // - // AMBIENT COLOR -------------------------------------------------- - // - if(AI_SUCCESS != aiGetMaterialColor(pcMat,AI_MATKEY_COLOR_AMBIENT, - (aiColor4D*)&pcMesh->vAmbientColor)) - { - pcMesh->vAmbientColor.x = 0.0f; - pcMesh->vAmbientColor.y = 0.0f; - pcMesh->vAmbientColor.z = 0.0f; - pcMesh->vAmbientColor.w = 1.0f; - } - // - // EMISSIVE COLOR ------------------------------------------------- - // - if(AI_SUCCESS != aiGetMaterialColor(pcMat,AI_MATKEY_COLOR_EMISSIVE, - (aiColor4D*)&pcMesh->vEmissiveColor)) - { - pcMesh->vEmissiveColor.x = 0.0f; - pcMesh->vEmissiveColor.y = 0.0f; - pcMesh->vEmissiveColor.z = 0.0f; - pcMesh->vEmissiveColor.w = 1.0f; - } - - // - // Opacity -------------------------------------------------------- - // - if(AI_SUCCESS != aiGetMaterialFloat(pcMat,AI_MATKEY_OPACITY,&pcMesh->fOpacity)) - { - pcMesh->fOpacity = 1.0f; - } - - // - // Shading Model -------------------------------------------------- - // - bool bDefault = false; - if(AI_SUCCESS != aiGetMaterialInteger(pcMat,AI_MATKEY_SHADING_MODEL,(int*)&pcMesh->eShadingMode )) - { - bDefault = true; - pcMesh->eShadingMode = aiShadingMode_Gouraud; - } - - - // - // Shininess ------------------------------------------------------ - // - if(AI_SUCCESS != aiGetMaterialFloat(pcMat,AI_MATKEY_SHININESS,&pcMesh->fShininess)) - { - // assume 15 as default shininess - pcMesh->fShininess = 15.0f; - } - else if (bDefault)pcMesh->eShadingMode = aiShadingMode_Phong; - - - // - // Shininess strength ------------------------------------------------------ - // - if(AI_SUCCESS != aiGetMaterialFloat(pcMat,AI_MATKEY_SHININESS_STRENGTH,&pcMesh->fSpecularStrength)) - { - // assume 1.0 as default shininess strength - pcMesh->fSpecularStrength = 1.0f; - } - - aiString szPath; - - aiTextureMapMode mapU(aiTextureMapMode_Wrap),mapV(aiTextureMapMode_Wrap); - - bool bib =false; - if (pcSource->mTextureCoords[0]) - { - - // - // DIFFUSE TEXTURE ------------------------------------------------ - // - if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_DIFFUSE(0),&szPath)) - { - LoadTexture(&pcMesh->piDiffuseTexture,&szPath); - - aiGetMaterialInteger(pcMat,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0),(int*)&mapU); - aiGetMaterialInteger(pcMat,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0),(int*)&mapV); - } - - // - // SPECULAR TEXTURE ------------------------------------------------ - // - if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_SPECULAR(0),&szPath)) - { - LoadTexture(&pcMesh->piSpecularTexture,&szPath); - } - - // - // OPACITY TEXTURE ------------------------------------------------ - // - if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_OPACITY(0),&szPath)) - { - LoadTexture(&pcMesh->piOpacityTexture,&szPath); - } - else - { - int flags = 0; - aiGetMaterialInteger(pcMat,AI_MATKEY_TEXFLAGS_DIFFUSE(0),&flags); - - // try to find out whether the diffuse texture has any - // non-opaque pixels. If we find a few, use it as opacity texture - if (pcMesh->piDiffuseTexture && !(flags & aiTextureFlags_IgnoreAlpha) && HasAlphaPixels(pcMesh->piDiffuseTexture)) - { - 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",0,0,&iVal)) - { - pcMesh->piOpacityTexture = pcMesh->piDiffuseTexture; - pcMesh->piOpacityTexture->AddRef(); - } - } - } - - // - // AMBIENT TEXTURE ------------------------------------------------ - // - if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_AMBIENT(0),&szPath)) - { - LoadTexture(&pcMesh->piAmbientTexture,&szPath); - } - - // - // EMISSIVE TEXTURE ------------------------------------------------ - // - if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_EMISSIVE(0),&szPath)) - { - LoadTexture(&pcMesh->piEmissiveTexture,&szPath); - } - - // - // Shininess TEXTURE ------------------------------------------------ - // - if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_SHININESS(0),&szPath)) - { - LoadTexture(&pcMesh->piShininessTexture,&szPath); - } - - // - // Lightmap TEXTURE ------------------------------------------------ - // - if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_LIGHTMAP(0),&szPath)) - { - LoadTexture(&pcMesh->piLightmapTexture,&szPath); - } - - - // - // NORMAL/HEIGHT MAP ------------------------------------------------ - // - bool bHM = false; - if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_NORMALS(0),&szPath)) - { - LoadTexture(&pcMesh->piNormalTexture,&szPath); - } - else - { - if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_HEIGHT(0),&szPath)) - { - LoadTexture(&pcMesh->piNormalTexture,&szPath); - } - else bib = true; - bHM = true; - } - - // normal/height maps are sometimes mixed up. Try to detect the type - // of the texture automatically - if (pcMesh->piNormalTexture) - { - HMtoNMIfNecessary(pcMesh->piNormalTexture, &pcMesh->piNormalTexture,bHM); - } - } - - // check whether a global background texture is contained - // in this material. Some loaders set this value ... - if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_GLOBAL_BACKGROUND_IMAGE,&szPath)) - { - CBackgroundPainter::Instance().SetTextureBG(szPath.data); - } - - // 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; - } - - int two_sided = 0; - aiGetMaterialInteger(pcMat,AI_MATKEY_TWOSIDED,&two_sided); - pcMesh->twosided = (two_sided != 0); - - // check whether we have already a material using the same - // shader. This will decrease loading time rapidly ... - for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) - { - if (g_pcAsset->pcScene->mMeshes[i] == pcSource) - { - break; - } - AssetHelper::MeshHelper* pc = g_pcAsset->apcMeshes[i]; - - if ((pcMesh->piDiffuseTexture != NULL ? true : false) != - (pc->piDiffuseTexture != NULL ? true : false)) - continue; - if ((pcMesh->piSpecularTexture != NULL ? true : false) != - (pc->piSpecularTexture != NULL ? true : false)) - continue; - if ((pcMesh->piAmbientTexture != NULL ? true : false) != - (pc->piAmbientTexture != NULL ? true : false)) - continue; - if ((pcMesh->piEmissiveTexture != NULL ? true : false) != - (pc->piEmissiveTexture != NULL ? true : false)) - continue; - if ((pcMesh->piNormalTexture != NULL ? true : false) != - (pc->piNormalTexture != NULL ? true : false)) - continue; - 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->piLightmapTexture != NULL ? true : false) != - (pc->piLightmapTexture != NULL ? true : false)) - continue; - if ((pcMesh->eShadingMode != aiShadingMode_Gouraud ? true : false) != - (pc->eShadingMode != aiShadingMode_Gouraud ? true : false)) - continue; - - if ((pcMesh->fOpacity != 1.0f ? true : false) != (pc->fOpacity != 1.0f ? true : false)) - continue; - - if (pcSource->HasBones() != g_pcAsset->pcScene->mMeshes[i]->HasBones()) - continue; - - // we can reuse this material - if (pc->piEffect) - { - pcMesh->piEffect = pc->piEffect; - pc->bSharedFX = pcMesh->bSharedFX = true; - pcMesh->piEffect->AddRef(); - return 2; - } - } - m_iShaderCount++; - - // build macros for the HLSL compiler - unsigned int iCurrent = 0; - if (pcMesh->piDiffuseTexture) - { - sMacro[iCurrent].Name = "AV_DIFFUSE_TEXTURE"; - sMacro[iCurrent].Definition = "1"; - ++iCurrent; - - if (mapU == aiTextureMapMode_Wrap) - sMacro[iCurrent].Name = "AV_WRAPU"; - else if (mapU == aiTextureMapMode_Mirror) - sMacro[iCurrent].Name = "AV_MIRRORU"; - else // if (mapU == aiTextureMapMode_Clamp) - sMacro[iCurrent].Name = "AV_CLAMPU"; - - sMacro[iCurrent].Definition = "1"; - ++iCurrent; - - - if (mapV == aiTextureMapMode_Wrap) - sMacro[iCurrent].Name = "AV_WRAPV"; - else if (mapV == aiTextureMapMode_Mirror) - sMacro[iCurrent].Name = "AV_MIRRORV"; - else // if (mapV == aiTextureMapMode_Clamp) - sMacro[iCurrent].Name = "AV_CLAMPV"; - - sMacro[iCurrent].Definition = "1"; - ++iCurrent; - } - if (pcMesh->piSpecularTexture) - { - sMacro[iCurrent].Name = "AV_SPECULAR_TEXTURE"; - sMacro[iCurrent].Definition = "1"; - ++iCurrent; - } - if (pcMesh->piAmbientTexture) - { - sMacro[iCurrent].Name = "AV_AMBIENT_TEXTURE"; - sMacro[iCurrent].Definition = "1"; - ++iCurrent; - } - if (pcMesh->piEmissiveTexture) - { - sMacro[iCurrent].Name = "AV_EMISSIVE_TEXTURE"; - sMacro[iCurrent].Definition = "1"; - ++iCurrent; - } - char buff[32]; - if (pcMesh->piLightmapTexture) - { - sMacro[iCurrent].Name = "AV_LIGHTMAP_TEXTURE"; - sMacro[iCurrent].Definition = "1"; - ++iCurrent; - - int idx; - if(AI_SUCCESS == aiGetMaterialInteger(pcMat,AI_MATKEY_UVWSRC_LIGHTMAP(0),&idx) && idx >= 1 && pcSource->mTextureCoords[idx]) { - sMacro[iCurrent].Name = "AV_TWO_UV"; - sMacro[iCurrent].Definition = "1"; - ++iCurrent; - - sMacro[iCurrent].Definition = "IN.TexCoord1"; - } - else sMacro[iCurrent].Definition = "IN.TexCoord0"; - sMacro[iCurrent].Name = "AV_LIGHTMAP_TEXTURE_UV_COORD"; - - ++iCurrent;float f= 1.f; - aiGetMaterialFloat(pcMat,AI_MATKEY_TEXBLEND_LIGHTMAP(0),&f); - sprintf(buff,"%f",f); - - sMacro[iCurrent].Name = "LM_STRENGTH"; - sMacro[iCurrent].Definition = buff; - ++iCurrent; - } - if (pcMesh->piNormalTexture && !bib) - { - sMacro[iCurrent].Name = "AV_NORMAL_TEXTURE"; - sMacro[iCurrent].Definition = "1"; - ++iCurrent; - } - if (pcMesh->piOpacityTexture) - { - sMacro[iCurrent].Name = "AV_OPACITY_TEXTURE"; - sMacro[iCurrent].Definition = "1"; - ++iCurrent; - - if (pcMesh->piOpacityTexture == pcMesh->piDiffuseTexture) - { - sMacro[iCurrent].Name = "AV_OPACITY_TEXTURE_REGISTER_MASK"; - sMacro[iCurrent].Definition = "a"; - ++iCurrent; - } - else - { - sMacro[iCurrent].Name = "AV_OPACITY_TEXTURE_REGISTER_MASK"; - sMacro[iCurrent].Definition = "r"; - ++iCurrent; - } - } - - 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) - { - sMacro[iCurrent].Name = "AV_OPACITY"; - sMacro[iCurrent].Definition = "1"; - ++iCurrent; - } - - if( pcSource->HasBones()) - { - sMacro[iCurrent].Name = "AV_SKINNING"; - sMacro[iCurrent].Definition = "1"; - ++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()) - { - sMacro[iCurrent].Name = "AV_SKYBOX_LOOKUP"; - sMacro[iCurrent].Definition = "1"; - ++iCurrent; - } - sMacro[iCurrent].Name = NULL; - sMacro[iCurrent].Definition = NULL; - - // compile the shader - if(FAILED( D3DXCreateEffect(g_piDevice, - g_szMaterialShader.c_str(),(UINT)g_szMaterialShader.length(), - (const D3DXMACRO*)sMacro,NULL,0,NULL,&pcMesh->piEffect,&piBuffer))) - { - // failed to compile the shader - if( piBuffer) - { - MessageBox(g_hDlg,(LPCSTR)piBuffer->GetBufferPointer(),"HLSL",MB_OK); - piBuffer->Release(); - } - // use the default material instead - if (g_piDefaultEffect) - { - pcMesh->piEffect = g_piDefaultEffect; - g_piDefaultEffect->AddRef(); - } - - // get the name of the material and use it in the log message - if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_NAME,&szPath) && - '\0' != szPath.data[0]) - { - std::string sz = "[ERROR] Unable to load material: "; - sz.append(szPath.data); - CLogDisplay::Instance().AddEntry(sz); - } - else - { - CLogDisplay::Instance().AddEntry("Unable to load material: UNNAMED"); - } - return 0; - } else - { - // use Fixed Function effect when working with shaderless cards - if( g_sCaps.PixelShaderVersion < D3DPS_VERSION(2,0)) - pcMesh->piEffect->SetTechnique( "MaterialFX_FF"); - } - - if( piBuffer) piBuffer->Release(); - - - // now commit all constants to the shader - // - // This is not necessary for shared shader. Shader constants for - // shared shaders are automatically recommited before the shader - // is being used for a particular mesh - - if (1.0f != pcMesh->fOpacity) - pcMesh->piEffect->SetFloat("TRANSPARENCY",pcMesh->fOpacity); - if (pcMesh->eShadingMode != aiShadingMode_Gouraud && !g_sOptions.bNoSpecular) - { - pcMesh->piEffect->SetFloat("SPECULARITY",pcMesh->fShininess); - pcMesh->piEffect->SetFloat("SPECULAR_STRENGTH",pcMesh->fSpecularStrength); - } - - 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->piDiffuseTexture) - pcMesh->piEffect->SetTexture("DIFFUSE_TEXTURE",pcMesh->piDiffuseTexture); - if (pcMesh->piOpacityTexture) - pcMesh->piEffect->SetTexture("OPACITY_TEXTURE",pcMesh->piOpacityTexture); - 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 (pcMesh->piLightmapTexture) - pcMesh->piEffect->SetTexture("LIGHTMAP_TEXTURE",pcMesh->piLightmapTexture); - - if (CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode()){ - pcMesh->piEffect->SetTexture("lw_tex_envmap",CBackgroundPainter::Instance().GetTexture()); - } - - return 1; -} -//------------------------------------------------------------------------------- -int CMaterialManager::SetupMaterial ( - AssetHelper::MeshHelper* pcMesh, - const aiMatrix4x4& pcProj, - const aiMatrix4x4& aiMe, - const aiMatrix4x4& pcCam, - const aiVector3D& vPos) -{ - ai_assert(NULL != pcMesh); - if (!pcMesh->piEffect)return 0; - - ID3DXEffect* piEnd = pcMesh->piEffect; - - piEnd->SetMatrix("WorldViewProjection", - (const D3DXMATRIX*)&pcProj); - - piEnd->SetMatrix("World",(const D3DXMATRIX*)&aiMe); - piEnd->SetMatrix("WorldInverseTranspose", - (const D3DXMATRIX*)&pcCam); - - D3DXVECTOR4 apcVec[5]; - memset(apcVec,0,sizeof(apcVec)); - apcVec[0].x = g_avLightDirs[0].x; - apcVec[0].y = g_avLightDirs[0].y; - apcVec[0].z = g_avLightDirs[0].z; - apcVec[0].w = 0.0f; - 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; - apcVec[1].w = 0.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; - - if( g_sOptions.b3Lights) - { - 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; - } else - { - 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 = ((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->SetFloat("SPECULAR_STRENGTH",pcMesh->fSpecularStrength); - } - - 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 (pcMesh->piLightmapTexture) - pcMesh->piEffect->SetTexture("LIGHTMAP_TEXTURE",pcMesh->piLightmapTexture); - - if (CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode()) - { - piEnd->SetTexture("lw_tex_envmap",CBackgroundPainter::Instance().GetTexture()); - } - } - - // disable culling, if necessary - if (pcMesh->twosided && g_sOptions.bCulling) { - g_piDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE); - } - - // setup the correct shader technique to be used for drawing - if( g_sCaps.PixelShaderVersion < D3DPS_VERSION(2,0)) - { - g_piDefaultEffect->SetTechnique( "MaterialFXSpecular_FF"); - } else - 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(); - - // reenable culling if necessary - if (pcMesh->twosided && g_sOptions.bCulling) { - g_piDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_CCW); - } - - return 1; -} -}; // end namespace AssimpView +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2015, assimp 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 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 "assimp_view.h" + +#include "MaterialManager.h" +#include "AssetHelper.h" + +#include <assimp/cimport.h> +#include <assimp/Importer.hpp> +#include <assimp/ai_assert.h> +#include <assimp/cfileio.h> +#include <assimp/postprocess.h> +#include <assimp/scene.h> +#include <assimp/IOSystem.hpp> +#include <assimp/IOStream.hpp> +#include <assimp/LogStream.hpp> +#include <assimp/DefaultLogger.hpp> +#include <../code/StringComparison.h> + +#include <vector> +#include <algorithm> + +namespace AssimpView { + +using namespace Assimp; + +extern std::string g_szMaterialShader; +extern HINSTANCE g_hInstance /*= NULL*/; +extern HWND g_hDlg /*= NULL*/; +extern IDirect3D9* g_piD3D /*= NULL*/; +extern IDirect3DDevice9* g_piDevice /*= NULL*/; +extern IDirect3DVertexDeclaration9* gDefaultVertexDecl /*= NULL*/; +extern double g_fFPS /*= 0.0f*/; +extern char g_szFileName[ MAX_PATH ]; +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*/; +extern bool g_bMousePressedBoth /*= false*/; +extern float g_fElpasedTime /*= 0.0f*/; +extern D3DCAPS9 g_sCaps; +extern bool g_bLoadingFinished /*= false*/; +extern HANDLE g_hThreadHandle /*= NULL*/; +extern float g_fWheelPos /*= -10.0f*/; +extern bool g_bLoadingCanceled /*= false*/; +extern IDirect3DTexture9* g_pcTexture /*= NULL*/; + +extern aiMatrix4x4 g_mWorld; +extern aiMatrix4x4 g_mWorldRotate; +extern aiVector3D g_vRotateSpeed /*= aiVector3D(0.5f,0.5f,0.5f)*/; + +extern aiVector3D g_avLightDirs[ 1 ] /* = + { aiVector3D(-0.5f,0.6f,0.2f) , + aiVector3D(-0.5f,0.5f,0.5f)} */; + + +extern POINT g_mousePos /*= {0,0};*/; +extern POINT g_LastmousePos /*= {0,0}*/; +extern bool g_bFPSView /*= false*/; +extern bool g_bInvert /*= false*/; +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 D3DCOLOR g_avLightColors[ 3 ]; + +extern RenderOptions g_sOptions; +extern Camera g_sCamera; +extern AssetHelper *g_pcAsset /*= NULL*/; + + +// +// Contains the mask image for the HUD +// (used to determine the position of a click) +// +// The size of the image is identical to the size of the main +// HUD texture +// +extern unsigned char* g_szImageMask /*= NULL*/; + + +extern float g_fACMR /*= 3.0f*/; +extern IDirect3DQuery9* g_piQuery; + +extern bool g_bPlay /*= false*/; + +extern double g_dCurrent; +extern float g_smoothAngle /*= 80.f*/; + +extern unsigned int ppsteps, ppstepsdefault; +extern bool nopointslines; + + +CMaterialManager CMaterialManager::s_cInstance; + +//------------------------------------------------------------------------------- +// D3DX callback function to fill a texture with a checkers pattern +// +// This pattern is used to mark textures which could not be loaded +//------------------------------------------------------------------------------- +VOID WINAPI FillFunc(D3DXVECTOR4* pOut, + CONST D3DXVECTOR2* pTexCoord, + CONST D3DXVECTOR2* pTexelSize, + LPVOID pData) +{ + UNREFERENCED_PARAMETER(pData); + UNREFERENCED_PARAMETER(pTexelSize); + + // generate a nice checker pattern (yellow/black) + // size of a square: 32 * 32 px + unsigned int iX = (unsigned int)(pTexCoord->x * 256.0f); + unsigned int iY = (unsigned int)(pTexCoord->y * 256.0f); + + bool bBlack = false; + if ((iX / 32) % 2 == 0) + { + if ((iY / 32) % 2 == 0)bBlack = true; + } + else + { + if ((iY / 32) % 2 != 0)bBlack = true; + } + pOut->w = 1.0f; + if (bBlack) + { + pOut->x = pOut->y = pOut->z = 0.0f; + } + else + { + pOut->x = pOut->y = 1.0f; + pOut->z = 0.0f; + } + return; +} + +//------------------------------------------------------------------------------- +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 CMaterialManager::SetDefaultTexture(IDirect3DTexture9** p_ppiOut) +{ + if (sDefaultTexture) { + sDefaultTexture->AddRef(); + *p_ppiOut = sDefaultTexture; + return 1; + } + if(FAILED(g_piDevice->CreateTexture( + 256, + 256, + 0, + 0, + D3DFMT_A8R8G8B8, + D3DPOOL_MANAGED, + p_ppiOut, + NULL))) + { + CLogDisplay::Instance().AddEntry("[ERROR] Unable to create default texture", + D3DCOLOR_ARGB(0xFF,0xFF,0,0)); + + *p_ppiOut = NULL; + return 0; + } + D3DXFillTexture(*p_ppiOut,&FillFunc,NULL); + sDefaultTexture = *p_ppiOut; + sDefaultTexture->AddRef(); + + // {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; +} +//------------------------------------------------------------------------------- +bool CMaterialManager::TryLongerPath(char* szTemp,aiString* p_szString) +{ + char szTempB[MAX_PATH]; + strcpy(szTempB,szTemp); + + // go to the beginning of the file name + char* szFile = strrchr(szTempB,'\\'); + if (!szFile)szFile = strrchr(szTempB,'/'); + + char* szFile2 = szTemp + (szFile - szTempB)+1; + szFile++; + char* szExt = strrchr(szFile,'.'); + if (!szExt)return false; + szExt++; + *szFile = 0; + + strcat(szTempB,"*.*"); + const unsigned int iSize = (const unsigned int) ( szExt - 1 - szFile ); + + HANDLE h; + WIN32_FIND_DATA info; + + // build a list of files + h = FindFirstFile(szTempB, &info); + if (h != INVALID_HANDLE_VALUE) + { + do + { + if (!(strcmp(info.cFileName, ".") == 0 || strcmp(info.cFileName, "..") == 0)) + { + char* szExtFound = strrchr(info.cFileName, '.'); + if (szExtFound) + { + ++szExtFound; + if (0 == ASSIMP_stricmp(szExtFound,szExt)) + { + const unsigned int iSizeFound = (const unsigned int) ( + szExtFound - 1 - info.cFileName); + + for (unsigned int i = 0; i < iSizeFound;++i) + info.cFileName[i] = (CHAR)tolower(info.cFileName[i]); + + if (0 == memcmp(info.cFileName,szFile2, min(iSizeFound,iSize))) + { + // we have it. Build the full path ... + char* sz = strrchr(szTempB,'*'); + *(sz-2) = 0x0; + + strcat(szTempB,info.cFileName); + + // copy the result string back to the aiString + const size_t iLen = strlen(szTempB); + size_t iLen2 = iLen+1; + iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2; + memcpy(p_szString->data,szTempB,iLen2); + p_szString->length = iLen; + return true; + } + } + // check whether the 8.3 DOS name is matching + if (0 == ASSIMP_stricmp(info.cAlternateFileName,p_szString->data)) + { + strcat(szTempB,info.cAlternateFileName); + + // copy the result string back to the aiString + const size_t iLen = strlen(szTempB); + size_t iLen2 = iLen+1; + iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2; + memcpy(p_szString->data,szTempB,iLen2); + p_szString->length = iLen; + return true; + } + } + } + } + while (FindNextFile(h, &info)); + + FindClose(h); + } + return false; +} +//------------------------------------------------------------------------------- +int CMaterialManager::FindValidPath(aiString* p_szString) +{ + ai_assert(NULL != p_szString); + aiString pcpy = *p_szString; + if ('*' == p_szString->data[0]) { + // '*' as first character indicates an embedded file + return 5; + } + + // first check whether we can directly load the file + FILE* pFile = fopen(p_szString->data,"rb"); + if (pFile)fclose(pFile); + else + { + // check whether we can use the directory of the asset as relative base + char szTemp[MAX_PATH*2], tmp2[MAX_PATH*2]; + strcpy(szTemp, g_szFileName); + strcpy(tmp2,szTemp); + + char* szData = p_szString->data; + if (*szData == '\\' || *szData == '/')++szData; + + char* szEnd = strrchr(szTemp,'\\'); + if (!szEnd) + { + szEnd = strrchr(szTemp,'/'); + if (!szEnd)szEnd = szTemp; + } + szEnd++; + *szEnd = 0; + strcat(szEnd,szData); + + + pFile = fopen(szTemp,"rb"); + if (!pFile) + { + // convert the string to lower case + for (unsigned int i = 0;;++i) + { + if ('\0' == szTemp[i])break; + szTemp[i] = (char)tolower(szTemp[i]); + } + + if(TryLongerPath(szTemp,p_szString))return 1; + *szEnd = 0; + + // search common sub directories + strcat(szEnd,"tex\\"); + strcat(szEnd,szData); + + pFile = fopen(szTemp,"rb"); + if (!pFile) + { + if(TryLongerPath(szTemp,p_szString))return 1; + + *szEnd = 0; + + strcat(szEnd,"textures\\"); + strcat(szEnd,szData); + + pFile = fopen(szTemp,"rb"); + if (!pFile) + { + if(TryLongerPath(szTemp, p_szString))return 1; + } + + // patch by mark sibly to look for textures files in the asset's base directory. + const char *path=pcpy.data; + const char *p=strrchr( path,'/' ); + if( !p ) p=strrchr( path,'\\' ); + if( p ){ + char *q=strrchr( tmp2,'/' ); + if( !q ) q=strrchr( tmp2,'\\' ); + if( q ){ + strcpy( q+1,p+1 ); + if((pFile=fopen( tmp2,"r" ))){ + fclose( pFile ); + strcpy(p_szString->data,tmp2); + p_szString->length = strlen(tmp2); + return 1; + } + } + } + return 0; + } + } + fclose(pFile); + + // copy the result string back to the aiString + const size_t iLen = strlen(szTemp); + size_t iLen2 = iLen+1; + iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2; + memcpy(p_szString->data,szTemp,iLen2); + p_szString->length = iLen; + + } + return 1; +} +//------------------------------------------------------------------------------- +int CMaterialManager::LoadTexture(IDirect3DTexture9** p_ppiOut,aiString* szPath) +{ + ai_assert(NULL != p_ppiOut); + ai_assert(NULL != szPath); + + *p_ppiOut = NULL; + + const std::string s = szPath->data; + TextureCache::iterator ff; + if ((ff = sCachedTextures.find(s)) != sCachedTextures.end()) { + *p_ppiOut = (*ff).second; + (*p_ppiOut)->AddRef(); + return 1; + } + + // first get a valid path to the texture + if( 5 == FindValidPath(szPath)) + { + // embedded file. Find its index + unsigned int iIndex = atoi(szPath->data+1); + if (iIndex < g_pcAsset->pcScene->mNumTextures) + { + if (0 == g_pcAsset->pcScene->mTextures[iIndex]->mHeight) + { + // it is an embedded file ... don't need the file format hint, + // simply let D3DX load the file + D3DXIMAGE_INFO info; + if (FAILED(D3DXCreateTextureFromFileInMemoryEx(g_piDevice, + g_pcAsset->pcScene->mTextures[iIndex]->pcData, + g_pcAsset->pcScene->mTextures[iIndex]->mWidth, + D3DX_DEFAULT, + D3DX_DEFAULT, + 1, + D3DUSAGE_AUTOGENMIPMAP, + D3DFMT_UNKNOWN, + D3DPOOL_MANAGED, + D3DX_DEFAULT, + D3DX_DEFAULT, + 0, + &info, + NULL, + p_ppiOut))) + { + std::string sz = "[ERROR] Unable to load embedded texture (#1): "; + sz.append(szPath->data); + CLogDisplay::Instance().AddEntry(sz,D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0)); + + this->SetDefaultTexture(p_ppiOut); + return 1; + } + } + else + { + // fill a new texture ... + if(FAILED(g_piDevice->CreateTexture( + g_pcAsset->pcScene->mTextures[iIndex]->mWidth, + g_pcAsset->pcScene->mTextures[iIndex]->mHeight, + 0,D3DUSAGE_AUTOGENMIPMAP,D3DFMT_A8R8G8B8,D3DPOOL_MANAGED,p_ppiOut,NULL))) + { + std::string sz = "[ERROR] Unable to load embedded texture (#2): "; + sz.append(szPath->data); + CLogDisplay::Instance().AddEntry(sz,D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0)); + + this->SetDefaultTexture(p_ppiOut); + return 1; + } + + // now copy the data to it ... (assume non pow2 to be supported) + D3DLOCKED_RECT sLock; + (*p_ppiOut)->LockRect(0,&sLock,NULL,0); + + const aiTexel* pcData = g_pcAsset->pcScene->mTextures[iIndex]->pcData; + + for (unsigned int y = 0; y < g_pcAsset->pcScene->mTextures[iIndex]->mHeight;++y) + { + memcpy(sLock.pBits,pcData,g_pcAsset->pcScene->mTextures[iIndex]-> + mWidth *sizeof(aiTexel)); + sLock.pBits = (char*)sLock.pBits + sLock.Pitch; + pcData += g_pcAsset->pcScene->mTextures[iIndex]->mWidth; + } + (*p_ppiOut)->UnlockRect(0); + (*p_ppiOut)->GenerateMipSubLevels(); + } + sCachedTextures[s] = *p_ppiOut; + (*p_ppiOut)->AddRef(); + return 1; + } + else + { + std::string sz = "[ERROR] Invalid index for embedded texture: "; + sz.append(szPath->data); + CLogDisplay::Instance().AddEntry(sz,D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0)); + + SetDefaultTexture(p_ppiOut); + return 1; + } + } + + // then call D3DX to load the texture + if (FAILED(D3DXCreateTextureFromFileEx( + g_piDevice, + szPath->data, + D3DX_DEFAULT, + D3DX_DEFAULT, + 0, + 0, + D3DFMT_A8R8G8B8, + D3DPOOL_MANAGED, + D3DX_DEFAULT, + D3DX_DEFAULT, + 0, + NULL, + NULL, + p_ppiOut))) + { + // error ... use the default texture instead + std::string sz = "[ERROR] Unable to load texture: "; + sz.append(szPath->data); + CLogDisplay::Instance().AddEntry(sz,D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0)); + + this->SetDefaultTexture(p_ppiOut); + } + sCachedTextures[s] = *p_ppiOut; + (*p_ppiOut)->AddRef(); + + return 1; +} +//------------------------------------------------------------------------------- +void CMaterialManager::DeleteMaterial(AssetHelper::MeshHelper* pcIn) +{ + if (!pcIn || !pcIn->piEffect)return; + pcIn->piEffect->Release(); + + // release all textures associated with the material + if (pcIn->piDiffuseTexture) + { + pcIn->piDiffuseTexture->Release(); + pcIn->piDiffuseTexture = NULL; + } + if (pcIn->piSpecularTexture) + { + pcIn->piSpecularTexture->Release(); + pcIn->piSpecularTexture = NULL; + } + if (pcIn->piEmissiveTexture) + { + pcIn->piEmissiveTexture->Release(); + pcIn->piEmissiveTexture = NULL; + } + if (pcIn->piAmbientTexture) + { + pcIn->piAmbientTexture->Release(); + pcIn->piAmbientTexture = NULL; + } + if (pcIn->piOpacityTexture) + { + pcIn->piOpacityTexture->Release(); + pcIn->piOpacityTexture = NULL; + } + if (pcIn->piNormalTexture) + { + pcIn->piNormalTexture->Release(); + pcIn->piNormalTexture = NULL; + } + if (pcIn->piShininessTexture) + { + pcIn->piShininessTexture->Release(); + pcIn->piShininessTexture = NULL; + } + if (pcIn->piLightmapTexture) + { + pcIn->piLightmapTexture->Release(); + pcIn->piLightmapTexture = NULL; + } + pcIn->piEffect = NULL; +} +//------------------------------------------------------------------------------- +void CMaterialManager::HMtoNMIfNecessary( + IDirect3DTexture9* piTexture, + IDirect3DTexture9** piTextureOut, + bool bWasOriginallyHM) +{ + ai_assert(NULL != piTexture); + ai_assert(NULL != piTextureOut); + + bool bMustConvert = false; + uintptr_t iElement = 3; + + *piTextureOut = piTexture; + + // Lock the input texture and try to determine its type. + // Criterias: + // - If r,g,b channel are identical it MUST be a height map + // - If one of the rgb channels is used and the others are empty it + // must be a height map, too. + // - If the average color of the whole image is something inside the + // purple range we can be sure it is a normal map + // + // - Otherwise we assume it is a normal map + // To increase performance we take not every pixel + + D3DLOCKED_RECT sRect; + D3DSURFACE_DESC sDesc; + piTexture->GetLevelDesc(0,&sDesc); + if (FAILED(piTexture->LockRect(0,&sRect,NULL,D3DLOCK_READONLY))) + { + return; + } + const int iPitchDiff = (int)sRect.Pitch - (int)(sDesc.Width * 4); + + struct SColor + { + union + { + struct {unsigned char b,g,r,a;}; + char _array[4]; + }; + }; + const SColor* pcData = (const SColor*)sRect.pBits; + + union + { + const SColor* pcPointer; + const unsigned char* pcCharPointer; + }; + pcPointer = pcData; + + // 1. If r,g,b channel are identical it MUST be a height map + bool bIsEqual = true; + for (unsigned int y = 0; y < sDesc.Height;++y) + { + for (unsigned int x = 0; x < sDesc.Width;++x) + { + if (pcPointer->b != pcPointer->r || pcPointer->b != pcPointer->g) + { + bIsEqual = false; + break; + } + pcPointer++; + } + pcCharPointer += iPitchDiff; + } + if (bIsEqual)bMustConvert = true; + else + { + // 2. If one of the rgb channels is used and the others are empty it + // must be a height map, too. + pcPointer = pcData; + while (*pcCharPointer == 0)pcCharPointer++; + + iElement = (uintptr_t)(pcCharPointer - (unsigned char*)pcData) % 4; + unsigned int aiIndex[3] = {0,1,2}; + if (3 != iElement)aiIndex[iElement] = 3; + + pcPointer = pcData; + + bIsEqual = true; + if (3 != iElement) + { + for (unsigned int y = 0; y < sDesc.Height;++y) + { + for (unsigned int x = 0; x < sDesc.Width;++x) + { + for (unsigned int ii = 0; ii < 3;++ii) + { + // don't take the alpha channel into account. + // if the texture was stored n RGB888 format D3DX has + // converted it to ARGB8888 format with a fixed alpha channel + if (aiIndex[ii] != 3 && pcPointer->_array[aiIndex[ii]] != 0) + { + bIsEqual = false; + break; + } + } + pcPointer++; + } + pcCharPointer += iPitchDiff; + } + if (bIsEqual)bMustConvert = true; + else + { + // If the average color of the whole image is something inside the + // purple range we can be sure it is a normal map + + // (calculate the average color line per line to prevent overflows!) + pcPointer = pcData; + aiColor3D clrColor; + for (unsigned int y = 0; y < sDesc.Height;++y) + { + aiColor3D clrColorLine; + for (unsigned int x = 0; x < sDesc.Width;++x) + { + clrColorLine.r += pcPointer->r; + clrColorLine.g += pcPointer->g; + clrColorLine.b += pcPointer->b; + pcPointer++; + } + clrColor.r += clrColorLine.r /= (float)sDesc.Width; + clrColor.g += clrColorLine.g /= (float)sDesc.Width; + clrColor.b += clrColorLine.b /= (float)sDesc.Width; + pcCharPointer += iPitchDiff; + } + clrColor.r /= (float)sDesc.Height; + clrColor.g /= (float)sDesc.Height; + clrColor.b /= (float)sDesc.Height; + + if (!(clrColor.b > 215 && + clrColor.r > 100 && clrColor.r < 140 && + clrColor.g > 100 && clrColor.g < 140)) + { + // Unable to detect. Believe the original value obtained from the loader + if (bWasOriginallyHM) + { + bMustConvert = true; + } + } + } + } + } + + piTexture->UnlockRect(0); + + // if the input data is assumed to be a height map we'll + // need to convert it NOW + if (bMustConvert) + { + D3DSURFACE_DESC sDesc; + piTexture->GetLevelDesc(0, &sDesc); + + IDirect3DTexture9* piTempTexture; + if(FAILED(g_piDevice->CreateTexture( + sDesc.Width, + sDesc.Height, + piTexture->GetLevelCount(), + sDesc.Usage, + sDesc.Format, + sDesc.Pool, &piTempTexture, NULL))) + { + CLogDisplay::Instance().AddEntry( + "[ERROR] Unable to create normal map texture", + D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0)); + return; + } + + DWORD dwFlags; + if (3 == iElement)dwFlags = D3DX_CHANNEL_LUMINANCE; + else if (2 == iElement)dwFlags = D3DX_CHANNEL_RED; + else if (1 == iElement)dwFlags = D3DX_CHANNEL_GREEN; + else /*if (0 == iElement)*/dwFlags = D3DX_CHANNEL_BLUE; + + if(FAILED(D3DXComputeNormalMap(piTempTexture, + piTexture,NULL,0,dwFlags,1.0f))) + { + CLogDisplay::Instance().AddEntry( + "[ERROR] Unable to compute normal map from height map", + D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0)); + + piTempTexture->Release(); + return; + } + *piTextureOut = piTempTexture; + piTexture->Release(); + } +} +//------------------------------------------------------------------------------- +bool CMaterialManager::HasAlphaPixels(IDirect3DTexture9* piTexture) +{ + ai_assert(NULL != piTexture); + + D3DLOCKED_RECT sRect; + D3DSURFACE_DESC sDesc; + piTexture->GetLevelDesc(0,&sDesc); + if (FAILED(piTexture->LockRect(0,&sRect,NULL,D3DLOCK_READONLY))) + { + return false; + } + const int iPitchDiff = (int)sRect.Pitch - (int)(sDesc.Width * 4); + + struct SColor + { + unsigned char b,g,r,a;; + }; + const SColor* pcData = (const SColor*)sRect.pBits; + + union + { + const SColor* pcPointer; + const unsigned char* pcCharPointer; + }; + pcPointer = pcData; + for (unsigned int y = 0; y < sDesc.Height;++y) + { + for (unsigned int x = 0; x < sDesc.Width;++x) + { + if (pcPointer->a != 0xFF) + { + piTexture->UnlockRect(0); + return true; + } + pcPointer++; + } + pcCharPointer += iPitchDiff; + } + piTexture->UnlockRect(0); + return false; +} +//------------------------------------------------------------------------------- +int CMaterialManager::CreateMaterial( + AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSource) +{ + ai_assert(NULL != pcMesh); + ai_assert(NULL != pcSource); + + ID3DXBuffer* piBuffer; + + D3DXMACRO sMacro[64]; + + // extract all properties from the ASSIMP material structure + const aiMaterial* pcMat = g_pcAsset->pcScene->mMaterials[pcSource->mMaterialIndex]; + + // + // DIFFUSE COLOR -------------------------------------------------- + // + if(AI_SUCCESS != aiGetMaterialColor(pcMat,AI_MATKEY_COLOR_DIFFUSE, + (aiColor4D*)&pcMesh->vDiffuseColor)) + { + pcMesh->vDiffuseColor.x = 1.0f; + pcMesh->vDiffuseColor.y = 1.0f; + pcMesh->vDiffuseColor.z = 1.0f; + pcMesh->vDiffuseColor.w = 1.0f; + } + // + // SPECULAR COLOR -------------------------------------------------- + // + if(AI_SUCCESS != aiGetMaterialColor(pcMat,AI_MATKEY_COLOR_SPECULAR, + (aiColor4D*)&pcMesh->vSpecularColor)) + { + pcMesh->vSpecularColor.x = 1.0f; + pcMesh->vSpecularColor.y = 1.0f; + pcMesh->vSpecularColor.z = 1.0f; + pcMesh->vSpecularColor.w = 1.0f; + } + // + // AMBIENT COLOR -------------------------------------------------- + // + if(AI_SUCCESS != aiGetMaterialColor(pcMat,AI_MATKEY_COLOR_AMBIENT, + (aiColor4D*)&pcMesh->vAmbientColor)) + { + pcMesh->vAmbientColor.x = 0.0f; + pcMesh->vAmbientColor.y = 0.0f; + pcMesh->vAmbientColor.z = 0.0f; + pcMesh->vAmbientColor.w = 1.0f; + } + // + // EMISSIVE COLOR ------------------------------------------------- + // + if(AI_SUCCESS != aiGetMaterialColor(pcMat,AI_MATKEY_COLOR_EMISSIVE, + (aiColor4D*)&pcMesh->vEmissiveColor)) + { + pcMesh->vEmissiveColor.x = 0.0f; + pcMesh->vEmissiveColor.y = 0.0f; + pcMesh->vEmissiveColor.z = 0.0f; + pcMesh->vEmissiveColor.w = 1.0f; + } + + // + // Opacity -------------------------------------------------------- + // + if(AI_SUCCESS != aiGetMaterialFloat(pcMat,AI_MATKEY_OPACITY,&pcMesh->fOpacity)) + { + pcMesh->fOpacity = 1.0f; + } + + // + // Shading Model -------------------------------------------------- + // + bool bDefault = false; + if(AI_SUCCESS != aiGetMaterialInteger(pcMat,AI_MATKEY_SHADING_MODEL,(int*)&pcMesh->eShadingMode )) + { + bDefault = true; + pcMesh->eShadingMode = aiShadingMode_Gouraud; + } + + + // + // Shininess ------------------------------------------------------ + // + if(AI_SUCCESS != aiGetMaterialFloat(pcMat,AI_MATKEY_SHININESS,&pcMesh->fShininess)) + { + // assume 15 as default shininess + pcMesh->fShininess = 15.0f; + } + else if (bDefault)pcMesh->eShadingMode = aiShadingMode_Phong; + + + // + // Shininess strength ------------------------------------------------------ + // + if(AI_SUCCESS != aiGetMaterialFloat(pcMat,AI_MATKEY_SHININESS_STRENGTH,&pcMesh->fSpecularStrength)) + { + // assume 1.0 as default shininess strength + pcMesh->fSpecularStrength = 1.0f; + } + + aiString szPath; + + aiTextureMapMode mapU(aiTextureMapMode_Wrap),mapV(aiTextureMapMode_Wrap); + + bool bib =false; + if (pcSource->mTextureCoords[0]) + { + + // + // DIFFUSE TEXTURE ------------------------------------------------ + // + if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_DIFFUSE(0),&szPath)) + { + LoadTexture(&pcMesh->piDiffuseTexture,&szPath); + + aiGetMaterialInteger(pcMat,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0),(int*)&mapU); + aiGetMaterialInteger(pcMat,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0),(int*)&mapV); + } + + // + // SPECULAR TEXTURE ------------------------------------------------ + // + if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_SPECULAR(0),&szPath)) + { + LoadTexture(&pcMesh->piSpecularTexture,&szPath); + } + + // + // OPACITY TEXTURE ------------------------------------------------ + // + if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_OPACITY(0),&szPath)) + { + LoadTexture(&pcMesh->piOpacityTexture,&szPath); + } + else + { + int flags = 0; + aiGetMaterialInteger(pcMat,AI_MATKEY_TEXFLAGS_DIFFUSE(0),&flags); + + // try to find out whether the diffuse texture has any + // non-opaque pixels. If we find a few, use it as opacity texture + if (pcMesh->piDiffuseTexture && !(flags & aiTextureFlags_IgnoreAlpha) && HasAlphaPixels(pcMesh->piDiffuseTexture)) + { + 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",0,0,&iVal)) + { + pcMesh->piOpacityTexture = pcMesh->piDiffuseTexture; + pcMesh->piOpacityTexture->AddRef(); + } + } + } + + // + // AMBIENT TEXTURE ------------------------------------------------ + // + if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_AMBIENT(0),&szPath)) + { + LoadTexture(&pcMesh->piAmbientTexture,&szPath); + } + + // + // EMISSIVE TEXTURE ------------------------------------------------ + // + if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_EMISSIVE(0),&szPath)) + { + LoadTexture(&pcMesh->piEmissiveTexture,&szPath); + } + + // + // Shininess TEXTURE ------------------------------------------------ + // + if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_SHININESS(0),&szPath)) + { + LoadTexture(&pcMesh->piShininessTexture,&szPath); + } + + // + // Lightmap TEXTURE ------------------------------------------------ + // + if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_LIGHTMAP(0),&szPath)) + { + LoadTexture(&pcMesh->piLightmapTexture,&szPath); + } + + + // + // NORMAL/HEIGHT MAP ------------------------------------------------ + // + bool bHM = false; + if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_NORMALS(0),&szPath)) + { + LoadTexture(&pcMesh->piNormalTexture,&szPath); + } + else + { + if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_HEIGHT(0),&szPath)) + { + LoadTexture(&pcMesh->piNormalTexture,&szPath); + } + else bib = true; + bHM = true; + } + + // normal/height maps are sometimes mixed up. Try to detect the type + // of the texture automatically + if (pcMesh->piNormalTexture) + { + HMtoNMIfNecessary(pcMesh->piNormalTexture, &pcMesh->piNormalTexture,bHM); + } + } + + // check whether a global background texture is contained + // in this material. Some loaders set this value ... + if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_GLOBAL_BACKGROUND_IMAGE,&szPath)) + { + CBackgroundPainter::Instance().SetTextureBG(szPath.data); + } + + // 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; + } + + int two_sided = 0; + aiGetMaterialInteger(pcMat,AI_MATKEY_TWOSIDED,&two_sided); + pcMesh->twosided = (two_sided != 0); + + // check whether we have already a material using the same + // shader. This will decrease loading time rapidly ... + for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) + { + if (g_pcAsset->pcScene->mMeshes[i] == pcSource) + { + break; + } + AssetHelper::MeshHelper* pc = g_pcAsset->apcMeshes[i]; + + if ((pcMesh->piDiffuseTexture != NULL ? true : false) != + (pc->piDiffuseTexture != NULL ? true : false)) + continue; + if ((pcMesh->piSpecularTexture != NULL ? true : false) != + (pc->piSpecularTexture != NULL ? true : false)) + continue; + if ((pcMesh->piAmbientTexture != NULL ? true : false) != + (pc->piAmbientTexture != NULL ? true : false)) + continue; + if ((pcMesh->piEmissiveTexture != NULL ? true : false) != + (pc->piEmissiveTexture != NULL ? true : false)) + continue; + if ((pcMesh->piNormalTexture != NULL ? true : false) != + (pc->piNormalTexture != NULL ? true : false)) + continue; + 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->piLightmapTexture != NULL ? true : false) != + (pc->piLightmapTexture != NULL ? true : false)) + continue; + if ((pcMesh->eShadingMode != aiShadingMode_Gouraud ? true : false) != + (pc->eShadingMode != aiShadingMode_Gouraud ? true : false)) + continue; + + if ((pcMesh->fOpacity != 1.0f ? true : false) != (pc->fOpacity != 1.0f ? true : false)) + continue; + + if (pcSource->HasBones() != g_pcAsset->pcScene->mMeshes[i]->HasBones()) + continue; + + // we can reuse this material + if (pc->piEffect) + { + pcMesh->piEffect = pc->piEffect; + pc->bSharedFX = pcMesh->bSharedFX = true; + pcMesh->piEffect->AddRef(); + return 2; + } + } + m_iShaderCount++; + + // build macros for the HLSL compiler + unsigned int iCurrent = 0; + if (pcMesh->piDiffuseTexture) + { + sMacro[iCurrent].Name = "AV_DIFFUSE_TEXTURE"; + sMacro[iCurrent].Definition = "1"; + ++iCurrent; + + if (mapU == aiTextureMapMode_Wrap) + sMacro[iCurrent].Name = "AV_WRAPU"; + else if (mapU == aiTextureMapMode_Mirror) + sMacro[iCurrent].Name = "AV_MIRRORU"; + else // if (mapU == aiTextureMapMode_Clamp) + sMacro[iCurrent].Name = "AV_CLAMPU"; + + sMacro[iCurrent].Definition = "1"; + ++iCurrent; + + + if (mapV == aiTextureMapMode_Wrap) + sMacro[iCurrent].Name = "AV_WRAPV"; + else if (mapV == aiTextureMapMode_Mirror) + sMacro[iCurrent].Name = "AV_MIRRORV"; + else // if (mapV == aiTextureMapMode_Clamp) + sMacro[iCurrent].Name = "AV_CLAMPV"; + + sMacro[iCurrent].Definition = "1"; + ++iCurrent; + } + if (pcMesh->piSpecularTexture) + { + sMacro[iCurrent].Name = "AV_SPECULAR_TEXTURE"; + sMacro[iCurrent].Definition = "1"; + ++iCurrent; + } + if (pcMesh->piAmbientTexture) + { + sMacro[iCurrent].Name = "AV_AMBIENT_TEXTURE"; + sMacro[iCurrent].Definition = "1"; + ++iCurrent; + } + if (pcMesh->piEmissiveTexture) + { + sMacro[iCurrent].Name = "AV_EMISSIVE_TEXTURE"; + sMacro[iCurrent].Definition = "1"; + ++iCurrent; + } + char buff[32]; + if (pcMesh->piLightmapTexture) + { + sMacro[iCurrent].Name = "AV_LIGHTMAP_TEXTURE"; + sMacro[iCurrent].Definition = "1"; + ++iCurrent; + + int idx; + if(AI_SUCCESS == aiGetMaterialInteger(pcMat,AI_MATKEY_UVWSRC_LIGHTMAP(0),&idx) && idx >= 1 && pcSource->mTextureCoords[idx]) { + sMacro[iCurrent].Name = "AV_TWO_UV"; + sMacro[iCurrent].Definition = "1"; + ++iCurrent; + + sMacro[iCurrent].Definition = "IN.TexCoord1"; + } + else sMacro[iCurrent].Definition = "IN.TexCoord0"; + sMacro[iCurrent].Name = "AV_LIGHTMAP_TEXTURE_UV_COORD"; + + ++iCurrent;float f= 1.f; + aiGetMaterialFloat(pcMat,AI_MATKEY_TEXBLEND_LIGHTMAP(0),&f); + sprintf(buff,"%f",f); + + sMacro[iCurrent].Name = "LM_STRENGTH"; + sMacro[iCurrent].Definition = buff; + ++iCurrent; + } + if (pcMesh->piNormalTexture && !bib) + { + sMacro[iCurrent].Name = "AV_NORMAL_TEXTURE"; + sMacro[iCurrent].Definition = "1"; + ++iCurrent; + } + if (pcMesh->piOpacityTexture) + { + sMacro[iCurrent].Name = "AV_OPACITY_TEXTURE"; + sMacro[iCurrent].Definition = "1"; + ++iCurrent; + + if (pcMesh->piOpacityTexture == pcMesh->piDiffuseTexture) + { + sMacro[iCurrent].Name = "AV_OPACITY_TEXTURE_REGISTER_MASK"; + sMacro[iCurrent].Definition = "a"; + ++iCurrent; + } + else + { + sMacro[iCurrent].Name = "AV_OPACITY_TEXTURE_REGISTER_MASK"; + sMacro[iCurrent].Definition = "r"; + ++iCurrent; + } + } + + 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) + { + sMacro[iCurrent].Name = "AV_OPACITY"; + sMacro[iCurrent].Definition = "1"; + ++iCurrent; + } + + if( pcSource->HasBones()) + { + sMacro[iCurrent].Name = "AV_SKINNING"; + sMacro[iCurrent].Definition = "1"; + ++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()) + { + sMacro[iCurrent].Name = "AV_SKYBOX_LOOKUP"; + sMacro[iCurrent].Definition = "1"; + ++iCurrent; + } + sMacro[iCurrent].Name = NULL; + sMacro[iCurrent].Definition = NULL; + + // compile the shader + if(FAILED( D3DXCreateEffect(g_piDevice, + g_szMaterialShader.c_str(),(UINT)g_szMaterialShader.length(), + (const D3DXMACRO*)sMacro,NULL,0,NULL,&pcMesh->piEffect,&piBuffer))) + { + // failed to compile the shader + if( piBuffer) + { + MessageBox(g_hDlg,(LPCSTR)piBuffer->GetBufferPointer(),"HLSL",MB_OK); + piBuffer->Release(); + } + // use the default material instead + if (g_piDefaultEffect) + { + pcMesh->piEffect = g_piDefaultEffect; + g_piDefaultEffect->AddRef(); + } + + // get the name of the material and use it in the log message + if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_NAME,&szPath) && + '\0' != szPath.data[0]) + { + std::string sz = "[ERROR] Unable to load material: "; + sz.append(szPath.data); + CLogDisplay::Instance().AddEntry(sz); + } + else + { + CLogDisplay::Instance().AddEntry("Unable to load material: UNNAMED"); + } + return 0; + } else + { + // use Fixed Function effect when working with shaderless cards + if( g_sCaps.PixelShaderVersion < D3DPS_VERSION(2,0)) + pcMesh->piEffect->SetTechnique( "MaterialFX_FF"); + } + + if( piBuffer) piBuffer->Release(); + + + // now commit all constants to the shader + // + // This is not necessary for shared shader. Shader constants for + // shared shaders are automatically recommited before the shader + // is being used for a particular mesh + + if (1.0f != pcMesh->fOpacity) + pcMesh->piEffect->SetFloat("TRANSPARENCY",pcMesh->fOpacity); + if (pcMesh->eShadingMode != aiShadingMode_Gouraud && !g_sOptions.bNoSpecular) + { + pcMesh->piEffect->SetFloat("SPECULARITY",pcMesh->fShininess); + pcMesh->piEffect->SetFloat("SPECULAR_STRENGTH",pcMesh->fSpecularStrength); + } + + 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->piDiffuseTexture) + pcMesh->piEffect->SetTexture("DIFFUSE_TEXTURE",pcMesh->piDiffuseTexture); + if (pcMesh->piOpacityTexture) + pcMesh->piEffect->SetTexture("OPACITY_TEXTURE",pcMesh->piOpacityTexture); + 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 (pcMesh->piLightmapTexture) + pcMesh->piEffect->SetTexture("LIGHTMAP_TEXTURE",pcMesh->piLightmapTexture); + + if (CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode()){ + pcMesh->piEffect->SetTexture("lw_tex_envmap",CBackgroundPainter::Instance().GetTexture()); + } + + return 1; +} +//------------------------------------------------------------------------------- +int CMaterialManager::SetupMaterial ( + AssetHelper::MeshHelper* pcMesh, + const aiMatrix4x4& pcProj, + const aiMatrix4x4& aiMe, + const aiMatrix4x4& pcCam, + const aiVector3D& vPos) +{ + ai_assert(NULL != pcMesh); + if (!pcMesh->piEffect)return 0; + + ID3DXEffect* piEnd = pcMesh->piEffect; + + piEnd->SetMatrix("WorldViewProjection", + (const D3DXMATRIX*)&pcProj); + + piEnd->SetMatrix("World",(const D3DXMATRIX*)&aiMe); + piEnd->SetMatrix("WorldInverseTranspose", + (const D3DXMATRIX*)&pcCam); + + D3DXVECTOR4 apcVec[5]; + memset(apcVec,0,sizeof(apcVec)); + apcVec[0].x = g_avLightDirs[0].x; + apcVec[0].y = g_avLightDirs[0].y; + apcVec[0].z = g_avLightDirs[0].z; + apcVec[0].w = 0.0f; + 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; + apcVec[1].w = 0.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; + + if( g_sOptions.b3Lights) + { + 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; + } else + { + 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 = ((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->SetFloat("SPECULAR_STRENGTH",pcMesh->fSpecularStrength); + } + + 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 (pcMesh->piLightmapTexture) + pcMesh->piEffect->SetTexture("LIGHTMAP_TEXTURE",pcMesh->piLightmapTexture); + + if (CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode()) + { + piEnd->SetTexture("lw_tex_envmap",CBackgroundPainter::Instance().GetTexture()); + } + } + + // disable culling, if necessary + if (pcMesh->twosided && g_sOptions.bCulling) { + g_piDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE); + } + + // setup the correct shader technique to be used for drawing + if( g_sCaps.PixelShaderVersion < D3DPS_VERSION(2,0)) + { + g_piDefaultEffect->SetTechnique( "MaterialFXSpecular_FF"); + } else + 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(); + + // reenable culling if necessary + if (pcMesh->twosided && g_sOptions.bCulling) { + g_piDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_CCW); + } + + return 1; +} +}; // end namespace AssimpView diff --git a/tools/assimp_view/MaterialManager.h b/tools/assimp_view/MaterialManager.h index 069d6dc2b..d1c9eb507 100644 --- a/tools/assimp_view/MaterialManager.h +++ b/tools/assimp_view/MaterialManager.h @@ -1,208 +1,208 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2012, assimp 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 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. ---------------------------------------------------------------------------- -*/ - -#pragma once - -#include <map> - -#include "AssetHelper.h" - -namespace AssimpView -{ - - //------------------------------------------------------------------------------- - /* Helper class to create, access and destroy materials - */ - //------------------------------------------------------------------------------- - class CMaterialManager - { - private: - - friend class CDisplay; - - // default constructor - CMaterialManager() - : m_iShaderCount( 0 ), sDefaultTexture() {} - - ~CMaterialManager() { - if( sDefaultTexture ) { - sDefaultTexture->Release(); - } - Reset(); - } - - 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; - for( TextureCache::iterator it = sCachedTextures.begin(); it != sCachedTextures.end(); ++it ) { - ( *it ).second->Release(); - } - sCachedTextures.clear(); - } - - 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; - IDirect3DTexture9* sDefaultTexture; - - typedef std::map<std::string, IDirect3DTexture9*> TextureCache; - TextureCache sCachedTextures; - }; - -} +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2012, assimp 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 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. +--------------------------------------------------------------------------- +*/ + +#pragma once + +#include <map> + +#include "AssetHelper.h" + +namespace AssimpView +{ + + //------------------------------------------------------------------------------- + /* Helper class to create, access and destroy materials + */ + //------------------------------------------------------------------------------- + class CMaterialManager + { + private: + + friend class CDisplay; + + // default constructor + CMaterialManager() + : m_iShaderCount( 0 ), sDefaultTexture() {} + + ~CMaterialManager() { + if( sDefaultTexture ) { + sDefaultTexture->Release(); + } + Reset(); + } + + 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; + for( TextureCache::iterator it = sCachedTextures.begin(); it != sCachedTextures.end(); ++it ) { + ( *it ).second->Release(); + } + sCachedTextures.clear(); + } + + 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; + IDirect3DTexture9* sDefaultTexture; + + typedef std::map<std::string, IDirect3DTexture9*> TextureCache; + TextureCache sCachedTextures; + }; + +} diff --git a/tools/assimp_view/MeshRenderer.cpp b/tools/assimp_view/MeshRenderer.cpp index 0fdaaf51e..834c5a9e2 100644 --- a/tools/assimp_view/MeshRenderer.cpp +++ b/tools/assimp_view/MeshRenderer.cpp @@ -1,166 +1,166 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2015, assimp 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 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 "assimp_view.h" - -#include <map> -#include <functional> - -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); - - D3DPRIMITIVETYPE type = D3DPT_POINTLIST; - switch (g_pcAsset->pcScene->mMeshes[iIndex]->mPrimitiveTypes) { - case aiPrimitiveType_POINT: - type = D3DPT_POINTLIST;break; - case aiPrimitiveType_LINE: - type = D3DPT_LINELIST;break; - case aiPrimitiveType_TRIANGLE: - type = D3DPT_TRIANGLELIST;break; - } - // and draw the mesh - g_piDevice->DrawIndexedPrimitive(type, - 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]; - - if (!pcHelper || !pcMesh || !pcHelper->piIB) - return -5; - - if (pcMesh->mPrimitiveTypes != aiPrimitiveType_TRIANGLE || pcMesh->HasBones() || g_sOptions.bNoAlphaBlending) - return DrawUnsorted(iIndex); - - - // compute the position of the camera in worldspace - aiMatrix4x4 mWorldInverse = mWorld; - mWorldInverse.Inverse(); - mWorldInverse.Transpose(); - const aiVector3D vLocalCamera = mWorldInverse * g_sCamera.vPos; - - // well ... this is really funny now. We must compute their distance - // from the camera. We take the average distance of a face and add it - // to a map which sorts it - std::map<float,unsigned int, std::greater<float> > smap; - - for (unsigned int iFace = 0; iFace < pcMesh->mNumFaces;++iFace) - { - const aiFace* pcFace = &pcMesh->mFaces[iFace]; - float fDist = 0.0f; - for (unsigned int c = 0; c < 3;++c) - { - aiVector3D vPos = pcMesh->mVertices[pcFace->mIndices[c]]; - vPos -= vLocalCamera; - fDist += vPos.SquareLength(); - } - smap.insert(std::pair<float, unsigned int>(fDist,iFace)); - } - - // now we can lock the index buffer and rebuild it - D3DINDEXBUFFER_DESC sDesc; - pcHelper->piIB->GetDesc(&sDesc); - - if (D3DFMT_INDEX16 == sDesc.Format) - { - uint16_t* aiIndices; - pcHelper->piIB->Lock(0,0,(void**)&aiIndices,D3DLOCK_DISCARD); - - for (std::map<float,unsigned int, std::greater<float> >::const_iterator - i = smap.begin(); - i != smap.end();++i) - { - const aiFace* pcFace = &pcMesh->mFaces[(*i).second]; - *aiIndices++ = (uint16_t)pcFace->mIndices[0]; - *aiIndices++ = (uint16_t)pcFace->mIndices[1]; - *aiIndices++ = (uint16_t)pcFace->mIndices[2]; - } - } - else if (D3DFMT_INDEX32 == sDesc.Format) - { - uint32_t* aiIndices; - pcHelper->piIB->Lock(0,0,(void**)&aiIndices,D3DLOCK_DISCARD); - - for (std::map<float,unsigned int, std::greater<float> >::const_iterator - i = smap.begin(); - i != smap.end();++i) - { - const aiFace* pcFace = &pcMesh->mFaces[(*i).second]; - *aiIndices++ = (uint32_t)pcFace->mIndices[0]; - *aiIndices++ = (uint32_t)pcFace->mIndices[1]; - *aiIndices++ = (uint32_t)pcFace->mIndices[2]; - } - } - pcHelper->piIB->Unlock(); - - // set vertex and index buffer - g_piDevice->SetStreamSource(0,pcHelper->piVB,0,sizeof(AssetHelper::Vertex)); - - // and draw the mesh - g_piDevice->SetIndices(pcHelper->piIB); - g_piDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, - 0,0, - pcMesh->mNumVertices,0, - pcMesh->mNumFaces); - - return 1; -} +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2015, assimp 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 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 "assimp_view.h" + +#include <map> +#include <functional> + +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); + + D3DPRIMITIVETYPE type = D3DPT_POINTLIST; + switch (g_pcAsset->pcScene->mMeshes[iIndex]->mPrimitiveTypes) { + case aiPrimitiveType_POINT: + type = D3DPT_POINTLIST;break; + case aiPrimitiveType_LINE: + type = D3DPT_LINELIST;break; + case aiPrimitiveType_TRIANGLE: + type = D3DPT_TRIANGLELIST;break; + } + // and draw the mesh + g_piDevice->DrawIndexedPrimitive(type, + 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]; + + if (!pcHelper || !pcMesh || !pcHelper->piIB) + return -5; + + if (pcMesh->mPrimitiveTypes != aiPrimitiveType_TRIANGLE || pcMesh->HasBones() || g_sOptions.bNoAlphaBlending) + return DrawUnsorted(iIndex); + + + // compute the position of the camera in worldspace + aiMatrix4x4 mWorldInverse = mWorld; + mWorldInverse.Inverse(); + mWorldInverse.Transpose(); + const aiVector3D vLocalCamera = mWorldInverse * g_sCamera.vPos; + + // well ... this is really funny now. We must compute their distance + // from the camera. We take the average distance of a face and add it + // to a map which sorts it + std::map<float,unsigned int, std::greater<float> > smap; + + for (unsigned int iFace = 0; iFace < pcMesh->mNumFaces;++iFace) + { + const aiFace* pcFace = &pcMesh->mFaces[iFace]; + float fDist = 0.0f; + for (unsigned int c = 0; c < 3;++c) + { + aiVector3D vPos = pcMesh->mVertices[pcFace->mIndices[c]]; + vPos -= vLocalCamera; + fDist += vPos.SquareLength(); + } + smap.insert(std::pair<float, unsigned int>(fDist,iFace)); + } + + // now we can lock the index buffer and rebuild it + D3DINDEXBUFFER_DESC sDesc; + pcHelper->piIB->GetDesc(&sDesc); + + if (D3DFMT_INDEX16 == sDesc.Format) + { + uint16_t* aiIndices; + pcHelper->piIB->Lock(0,0,(void**)&aiIndices,D3DLOCK_DISCARD); + + for (std::map<float,unsigned int, std::greater<float> >::const_iterator + i = smap.begin(); + i != smap.end();++i) + { + const aiFace* pcFace = &pcMesh->mFaces[(*i).second]; + *aiIndices++ = (uint16_t)pcFace->mIndices[0]; + *aiIndices++ = (uint16_t)pcFace->mIndices[1]; + *aiIndices++ = (uint16_t)pcFace->mIndices[2]; + } + } + else if (D3DFMT_INDEX32 == sDesc.Format) + { + uint32_t* aiIndices; + pcHelper->piIB->Lock(0,0,(void**)&aiIndices,D3DLOCK_DISCARD); + + for (std::map<float,unsigned int, std::greater<float> >::const_iterator + i = smap.begin(); + i != smap.end();++i) + { + const aiFace* pcFace = &pcMesh->mFaces[(*i).second]; + *aiIndices++ = (uint32_t)pcFace->mIndices[0]; + *aiIndices++ = (uint32_t)pcFace->mIndices[1]; + *aiIndices++ = (uint32_t)pcFace->mIndices[2]; + } + } + pcHelper->piIB->Unlock(); + + // set vertex and index buffer + g_piDevice->SetStreamSource(0,pcHelper->piVB,0,sizeof(AssetHelper::Vertex)); + + // and draw the mesh + g_piDevice->SetIndices(pcHelper->piIB); + g_piDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, + 0,0, + pcMesh->mNumVertices,0, + pcMesh->mNumFaces); + + return 1; +} }; \ No newline at end of file diff --git a/tools/assimp_view/MeshRenderer.h b/tools/assimp_view/MeshRenderer.h index 2e9df0616..e9da93f6b 100644 --- a/tools/assimp_view/MeshRenderer.h +++ b/tools/assimp_view/MeshRenderer.h @@ -1,99 +1,99 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2012, assimp 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 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 - -namespace AssimpView { - - - //------------------------------------------------------------------------------- - /* Helper class tp render meshes - */ - //------------------------------------------------------------------------------- - class CMeshRenderer - { - private: - - // default constructor - CMeshRenderer() - - { - // 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 ); - - - - private: - - - }; - -} +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2012, assimp 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 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 + +namespace AssimpView { + + + //------------------------------------------------------------------------------- + /* Helper class tp render meshes + */ + //------------------------------------------------------------------------------- + class CMeshRenderer + { + private: + + // default constructor + CMeshRenderer() + + { + // 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 ); + + + + private: + + + }; + +} #endif //!! include guard \ No newline at end of file diff --git a/tools/assimp_view/MessageProc.cpp b/tools/assimp_view/MessageProc.cpp index 10d026ca3..4fed990eb 100644 --- a/tools/assimp_view/MessageProc.cpp +++ b/tools/assimp_view/MessageProc.cpp @@ -1,2644 +1,2644 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2015, assimp 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 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 "assimp_view.h" -#include <assimp/Exporter.hpp> -#include <algorithm> - -#include <windowsx.h> - -namespace AssimpView { - -using namespace Assimp; - -// 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<std::string> g_aPreviousFiles; - -// history menu item -HMENU g_hHistoryMenu = NULL; - -float g_fACMR = 3.0f; - -#define AI_VIEW_NUM_RECENT_FILES 0x8 -#define AI_VIEW_RECENT_FILE_ID(_n_) (5678 + _n_) - -#define AI_VIEW_EXPORT_FMT_BASE 7912 -#define AI_VIEW_EXPORT_FMT_ID(_n_) (AI_VIEW_EXPORT_FMT_BASE + _n_) - -void UpdateHistory(); -void SaveHistory(); - -//------------------------------------------------------------------------------- -// Setup file associations for all formats supported by the library -// -// File associations are registered in HKCU\Software\Classes. They might -// be overwritten by global file associations. -//------------------------------------------------------------------------------- -void MakeFileAssociations() - { - char szTemp2[MAX_PATH]; - char szTemp[MAX_PATH + 10]; - - GetModuleFileName(NULL,szTemp2,MAX_PATH); - sprintf(szTemp,"%s %%1",szTemp2); - - HKEY g_hRegistry; - - aiString list, tmp; - aiGetExtensionList(&list); - tmp = list; - - const char* sz = strtok(list.data,";"); - do - { - char buf[256]; - ai_assert(sz[0] == '*'); - sprintf(buf,"Software\\Classes\\%s",sz+1); - - RegCreateKeyEx(HKEY_CURRENT_USER,buf,0,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); - } - while ((sz = strtok(NULL,";"))); - - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\ASSIMPVIEW_CLASS",0,NULL,0,KEY_ALL_ACCESS, NULL, &g_hRegistry,NULL); - RegCloseKey(g_hRegistry); - - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\ASSIMPVIEW_CLASS\\shell\\open\\command",0,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)); - - CLogDisplay::Instance().AddEntry(tmp.data,D3DCOLOR_ARGB(0xFF,0,0xFF,0)); - } - - -//------------------------------------------------------------------------------- -// Handle command line parameters -// -// The function loads an asset specified on the command line as first argument -// Other command line parameters are not handled -//------------------------------------------------------------------------------- -void HandleCommandLine(char* p_szCommand) - { - char* sz = p_szCommand; - //bool bQuak = false; - - if (strlen(sz) < 2)return; - - if (*sz == '\"') - { - char* sz2 = strrchr(sz,'\"'); - if (sz2)*sz2 = 0; - sz++; // skip the starting quote - } - - 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); -} - - -//------------------------------------------------------------------------------- -// Save the checker pattern colors to the registry -//------------------------------------------------------------------------------- -void SaveCheckerPatternColors() -{ - // we have it as float4. save it as binary value --. - RegSetValueExA(g_hRegistry,"CheckerPattern0",0,REG_BINARY, - (const BYTE*)CDisplay::Instance().GetFirstCheckerColor(), - sizeof(D3DXVECTOR3)); - - RegSetValueExA(g_hRegistry,"CheckerPattern1",0,REG_BINARY, - (const BYTE*)CDisplay::Instance().GetSecondCheckerColor(), - sizeof(D3DXVECTOR3)); -} - -//------------------------------------------------------------------------------- -// Load the checker pattern colors from the registry -//------------------------------------------------------------------------------- -void LoadCheckerPatternColors() -{ - DWORD dwTemp = sizeof(D3DXVECTOR3); - RegQueryValueEx(g_hRegistry,"CheckerPattern0",NULL,NULL, - (BYTE*) /* jep, this is evil */ CDisplay::Instance().GetFirstCheckerColor(),&dwTemp); - - RegQueryValueEx(g_hRegistry,"CheckerPattern1",NULL,NULL, - (BYTE*) /* jep, this is evil */ CDisplay::Instance().GetSecondCheckerColor(),&dwTemp); -} - -//------------------------------------------------------------------------------- -// Changed pp setup -//------------------------------------------------------------------------------- -void UpdatePPSettings() -{ - DWORD dwValue = ppsteps; - RegSetValueExA(g_hRegistry,"PostProcessing",0,REG_DWORD,(const BYTE*)&dwValue,4); - UpdateWindow(g_hDlg); -} - -//------------------------------------------------------------------------------- -// 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); -} - -//------------------------------------------------------------------------------- -// 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); -} - -//------------------------------------------------------------------------------- -// 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); -} - -//------------------------------------------------------------------------------- -// 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); -} - -//------------------------------------------------------------------------------- -// Toggle the "NoTransparency" state -//------------------------------------------------------------------------------- -void ToggleTransparency() -{ - g_sOptions.bNoAlphaBlending = !g_sOptions.bNoAlphaBlending; - - // store this in the registry, too - DWORD dwValue = 0; - if (g_sOptions.bNoAlphaBlending)dwValue = 1; - RegSetValueExA(g_hRegistry,"NoTransparency",0,REG_DWORD,(const BYTE*)&dwValue,4); -} - -//------------------------------------------------------------------------------- -// 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); -} - -//------------------------------------------------------------------------------- -// 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(); -} - -//------------------------------------------------------------------------------- -// 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(); -} - -//------------------------------------------------------------------------------- -// Toggle the "Culling" state -//------------------------------------------------------------------------------- -void ToggleCulling() -{ - g_sOptions.bCulling = !g_sOptions.bCulling; - - // store this in the registry, too - DWORD dwValue = 0; - if (g_sOptions.bCulling)dwValue = 1; - RegSetValueExA(g_hRegistry,"Culling",0,REG_DWORD,(const BYTE*)&dwValue,4); -} - -//------------------------------------------------------------------------------- -// Toggle the "Skeleton" state -//------------------------------------------------------------------------------- -void ToggleSkeleton() -{ - g_sOptions.bSkeleton = !g_sOptions.bSkeleton; - - // store this in the registry, too - DWORD dwValue = 0; - if (g_sOptions.bCulling)dwValue = 1; - RegSetValueExA(g_hRegistry,"Skeleton",0,REG_DWORD,(const BYTE*)&dwValue,4); -} - -//------------------------------------------------------------------------------- -// 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); -} - - -//------------------------------------------------------------------------------- -// 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); -} - -//------------------------------------------------------------------------------- -// 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-214,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+214,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((*pclrResult >> 16) & 0xff,(*pclrResult >> 8) & 0xff,*pclrResult & 0xff); - clr.lpCustColors = g_aclCustomColors; - clr.lpfnHook = NULL; - clr.lpTemplateName = NULL; - clr.lCustData = 0; - - ChooseColor(&clr); - - *pclrResult = D3DCOLOR_ARGB(0xFF, - GetRValue(clr.rgbResult), - GetGValue(clr.rgbResult), - GetBValue(clr.rgbResult)); - return; -} - - -//------------------------------------------------------------------------------- -// Let the user choose a color in a windows standard color dialog -//------------------------------------------------------------------------------- -void DisplayColorDialog(D3DXVECTOR4* pclrResult) -{ - CHOOSECOLOR clr; - clr.lStructSize = sizeof(CHOOSECOLOR); - clr.hwndOwner = g_hDlg; - clr.Flags = CC_RGBINIT | CC_FULLOPEN; - clr.rgbResult = RGB(clamp<unsigned char>(pclrResult->x * 255.0f), - clamp<unsigned char>(pclrResult->y * 255.0f), - clamp<unsigned char>(pclrResult->z * 255.0f)); - clr.lpCustColors = g_aclCustomColors; - clr.lpfnHook = NULL; - clr.lpTemplateName = NULL; - clr.lCustData = 0; - - ChooseColor(&clr); - - pclrResult->x = GetRValue(clr.rgbResult) / 255.0f; - pclrResult->y = GetGValue(clr.rgbResult) / 255.0f; - pclrResult->z = GetBValue(clr.rgbResult) / 255.0f; - 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 KiB = 1024 bytes)\n\n" - "ASSIMP Import Data: \t%i KiB\n" - "Texture data:\t\t%i KiB\n" - "Vertex buffers:\t\t%i KiB\n" - "Index buffers:\t\t%i KiB\n" - "Video Memory:\t\t%i KiB\n\n" - "Total: \t\t\t%i KiB", - 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 = "<empty>"; - 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),"<empty>"); - } - - 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 = "<empty>"; - 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; -} - -//------------------------------------------------------------------------------- -void SetupPPUIState() -{ - - // that's ugly. anyone willing to rewrite me from scratch? - HMENU hMenu = GetMenu(g_hDlg); - CheckMenuItem(hMenu,ID_VIEWER_PP_JIV,ppsteps & aiProcess_JoinIdenticalVertices ? MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(hMenu,ID_VIEWER_PP_CTS,ppsteps & aiProcess_CalcTangentSpace ? MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(hMenu,ID_VIEWER_PP_FD,ppsteps & aiProcess_FindDegenerates ? MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(hMenu,ID_VIEWER_PP_FID,ppsteps & aiProcess_FindInvalidData ? MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(hMenu,ID_VIEWER_PP_FIM,ppsteps & aiProcess_FindInstances ? MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(hMenu,ID_VIEWER_PP_FIN,ppsteps & aiProcess_FixInfacingNormals ? MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(hMenu,ID_VIEWER_PP_GUV,ppsteps & aiProcess_GenUVCoords ? MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(hMenu,ID_VIEWER_PP_ICL,ppsteps & aiProcess_ImproveCacheLocality ? MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(hMenu,ID_VIEWER_PP_OG,ppsteps & aiProcess_OptimizeGraph ? MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(hMenu,ID_VIEWER_PP_OM,ppsteps & aiProcess_OptimizeMeshes ? MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(hMenu,ID_VIEWER_PP_PTV,ppsteps & aiProcess_PreTransformVertices ? MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(hMenu,ID_VIEWER_PP_RRM2,ppsteps & aiProcess_RemoveRedundantMaterials ? MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(hMenu,ID_VIEWER_PP_TUV,ppsteps & aiProcess_TransformUVCoords ? MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(hMenu,ID_VIEWER_PP_VDS,ppsteps & aiProcess_ValidateDataStructure ? MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(hMenu,ID_VIEWER_PP_DB,ppsteps & aiProcess_Debone ? MF_CHECKED : MF_UNCHECKED); -} - -#ifndef ASSIMP_BUILD_NO_EXPORT -//------------------------------------------------------------------------------- -// Fill the 'export' top level menu with a list of all supported export formats -//------------------------------------------------------------------------------- -void PopulateExportMenu() -{ - // add sub items for all recent files - Exporter exp; - HMENU hm = ::CreateMenu(); - for(size_t i = 0; i < exp.GetExportFormatCount(); ++i) - { - const aiExportFormatDesc* const e = exp.GetExportFormatDescription(i); - char tmp[256]; - sprintf(tmp,"%s (%s)",e->description,e->id); - - AppendMenu(hm,MF_STRING,AI_VIEW_EXPORT_FMT_ID(i),tmp); - } - - ModifyMenu(GetMenu(g_hDlg),ID_EXPORT,MF_BYCOMMAND | MF_POPUP, - (UINT_PTR)hm,"Export"); -} - -//------------------------------------------------------------------------------- -//------------------------------------------------------------------------------- -void DoExport(size_t formatId) -{ - if (!g_szFileName[0]) { - MessageBox(g_hDlg, "No model loaded", "Export", MB_ICONERROR); - return; - } - Exporter exp; - const aiExportFormatDesc* const e = exp.GetExportFormatDescription(formatId); - ai_assert(e); - - char szFileName[MAX_PATH*2]; - DWORD dwTemp = sizeof(szFileName); - if(ERROR_SUCCESS == RegQueryValueEx(g_hRegistry,"ModelExportDest",NULL,NULL,(BYTE*)szFileName, &dwTemp)) { - ai_assert(strlen(szFileName) <= MAX_PATH); - - // invent a nice default file name - char* sz = max(strrchr(szFileName,'\\'),strrchr(szFileName,'/')); - if (sz) { - strncpy(sz,max(strrchr(g_szFileName,'\\'),strrchr(g_szFileName,'/')),MAX_PATH); - } - } - else { - // Key was not found. Use the folder where the asset comes from - strncpy(szFileName,g_szFileName,MAX_PATH); - } - - // fix file extension - { char * const sz = strrchr(szFileName,'.'); - if(sz) { - ai_assert((sz - &szFileName[0]) + strlen(e->fileExtension) + 1 <= MAX_PATH); - strcpy(sz+1,e->fileExtension); - } - } - - // build the stupid info string for GetSaveFileName() - can't use sprintf() because the string must contain binary zeros. - char desc[256] = {0}; - char* c = strcpy(desc,e->description) + strlen(e->description)+1; - c += sprintf(c,"*.%s",e->fileExtension)+1; - strcpy(c, "*.*\0"); c += 4; - - ai_assert(c - &desc[0] <= 256); - - const std::string ext = "."+std::string(e->fileExtension); - OPENFILENAME sFilename1 = { - sizeof(OPENFILENAME), - g_hDlg,GetModuleHandle(NULL), - desc, NULL, 0, 1, - szFileName, MAX_PATH, NULL, 0, NULL, - "Export asset", - OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR, - 0, 1, ext.c_str(), 0, NULL, NULL - }; - if(::GetSaveFileName(&sFilename1) == 0) { - return; - } - - // Now store the file in the registry unless the user decided to stay in the model directory - const std::string sFinal = szFileName, sub = sFinal.substr(0,sFinal.find_last_of("\\/")); - if (strncmp(sub.c_str(),g_szFileName,sub.length())) { - RegSetValueExA(g_hRegistry,"ModelExportDest",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH); - } - - // export the file - const aiReturn res = exp.Export(g_pcAsset->pcScene,e->id,sFinal.c_str(), - ppsteps | /* configurable pp steps */ - aiProcess_GenSmoothNormals | // generate smooth normal vectors if not existing - aiProcess_SplitLargeMeshes | // split large, unrenderable meshes into submeshes - aiProcess_Triangulate | // triangulate polygons with more than 3 edges - aiProcess_ConvertToLeftHanded | // convert everything to D3D left handed space - aiProcess_SortByPType | // make 'clean' meshes which consist of a single typ of primitives - 0 - ); - if (res == aiReturn_SUCCESS) { - CLogDisplay::Instance().AddEntry("[INFO] Exported file " + sFinal,D3DCOLOR_ARGB(0xFF,0x00,0xFF,0x00)); - return; - } - CLogDisplay::Instance().AddEntry("[INFO] Failure exporting file " + - sFinal,D3DCOLOR_ARGB(0xFF,0xFF,0x00,0x00)); -} -#endif - -//------------------------------------------------------------------------------- -// 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_ENODEWND,"0"); - SetDlgItemText(g_hDlg,IDC_ETEX,"0"); - SetDlgItemText(g_hDlg,IDC_EMESH,"0"); - -#ifndef ASSIMP_BUILD_NO_EXPORT - PopulateExportMenu(); -#endif - - // 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", - 0,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-214,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); - } - - // LowQuality - if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"NoTransparency",NULL,NULL, - (BYTE*)&dwValue,&dwTemp))dwValue = 0; - if (0 == dwValue) - { - g_sOptions.bNoAlphaBlending = false; - CheckDlgButton(g_hDlg,IDC_NOAB,BST_UNCHECKED); - } - else - { - g_sOptions.bNoAlphaBlending = true; - CheckDlgButton(g_hDlg,IDC_NOAB,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); - } - - if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"PostProcessing",NULL,NULL,(BYTE*)&dwValue,&dwTemp)) - ppsteps = ppstepsdefault; - else ppsteps = dwValue; - - SetupPPUIState(); - LoadCheckerPatternColors(); - - SendDlgItemMessage(g_hDlg,IDC_SLIDERANIM,TBM_SETRANGEMIN,TRUE,0); - SendDlgItemMessage(g_hDlg,IDC_SLIDERANIM,TBM_SETRANGEMAX,TRUE,10000); - return; -} - -//------------------------------------------------------------------------------- -// Message prcoedure for the smooth normals dialog -//------------------------------------------------------------------------------- -INT_PTR CALLBACK SMMessageProc(HWND hwndDlg,UINT uMsg, - WPARAM wParam,LPARAM lParam) -{ - UNREFERENCED_PARAMETER(lParam); - switch (uMsg) - { - case WM_INITDIALOG: - char s[30]; - ::sprintf(s,"%.2f",g_smoothAngle); - SetDlgItemText(hwndDlg,IDC_EDITSM,s); - return TRUE; - - case WM_CLOSE: - EndDialog(hwndDlg,0); - return TRUE; - - case WM_COMMAND: - - if (IDOK == LOWORD(wParam)) { - char s[30]; - GetDlgItemText(hwndDlg,IDC_EDITSM,s,30); - g_smoothAngle = (float)atof(s); - - EndDialog(hwndDlg,0); - } - else if (IDCANCEL == LOWORD(wParam)) { - EndDialog(hwndDlg,1); - } - return TRUE; - } - return FALSE; -} - -//------------------------------------------------------------------------------- -// Main message procedure of the application -// -// The function handles all incoming messages for the main window. -// However, if does not directly process input commands. -// NOTE: Due to the impossibility to process WM_CHAR messages in dialogs -// properly the code for all hotkeys has been moved to the WndMain -//------------------------------------------------------------------------------- -INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, - WPARAM wParam,LPARAM lParam) - { - UNREFERENCED_PARAMETER(lParam); - UNREFERENCED_PARAMETER(wParam); - - int xPos,yPos; - int xPos2,yPos2; - int fHalfX; - int fHalfY; - - TRACKMOUSEEVENT sEvent; - switch (uMsg) - { - case WM_INITDIALOG: - - g_hDlg = hwndDlg; - - // load the state of the usr interface - InitUI(); - - // load the file history - LoadHistory(); - - // load the current color of the lights - LoadLightColors(); - return TRUE; - - case WM_HSCROLL: - - // XXX quick and dirty fix for #3029892 - if (GetDlgItem(g_hDlg, IDC_SLIDERANIM) == (HWND)lParam && g_pcAsset && g_pcAsset->pcScene->mAnimations) - { - double num = (double)SendDlgItemMessage(g_hDlg,IDC_SLIDERANIM,TBM_GETPOS,0,0); - const aiAnimation* anim = g_pcAsset->pcScene->mAnimations[ g_pcAsset->mAnimator->CurrentAnimIndex() ]; - - g_dCurrent = (anim->mDuration/anim->mTicksPerSecond) * num/10000; - g_pcAsset->mAnimator->Calculate(g_dCurrent); - } - break; - - case WM_MOUSEWHEEL: - - if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode()) - { - CDisplay::Instance().SetTextureViewZoom ( GET_WHEEL_DELTA_WPARAM(wParam) / 50.0f ); - } - else - { - 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: - - g_bMousePressed = false; - g_bMousePressedR = false; - g_bMousePressedM = false; - g_bMousePressedBoth = false; - return TRUE; - - case WM_LBUTTONDBLCLK: - - CheckDlgButton(hwndDlg,IDC_AUTOROTATE, - IsDlgButtonChecked(hwndDlg,IDC_AUTOROTATE) == BST_CHECKED - ? BST_UNCHECKED : BST_CHECKED); - - ToggleAutoRotate(); - return TRUE; - - - case WM_CLOSE: - PostQuitMessage(0); - 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,g,b; - const char* szText; - if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode() || - CDisplay::VIEWMODE_MATERIAL == CDisplay::Instance().GetViewMode()) - { - r = (unsigned char)(CDisplay::Instance().GetFirstCheckerColor()->x * 255.0f); - g = (unsigned char)(CDisplay::Instance().GetFirstCheckerColor()->y * 255.0f); - b = (unsigned char)(CDisplay::Instance().GetFirstCheckerColor()->z * 255.0f); - szText = "Background #0"; - } - else if (!g_pcAsset) - { - r = g = b = 150;szText = ""; - } - else - { - r = (unsigned char)((g_avLightColors[0] >> 16) & 0xFF); - g = (unsigned char)((g_avLightColors[0] >> 8) & 0xFF); - b = (unsigned char)((g_avLightColors[0]) & 0xFF); - szText = "Light #0"; - } - 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,szText,strlen(szText)); - bDraw = true; - } - else if(IDC_LCOLOR2 == pcStruct->CtlID) - { - unsigned char r,g,b; - const char* szText; - if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode() || - CDisplay::VIEWMODE_MATERIAL == CDisplay::Instance().GetViewMode()) - { - r = (unsigned char)(CDisplay::Instance().GetSecondCheckerColor()->x * 255.0f); - g = (unsigned char)(CDisplay::Instance().GetSecondCheckerColor()->y * 255.0f); - b = (unsigned char)(CDisplay::Instance().GetSecondCheckerColor()->z * 255.0f); - szText = "Background #1"; - } - else if (!g_pcAsset) - { - r = g = b = 150;szText = ""; - } - else - { - r = (unsigned char)((g_avLightColors[1] >> 16) & 0xFF); - g = (unsigned char)((g_avLightColors[1] >> 8) & 0xFF); - b = (unsigned char)((g_avLightColors[1]) & 0xFF); - szText = "Light #1"; - } - 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,szText,strlen(szText)); - bDraw = true; - } - else if(IDC_LCOLOR3 == pcStruct->CtlID) - { - unsigned char r,g,b; - const char* szText; - if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode() || - CDisplay::VIEWMODE_MATERIAL == CDisplay::Instance().GetViewMode()) - { - r = g = b = 0; - szText = ""; - } - else if (!g_pcAsset) - { - r = g = b = 150;szText = ""; - } - else - { - r = (unsigned char)((g_avLightColors[2] >> 16) & 0xFF); - g = (unsigned char)((g_avLightColors[2] >> 8) & 0xFF); - b = (unsigned char)((g_avLightColors[2]) & 0xFF); - szText = "Ambient"; - } - 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,szText,strlen(szText)); - 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; - - // register a mouse track handler to be sure we'll know - // when the mouse leaves the display view again - sEvent.cbSize = sizeof(TRACKMOUSEEVENT); - sEvent.dwFlags = TME_LEAVE; - sEvent.hwndTrack = g_hDlg; - sEvent.dwHoverTime = HOVER_DEFAULT; - TrackMouseEvent(&sEvent); - - if (g_bMousePressedR) - { - g_bMousePressed = false; - g_bMousePressedR = false; - g_bMousePressedBoth = true; - return TRUE; - } - - // need to determine the position of the mouse and the - // distance from the center - //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;*/ - - RECT sRect; - GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect); - sRect.right -= sRect.left; - sRect.bottom -= sRect.top; - - // if the mouse klick was inside the viewer panel - // give the focus to it - if (xPos > 0 && xPos < sRect.right && yPos > 0 && yPos < sRect.bottom) - { - SetFocus(GetDlgItem(g_hDlg,IDC_RT)); - } - - // g_bInvert stores whether the mouse has started on the negative - // x or on the positive x axis of the imaginary coordinate system - // with origin p at the center of the HUD texture - xPos -= sRect.right/2; - yPos -= sRect.bottom/2; - - if (xPos > 0)g_bInvert = true; - else g_bInvert = false; - - D3DSURFACE_DESC sDesc; - g_pcTexture->GetLevelDesc(0,&sDesc); - - fHalfX = (int)(((float)sRect.right-(float)sDesc.Width) / 2.0f); - fHalfY = (int)(((float)sRect.bottom-(float)sDesc.Height) / 2.0f); - - // Determine the input operation to perform for this position - g_eClick = EClickPos_Outside; - if (xPos2 >= fHalfX && xPos2 < fHalfX + (int)sDesc.Width && - yPos2 >= fHalfY && yPos2 < fHalfY + (int)sDesc.Height && - NULL != g_szImageMask) - { - // inside the texture. Lookup the grayscale value from it - xPos2 -= fHalfX; - yPos2 -= fHalfY; - - unsigned char chValue = g_szImageMask[xPos2 + yPos2 * sDesc.Width]; - if (chValue > 0xFF-20) - { - g_eClick = EClickPos_Circle; - } - else if (chValue < 0xFF-20 && chValue > 185) - { - g_eClick = EClickPos_CircleHor; - } - else if (chValue > 0x10 && chValue < 185) - { - g_eClick = EClickPos_CircleVert; - } - } - return TRUE; - - case WM_RBUTTONDOWN: - g_bMousePressedR = true; - - sEvent.cbSize = sizeof(TRACKMOUSEEVENT); - sEvent.dwFlags = TME_LEAVE; - sEvent.hwndTrack = g_hDlg; - sEvent.dwHoverTime = HOVER_DEFAULT; - TrackMouseEvent(&sEvent); - - if (g_bMousePressed) - { - g_bMousePressedR = false; - g_bMousePressed = false; - g_bMousePressedBoth = true; - } - - return TRUE; - - case WM_MBUTTONDOWN: - - - g_bMousePressedM = true; - - sEvent.cbSize = sizeof(TRACKMOUSEEVENT); - sEvent.dwFlags = TME_LEAVE; - sEvent.hwndTrack = g_hDlg; - sEvent.dwHoverTime = HOVER_DEFAULT; - TrackMouseEvent(&sEvent); - return TRUE; - - case WM_LBUTTONUP: - g_bMousePressed = false; - g_bMousePressedBoth = false; - return TRUE; - - case WM_RBUTTONUP: - g_bMousePressedR = false; - g_bMousePressedBoth = false; - return TRUE; - - case WM_MBUTTONUP: - g_bMousePressedM = false; - return TRUE; - - case WM_DROPFILES: - { - HDROP hDrop = (HDROP)wParam; - - char szFile[MAX_PATH]; - DragQueryFile(hDrop,0,szFile,sizeof(szFile)); - - const char* sz = strrchr(szFile,'.'); - if (!sz) - sz = szFile; - - if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode()) - { - // replace the selected texture with the new one ... - CDisplay::Instance().ReplaceCurrentTexture(szFile); - } - else - { - // check whether it is a typical texture file format ... - ++sz; - if (0 == ASSIMP_stricmp(sz,"png") || - 0 == ASSIMP_stricmp(sz,"bmp") || - 0 == ASSIMP_stricmp(sz,"jpg") || - 0 == ASSIMP_stricmp(sz,"tga") || - 0 == ASSIMP_stricmp(sz,"tif") || - 0 == ASSIMP_stricmp(sz,"hdr") || - 0 == ASSIMP_stricmp(sz,"ppm") || - 0 == ASSIMP_stricmp(sz,"pfm")) - { - CBackgroundPainter::Instance().SetTextureBG(szFile); - } - 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) - return TRUE; - - // 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 - { - strcpy(g_szFileName,szFile); - - DeleteAsset(); - LoadAsset(); - UpdateHistory(); - SaveHistory(); - } - } - DragFinish(hDrop); - } - return TRUE; - - case WM_COMMAND: - - HMENU hMenu = GetMenu(g_hDlg); - if (ID_VIEWER_QUIT == LOWORD(wParam)) - { - PostQuitMessage(0); - DestroyWindow(hwndDlg); - } - else if (IDC_COMBO1 == LOWORD(wParam)) - { - if(HIWORD(wParam) == CBN_SELCHANGE) { - const size_t sel = static_cast<size_t>(ComboBox_GetCurSel(GetDlgItem(hwndDlg,IDC_COMBO1))); - if(g_pcAsset) { - g_pcAsset->mAnimator->SetAnimIndex(sel); - SendDlgItemMessage(hwndDlg,IDC_SLIDERANIM,TBM_SETPOS,TRUE,0); - } - } - } - else if (ID_VIEWER_RESETVIEW == LOWORD(wParam)) - { - 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); - g_mWorldRotate = aiMatrix4x4(); - g_mWorld = aiMatrix4x4(); - - // don't forget to reset the st - CBackgroundPainter::Instance().ResetSB(); - } - else if (ID__HELP == LOWORD(wParam)) - { - DialogBox(g_hInstance,MAKEINTRESOURCE(IDD_AVHELP), - hwndDlg,&HelpDialogProc); - } - else if (ID__ABOUT == LOWORD(wParam)) - { - DialogBox(g_hInstance,MAKEINTRESOURCE(IDD_ABOUTBOX), - hwndDlg,&AboutMessageProc); - } - else if (ID_TOOLS_LOGWINDOW == LOWORD(wParam)) - { - CLogWindow::Instance().Show(); - } - else if (ID__WEBSITE == LOWORD(wParam)) - { - ShellExecute(NULL,"open","http://assimp.sourceforge.net","","",SW_SHOW); - } - else if (ID__WEBSITESF == LOWORD(wParam)) - { - ShellExecute(NULL,"open","https://sourceforge.net/projects/assimp","","",SW_SHOW); - } - else if (ID_REPORTBUG == LOWORD(wParam)) - { - ShellExecute(NULL,"open","https://sourceforge.net/tracker/?func=add&group_id=226462&atid=1067632","","",SW_SHOW); - } - else if (ID_FR == LOWORD(wParam)) - { - ShellExecute(NULL,"open","https://sourceforge.net/forum/forum.php?forum_id=817653","","",SW_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)) - { - ClearBG(); - } - else if (ID_BACKGROUND_SETCOLOR == LOWORD(wParam)) - { - ChooseBGColor(); - } - else if (ID_BACKGROUND_LOADTEXTURE == LOWORD(wParam)) - { - LoadBGTexture(); - } - else if (ID_BACKGROUND_LOADSKYBOX == LOWORD(wParam)) - { - LoadSkybox(); - } - else if (ID_VIEWER_SAVESCREENSHOTTOFILE == LOWORD(wParam)) - { - SaveScreenshot(); - } - else if (ID_VIEWER_OPEN == LOWORD(wParam)) - { - OpenAsset(); - } - else if (ID_TOOLS_FLIPNORMALS == LOWORD(wParam)) - { - if (g_pcAsset && g_pcAsset->pcScene) - { - g_pcAsset->FlipNormals(); - } - } - - // this is ugly. anyone willing to rewrite it from scratch using wxwidgets or similar? - else if (ID_VIEWER_PP_JIV == LOWORD(wParam)) { - ppsteps ^= aiProcess_JoinIdenticalVertices; - CheckMenuItem(hMenu,ID_VIEWER_PP_JIV,ppsteps & aiProcess_JoinIdenticalVertices ? MF_CHECKED : MF_UNCHECKED); - UpdatePPSettings(); - } - else if (ID_VIEWER_PP_CTS == LOWORD(wParam)) { - ppsteps ^= aiProcess_CalcTangentSpace; - CheckMenuItem(hMenu,ID_VIEWER_PP_CTS,ppsteps & aiProcess_CalcTangentSpace ? MF_CHECKED : MF_UNCHECKED); - UpdatePPSettings(); - } - else if (ID_VIEWER_PP_FD == LOWORD(wParam)) { - ppsteps ^= aiProcess_FindDegenerates; - CheckMenuItem(hMenu,ID_VIEWER_PP_FD,ppsteps & aiProcess_FindDegenerates ? MF_CHECKED : MF_UNCHECKED); - UpdatePPSettings(); - } - else if (ID_VIEWER_PP_FID == LOWORD(wParam)) { - ppsteps ^= aiProcess_FindInvalidData; - CheckMenuItem(hMenu,ID_VIEWER_PP_FID,ppsteps & aiProcess_FindInvalidData ? MF_CHECKED : MF_UNCHECKED); - UpdatePPSettings(); - } - else if (ID_VIEWER_PP_FIM == LOWORD(wParam)) { - ppsteps ^= aiProcess_FindInstances; - CheckMenuItem(hMenu,ID_VIEWER_PP_FIM,ppsteps & aiProcess_FindInstances ? MF_CHECKED : MF_UNCHECKED); - UpdatePPSettings(); - } - else if (ID_VIEWER_PP_FIN == LOWORD(wParam)) { - ppsteps ^= aiProcess_FixInfacingNormals; - CheckMenuItem(hMenu,ID_VIEWER_PP_FIN,ppsteps & aiProcess_FixInfacingNormals ? MF_CHECKED : MF_UNCHECKED); - UpdatePPSettings(); - } - else if (ID_VIEWER_PP_GUV == LOWORD(wParam)) { - ppsteps ^= aiProcess_GenUVCoords; - CheckMenuItem(hMenu,ID_VIEWER_PP_GUV,ppsteps & aiProcess_GenUVCoords ? MF_CHECKED : MF_UNCHECKED); - UpdatePPSettings(); - } - else if (ID_VIEWER_PP_ICL == LOWORD(wParam)) { - ppsteps ^= aiProcess_ImproveCacheLocality; - CheckMenuItem(hMenu,ID_VIEWER_PP_ICL,ppsteps & aiProcess_ImproveCacheLocality ? MF_CHECKED : MF_UNCHECKED); - UpdatePPSettings(); - } - else if (ID_VIEWER_PP_OG == LOWORD(wParam)) { - if (ppsteps & aiProcess_PreTransformVertices) { - CLogDisplay::Instance().AddEntry("[ERROR] This setting is incompatible with \'Pretransform Vertices\'"); - } - else { - ppsteps ^= aiProcess_OptimizeGraph; - CheckMenuItem(hMenu,ID_VIEWER_PP_OG,ppsteps & aiProcess_OptimizeGraph ? MF_CHECKED : MF_UNCHECKED); - UpdatePPSettings(); - } - } - else if (ID_VIEWER_PP_OM == LOWORD(wParam)) { - ppsteps ^= aiProcess_OptimizeMeshes; - CheckMenuItem(hMenu,ID_VIEWER_PP_OM,ppsteps & aiProcess_OptimizeMeshes ? MF_CHECKED : MF_UNCHECKED); - UpdatePPSettings(); - } - else if (ID_VIEWER_PP_PTV == LOWORD(wParam)) { - if (ppsteps & aiProcess_OptimizeGraph) { - CLogDisplay::Instance().AddEntry("[ERROR] This setting is incompatible with \'Optimize Scenegraph\'"); - } - else { - ppsteps ^= aiProcess_PreTransformVertices; - CheckMenuItem(hMenu,ID_VIEWER_PP_PTV,ppsteps & aiProcess_PreTransformVertices ? MF_CHECKED : MF_UNCHECKED); - UpdatePPSettings(); - } - } - else if (ID_VIEWER_PP_RRM2 == LOWORD(wParam)) { - ppsteps ^= aiProcess_RemoveRedundantMaterials; - CheckMenuItem(hMenu,ID_VIEWER_PP_RRM2,ppsteps & aiProcess_RemoveRedundantMaterials ? MF_CHECKED : MF_UNCHECKED); - UpdatePPSettings(); - } - else if (ID_VIEWER_PP_TUV == LOWORD(wParam)) { - ppsteps ^= aiProcess_TransformUVCoords; - CheckMenuItem(hMenu,ID_VIEWER_PP_TUV,ppsteps & aiProcess_TransformUVCoords ? MF_CHECKED : MF_UNCHECKED); - UpdatePPSettings(); - } - else if (ID_VIEWER_PP_DB == LOWORD(wParam)) { - ppsteps ^= aiProcess_Debone; - CheckMenuItem(hMenu,ID_VIEWER_PP_DB,ppsteps & aiProcess_Debone ? MF_CHECKED : MF_UNCHECKED); - UpdatePPSettings(); - } - else if (ID_VIEWER_PP_VDS == LOWORD(wParam)) { - ppsteps ^= aiProcess_ValidateDataStructure; - CheckMenuItem(hMenu,ID_VIEWER_PP_VDS,ppsteps & aiProcess_ValidateDataStructure ? MF_CHECKED : MF_UNCHECKED); - UpdatePPSettings(); - } - else if (ID_VIEWER_RELOAD == LOWORD(wParam)) - { - DeleteAsset(); - LoadAsset(); - } - else if (ID_IMPORTSETTINGS_RESETTODEFAULT == LOWORD(wParam)) - { - ppsteps = ppstepsdefault; - UpdatePPSettings(); - SetupPPUIState(); - } - else if (ID_IMPORTSETTINGS_OPENPOST == LOWORD(wParam)) - { - ShellExecute(NULL,"open","http://assimp.sourceforge.net/lib_html/ai_post_process_8h.html","","",SW_SHOW); - } - else if (ID_TOOLS_ORIGINALNORMALS == LOWORD(wParam)) - { - if (g_pcAsset && g_pcAsset->pcScene) - { - g_pcAsset->SetNormalSet(AssimpView::AssetHelper::ORIGINAL); - CheckMenuItem(hMenu,ID_TOOLS_ORIGINALNORMALS,MF_BYCOMMAND | MF_CHECKED); - CheckMenuItem(hMenu,ID_TOOLS_HARDNORMALS,MF_BYCOMMAND | MF_UNCHECKED); - CheckMenuItem(hMenu,ID_TOOLS_SMOOTHNORMALS,MF_BYCOMMAND | MF_UNCHECKED); - } - } - - else if (ID_TOOLS_SMOOTHNORMALS == LOWORD(wParam)) - { - if (g_pcAsset && g_pcAsset->pcScene) - { - g_pcAsset->SetNormalSet(AssimpView::AssetHelper::SMOOTH); - CheckMenuItem(hMenu,ID_TOOLS_ORIGINALNORMALS,MF_BYCOMMAND | MF_UNCHECKED); - CheckMenuItem(hMenu,ID_TOOLS_HARDNORMALS,MF_BYCOMMAND | MF_UNCHECKED); - CheckMenuItem(hMenu,ID_TOOLS_SMOOTHNORMALS,MF_BYCOMMAND | MF_CHECKED); - } - } - else if (ID_TOOLS_HARDNORMALS == LOWORD(wParam)) - { - if (g_pcAsset && g_pcAsset->pcScene) - { - g_pcAsset->SetNormalSet(AssimpView::AssetHelper::HARD); - CheckMenuItem(hMenu,ID_TOOLS_ORIGINALNORMALS,MF_BYCOMMAND | MF_UNCHECKED); - CheckMenuItem(hMenu,ID_TOOLS_HARDNORMALS,MF_BYCOMMAND | MF_CHECKED); - CheckMenuItem(hMenu,ID_TOOLS_SMOOTHNORMALS,MF_BYCOMMAND | MF_UNCHECKED); - } - } - 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_TOOLS_SETANGLELIMIT == LOWORD(wParam)) - { - DialogBox(g_hInstance,MAKEINTRESOURCE(IDD_DIALOGSMOOTH),g_hDlg,&SMMessageProc); - } - else if (ID_VIEWER_CLEARHISTORY == LOWORD(wParam)) - { - ClearHistory(); - } - else if (ID_VIEWER_CLOSEASSET == LOWORD(wParam)) - { - DeleteAssetData(); - DeleteAsset(); - } - else if (BN_CLICKED == HIWORD(wParam)) - { - if (IDC_TOGGLEMS == LOWORD(wParam)) - { - ToggleMS(); - } - else if (IDC_TOGGLEMAT == LOWORD(wParam)) - { - ToggleMats(); - } - else if (IDC_LCOLOR1 == LOWORD(wParam)) - { - - if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode() || - CDisplay::VIEWMODE_MATERIAL == CDisplay::Instance().GetViewMode()) - { - // hey, I'm tired and yes, I KNOW IT IS EVIL! - DisplayColorDialog(const_cast<D3DXVECTOR4*>(CDisplay::Instance().GetFirstCheckerColor())); - SaveCheckerPatternColors(); - } - else - { - DisplayColorDialog(&g_avLightColors[0]); - SaveLightColors(); - } - InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR1),NULL,TRUE); - UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR1)); - } - else if (IDC_LCOLOR2 == LOWORD(wParam)) - { - if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode() || - CDisplay::VIEWMODE_MATERIAL == CDisplay::Instance().GetViewMode()) - { - // hey, I'm tired and yes, I KNOW IT IS EVIL! - DisplayColorDialog(const_cast<D3DXVECTOR4*>(CDisplay::Instance().GetSecondCheckerColor())); - SaveCheckerPatternColors(); - } - else - { - DisplayColorDialog(&g_avLightColors[1]); - SaveLightColors(); - } - InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR2),NULL,TRUE); - UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR2)); - } - 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)) - { - if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode() || - CDisplay::VIEWMODE_MATERIAL == CDisplay::Instance().GetViewMode()) - { - CDisplay::Instance().SetFirstCheckerColor(D3DXVECTOR4(0.4f,0.4f,0.4f,1.0f)); - CDisplay::Instance().SetSecondCheckerColor(D3DXVECTOR4(0.6f,0.6f,0.6f,1.0f)); - SaveCheckerPatternColors(); - } - else - { - 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); - SaveLightColors(); - } - - 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)); - } - else if (IDC_NOSPECULAR == LOWORD(wParam)) - { - ToggleSpecular(); - } - else if (IDC_NOAB == LOWORD(wParam)) - { - ToggleTransparency(); - } - else if (IDC_ZOOM == LOWORD(wParam)) - { - ToggleFPSView(); - } - else if (IDC_BLUBB == LOWORD(wParam)) - { - ToggleUIState(); - } - else if (IDC_TOGGLENORMALS == LOWORD(wParam)) - { - ToggleNormals(); - } - else if (IDC_LOWQUALITY == LOWORD(wParam)) - { - ToggleLowQuality(); - } - else if (IDC_3LIGHTS == LOWORD(wParam)) - { - ToggleMultipleLights(); - } - else if (IDC_LIGHTROTATE == LOWORD(wParam)) - { - ToggleLightRotate(); - } - else if (IDC_AUTOROTATE == LOWORD(wParam)) - { - ToggleAutoRotate(); - } - else if (IDC_TOGGLEWIRE == LOWORD(wParam)) - { - ToggleWireFrame(); - } - else if (IDC_SHOWSKELETON == LOWORD(wParam)) - { - ToggleSkeleton(); - } - else if (IDC_BFCULL == LOWORD(wParam)) - { - ToggleCulling(); - } - else if (IDC_PLAY == LOWORD(wParam)) - { - g_bPlay = !g_bPlay; - SetDlgItemText(g_hDlg,IDC_PLAY,(g_bPlay ? "Stop" : "Play")); - - if (g_bPlay) - EnableWindow(GetDlgItem(g_hDlg,IDC_SLIDERANIM),FALSE); - else EnableWindow(GetDlgItem(g_hDlg,IDC_SLIDERANIM),TRUE); - } - } - // 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(); - } - } - -#ifndef ASSIMP_BUILD_NO_EXPORT - if (LOWORD(wParam) >= AI_VIEW_EXPORT_FMT_BASE && LOWORD(wParam) < AI_VIEW_EXPORT_FMT_BASE+Assimp::Exporter().GetExportFormatCount()) { - DoExport(LOWORD(wParam) - AI_VIEW_EXPORT_FMT_BASE); - } -#endif - - // handle popup menus for the tree window - CDisplay::Instance().HandleTreeViewPopup(wParam,lParam); - - return TRUE; - }; - return FALSE; - } - - -//------------------------------------------------------------------------------- -// Message prcoedure for the progress dialog -//------------------------------------------------------------------------------- -INT_PTR CALLBACK ProgressMessageProc(HWND hwndDlg,UINT uMsg, - WPARAM wParam,LPARAM lParam) - { - UNREFERENCED_PARAMETER(lParam); - switch (uMsg) - { - case WM_INITDIALOG: - - SendDlgItemMessage(hwndDlg,IDC_PROGRESS,PBM_SETRANGE,0, - MAKELPARAM(0,500)); - - SetTimer(hwndDlg,0,40,NULL); - return TRUE; - - case WM_CLOSE: - EndDialog(hwndDlg,0); - return TRUE; - - case WM_COMMAND: - - if (IDOK == LOWORD(wParam)) - { -#if 0 - g_bLoadingCanceled = true; - TerminateThread(g_hThreadHandle,5); - g_pcAsset = NULL; - - EndDialog(hwndDlg,0); -#endif - - // PROBLEM: If we terminate the loader thread, ASSIMP's state - // is undefined. Any further attempts to load assets will - // fail. - exit(5); -// return TRUE; - } - case WM_TIMER: - - UINT iPos = (UINT)SendDlgItemMessage(hwndDlg,IDC_PROGRESS,PBM_GETPOS,0,0); - iPos += 10; - if (iPos > 490)iPos = 0; - SendDlgItemMessage(hwndDlg,IDC_PROGRESS,PBM_SETPOS,iPos,0); - - if (g_bLoadingFinished) - { - EndDialog(hwndDlg,0); - return TRUE; - } - - return TRUE; - } - return FALSE; - } - - -//------------------------------------------------------------------------------- -// Message procedure for the about dialog -//------------------------------------------------------------------------------- -INT_PTR CALLBACK AboutMessageProc(HWND hwndDlg,UINT uMsg, - WPARAM wParam,LPARAM lParam) - { - UNREFERENCED_PARAMETER(lParam); - switch (uMsg) - { - case WM_CLOSE: - EndDialog(hwndDlg,0); - return TRUE; - - case WM_COMMAND: - - if (IDOK == LOWORD(wParam)) - { - EndDialog(hwndDlg,0); - return TRUE; - } - } - return FALSE; - } -}; - -using namespace AssimpView; - -//------------------------------------------------------------------------------- -// Entry point to the application -//------------------------------------------------------------------------------- -int APIENTRY _tWinMain(HINSTANCE hInstance, - HINSTANCE hPrevInstance, - LPTSTR lpCmdLine, - int nCmdShow) - { - UNREFERENCED_PARAMETER(hPrevInstance); - UNREFERENCED_PARAMETER(lpCmdLine); - - // 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()) - { - MessageBox(NULL,"Failed to initialize Direct3D 9", - "ASSIMP ModelViewer",MB_OK); - return -6; - } - - // create the main dialog - HWND hDlg = CreateDialog(hInstance,MAKEINTRESOURCE(IDD_DIALOGMAIN), - NULL,&MessageProc); - - // ensure we get high priority - ::SetPriorityClass(GetCurrentProcess(),HIGH_PRIORITY_CLASS); - - // initialize the default logger if necessary - Assimp::DefaultLogger::create("",Assimp::Logger::VERBOSE); - - CLogWindow::Instance().pcStream = new CMyLogStream(); - Assimp::DefaultLogger::get()->attachStream(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", - "ASSIMP ModelViewer",MB_OK); - return -5; - } - - // display the window - g_hDlg = hDlg; - MSG uMsg; - memset(&uMsg,0,sizeof( MSG)); - ShowWindow( hDlg, nCmdShow ); - UpdateWindow( hDlg ); - - // 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; - } - CLogDisplay::Instance().AddEntry("[OK] Here we go!"); - - // create the log window - CLogWindow::Instance().Init(); - // set the focus to the main window - SetFocus(g_hDlg); - - // recover background skyboxes/textures from the last session - HKEY g_hRegistry; - union - { - char szFileName[MAX_PATH]; - D3DCOLOR clrColor; - }; - DWORD dwTemp = MAX_PATH; - RegCreateKeyEx(HKEY_CURRENT_USER, - "Software\\ASSIMP\\Viewer",0,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(g_hRegistry,"LastTextureSrc",NULL,NULL, - (BYTE*)szFileName,&dwTemp) && '\0' != szFileName[0]) - { - CBackgroundPainter::Instance().SetTextureBG(szFileName); - } - else if(ERROR_SUCCESS == RegQueryValueEx(g_hRegistry,"Color",NULL,NULL, - (BYTE*)&clrColor,&dwTemp)) - { - CBackgroundPainter::Instance().SetColor(clrColor); - } - RegCloseKey(g_hRegistry); - - // now handle command line arguments - HandleCommandLine(lpCmdLine); - - - double adLast[30]; - for (int i = 0; i < 30;++i)adLast[i] = 0.0f; - int iCurrent = 0; - - double g_dCurTime = 0; - double g_dLastTime = 0; - while( uMsg.message != WM_QUIT ) - { - if( PeekMessage( &uMsg, NULL, 0, 0, PM_REMOVE ) ) - { - TranslateMessage( &uMsg ); - DispatchMessage( &uMsg ); - - if (WM_CHAR == uMsg.message) - { - - switch ((char)uMsg.wParam) - { - case 'M': - case 'm': - - CheckDlgButton(g_hDlg,IDC_TOGGLEMS, - IsDlgButtonChecked(g_hDlg,IDC_TOGGLEMS) == BST_CHECKED - ? BST_UNCHECKED : BST_CHECKED); - - ToggleMS(); - break; - - case 'L': - case 'l': - - CheckDlgButton(g_hDlg,IDC_3LIGHTS, - IsDlgButtonChecked(g_hDlg,IDC_3LIGHTS) == BST_CHECKED - ? BST_UNCHECKED : BST_CHECKED); - - ToggleMultipleLights(); - break; - - case 'P': - case 'p': - - CheckDlgButton(g_hDlg,IDC_LOWQUALITY, - IsDlgButtonChecked(g_hDlg,IDC_LOWQUALITY) == BST_CHECKED - ? BST_UNCHECKED : BST_CHECKED); - - ToggleLowQuality(); - break; - - case 'D': - case 'd': - - CheckDlgButton(g_hDlg,IDC_TOGGLEMAT, - IsDlgButtonChecked(g_hDlg,IDC_TOGGLEMAT) == BST_CHECKED - ? BST_UNCHECKED : BST_CHECKED); - - ToggleMats(); - break; - - - case 'N': - case 'n': - - CheckDlgButton(g_hDlg,IDC_TOGGLENORMALS, - IsDlgButtonChecked(g_hDlg,IDC_TOGGLENORMALS) == BST_CHECKED - ? BST_UNCHECKED : BST_CHECKED); - ToggleNormals(); - break; - - - case 'S': - case 's': - - CheckDlgButton(g_hDlg,IDC_NOSPECULAR, - IsDlgButtonChecked(g_hDlg,IDC_NOSPECULAR) == BST_CHECKED - ? BST_UNCHECKED : BST_CHECKED); - - ToggleSpecular(); - break; - - case 'A': - case 'a': - - CheckDlgButton(g_hDlg,IDC_AUTOROTATE, - IsDlgButtonChecked(g_hDlg,IDC_AUTOROTATE) == BST_CHECKED - ? BST_UNCHECKED : BST_CHECKED); - - ToggleAutoRotate(); - break; - - - case 'R': - case 'r': - - CheckDlgButton(g_hDlg,IDC_LIGHTROTATE, - IsDlgButtonChecked(g_hDlg,IDC_LIGHTROTATE) == BST_CHECKED - ? BST_UNCHECKED : BST_CHECKED); - - ToggleLightRotate(); - break; - - case 'Z': - case 'z': - - CheckDlgButton(g_hDlg,IDC_ZOOM, - IsDlgButtonChecked(g_hDlg,IDC_ZOOM) == BST_CHECKED - ? BST_UNCHECKED : BST_CHECKED); - - ToggleFPSView(); - break; - - - case 'W': - case 'w': - - CheckDlgButton(g_hDlg,IDC_TOGGLEWIRE, - IsDlgButtonChecked(g_hDlg,IDC_TOGGLEWIRE) == BST_CHECKED - ? BST_UNCHECKED : BST_CHECKED); - - ToggleWireFrame(); - break; - - case 'K': - case 'k': - - CheckDlgButton(g_hDlg,IDC_SHOWSKELETON, - IsDlgButtonChecked(g_hDlg,IDC_SHOWSKELETON) == BST_CHECKED - ? BST_UNCHECKED : BST_CHECKED); - - ToggleSkeleton(); - break; - - case 'C': - case 'c': - - CheckDlgButton(g_hDlg,IDC_BFCULL, - IsDlgButtonChecked(g_hDlg,IDC_BFCULL) == BST_CHECKED - ? BST_UNCHECKED : BST_CHECKED); - - ToggleCulling(); - break; - - case 'T': - case 't': - - CheckDlgButton(g_hDlg,IDC_NOAB, - IsDlgButtonChecked(g_hDlg,IDC_NOAB) == BST_CHECKED - ? BST_UNCHECKED : BST_CHECKED); - - ToggleTransparency(); - break; - } - } - } - - - // render the scene - CDisplay::Instance().OnRender(); - - - // measure FPS, average it out - g_dCurTime = timeGetTime(); - g_fElpasedTime = (float)((g_dCurTime - g_dLastTime) * 0.001); - g_dLastTime = g_dCurTime; - - adLast[iCurrent++] = 1.0f / g_fElpasedTime; - - double dFPS = 0.0; - for (int i = 0;i < 30;++i) - dFPS += adLast[i]; - dFPS /= 30.0; - - if (30 == iCurrent) - { - iCurrent = 0; - if (dFPS != g_fFPS) - { - g_fFPS = dFPS; - char szOut[256]; - - sprintf(szOut,"%i",(int)floorf((float)dFPS+0.5f)); - SetDlgItemText(g_hDlg,IDC_EFPS,szOut); - } - } - } - DeleteAsset(); - Assimp::DefaultLogger::kill(); - ShutdownDevice(); - ShutdownD3D(); - return 0; - } \ No newline at end of file +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2015, assimp 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 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 "assimp_view.h" +#include <assimp/Exporter.hpp> +#include <algorithm> + +#include <windowsx.h> + +namespace AssimpView { + +using namespace Assimp; + +// 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<std::string> g_aPreviousFiles; + +// history menu item +HMENU g_hHistoryMenu = NULL; + +float g_fACMR = 3.0f; + +#define AI_VIEW_NUM_RECENT_FILES 0x8 +#define AI_VIEW_RECENT_FILE_ID(_n_) (5678 + _n_) + +#define AI_VIEW_EXPORT_FMT_BASE 7912 +#define AI_VIEW_EXPORT_FMT_ID(_n_) (AI_VIEW_EXPORT_FMT_BASE + _n_) + +void UpdateHistory(); +void SaveHistory(); + +//------------------------------------------------------------------------------- +// Setup file associations for all formats supported by the library +// +// File associations are registered in HKCU\Software\Classes. They might +// be overwritten by global file associations. +//------------------------------------------------------------------------------- +void MakeFileAssociations() + { + char szTemp2[MAX_PATH]; + char szTemp[MAX_PATH + 10]; + + GetModuleFileName(NULL,szTemp2,MAX_PATH); + sprintf(szTemp,"%s %%1",szTemp2); + + HKEY g_hRegistry; + + aiString list, tmp; + aiGetExtensionList(&list); + tmp = list; + + const char* sz = strtok(list.data,";"); + do + { + char buf[256]; + ai_assert(sz[0] == '*'); + sprintf(buf,"Software\\Classes\\%s",sz+1); + + RegCreateKeyEx(HKEY_CURRENT_USER,buf,0,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); + } + while ((sz = strtok(NULL,";"))); + + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\ASSIMPVIEW_CLASS",0,NULL,0,KEY_ALL_ACCESS, NULL, &g_hRegistry,NULL); + RegCloseKey(g_hRegistry); + + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\ASSIMPVIEW_CLASS\\shell\\open\\command",0,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)); + + CLogDisplay::Instance().AddEntry(tmp.data,D3DCOLOR_ARGB(0xFF,0,0xFF,0)); + } + + +//------------------------------------------------------------------------------- +// Handle command line parameters +// +// The function loads an asset specified on the command line as first argument +// Other command line parameters are not handled +//------------------------------------------------------------------------------- +void HandleCommandLine(char* p_szCommand) + { + char* sz = p_szCommand; + //bool bQuak = false; + + if (strlen(sz) < 2)return; + + if (*sz == '\"') + { + char* sz2 = strrchr(sz,'\"'); + if (sz2)*sz2 = 0; + sz++; // skip the starting quote + } + + 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); +} + + +//------------------------------------------------------------------------------- +// Save the checker pattern colors to the registry +//------------------------------------------------------------------------------- +void SaveCheckerPatternColors() +{ + // we have it as float4. save it as binary value --. + RegSetValueExA(g_hRegistry,"CheckerPattern0",0,REG_BINARY, + (const BYTE*)CDisplay::Instance().GetFirstCheckerColor(), + sizeof(D3DXVECTOR3)); + + RegSetValueExA(g_hRegistry,"CheckerPattern1",0,REG_BINARY, + (const BYTE*)CDisplay::Instance().GetSecondCheckerColor(), + sizeof(D3DXVECTOR3)); +} + +//------------------------------------------------------------------------------- +// Load the checker pattern colors from the registry +//------------------------------------------------------------------------------- +void LoadCheckerPatternColors() +{ + DWORD dwTemp = sizeof(D3DXVECTOR3); + RegQueryValueEx(g_hRegistry,"CheckerPattern0",NULL,NULL, + (BYTE*) /* jep, this is evil */ CDisplay::Instance().GetFirstCheckerColor(),&dwTemp); + + RegQueryValueEx(g_hRegistry,"CheckerPattern1",NULL,NULL, + (BYTE*) /* jep, this is evil */ CDisplay::Instance().GetSecondCheckerColor(),&dwTemp); +} + +//------------------------------------------------------------------------------- +// Changed pp setup +//------------------------------------------------------------------------------- +void UpdatePPSettings() +{ + DWORD dwValue = ppsteps; + RegSetValueExA(g_hRegistry,"PostProcessing",0,REG_DWORD,(const BYTE*)&dwValue,4); + UpdateWindow(g_hDlg); +} + +//------------------------------------------------------------------------------- +// 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); +} + +//------------------------------------------------------------------------------- +// 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); +} + +//------------------------------------------------------------------------------- +// 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); +} + +//------------------------------------------------------------------------------- +// 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); +} + +//------------------------------------------------------------------------------- +// Toggle the "NoTransparency" state +//------------------------------------------------------------------------------- +void ToggleTransparency() +{ + g_sOptions.bNoAlphaBlending = !g_sOptions.bNoAlphaBlending; + + // store this in the registry, too + DWORD dwValue = 0; + if (g_sOptions.bNoAlphaBlending)dwValue = 1; + RegSetValueExA(g_hRegistry,"NoTransparency",0,REG_DWORD,(const BYTE*)&dwValue,4); +} + +//------------------------------------------------------------------------------- +// 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); +} + +//------------------------------------------------------------------------------- +// 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(); +} + +//------------------------------------------------------------------------------- +// 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(); +} + +//------------------------------------------------------------------------------- +// Toggle the "Culling" state +//------------------------------------------------------------------------------- +void ToggleCulling() +{ + g_sOptions.bCulling = !g_sOptions.bCulling; + + // store this in the registry, too + DWORD dwValue = 0; + if (g_sOptions.bCulling)dwValue = 1; + RegSetValueExA(g_hRegistry,"Culling",0,REG_DWORD,(const BYTE*)&dwValue,4); +} + +//------------------------------------------------------------------------------- +// Toggle the "Skeleton" state +//------------------------------------------------------------------------------- +void ToggleSkeleton() +{ + g_sOptions.bSkeleton = !g_sOptions.bSkeleton; + + // store this in the registry, too + DWORD dwValue = 0; + if (g_sOptions.bCulling)dwValue = 1; + RegSetValueExA(g_hRegistry,"Skeleton",0,REG_DWORD,(const BYTE*)&dwValue,4); +} + +//------------------------------------------------------------------------------- +// 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); +} + + +//------------------------------------------------------------------------------- +// 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); +} + +//------------------------------------------------------------------------------- +// 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-214,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+214,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((*pclrResult >> 16) & 0xff,(*pclrResult >> 8) & 0xff,*pclrResult & 0xff); + clr.lpCustColors = g_aclCustomColors; + clr.lpfnHook = NULL; + clr.lpTemplateName = NULL; + clr.lCustData = 0; + + ChooseColor(&clr); + + *pclrResult = D3DCOLOR_ARGB(0xFF, + GetRValue(clr.rgbResult), + GetGValue(clr.rgbResult), + GetBValue(clr.rgbResult)); + return; +} + + +//------------------------------------------------------------------------------- +// Let the user choose a color in a windows standard color dialog +//------------------------------------------------------------------------------- +void DisplayColorDialog(D3DXVECTOR4* pclrResult) +{ + CHOOSECOLOR clr; + clr.lStructSize = sizeof(CHOOSECOLOR); + clr.hwndOwner = g_hDlg; + clr.Flags = CC_RGBINIT | CC_FULLOPEN; + clr.rgbResult = RGB(clamp<unsigned char>(pclrResult->x * 255.0f), + clamp<unsigned char>(pclrResult->y * 255.0f), + clamp<unsigned char>(pclrResult->z * 255.0f)); + clr.lpCustColors = g_aclCustomColors; + clr.lpfnHook = NULL; + clr.lpTemplateName = NULL; + clr.lCustData = 0; + + ChooseColor(&clr); + + pclrResult->x = GetRValue(clr.rgbResult) / 255.0f; + pclrResult->y = GetGValue(clr.rgbResult) / 255.0f; + pclrResult->z = GetBValue(clr.rgbResult) / 255.0f; + 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 KiB = 1024 bytes)\n\n" + "ASSIMP Import Data: \t%i KiB\n" + "Texture data:\t\t%i KiB\n" + "Vertex buffers:\t\t%i KiB\n" + "Index buffers:\t\t%i KiB\n" + "Video Memory:\t\t%i KiB\n\n" + "Total: \t\t\t%i KiB", + 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 = "<empty>"; + 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),"<empty>"); + } + + 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 = "<empty>"; + 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; +} + +//------------------------------------------------------------------------------- +void SetupPPUIState() +{ + + // that's ugly. anyone willing to rewrite me from scratch? + HMENU hMenu = GetMenu(g_hDlg); + CheckMenuItem(hMenu,ID_VIEWER_PP_JIV,ppsteps & aiProcess_JoinIdenticalVertices ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu,ID_VIEWER_PP_CTS,ppsteps & aiProcess_CalcTangentSpace ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu,ID_VIEWER_PP_FD,ppsteps & aiProcess_FindDegenerates ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu,ID_VIEWER_PP_FID,ppsteps & aiProcess_FindInvalidData ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu,ID_VIEWER_PP_FIM,ppsteps & aiProcess_FindInstances ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu,ID_VIEWER_PP_FIN,ppsteps & aiProcess_FixInfacingNormals ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu,ID_VIEWER_PP_GUV,ppsteps & aiProcess_GenUVCoords ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu,ID_VIEWER_PP_ICL,ppsteps & aiProcess_ImproveCacheLocality ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu,ID_VIEWER_PP_OG,ppsteps & aiProcess_OptimizeGraph ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu,ID_VIEWER_PP_OM,ppsteps & aiProcess_OptimizeMeshes ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu,ID_VIEWER_PP_PTV,ppsteps & aiProcess_PreTransformVertices ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu,ID_VIEWER_PP_RRM2,ppsteps & aiProcess_RemoveRedundantMaterials ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu,ID_VIEWER_PP_TUV,ppsteps & aiProcess_TransformUVCoords ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu,ID_VIEWER_PP_VDS,ppsteps & aiProcess_ValidateDataStructure ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu,ID_VIEWER_PP_DB,ppsteps & aiProcess_Debone ? MF_CHECKED : MF_UNCHECKED); +} + +#ifndef ASSIMP_BUILD_NO_EXPORT +//------------------------------------------------------------------------------- +// Fill the 'export' top level menu with a list of all supported export formats +//------------------------------------------------------------------------------- +void PopulateExportMenu() +{ + // add sub items for all recent files + Exporter exp; + HMENU hm = ::CreateMenu(); + for(size_t i = 0; i < exp.GetExportFormatCount(); ++i) + { + const aiExportFormatDesc* const e = exp.GetExportFormatDescription(i); + char tmp[256]; + sprintf(tmp,"%s (%s)",e->description,e->id); + + AppendMenu(hm,MF_STRING,AI_VIEW_EXPORT_FMT_ID(i),tmp); + } + + ModifyMenu(GetMenu(g_hDlg),ID_EXPORT,MF_BYCOMMAND | MF_POPUP, + (UINT_PTR)hm,"Export"); +} + +//------------------------------------------------------------------------------- +//------------------------------------------------------------------------------- +void DoExport(size_t formatId) +{ + if (!g_szFileName[0]) { + MessageBox(g_hDlg, "No model loaded", "Export", MB_ICONERROR); + return; + } + Exporter exp; + const aiExportFormatDesc* const e = exp.GetExportFormatDescription(formatId); + ai_assert(e); + + char szFileName[MAX_PATH*2]; + DWORD dwTemp = sizeof(szFileName); + if(ERROR_SUCCESS == RegQueryValueEx(g_hRegistry,"ModelExportDest",NULL,NULL,(BYTE*)szFileName, &dwTemp)) { + ai_assert(strlen(szFileName) <= MAX_PATH); + + // invent a nice default file name + char* sz = max(strrchr(szFileName,'\\'),strrchr(szFileName,'/')); + if (sz) { + strncpy(sz,max(strrchr(g_szFileName,'\\'),strrchr(g_szFileName,'/')),MAX_PATH); + } + } + else { + // Key was not found. Use the folder where the asset comes from + strncpy(szFileName,g_szFileName,MAX_PATH); + } + + // fix file extension + { char * const sz = strrchr(szFileName,'.'); + if(sz) { + ai_assert((sz - &szFileName[0]) + strlen(e->fileExtension) + 1 <= MAX_PATH); + strcpy(sz+1,e->fileExtension); + } + } + + // build the stupid info string for GetSaveFileName() - can't use sprintf() because the string must contain binary zeros. + char desc[256] = {0}; + char* c = strcpy(desc,e->description) + strlen(e->description)+1; + c += sprintf(c,"*.%s",e->fileExtension)+1; + strcpy(c, "*.*\0"); c += 4; + + ai_assert(c - &desc[0] <= 256); + + const std::string ext = "."+std::string(e->fileExtension); + OPENFILENAME sFilename1 = { + sizeof(OPENFILENAME), + g_hDlg,GetModuleHandle(NULL), + desc, NULL, 0, 1, + szFileName, MAX_PATH, NULL, 0, NULL, + "Export asset", + OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR, + 0, 1, ext.c_str(), 0, NULL, NULL + }; + if(::GetSaveFileName(&sFilename1) == 0) { + return; + } + + // Now store the file in the registry unless the user decided to stay in the model directory + const std::string sFinal = szFileName, sub = sFinal.substr(0,sFinal.find_last_of("\\/")); + if (strncmp(sub.c_str(),g_szFileName,sub.length())) { + RegSetValueExA(g_hRegistry,"ModelExportDest",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH); + } + + // export the file + const aiReturn res = exp.Export(g_pcAsset->pcScene,e->id,sFinal.c_str(), + ppsteps | /* configurable pp steps */ + aiProcess_GenSmoothNormals | // generate smooth normal vectors if not existing + aiProcess_SplitLargeMeshes | // split large, unrenderable meshes into submeshes + aiProcess_Triangulate | // triangulate polygons with more than 3 edges + aiProcess_ConvertToLeftHanded | // convert everything to D3D left handed space + aiProcess_SortByPType | // make 'clean' meshes which consist of a single typ of primitives + 0 + ); + if (res == aiReturn_SUCCESS) { + CLogDisplay::Instance().AddEntry("[INFO] Exported file " + sFinal,D3DCOLOR_ARGB(0xFF,0x00,0xFF,0x00)); + return; + } + CLogDisplay::Instance().AddEntry("[INFO] Failure exporting file " + + sFinal,D3DCOLOR_ARGB(0xFF,0xFF,0x00,0x00)); +} +#endif + +//------------------------------------------------------------------------------- +// 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_ENODEWND,"0"); + SetDlgItemText(g_hDlg,IDC_ETEX,"0"); + SetDlgItemText(g_hDlg,IDC_EMESH,"0"); + +#ifndef ASSIMP_BUILD_NO_EXPORT + PopulateExportMenu(); +#endif + + // 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", + 0,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-214,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); + } + + // LowQuality + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"NoTransparency",NULL,NULL, + (BYTE*)&dwValue,&dwTemp))dwValue = 0; + if (0 == dwValue) + { + g_sOptions.bNoAlphaBlending = false; + CheckDlgButton(g_hDlg,IDC_NOAB,BST_UNCHECKED); + } + else + { + g_sOptions.bNoAlphaBlending = true; + CheckDlgButton(g_hDlg,IDC_NOAB,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); + } + + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"PostProcessing",NULL,NULL,(BYTE*)&dwValue,&dwTemp)) + ppsteps = ppstepsdefault; + else ppsteps = dwValue; + + SetupPPUIState(); + LoadCheckerPatternColors(); + + SendDlgItemMessage(g_hDlg,IDC_SLIDERANIM,TBM_SETRANGEMIN,TRUE,0); + SendDlgItemMessage(g_hDlg,IDC_SLIDERANIM,TBM_SETRANGEMAX,TRUE,10000); + return; +} + +//------------------------------------------------------------------------------- +// Message prcoedure for the smooth normals dialog +//------------------------------------------------------------------------------- +INT_PTR CALLBACK SMMessageProc(HWND hwndDlg,UINT uMsg, + WPARAM wParam,LPARAM lParam) +{ + UNREFERENCED_PARAMETER(lParam); + switch (uMsg) + { + case WM_INITDIALOG: + char s[30]; + ::sprintf(s,"%.2f",g_smoothAngle); + SetDlgItemText(hwndDlg,IDC_EDITSM,s); + return TRUE; + + case WM_CLOSE: + EndDialog(hwndDlg,0); + return TRUE; + + case WM_COMMAND: + + if (IDOK == LOWORD(wParam)) { + char s[30]; + GetDlgItemText(hwndDlg,IDC_EDITSM,s,30); + g_smoothAngle = (float)atof(s); + + EndDialog(hwndDlg,0); + } + else if (IDCANCEL == LOWORD(wParam)) { + EndDialog(hwndDlg,1); + } + return TRUE; + } + return FALSE; +} + +//------------------------------------------------------------------------------- +// Main message procedure of the application +// +// The function handles all incoming messages for the main window. +// However, if does not directly process input commands. +// NOTE: Due to the impossibility to process WM_CHAR messages in dialogs +// properly the code for all hotkeys has been moved to the WndMain +//------------------------------------------------------------------------------- +INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, + WPARAM wParam,LPARAM lParam) + { + UNREFERENCED_PARAMETER(lParam); + UNREFERENCED_PARAMETER(wParam); + + int xPos,yPos; + int xPos2,yPos2; + int fHalfX; + int fHalfY; + + TRACKMOUSEEVENT sEvent; + switch (uMsg) + { + case WM_INITDIALOG: + + g_hDlg = hwndDlg; + + // load the state of the usr interface + InitUI(); + + // load the file history + LoadHistory(); + + // load the current color of the lights + LoadLightColors(); + return TRUE; + + case WM_HSCROLL: + + // XXX quick and dirty fix for #3029892 + if (GetDlgItem(g_hDlg, IDC_SLIDERANIM) == (HWND)lParam && g_pcAsset && g_pcAsset->pcScene->mAnimations) + { + double num = (double)SendDlgItemMessage(g_hDlg,IDC_SLIDERANIM,TBM_GETPOS,0,0); + const aiAnimation* anim = g_pcAsset->pcScene->mAnimations[ g_pcAsset->mAnimator->CurrentAnimIndex() ]; + + g_dCurrent = (anim->mDuration/anim->mTicksPerSecond) * num/10000; + g_pcAsset->mAnimator->Calculate(g_dCurrent); + } + break; + + case WM_MOUSEWHEEL: + + if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode()) + { + CDisplay::Instance().SetTextureViewZoom ( GET_WHEEL_DELTA_WPARAM(wParam) / 50.0f ); + } + else + { + 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: + + g_bMousePressed = false; + g_bMousePressedR = false; + g_bMousePressedM = false; + g_bMousePressedBoth = false; + return TRUE; + + case WM_LBUTTONDBLCLK: + + CheckDlgButton(hwndDlg,IDC_AUTOROTATE, + IsDlgButtonChecked(hwndDlg,IDC_AUTOROTATE) == BST_CHECKED + ? BST_UNCHECKED : BST_CHECKED); + + ToggleAutoRotate(); + return TRUE; + + + case WM_CLOSE: + PostQuitMessage(0); + 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,g,b; + const char* szText; + if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode() || + CDisplay::VIEWMODE_MATERIAL == CDisplay::Instance().GetViewMode()) + { + r = (unsigned char)(CDisplay::Instance().GetFirstCheckerColor()->x * 255.0f); + g = (unsigned char)(CDisplay::Instance().GetFirstCheckerColor()->y * 255.0f); + b = (unsigned char)(CDisplay::Instance().GetFirstCheckerColor()->z * 255.0f); + szText = "Background #0"; + } + else if (!g_pcAsset) + { + r = g = b = 150;szText = ""; + } + else + { + r = (unsigned char)((g_avLightColors[0] >> 16) & 0xFF); + g = (unsigned char)((g_avLightColors[0] >> 8) & 0xFF); + b = (unsigned char)((g_avLightColors[0]) & 0xFF); + szText = "Light #0"; + } + 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,szText,strlen(szText)); + bDraw = true; + } + else if(IDC_LCOLOR2 == pcStruct->CtlID) + { + unsigned char r,g,b; + const char* szText; + if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode() || + CDisplay::VIEWMODE_MATERIAL == CDisplay::Instance().GetViewMode()) + { + r = (unsigned char)(CDisplay::Instance().GetSecondCheckerColor()->x * 255.0f); + g = (unsigned char)(CDisplay::Instance().GetSecondCheckerColor()->y * 255.0f); + b = (unsigned char)(CDisplay::Instance().GetSecondCheckerColor()->z * 255.0f); + szText = "Background #1"; + } + else if (!g_pcAsset) + { + r = g = b = 150;szText = ""; + } + else + { + r = (unsigned char)((g_avLightColors[1] >> 16) & 0xFF); + g = (unsigned char)((g_avLightColors[1] >> 8) & 0xFF); + b = (unsigned char)((g_avLightColors[1]) & 0xFF); + szText = "Light #1"; + } + 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,szText,strlen(szText)); + bDraw = true; + } + else if(IDC_LCOLOR3 == pcStruct->CtlID) + { + unsigned char r,g,b; + const char* szText; + if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode() || + CDisplay::VIEWMODE_MATERIAL == CDisplay::Instance().GetViewMode()) + { + r = g = b = 0; + szText = ""; + } + else if (!g_pcAsset) + { + r = g = b = 150;szText = ""; + } + else + { + r = (unsigned char)((g_avLightColors[2] >> 16) & 0xFF); + g = (unsigned char)((g_avLightColors[2] >> 8) & 0xFF); + b = (unsigned char)((g_avLightColors[2]) & 0xFF); + szText = "Ambient"; + } + 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,szText,strlen(szText)); + 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; + + // register a mouse track handler to be sure we'll know + // when the mouse leaves the display view again + sEvent.cbSize = sizeof(TRACKMOUSEEVENT); + sEvent.dwFlags = TME_LEAVE; + sEvent.hwndTrack = g_hDlg; + sEvent.dwHoverTime = HOVER_DEFAULT; + TrackMouseEvent(&sEvent); + + if (g_bMousePressedR) + { + g_bMousePressed = false; + g_bMousePressedR = false; + g_bMousePressedBoth = true; + return TRUE; + } + + // need to determine the position of the mouse and the + // distance from the center + //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;*/ + + RECT sRect; + GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect); + sRect.right -= sRect.left; + sRect.bottom -= sRect.top; + + // if the mouse klick was inside the viewer panel + // give the focus to it + if (xPos > 0 && xPos < sRect.right && yPos > 0 && yPos < sRect.bottom) + { + SetFocus(GetDlgItem(g_hDlg,IDC_RT)); + } + + // g_bInvert stores whether the mouse has started on the negative + // x or on the positive x axis of the imaginary coordinate system + // with origin p at the center of the HUD texture + xPos -= sRect.right/2; + yPos -= sRect.bottom/2; + + if (xPos > 0)g_bInvert = true; + else g_bInvert = false; + + D3DSURFACE_DESC sDesc; + g_pcTexture->GetLevelDesc(0,&sDesc); + + fHalfX = (int)(((float)sRect.right-(float)sDesc.Width) / 2.0f); + fHalfY = (int)(((float)sRect.bottom-(float)sDesc.Height) / 2.0f); + + // Determine the input operation to perform for this position + g_eClick = EClickPos_Outside; + if (xPos2 >= fHalfX && xPos2 < fHalfX + (int)sDesc.Width && + yPos2 >= fHalfY && yPos2 < fHalfY + (int)sDesc.Height && + NULL != g_szImageMask) + { + // inside the texture. Lookup the grayscale value from it + xPos2 -= fHalfX; + yPos2 -= fHalfY; + + unsigned char chValue = g_szImageMask[xPos2 + yPos2 * sDesc.Width]; + if (chValue > 0xFF-20) + { + g_eClick = EClickPos_Circle; + } + else if (chValue < 0xFF-20 && chValue > 185) + { + g_eClick = EClickPos_CircleHor; + } + else if (chValue > 0x10 && chValue < 185) + { + g_eClick = EClickPos_CircleVert; + } + } + return TRUE; + + case WM_RBUTTONDOWN: + g_bMousePressedR = true; + + sEvent.cbSize = sizeof(TRACKMOUSEEVENT); + sEvent.dwFlags = TME_LEAVE; + sEvent.hwndTrack = g_hDlg; + sEvent.dwHoverTime = HOVER_DEFAULT; + TrackMouseEvent(&sEvent); + + if (g_bMousePressed) + { + g_bMousePressedR = false; + g_bMousePressed = false; + g_bMousePressedBoth = true; + } + + return TRUE; + + case WM_MBUTTONDOWN: + + + g_bMousePressedM = true; + + sEvent.cbSize = sizeof(TRACKMOUSEEVENT); + sEvent.dwFlags = TME_LEAVE; + sEvent.hwndTrack = g_hDlg; + sEvent.dwHoverTime = HOVER_DEFAULT; + TrackMouseEvent(&sEvent); + return TRUE; + + case WM_LBUTTONUP: + g_bMousePressed = false; + g_bMousePressedBoth = false; + return TRUE; + + case WM_RBUTTONUP: + g_bMousePressedR = false; + g_bMousePressedBoth = false; + return TRUE; + + case WM_MBUTTONUP: + g_bMousePressedM = false; + return TRUE; + + case WM_DROPFILES: + { + HDROP hDrop = (HDROP)wParam; + + char szFile[MAX_PATH]; + DragQueryFile(hDrop,0,szFile,sizeof(szFile)); + + const char* sz = strrchr(szFile,'.'); + if (!sz) + sz = szFile; + + if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode()) + { + // replace the selected texture with the new one ... + CDisplay::Instance().ReplaceCurrentTexture(szFile); + } + else + { + // check whether it is a typical texture file format ... + ++sz; + if (0 == ASSIMP_stricmp(sz,"png") || + 0 == ASSIMP_stricmp(sz,"bmp") || + 0 == ASSIMP_stricmp(sz,"jpg") || + 0 == ASSIMP_stricmp(sz,"tga") || + 0 == ASSIMP_stricmp(sz,"tif") || + 0 == ASSIMP_stricmp(sz,"hdr") || + 0 == ASSIMP_stricmp(sz,"ppm") || + 0 == ASSIMP_stricmp(sz,"pfm")) + { + CBackgroundPainter::Instance().SetTextureBG(szFile); + } + 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) + return TRUE; + + // 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 + { + strcpy(g_szFileName,szFile); + + DeleteAsset(); + LoadAsset(); + UpdateHistory(); + SaveHistory(); + } + } + DragFinish(hDrop); + } + return TRUE; + + case WM_COMMAND: + + HMENU hMenu = GetMenu(g_hDlg); + if (ID_VIEWER_QUIT == LOWORD(wParam)) + { + PostQuitMessage(0); + DestroyWindow(hwndDlg); + } + else if (IDC_COMBO1 == LOWORD(wParam)) + { + if(HIWORD(wParam) == CBN_SELCHANGE) { + const size_t sel = static_cast<size_t>(ComboBox_GetCurSel(GetDlgItem(hwndDlg,IDC_COMBO1))); + if(g_pcAsset) { + g_pcAsset->mAnimator->SetAnimIndex(sel); + SendDlgItemMessage(hwndDlg,IDC_SLIDERANIM,TBM_SETPOS,TRUE,0); + } + } + } + else if (ID_VIEWER_RESETVIEW == LOWORD(wParam)) + { + 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); + g_mWorldRotate = aiMatrix4x4(); + g_mWorld = aiMatrix4x4(); + + // don't forget to reset the st + CBackgroundPainter::Instance().ResetSB(); + } + else if (ID__HELP == LOWORD(wParam)) + { + DialogBox(g_hInstance,MAKEINTRESOURCE(IDD_AVHELP), + hwndDlg,&HelpDialogProc); + } + else if (ID__ABOUT == LOWORD(wParam)) + { + DialogBox(g_hInstance,MAKEINTRESOURCE(IDD_ABOUTBOX), + hwndDlg,&AboutMessageProc); + } + else if (ID_TOOLS_LOGWINDOW == LOWORD(wParam)) + { + CLogWindow::Instance().Show(); + } + else if (ID__WEBSITE == LOWORD(wParam)) + { + ShellExecute(NULL,"open","http://assimp.sourceforge.net","","",SW_SHOW); + } + else if (ID__WEBSITESF == LOWORD(wParam)) + { + ShellExecute(NULL,"open","https://sourceforge.net/projects/assimp","","",SW_SHOW); + } + else if (ID_REPORTBUG == LOWORD(wParam)) + { + ShellExecute(NULL,"open","https://sourceforge.net/tracker/?func=add&group_id=226462&atid=1067632","","",SW_SHOW); + } + else if (ID_FR == LOWORD(wParam)) + { + ShellExecute(NULL,"open","https://sourceforge.net/forum/forum.php?forum_id=817653","","",SW_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)) + { + ClearBG(); + } + else if (ID_BACKGROUND_SETCOLOR == LOWORD(wParam)) + { + ChooseBGColor(); + } + else if (ID_BACKGROUND_LOADTEXTURE == LOWORD(wParam)) + { + LoadBGTexture(); + } + else if (ID_BACKGROUND_LOADSKYBOX == LOWORD(wParam)) + { + LoadSkybox(); + } + else if (ID_VIEWER_SAVESCREENSHOTTOFILE == LOWORD(wParam)) + { + SaveScreenshot(); + } + else if (ID_VIEWER_OPEN == LOWORD(wParam)) + { + OpenAsset(); + } + else if (ID_TOOLS_FLIPNORMALS == LOWORD(wParam)) + { + if (g_pcAsset && g_pcAsset->pcScene) + { + g_pcAsset->FlipNormals(); + } + } + + // this is ugly. anyone willing to rewrite it from scratch using wxwidgets or similar? + else if (ID_VIEWER_PP_JIV == LOWORD(wParam)) { + ppsteps ^= aiProcess_JoinIdenticalVertices; + CheckMenuItem(hMenu,ID_VIEWER_PP_JIV,ppsteps & aiProcess_JoinIdenticalVertices ? MF_CHECKED : MF_UNCHECKED); + UpdatePPSettings(); + } + else if (ID_VIEWER_PP_CTS == LOWORD(wParam)) { + ppsteps ^= aiProcess_CalcTangentSpace; + CheckMenuItem(hMenu,ID_VIEWER_PP_CTS,ppsteps & aiProcess_CalcTangentSpace ? MF_CHECKED : MF_UNCHECKED); + UpdatePPSettings(); + } + else if (ID_VIEWER_PP_FD == LOWORD(wParam)) { + ppsteps ^= aiProcess_FindDegenerates; + CheckMenuItem(hMenu,ID_VIEWER_PP_FD,ppsteps & aiProcess_FindDegenerates ? MF_CHECKED : MF_UNCHECKED); + UpdatePPSettings(); + } + else if (ID_VIEWER_PP_FID == LOWORD(wParam)) { + ppsteps ^= aiProcess_FindInvalidData; + CheckMenuItem(hMenu,ID_VIEWER_PP_FID,ppsteps & aiProcess_FindInvalidData ? MF_CHECKED : MF_UNCHECKED); + UpdatePPSettings(); + } + else if (ID_VIEWER_PP_FIM == LOWORD(wParam)) { + ppsteps ^= aiProcess_FindInstances; + CheckMenuItem(hMenu,ID_VIEWER_PP_FIM,ppsteps & aiProcess_FindInstances ? MF_CHECKED : MF_UNCHECKED); + UpdatePPSettings(); + } + else if (ID_VIEWER_PP_FIN == LOWORD(wParam)) { + ppsteps ^= aiProcess_FixInfacingNormals; + CheckMenuItem(hMenu,ID_VIEWER_PP_FIN,ppsteps & aiProcess_FixInfacingNormals ? MF_CHECKED : MF_UNCHECKED); + UpdatePPSettings(); + } + else if (ID_VIEWER_PP_GUV == LOWORD(wParam)) { + ppsteps ^= aiProcess_GenUVCoords; + CheckMenuItem(hMenu,ID_VIEWER_PP_GUV,ppsteps & aiProcess_GenUVCoords ? MF_CHECKED : MF_UNCHECKED); + UpdatePPSettings(); + } + else if (ID_VIEWER_PP_ICL == LOWORD(wParam)) { + ppsteps ^= aiProcess_ImproveCacheLocality; + CheckMenuItem(hMenu,ID_VIEWER_PP_ICL,ppsteps & aiProcess_ImproveCacheLocality ? MF_CHECKED : MF_UNCHECKED); + UpdatePPSettings(); + } + else if (ID_VIEWER_PP_OG == LOWORD(wParam)) { + if (ppsteps & aiProcess_PreTransformVertices) { + CLogDisplay::Instance().AddEntry("[ERROR] This setting is incompatible with \'Pretransform Vertices\'"); + } + else { + ppsteps ^= aiProcess_OptimizeGraph; + CheckMenuItem(hMenu,ID_VIEWER_PP_OG,ppsteps & aiProcess_OptimizeGraph ? MF_CHECKED : MF_UNCHECKED); + UpdatePPSettings(); + } + } + else if (ID_VIEWER_PP_OM == LOWORD(wParam)) { + ppsteps ^= aiProcess_OptimizeMeshes; + CheckMenuItem(hMenu,ID_VIEWER_PP_OM,ppsteps & aiProcess_OptimizeMeshes ? MF_CHECKED : MF_UNCHECKED); + UpdatePPSettings(); + } + else if (ID_VIEWER_PP_PTV == LOWORD(wParam)) { + if (ppsteps & aiProcess_OptimizeGraph) { + CLogDisplay::Instance().AddEntry("[ERROR] This setting is incompatible with \'Optimize Scenegraph\'"); + } + else { + ppsteps ^= aiProcess_PreTransformVertices; + CheckMenuItem(hMenu,ID_VIEWER_PP_PTV,ppsteps & aiProcess_PreTransformVertices ? MF_CHECKED : MF_UNCHECKED); + UpdatePPSettings(); + } + } + else if (ID_VIEWER_PP_RRM2 == LOWORD(wParam)) { + ppsteps ^= aiProcess_RemoveRedundantMaterials; + CheckMenuItem(hMenu,ID_VIEWER_PP_RRM2,ppsteps & aiProcess_RemoveRedundantMaterials ? MF_CHECKED : MF_UNCHECKED); + UpdatePPSettings(); + } + else if (ID_VIEWER_PP_TUV == LOWORD(wParam)) { + ppsteps ^= aiProcess_TransformUVCoords; + CheckMenuItem(hMenu,ID_VIEWER_PP_TUV,ppsteps & aiProcess_TransformUVCoords ? MF_CHECKED : MF_UNCHECKED); + UpdatePPSettings(); + } + else if (ID_VIEWER_PP_DB == LOWORD(wParam)) { + ppsteps ^= aiProcess_Debone; + CheckMenuItem(hMenu,ID_VIEWER_PP_DB,ppsteps & aiProcess_Debone ? MF_CHECKED : MF_UNCHECKED); + UpdatePPSettings(); + } + else if (ID_VIEWER_PP_VDS == LOWORD(wParam)) { + ppsteps ^= aiProcess_ValidateDataStructure; + CheckMenuItem(hMenu,ID_VIEWER_PP_VDS,ppsteps & aiProcess_ValidateDataStructure ? MF_CHECKED : MF_UNCHECKED); + UpdatePPSettings(); + } + else if (ID_VIEWER_RELOAD == LOWORD(wParam)) + { + DeleteAsset(); + LoadAsset(); + } + else if (ID_IMPORTSETTINGS_RESETTODEFAULT == LOWORD(wParam)) + { + ppsteps = ppstepsdefault; + UpdatePPSettings(); + SetupPPUIState(); + } + else if (ID_IMPORTSETTINGS_OPENPOST == LOWORD(wParam)) + { + ShellExecute(NULL,"open","http://assimp.sourceforge.net/lib_html/ai_post_process_8h.html","","",SW_SHOW); + } + else if (ID_TOOLS_ORIGINALNORMALS == LOWORD(wParam)) + { + if (g_pcAsset && g_pcAsset->pcScene) + { + g_pcAsset->SetNormalSet(AssimpView::AssetHelper::ORIGINAL); + CheckMenuItem(hMenu,ID_TOOLS_ORIGINALNORMALS,MF_BYCOMMAND | MF_CHECKED); + CheckMenuItem(hMenu,ID_TOOLS_HARDNORMALS,MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(hMenu,ID_TOOLS_SMOOTHNORMALS,MF_BYCOMMAND | MF_UNCHECKED); + } + } + + else if (ID_TOOLS_SMOOTHNORMALS == LOWORD(wParam)) + { + if (g_pcAsset && g_pcAsset->pcScene) + { + g_pcAsset->SetNormalSet(AssimpView::AssetHelper::SMOOTH); + CheckMenuItem(hMenu,ID_TOOLS_ORIGINALNORMALS,MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(hMenu,ID_TOOLS_HARDNORMALS,MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(hMenu,ID_TOOLS_SMOOTHNORMALS,MF_BYCOMMAND | MF_CHECKED); + } + } + else if (ID_TOOLS_HARDNORMALS == LOWORD(wParam)) + { + if (g_pcAsset && g_pcAsset->pcScene) + { + g_pcAsset->SetNormalSet(AssimpView::AssetHelper::HARD); + CheckMenuItem(hMenu,ID_TOOLS_ORIGINALNORMALS,MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(hMenu,ID_TOOLS_HARDNORMALS,MF_BYCOMMAND | MF_CHECKED); + CheckMenuItem(hMenu,ID_TOOLS_SMOOTHNORMALS,MF_BYCOMMAND | MF_UNCHECKED); + } + } + 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_TOOLS_SETANGLELIMIT == LOWORD(wParam)) + { + DialogBox(g_hInstance,MAKEINTRESOURCE(IDD_DIALOGSMOOTH),g_hDlg,&SMMessageProc); + } + else if (ID_VIEWER_CLEARHISTORY == LOWORD(wParam)) + { + ClearHistory(); + } + else if (ID_VIEWER_CLOSEASSET == LOWORD(wParam)) + { + DeleteAssetData(); + DeleteAsset(); + } + else if (BN_CLICKED == HIWORD(wParam)) + { + if (IDC_TOGGLEMS == LOWORD(wParam)) + { + ToggleMS(); + } + else if (IDC_TOGGLEMAT == LOWORD(wParam)) + { + ToggleMats(); + } + else if (IDC_LCOLOR1 == LOWORD(wParam)) + { + + if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode() || + CDisplay::VIEWMODE_MATERIAL == CDisplay::Instance().GetViewMode()) + { + // hey, I'm tired and yes, I KNOW IT IS EVIL! + DisplayColorDialog(const_cast<D3DXVECTOR4*>(CDisplay::Instance().GetFirstCheckerColor())); + SaveCheckerPatternColors(); + } + else + { + DisplayColorDialog(&g_avLightColors[0]); + SaveLightColors(); + } + InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR1),NULL,TRUE); + UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR1)); + } + else if (IDC_LCOLOR2 == LOWORD(wParam)) + { + if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode() || + CDisplay::VIEWMODE_MATERIAL == CDisplay::Instance().GetViewMode()) + { + // hey, I'm tired and yes, I KNOW IT IS EVIL! + DisplayColorDialog(const_cast<D3DXVECTOR4*>(CDisplay::Instance().GetSecondCheckerColor())); + SaveCheckerPatternColors(); + } + else + { + DisplayColorDialog(&g_avLightColors[1]); + SaveLightColors(); + } + InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR2),NULL,TRUE); + UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR2)); + } + 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)) + { + if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode() || + CDisplay::VIEWMODE_MATERIAL == CDisplay::Instance().GetViewMode()) + { + CDisplay::Instance().SetFirstCheckerColor(D3DXVECTOR4(0.4f,0.4f,0.4f,1.0f)); + CDisplay::Instance().SetSecondCheckerColor(D3DXVECTOR4(0.6f,0.6f,0.6f,1.0f)); + SaveCheckerPatternColors(); + } + else + { + 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); + SaveLightColors(); + } + + 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)); + } + else if (IDC_NOSPECULAR == LOWORD(wParam)) + { + ToggleSpecular(); + } + else if (IDC_NOAB == LOWORD(wParam)) + { + ToggleTransparency(); + } + else if (IDC_ZOOM == LOWORD(wParam)) + { + ToggleFPSView(); + } + else if (IDC_BLUBB == LOWORD(wParam)) + { + ToggleUIState(); + } + else if (IDC_TOGGLENORMALS == LOWORD(wParam)) + { + ToggleNormals(); + } + else if (IDC_LOWQUALITY == LOWORD(wParam)) + { + ToggleLowQuality(); + } + else if (IDC_3LIGHTS == LOWORD(wParam)) + { + ToggleMultipleLights(); + } + else if (IDC_LIGHTROTATE == LOWORD(wParam)) + { + ToggleLightRotate(); + } + else if (IDC_AUTOROTATE == LOWORD(wParam)) + { + ToggleAutoRotate(); + } + else if (IDC_TOGGLEWIRE == LOWORD(wParam)) + { + ToggleWireFrame(); + } + else if (IDC_SHOWSKELETON == LOWORD(wParam)) + { + ToggleSkeleton(); + } + else if (IDC_BFCULL == LOWORD(wParam)) + { + ToggleCulling(); + } + else if (IDC_PLAY == LOWORD(wParam)) + { + g_bPlay = !g_bPlay; + SetDlgItemText(g_hDlg,IDC_PLAY,(g_bPlay ? "Stop" : "Play")); + + if (g_bPlay) + EnableWindow(GetDlgItem(g_hDlg,IDC_SLIDERANIM),FALSE); + else EnableWindow(GetDlgItem(g_hDlg,IDC_SLIDERANIM),TRUE); + } + } + // 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(); + } + } + +#ifndef ASSIMP_BUILD_NO_EXPORT + if (LOWORD(wParam) >= AI_VIEW_EXPORT_FMT_BASE && LOWORD(wParam) < AI_VIEW_EXPORT_FMT_BASE+Assimp::Exporter().GetExportFormatCount()) { + DoExport(LOWORD(wParam) - AI_VIEW_EXPORT_FMT_BASE); + } +#endif + + // handle popup menus for the tree window + CDisplay::Instance().HandleTreeViewPopup(wParam,lParam); + + return TRUE; + }; + return FALSE; + } + + +//------------------------------------------------------------------------------- +// Message prcoedure for the progress dialog +//------------------------------------------------------------------------------- +INT_PTR CALLBACK ProgressMessageProc(HWND hwndDlg,UINT uMsg, + WPARAM wParam,LPARAM lParam) + { + UNREFERENCED_PARAMETER(lParam); + switch (uMsg) + { + case WM_INITDIALOG: + + SendDlgItemMessage(hwndDlg,IDC_PROGRESS,PBM_SETRANGE,0, + MAKELPARAM(0,500)); + + SetTimer(hwndDlg,0,40,NULL); + return TRUE; + + case WM_CLOSE: + EndDialog(hwndDlg,0); + return TRUE; + + case WM_COMMAND: + + if (IDOK == LOWORD(wParam)) + { +#if 0 + g_bLoadingCanceled = true; + TerminateThread(g_hThreadHandle,5); + g_pcAsset = NULL; + + EndDialog(hwndDlg,0); +#endif + + // PROBLEM: If we terminate the loader thread, ASSIMP's state + // is undefined. Any further attempts to load assets will + // fail. + exit(5); +// return TRUE; + } + case WM_TIMER: + + UINT iPos = (UINT)SendDlgItemMessage(hwndDlg,IDC_PROGRESS,PBM_GETPOS,0,0); + iPos += 10; + if (iPos > 490)iPos = 0; + SendDlgItemMessage(hwndDlg,IDC_PROGRESS,PBM_SETPOS,iPos,0); + + if (g_bLoadingFinished) + { + EndDialog(hwndDlg,0); + return TRUE; + } + + return TRUE; + } + return FALSE; + } + + +//------------------------------------------------------------------------------- +// Message procedure for the about dialog +//------------------------------------------------------------------------------- +INT_PTR CALLBACK AboutMessageProc(HWND hwndDlg,UINT uMsg, + WPARAM wParam,LPARAM lParam) + { + UNREFERENCED_PARAMETER(lParam); + switch (uMsg) + { + case WM_CLOSE: + EndDialog(hwndDlg,0); + return TRUE; + + case WM_COMMAND: + + if (IDOK == LOWORD(wParam)) + { + EndDialog(hwndDlg,0); + return TRUE; + } + } + return FALSE; + } +}; + +using namespace AssimpView; + +//------------------------------------------------------------------------------- +// Entry point to the application +//------------------------------------------------------------------------------- +int APIENTRY _tWinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPTSTR lpCmdLine, + int nCmdShow) + { + UNREFERENCED_PARAMETER(hPrevInstance); + UNREFERENCED_PARAMETER(lpCmdLine); + + // 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()) + { + MessageBox(NULL,"Failed to initialize Direct3D 9", + "ASSIMP ModelViewer",MB_OK); + return -6; + } + + // create the main dialog + HWND hDlg = CreateDialog(hInstance,MAKEINTRESOURCE(IDD_DIALOGMAIN), + NULL,&MessageProc); + + // ensure we get high priority + ::SetPriorityClass(GetCurrentProcess(),HIGH_PRIORITY_CLASS); + + // initialize the default logger if necessary + Assimp::DefaultLogger::create("",Assimp::Logger::VERBOSE); + + CLogWindow::Instance().pcStream = new CMyLogStream(); + Assimp::DefaultLogger::get()->attachStream(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", + "ASSIMP ModelViewer",MB_OK); + return -5; + } + + // display the window + g_hDlg = hDlg; + MSG uMsg; + memset(&uMsg,0,sizeof( MSG)); + ShowWindow( hDlg, nCmdShow ); + UpdateWindow( hDlg ); + + // 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; + } + CLogDisplay::Instance().AddEntry("[OK] Here we go!"); + + // create the log window + CLogWindow::Instance().Init(); + // set the focus to the main window + SetFocus(g_hDlg); + + // recover background skyboxes/textures from the last session + HKEY g_hRegistry; + union + { + char szFileName[MAX_PATH]; + D3DCOLOR clrColor; + }; + DWORD dwTemp = MAX_PATH; + RegCreateKeyEx(HKEY_CURRENT_USER, + "Software\\ASSIMP\\Viewer",0,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(g_hRegistry,"LastTextureSrc",NULL,NULL, + (BYTE*)szFileName,&dwTemp) && '\0' != szFileName[0]) + { + CBackgroundPainter::Instance().SetTextureBG(szFileName); + } + else if(ERROR_SUCCESS == RegQueryValueEx(g_hRegistry,"Color",NULL,NULL, + (BYTE*)&clrColor,&dwTemp)) + { + CBackgroundPainter::Instance().SetColor(clrColor); + } + RegCloseKey(g_hRegistry); + + // now handle command line arguments + HandleCommandLine(lpCmdLine); + + + double adLast[30]; + for (int i = 0; i < 30;++i)adLast[i] = 0.0f; + int iCurrent = 0; + + double g_dCurTime = 0; + double g_dLastTime = 0; + while( uMsg.message != WM_QUIT ) + { + if( PeekMessage( &uMsg, NULL, 0, 0, PM_REMOVE ) ) + { + TranslateMessage( &uMsg ); + DispatchMessage( &uMsg ); + + if (WM_CHAR == uMsg.message) + { + + switch ((char)uMsg.wParam) + { + case 'M': + case 'm': + + CheckDlgButton(g_hDlg,IDC_TOGGLEMS, + IsDlgButtonChecked(g_hDlg,IDC_TOGGLEMS) == BST_CHECKED + ? BST_UNCHECKED : BST_CHECKED); + + ToggleMS(); + break; + + case 'L': + case 'l': + + CheckDlgButton(g_hDlg,IDC_3LIGHTS, + IsDlgButtonChecked(g_hDlg,IDC_3LIGHTS) == BST_CHECKED + ? BST_UNCHECKED : BST_CHECKED); + + ToggleMultipleLights(); + break; + + case 'P': + case 'p': + + CheckDlgButton(g_hDlg,IDC_LOWQUALITY, + IsDlgButtonChecked(g_hDlg,IDC_LOWQUALITY) == BST_CHECKED + ? BST_UNCHECKED : BST_CHECKED); + + ToggleLowQuality(); + break; + + case 'D': + case 'd': + + CheckDlgButton(g_hDlg,IDC_TOGGLEMAT, + IsDlgButtonChecked(g_hDlg,IDC_TOGGLEMAT) == BST_CHECKED + ? BST_UNCHECKED : BST_CHECKED); + + ToggleMats(); + break; + + + case 'N': + case 'n': + + CheckDlgButton(g_hDlg,IDC_TOGGLENORMALS, + IsDlgButtonChecked(g_hDlg,IDC_TOGGLENORMALS) == BST_CHECKED + ? BST_UNCHECKED : BST_CHECKED); + ToggleNormals(); + break; + + + case 'S': + case 's': + + CheckDlgButton(g_hDlg,IDC_NOSPECULAR, + IsDlgButtonChecked(g_hDlg,IDC_NOSPECULAR) == BST_CHECKED + ? BST_UNCHECKED : BST_CHECKED); + + ToggleSpecular(); + break; + + case 'A': + case 'a': + + CheckDlgButton(g_hDlg,IDC_AUTOROTATE, + IsDlgButtonChecked(g_hDlg,IDC_AUTOROTATE) == BST_CHECKED + ? BST_UNCHECKED : BST_CHECKED); + + ToggleAutoRotate(); + break; + + + case 'R': + case 'r': + + CheckDlgButton(g_hDlg,IDC_LIGHTROTATE, + IsDlgButtonChecked(g_hDlg,IDC_LIGHTROTATE) == BST_CHECKED + ? BST_UNCHECKED : BST_CHECKED); + + ToggleLightRotate(); + break; + + case 'Z': + case 'z': + + CheckDlgButton(g_hDlg,IDC_ZOOM, + IsDlgButtonChecked(g_hDlg,IDC_ZOOM) == BST_CHECKED + ? BST_UNCHECKED : BST_CHECKED); + + ToggleFPSView(); + break; + + + case 'W': + case 'w': + + CheckDlgButton(g_hDlg,IDC_TOGGLEWIRE, + IsDlgButtonChecked(g_hDlg,IDC_TOGGLEWIRE) == BST_CHECKED + ? BST_UNCHECKED : BST_CHECKED); + + ToggleWireFrame(); + break; + + case 'K': + case 'k': + + CheckDlgButton(g_hDlg,IDC_SHOWSKELETON, + IsDlgButtonChecked(g_hDlg,IDC_SHOWSKELETON) == BST_CHECKED + ? BST_UNCHECKED : BST_CHECKED); + + ToggleSkeleton(); + break; + + case 'C': + case 'c': + + CheckDlgButton(g_hDlg,IDC_BFCULL, + IsDlgButtonChecked(g_hDlg,IDC_BFCULL) == BST_CHECKED + ? BST_UNCHECKED : BST_CHECKED); + + ToggleCulling(); + break; + + case 'T': + case 't': + + CheckDlgButton(g_hDlg,IDC_NOAB, + IsDlgButtonChecked(g_hDlg,IDC_NOAB) == BST_CHECKED + ? BST_UNCHECKED : BST_CHECKED); + + ToggleTransparency(); + break; + } + } + } + + + // render the scene + CDisplay::Instance().OnRender(); + + + // measure FPS, average it out + g_dCurTime = timeGetTime(); + g_fElpasedTime = (float)((g_dCurTime - g_dLastTime) * 0.001); + g_dLastTime = g_dCurTime; + + adLast[iCurrent++] = 1.0f / g_fElpasedTime; + + double dFPS = 0.0; + for (int i = 0;i < 30;++i) + dFPS += adLast[i]; + dFPS /= 30.0; + + if (30 == iCurrent) + { + iCurrent = 0; + if (dFPS != g_fFPS) + { + g_fFPS = dFPS; + char szOut[256]; + + sprintf(szOut,"%i",(int)floorf((float)dFPS+0.5f)); + SetDlgItemText(g_hDlg,IDC_EFPS,szOut); + } + } + } + DeleteAsset(); + Assimp::DefaultLogger::kill(); + ShutdownDevice(); + ShutdownD3D(); + return 0; + } \ No newline at end of file diff --git a/tools/assimp_view/NOTE@help.rtf.txt b/tools/assimp_view/NOTE@help.rtf.txt index 26eb96510..f00962db6 100644 --- a/tools/assimp_view/NOTE@help.rtf.txt +++ b/tools/assimp_view/NOTE@help.rtf.txt @@ -1,2 +1,2 @@ -text1.bin is the corresponding bin file to be included with the executable file. +text1.bin is the corresponding bin file to be included with the executable file. When updating the rich formatted text inside Visual Studio, a terminating 0 character must be appended \ No newline at end of file diff --git a/tools/assimp_view/Normals.cpp b/tools/assimp_view/Normals.cpp index f87eccf95..240825905 100644 --- a/tools/assimp_view/Normals.cpp +++ b/tools/assimp_view/Normals.cpp @@ -1,175 +1,175 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2015, assimp 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 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 "assimp_view.h" - -// note: these are no longer part of the public API, but they are -// exported on Windows to keep AssimpView alive. -#include "GenFaceNormalsProcess.h" -#include "GenVertexNormalsProcess.h" -#include "JoinVerticesProcess.h" -#include "CalcTangentsProcess.h" -#include "MakeVerboseFormat.h" - -namespace AssimpView { - -using namespace Assimp; - -bool g_bWasFlipped = false; -float g_smoothAngle = 80.f; - -//------------------------------------------------------------------------------- -// Flip all normal vectors -//------------------------------------------------------------------------------- -void AssetHelper::FlipNormalsInt() -{ - // invert all normal vectors - for (unsigned int i = 0; i < this->pcScene->mNumMeshes;++i) - { - aiMesh* pcMesh = this->pcScene->mMeshes[i]; - - if (!pcMesh->mNormals) - continue; - - for (unsigned int a = 0; a < pcMesh->mNumVertices;++a){ - pcMesh->mNormals[a] *= -1.0f; - } - } -} - -//------------------------------------------------------------------------------- -void AssetHelper::FlipNormals() -{ - FlipNormalsInt(); - - // recreate native data - DeleteAssetData(true); - CreateAssetData(); - g_bWasFlipped = ! g_bWasFlipped; -} - -//------------------------------------------------------------------------------- -// Set the normal set of the scene -//------------------------------------------------------------------------------- -void AssetHelper::SetNormalSet(unsigned int iSet) -{ - // we need to build an unique set of vertices for this ... - { - MakeVerboseFormatProcess* pcProcess = new MakeVerboseFormatProcess(); - pcProcess->Execute(pcScene); - delete pcProcess; - - for (unsigned int i = 0; i < pcScene->mNumMeshes;++i) - { - if (!apcMeshes[i]->pvOriginalNormals) - { - apcMeshes[i]->pvOriginalNormals = new aiVector3D[pcScene->mMeshes[i]->mNumVertices]; - memcpy( apcMeshes[i]->pvOriginalNormals,pcScene->mMeshes[i]->mNormals, - pcScene->mMeshes[i]->mNumVertices * sizeof(aiVector3D)); - } - delete[] pcScene->mMeshes[i]->mNormals; - pcScene->mMeshes[i]->mNormals = NULL; - } - } - - - // now we can start to calculate a new set of normals - if (HARD == iSet) - { - GenFaceNormalsProcess* pcProcess = new GenFaceNormalsProcess(); - pcProcess->Execute(pcScene); - FlipNormalsInt(); - delete pcProcess; - } - else if (SMOOTH == iSet) - { - GenVertexNormalsProcess* pcProcess = new GenVertexNormalsProcess(); - pcProcess->SetMaxSmoothAngle((float)AI_DEG_TO_RAD(g_smoothAngle)); - pcProcess->Execute(pcScene); - FlipNormalsInt(); - delete pcProcess; - } - else if (ORIGINAL == iSet) - { - for (unsigned int i = 0; i < pcScene->mNumMeshes;++i) - { - if (apcMeshes[i]->pvOriginalNormals) - { - delete[] pcScene->mMeshes[i]->mNormals; - pcScene->mMeshes[i]->mNormals = apcMeshes[i]->pvOriginalNormals; - apcMeshes[i]->pvOriginalNormals = NULL; - } - } - } - - // recalculate tangents and bitangents - Assimp::BaseProcess* pcProcess = new CalcTangentsProcess(); - pcProcess->Execute(pcScene); - delete pcProcess; - - // join the mesh vertices again - pcProcess = new JoinVerticesProcess(); - pcProcess->Execute(pcScene); - delete pcProcess; - - iNormalSet = iSet; - - if (g_bWasFlipped) - { - // invert all normal vectors - for (unsigned int i = 0; i < pcScene->mNumMeshes;++i) - { - aiMesh* pcMesh = pcScene->mMeshes[i]; - for (unsigned int a = 0; a < pcMesh->mNumVertices;++a) - { - pcMesh->mNormals[a] *= -1.0f; - } - } - } - - // recreate native data - DeleteAssetData(true); - CreateAssetData(); - return; -} - +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2015, assimp 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 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 "assimp_view.h" + +// note: these are no longer part of the public API, but they are +// exported on Windows to keep AssimpView alive. +#include "GenFaceNormalsProcess.h" +#include "GenVertexNormalsProcess.h" +#include "JoinVerticesProcess.h" +#include "CalcTangentsProcess.h" +#include "MakeVerboseFormat.h" + +namespace AssimpView { + +using namespace Assimp; + +bool g_bWasFlipped = false; +float g_smoothAngle = 80.f; + +//------------------------------------------------------------------------------- +// Flip all normal vectors +//------------------------------------------------------------------------------- +void AssetHelper::FlipNormalsInt() +{ + // invert all normal vectors + for (unsigned int i = 0; i < this->pcScene->mNumMeshes;++i) + { + aiMesh* pcMesh = this->pcScene->mMeshes[i]; + + if (!pcMesh->mNormals) + continue; + + for (unsigned int a = 0; a < pcMesh->mNumVertices;++a){ + pcMesh->mNormals[a] *= -1.0f; + } + } +} + +//------------------------------------------------------------------------------- +void AssetHelper::FlipNormals() +{ + FlipNormalsInt(); + + // recreate native data + DeleteAssetData(true); + CreateAssetData(); + g_bWasFlipped = ! g_bWasFlipped; +} + +//------------------------------------------------------------------------------- +// Set the normal set of the scene +//------------------------------------------------------------------------------- +void AssetHelper::SetNormalSet(unsigned int iSet) +{ + // we need to build an unique set of vertices for this ... + { + MakeVerboseFormatProcess* pcProcess = new MakeVerboseFormatProcess(); + pcProcess->Execute(pcScene); + delete pcProcess; + + for (unsigned int i = 0; i < pcScene->mNumMeshes;++i) + { + if (!apcMeshes[i]->pvOriginalNormals) + { + apcMeshes[i]->pvOriginalNormals = new aiVector3D[pcScene->mMeshes[i]->mNumVertices]; + memcpy( apcMeshes[i]->pvOriginalNormals,pcScene->mMeshes[i]->mNormals, + pcScene->mMeshes[i]->mNumVertices * sizeof(aiVector3D)); + } + delete[] pcScene->mMeshes[i]->mNormals; + pcScene->mMeshes[i]->mNormals = NULL; + } + } + + + // now we can start to calculate a new set of normals + if (HARD == iSet) + { + GenFaceNormalsProcess* pcProcess = new GenFaceNormalsProcess(); + pcProcess->Execute(pcScene); + FlipNormalsInt(); + delete pcProcess; + } + else if (SMOOTH == iSet) + { + GenVertexNormalsProcess* pcProcess = new GenVertexNormalsProcess(); + pcProcess->SetMaxSmoothAngle((float)AI_DEG_TO_RAD(g_smoothAngle)); + pcProcess->Execute(pcScene); + FlipNormalsInt(); + delete pcProcess; + } + else if (ORIGINAL == iSet) + { + for (unsigned int i = 0; i < pcScene->mNumMeshes;++i) + { + if (apcMeshes[i]->pvOriginalNormals) + { + delete[] pcScene->mMeshes[i]->mNormals; + pcScene->mMeshes[i]->mNormals = apcMeshes[i]->pvOriginalNormals; + apcMeshes[i]->pvOriginalNormals = NULL; + } + } + } + + // recalculate tangents and bitangents + Assimp::BaseProcess* pcProcess = new CalcTangentsProcess(); + pcProcess->Execute(pcScene); + delete pcProcess; + + // join the mesh vertices again + pcProcess = new JoinVerticesProcess(); + pcProcess->Execute(pcScene); + delete pcProcess; + + iNormalSet = iSet; + + if (g_bWasFlipped) + { + // invert all normal vectors + for (unsigned int i = 0; i < pcScene->mNumMeshes;++i) + { + aiMesh* pcMesh = 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 863064d72..73468f11a 100644 --- a/tools/assimp_view/RenderOptions.h +++ b/tools/assimp_view/RenderOptions.h @@ -1,113 +1,113 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2012, assimp 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 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_RO_H_INCLUDED) -#define AV_RO_H_INCLUDED - - -//------------------------------------------------------------------------------- -/** \brief Class to manage render options. One global instance -*/ -//------------------------------------------------------------------------------- -class RenderOptions - { - public: - - // enumerates different drawing modi. POINT is currently - // not supported and probably will never be. - enum DrawMode {NORMAL, WIREFRAME, POINT}; - - inline RenderOptions (void) : - bMultiSample (true), - bSuperSample (false), - bRenderMats (true), - bRenderNormals (false), - b3Lights (false), - bLightRotate (false), - bRotate (true), - bLowQuality (false), - bNoSpecular (false), - bStereoView (false), - bNoAlphaBlending(false), - eDrawMode (NORMAL), - bCulling (false), - bSkeleton (false) - - {} - - bool bMultiSample; - - // SuperSampling has not yet been implemented - bool bSuperSample; - - // Display the real material of the object - bool bRenderMats; - - // Render the normals - bool bRenderNormals; - - // Use 2 directional light sources - bool b3Lights; - - // Automatically rotate the light source(s) - bool bLightRotate; - - // Automatically rotate the asset around its origin - bool bRotate; - - // use standard lambertian lighting - bool bLowQuality; - - // disable specular lighting got all elements in the scene - bool bNoSpecular; - - // enable stereo view - bool bStereoView; - - bool bNoAlphaBlending; - - // wireframe or solid rendering? - DrawMode eDrawMode; - - bool bCulling,bSkeleton; - }; - +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2012, assimp 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 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_RO_H_INCLUDED) +#define AV_RO_H_INCLUDED + + +//------------------------------------------------------------------------------- +/** \brief Class to manage render options. One global instance +*/ +//------------------------------------------------------------------------------- +class RenderOptions + { + public: + + // enumerates different drawing modi. POINT is currently + // not supported and probably will never be. + enum DrawMode {NORMAL, WIREFRAME, POINT}; + + inline RenderOptions (void) : + bMultiSample (true), + bSuperSample (false), + bRenderMats (true), + bRenderNormals (false), + b3Lights (false), + bLightRotate (false), + bRotate (true), + bLowQuality (false), + bNoSpecular (false), + bStereoView (false), + bNoAlphaBlending(false), + eDrawMode (NORMAL), + bCulling (false), + bSkeleton (false) + + {} + + bool bMultiSample; + + // SuperSampling has not yet been implemented + bool bSuperSample; + + // Display the real material of the object + bool bRenderMats; + + // Render the normals + bool bRenderNormals; + + // Use 2 directional light sources + bool b3Lights; + + // Automatically rotate the light source(s) + bool bLightRotate; + + // Automatically rotate the asset around its origin + bool bRotate; + + // use standard lambertian lighting + bool bLowQuality; + + // disable specular lighting got all elements in the scene + bool bNoSpecular; + + // enable stereo view + bool bStereoView; + + bool bNoAlphaBlending; + + // wireframe or solid rendering? + DrawMode eDrawMode; + + bool bCulling,bSkeleton; + }; + #endif // !! IG \ No newline at end of file diff --git a/tools/assimp_view/SceneAnimator.cpp b/tools/assimp_view/SceneAnimator.cpp index 8cfac68e5..6e507cb41 100644 --- a/tools/assimp_view/SceneAnimator.cpp +++ b/tools/assimp_view/SceneAnimator.cpp @@ -1,245 +1,245 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2015, assimp 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 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 SceneAnimator.cpp - * @brief Implementation of the utility class SceneAnimator - */ - -#include "assimp_view.h" - -using namespace AssimpView; - -// ------------------------------------------------------------------------------------------------ -// Constructor for a given scene. -SceneAnimator::SceneAnimator( const aiScene* pScene, size_t pAnimIndex) -{ - mScene = pScene; - mCurrentAnimIndex = -1; - mAnimEvaluator = NULL; - mRootNode = NULL; - - // build the nodes-for-bones table - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) - { - const aiMesh* mesh = pScene->mMeshes[i]; - for (unsigned int n = 0; n < mesh->mNumBones;++n) - { - const aiBone* bone = mesh->mBones[n]; - - mBoneNodesByName[bone->mName.data] = pScene->mRootNode->FindNode(bone->mName); - } - } - - // changing the current animation also creates the node tree for this animation - SetAnimIndex( pAnimIndex); -} - -// ------------------------------------------------------------------------------------------------ -// Destructor -SceneAnimator::~SceneAnimator() -{ - delete mRootNode; - delete mAnimEvaluator; -} - -// ------------------------------------------------------------------------------------------------ -// Sets the animation to use for playback. -void SceneAnimator::SetAnimIndex( size_t pAnimIndex) -{ - // no change - if( pAnimIndex == mCurrentAnimIndex) - return; - - // kill data of the previous anim - delete mRootNode; mRootNode = NULL; - delete mAnimEvaluator; mAnimEvaluator = NULL; - mNodesByName.clear(); - - mCurrentAnimIndex = pAnimIndex; - - // create the internal node tree. Do this even in case of invalid animation index - // so that the transformation matrices are properly set up to mimic the current scene - mRootNode = CreateNodeTree( mScene->mRootNode, NULL); - - // invalid anim index - if( mCurrentAnimIndex >= mScene->mNumAnimations) - return; - - // create an evaluator for this animation - mAnimEvaluator = new AnimEvaluator( mScene->mAnimations[mCurrentAnimIndex]); -} - -// ------------------------------------------------------------------------------------------------ -// Calculates the node transformations for the scene. -void SceneAnimator::Calculate( double pTime) -{ - // invalid anim - if( !mAnimEvaluator) - return; - - // calculate current local transformations - mAnimEvaluator->Evaluate( pTime); - - // and update all node transformations with the results - UpdateTransforms( mRootNode, mAnimEvaluator->GetTransformations()); -} - -// ------------------------------------------------------------------------------------------------ -// Retrieves the most recent local transformation matrix for the given node. -const aiMatrix4x4& SceneAnimator::GetLocalTransform( const aiNode* node) const -{ - NodeMap::const_iterator it = mNodesByName.find( node); - if( it == mNodesByName.end()) - return mIdentityMatrix; - - return it->second->mLocalTransform; -} - -// ------------------------------------------------------------------------------------------------ -// Retrieves the most recent global transformation matrix for the given node. -const aiMatrix4x4& SceneAnimator::GetGlobalTransform( const aiNode* node) const -{ - NodeMap::const_iterator it = mNodesByName.find( node); - if( it == mNodesByName.end()) - return mIdentityMatrix; - - return it->second->mGlobalTransform; -} - -// ------------------------------------------------------------------------------------------------ -// Calculates the bone matrices for the given mesh. -const std::vector<aiMatrix4x4>& SceneAnimator::GetBoneMatrices( const aiNode* pNode, size_t pMeshIndex /* = 0 */) -{ - ai_assert( pMeshIndex < pNode->mNumMeshes); - size_t meshIndex = pNode->mMeshes[pMeshIndex]; - ai_assert( meshIndex < mScene->mNumMeshes); - const aiMesh* mesh = mScene->mMeshes[meshIndex]; - - // resize array and initialise it with identity matrices - mTransforms.resize( mesh->mNumBones, aiMatrix4x4()); - - // calculate the mesh's inverse global transform - aiMatrix4x4 globalInverseMeshTransform = GetGlobalTransform( pNode); - globalInverseMeshTransform.Inverse(); - - // Bone matrices transform from mesh coordinates in bind pose to mesh coordinates in skinned pose - // Therefore the formula is offsetMatrix * currentGlobalTransform * inverseCurrentMeshTransform - for( size_t a = 0; a < mesh->mNumBones; ++a) - { - const aiBone* bone = mesh->mBones[a]; - const aiMatrix4x4& currentGlobalTransform = GetGlobalTransform( mBoneNodesByName[ bone->mName.data ]); - mTransforms[a] = globalInverseMeshTransform * currentGlobalTransform * bone->mOffsetMatrix; - } - - // and return the result - return mTransforms; -} - -// ------------------------------------------------------------------------------------------------ -// Recursively creates an internal node structure matching the current scene and animation. -SceneAnimNode* SceneAnimator::CreateNodeTree( aiNode* pNode, SceneAnimNode* pParent) -{ - // create a node - SceneAnimNode* internalNode = new SceneAnimNode( pNode->mName.data); - internalNode->mParent = pParent; - mNodesByName[pNode] = internalNode; - - // copy its transformation - internalNode->mLocalTransform = pNode->mTransformation; - CalculateGlobalTransform( internalNode); - - // find the index of the animation track affecting this node, if any - if( mCurrentAnimIndex < mScene->mNumAnimations) - { - internalNode->mChannelIndex = -1; - const aiAnimation* currentAnim = mScene->mAnimations[mCurrentAnimIndex]; - for( unsigned int a = 0; a < currentAnim->mNumChannels; a++) - { - if( currentAnim->mChannels[a]->mNodeName.data == internalNode->mName) - { - internalNode->mChannelIndex = a; - break; - } - } - } - - // continue for all child nodes and assign the created internal nodes as our children - for( unsigned int a = 0; a < pNode->mNumChildren; a++) - { - SceneAnimNode* childNode = CreateNodeTree( pNode->mChildren[a], internalNode); - internalNode->mChildren.push_back( childNode); - } - - return internalNode; -} - -// ------------------------------------------------------------------------------------------------ -// Recursively updates the internal node transformations from the given matrix array -void SceneAnimator::UpdateTransforms( SceneAnimNode* pNode, const std::vector<aiMatrix4x4>& pTransforms) -{ - // update node local transform - if( pNode->mChannelIndex != -1) - { - ai_assert( pNode->mChannelIndex < pTransforms.size()); - pNode->mLocalTransform = pTransforms[pNode->mChannelIndex]; - } - - // update global transform as well - CalculateGlobalTransform( pNode); - - // continue for all children - for( std::vector<SceneAnimNode*>::iterator it = pNode->mChildren.begin(); it != pNode->mChildren.end(); ++it) - UpdateTransforms( *it, pTransforms); -} - -// ------------------------------------------------------------------------------------------------ -// Calculates the global transformation matrix for the given internal node -void SceneAnimator::CalculateGlobalTransform( SceneAnimNode* pInternalNode) -{ - // concatenate all parent transforms to get the global transform for this node - pInternalNode->mGlobalTransform = pInternalNode->mLocalTransform; - SceneAnimNode* node = pInternalNode->mParent; - while( node) - { - pInternalNode->mGlobalTransform = node->mLocalTransform * pInternalNode->mGlobalTransform; - node = node->mParent; - } -} +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2015, assimp 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 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 SceneAnimator.cpp + * @brief Implementation of the utility class SceneAnimator + */ + +#include "assimp_view.h" + +using namespace AssimpView; + +// ------------------------------------------------------------------------------------------------ +// Constructor for a given scene. +SceneAnimator::SceneAnimator( const aiScene* pScene, size_t pAnimIndex) +{ + mScene = pScene; + mCurrentAnimIndex = -1; + mAnimEvaluator = NULL; + mRootNode = NULL; + + // build the nodes-for-bones table + for (unsigned int i = 0; i < pScene->mNumMeshes;++i) + { + const aiMesh* mesh = pScene->mMeshes[i]; + for (unsigned int n = 0; n < mesh->mNumBones;++n) + { + const aiBone* bone = mesh->mBones[n]; + + mBoneNodesByName[bone->mName.data] = pScene->mRootNode->FindNode(bone->mName); + } + } + + // changing the current animation also creates the node tree for this animation + SetAnimIndex( pAnimIndex); +} + +// ------------------------------------------------------------------------------------------------ +// Destructor +SceneAnimator::~SceneAnimator() +{ + delete mRootNode; + delete mAnimEvaluator; +} + +// ------------------------------------------------------------------------------------------------ +// Sets the animation to use for playback. +void SceneAnimator::SetAnimIndex( size_t pAnimIndex) +{ + // no change + if( pAnimIndex == mCurrentAnimIndex) + return; + + // kill data of the previous anim + delete mRootNode; mRootNode = NULL; + delete mAnimEvaluator; mAnimEvaluator = NULL; + mNodesByName.clear(); + + mCurrentAnimIndex = pAnimIndex; + + // create the internal node tree. Do this even in case of invalid animation index + // so that the transformation matrices are properly set up to mimic the current scene + mRootNode = CreateNodeTree( mScene->mRootNode, NULL); + + // invalid anim index + if( mCurrentAnimIndex >= mScene->mNumAnimations) + return; + + // create an evaluator for this animation + mAnimEvaluator = new AnimEvaluator( mScene->mAnimations[mCurrentAnimIndex]); +} + +// ------------------------------------------------------------------------------------------------ +// Calculates the node transformations for the scene. +void SceneAnimator::Calculate( double pTime) +{ + // invalid anim + if( !mAnimEvaluator) + return; + + // calculate current local transformations + mAnimEvaluator->Evaluate( pTime); + + // and update all node transformations with the results + UpdateTransforms( mRootNode, mAnimEvaluator->GetTransformations()); +} + +// ------------------------------------------------------------------------------------------------ +// Retrieves the most recent local transformation matrix for the given node. +const aiMatrix4x4& SceneAnimator::GetLocalTransform( const aiNode* node) const +{ + NodeMap::const_iterator it = mNodesByName.find( node); + if( it == mNodesByName.end()) + return mIdentityMatrix; + + return it->second->mLocalTransform; +} + +// ------------------------------------------------------------------------------------------------ +// Retrieves the most recent global transformation matrix for the given node. +const aiMatrix4x4& SceneAnimator::GetGlobalTransform( const aiNode* node) const +{ + NodeMap::const_iterator it = mNodesByName.find( node); + if( it == mNodesByName.end()) + return mIdentityMatrix; + + return it->second->mGlobalTransform; +} + +// ------------------------------------------------------------------------------------------------ +// Calculates the bone matrices for the given mesh. +const std::vector<aiMatrix4x4>& SceneAnimator::GetBoneMatrices( const aiNode* pNode, size_t pMeshIndex /* = 0 */) +{ + ai_assert( pMeshIndex < pNode->mNumMeshes); + size_t meshIndex = pNode->mMeshes[pMeshIndex]; + ai_assert( meshIndex < mScene->mNumMeshes); + const aiMesh* mesh = mScene->mMeshes[meshIndex]; + + // resize array and initialise it with identity matrices + mTransforms.resize( mesh->mNumBones, aiMatrix4x4()); + + // calculate the mesh's inverse global transform + aiMatrix4x4 globalInverseMeshTransform = GetGlobalTransform( pNode); + globalInverseMeshTransform.Inverse(); + + // Bone matrices transform from mesh coordinates in bind pose to mesh coordinates in skinned pose + // Therefore the formula is offsetMatrix * currentGlobalTransform * inverseCurrentMeshTransform + for( size_t a = 0; a < mesh->mNumBones; ++a) + { + const aiBone* bone = mesh->mBones[a]; + const aiMatrix4x4& currentGlobalTransform = GetGlobalTransform( mBoneNodesByName[ bone->mName.data ]); + mTransforms[a] = globalInverseMeshTransform * currentGlobalTransform * bone->mOffsetMatrix; + } + + // and return the result + return mTransforms; +} + +// ------------------------------------------------------------------------------------------------ +// Recursively creates an internal node structure matching the current scene and animation. +SceneAnimNode* SceneAnimator::CreateNodeTree( aiNode* pNode, SceneAnimNode* pParent) +{ + // create a node + SceneAnimNode* internalNode = new SceneAnimNode( pNode->mName.data); + internalNode->mParent = pParent; + mNodesByName[pNode] = internalNode; + + // copy its transformation + internalNode->mLocalTransform = pNode->mTransformation; + CalculateGlobalTransform( internalNode); + + // find the index of the animation track affecting this node, if any + if( mCurrentAnimIndex < mScene->mNumAnimations) + { + internalNode->mChannelIndex = -1; + const aiAnimation* currentAnim = mScene->mAnimations[mCurrentAnimIndex]; + for( unsigned int a = 0; a < currentAnim->mNumChannels; a++) + { + if( currentAnim->mChannels[a]->mNodeName.data == internalNode->mName) + { + internalNode->mChannelIndex = a; + break; + } + } + } + + // continue for all child nodes and assign the created internal nodes as our children + for( unsigned int a = 0; a < pNode->mNumChildren; a++) + { + SceneAnimNode* childNode = CreateNodeTree( pNode->mChildren[a], internalNode); + internalNode->mChildren.push_back( childNode); + } + + return internalNode; +} + +// ------------------------------------------------------------------------------------------------ +// Recursively updates the internal node transformations from the given matrix array +void SceneAnimator::UpdateTransforms( SceneAnimNode* pNode, const std::vector<aiMatrix4x4>& pTransforms) +{ + // update node local transform + if( pNode->mChannelIndex != -1) + { + ai_assert( pNode->mChannelIndex < pTransforms.size()); + pNode->mLocalTransform = pTransforms[pNode->mChannelIndex]; + } + + // update global transform as well + CalculateGlobalTransform( pNode); + + // continue for all children + for( std::vector<SceneAnimNode*>::iterator it = pNode->mChildren.begin(); it != pNode->mChildren.end(); ++it) + UpdateTransforms( *it, pTransforms); +} + +// ------------------------------------------------------------------------------------------------ +// Calculates the global transformation matrix for the given internal node +void SceneAnimator::CalculateGlobalTransform( SceneAnimNode* pInternalNode) +{ + // concatenate all parent transforms to get the global transform for this node + pInternalNode->mGlobalTransform = pInternalNode->mLocalTransform; + SceneAnimNode* node = pInternalNode->mParent; + while( node) + { + pInternalNode->mGlobalTransform = node->mLocalTransform * pInternalNode->mGlobalTransform; + node = node->mParent; + } +} diff --git a/tools/assimp_view/SceneAnimator.h b/tools/assimp_view/SceneAnimator.h index 4c9c012b8..ba79b4faa 100644 --- a/tools/assimp_view/SceneAnimator.h +++ b/tools/assimp_view/SceneAnimator.h @@ -1,243 +1,243 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2012, assimp 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 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 SceneAnimator.h - * Manages animations for a given scene and calculates present - * transformations for all nodes - */ - -#ifndef AV_SCENEANIMATOR_H_INCLUDED -#define AV_SCENEANIMATOR_H_INCLUDED - -#include <map> - -namespace AssimpView { - -// --------------------------------------------------------------------------------- -/** A little tree structure to match the scene's node structure, but holding - * additional data. Needs to be public to allow using it in templates at - * certain compilers. - */ -struct SceneAnimNode -{ - std::string mName; - SceneAnimNode* mParent; - std::vector<SceneAnimNode*> mChildren; - - //! most recently calculated local transform - aiMatrix4x4 mLocalTransform; - - //! same, but in world space - aiMatrix4x4 mGlobalTransform; - - //! index in the current animation's channel array. -1 if not animated. - size_t mChannelIndex; - - //! Default construction - SceneAnimNode() { - mChannelIndex = -1; mParent = NULL; - } - - //! Construction from a given name - SceneAnimNode( const std::string& pName) - : mName( pName) { - mChannelIndex = -1; mParent = NULL; - } - - //! Destruct all children recursively - ~SceneAnimNode() { - for( std::vector<SceneAnimNode*>::iterator it = mChildren.begin(); it != mChildren.end(); ++it) - delete *it; - } -}; - -// --------------------------------------------------------------------------------- -/** Calculates the animated node transformations for a given scene and timestamp. - * - * Create an instance for a aiScene you want to animate and set the current animation - * to play. You can then have the instance calculate the current pose for all nodes - * by calling Calculate() for a given timestamp. After this you can retrieve the - * present transformation for a given node by calling GetLocalTransform() or - * GetGlobalTransform(). A full set of bone matrices can be retrieved by - * GetBoneMatrices() for a given mesh. - */ -class SceneAnimator -{ -public: - - // ---------------------------------------------------------------------------- - /** Constructor for a given scene. - * - * The object keeps a reference to the scene during its lifetime, but - * ownership stays at the caller. - * @param pScene The scene to animate. - * @param pAnimIndex [optional] Index of the animation to play. Assumed to - * be 0 if not given. - */ - SceneAnimator( const aiScene* pScene, size_t pAnimIndex = 0); - - /** Destructor */ - ~SceneAnimator(); - - // ---------------------------------------------------------------------------- - /** Sets the animation to use for playback. This also recreates the internal - * mapping structures, which might take a few cycles. - * @param pAnimIndex Index of the animation in the scene's animation array - */ - void SetAnimIndex( size_t pAnimIndex); - - // ---------------------------------------------------------------------------- - /** Calculates the node transformations for the scene. Call this to get - * uptodate results before calling one of the getters. - * @param pTime Current time. Can be an arbitrary range. - */ - void Calculate( double pTime); - - // ---------------------------------------------------------------------------- - /** Retrieves the most recent local transformation matrix for the given node. - * - * The returned matrix is in the node's parent's local space, just like the - * original node's transformation matrix. If the node is not animated, the - * node's original transformation is returned so that you can safely use or - * assign it to the node itsself. If there is no node with the given name, - * the identity matrix is returned. All transformations are updated whenever - * Calculate() is called. - * @param pNodeName Name of the node - * @return A reference to the node's most recently calculated local - * transformation matrix. - */ - const aiMatrix4x4& GetLocalTransform( const aiNode* node) const; - - // ---------------------------------------------------------------------------- - /** Retrieves the most recent global transformation matrix for the given node. - * - * The returned matrix is in world space, which is the same coordinate space - * as the transformation of the scene's root node. If the node is not animated, - * the node's original transformation is returned so that you can safely use or - * assign it to the node itsself. If there is no node with the given name, the - * identity matrix is returned. All transformations are updated whenever - * Calculate() is called. - * @param pNodeName Name of the node - * @return A reference to the node's most recently calculated global - * transformation matrix. - */ - const aiMatrix4x4& GetGlobalTransform( const aiNode* node) const; - - // ---------------------------------------------------------------------------- - /** Calculates the bone matrices for the given mesh. - * - * Each bone matrix transforms from mesh space in bind pose to mesh space in - * skinned pose, it does not contain the mesh's world matrix. Thus the usual - * matrix chain for using in the vertex shader is - * @code - * boneMatrix * worldMatrix * viewMatrix * projMatrix - * @endcode - * @param pNode The node carrying the mesh. - * @param pMeshIndex Index of the mesh in the node's mesh array. The NODE's - * mesh array, not the scene's mesh array! Leave out to use the first mesh - * of the node, which is usually also the only one. - * @return A reference to a vector of bone matrices. Stays stable till the - * next call to GetBoneMatrices(); - */ - const std::vector<aiMatrix4x4>& GetBoneMatrices( const aiNode* pNode, - size_t pMeshIndex = 0); - - - // ---------------------------------------------------------------------------- - /** @brief Get the current animation index - */ - size_t CurrentAnimIndex() const { - return mCurrentAnimIndex; - } - - // ---------------------------------------------------------------------------- - /** @brief Get the current animation or NULL - */ - aiAnimation* CurrentAnim() const { - return mCurrentAnimIndex < mScene->mNumAnimations ? mScene->mAnimations[ mCurrentAnimIndex ] : NULL; - } - -protected: - - /** Recursively creates an internal node structure matching the - * current scene and animation. - */ - SceneAnimNode* CreateNodeTree( aiNode* pNode, SceneAnimNode* pParent); - - /** Recursively updates the internal node transformations from the - * given matrix array - */ - void UpdateTransforms( SceneAnimNode* pNode, const std::vector<aiMatrix4x4>& pTransforms); - - /** Calculates the global transformation matrix for the given internal node */ - void CalculateGlobalTransform( SceneAnimNode* pInternalNode); - -protected: - /** The scene we're operating on */ - const aiScene* mScene; - - /** Current animation index */ - size_t mCurrentAnimIndex; - - /** The AnimEvaluator we use to calculate the current pose for the current animation */ - AnimEvaluator* mAnimEvaluator; - - /** Root node of the internal scene structure */ - SceneAnimNode* mRootNode; - - /** Name to node map to quickly find nodes by their name */ - typedef std::map<const aiNode*, SceneAnimNode*> NodeMap; - NodeMap mNodesByName; - - /** Name to node map to quickly find nodes for given bones by their name */ - typedef std::map<const char*, const aiNode*> BoneMap; - BoneMap mBoneNodesByName; - - /** Array to return transformations results inside. */ - std::vector<aiMatrix4x4> mTransforms; - - /** Identity matrix to return a reference to in case of error */ - aiMatrix4x4 mIdentityMatrix; -}; - -} // end of namespace AssimpView - +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2012, assimp 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 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 SceneAnimator.h + * Manages animations for a given scene and calculates present + * transformations for all nodes + */ + +#ifndef AV_SCENEANIMATOR_H_INCLUDED +#define AV_SCENEANIMATOR_H_INCLUDED + +#include <map> + +namespace AssimpView { + +// --------------------------------------------------------------------------------- +/** A little tree structure to match the scene's node structure, but holding + * additional data. Needs to be public to allow using it in templates at + * certain compilers. + */ +struct SceneAnimNode +{ + std::string mName; + SceneAnimNode* mParent; + std::vector<SceneAnimNode*> mChildren; + + //! most recently calculated local transform + aiMatrix4x4 mLocalTransform; + + //! same, but in world space + aiMatrix4x4 mGlobalTransform; + + //! index in the current animation's channel array. -1 if not animated. + size_t mChannelIndex; + + //! Default construction + SceneAnimNode() { + mChannelIndex = -1; mParent = NULL; + } + + //! Construction from a given name + SceneAnimNode( const std::string& pName) + : mName( pName) { + mChannelIndex = -1; mParent = NULL; + } + + //! Destruct all children recursively + ~SceneAnimNode() { + for( std::vector<SceneAnimNode*>::iterator it = mChildren.begin(); it != mChildren.end(); ++it) + delete *it; + } +}; + +// --------------------------------------------------------------------------------- +/** Calculates the animated node transformations for a given scene and timestamp. + * + * Create an instance for a aiScene you want to animate and set the current animation + * to play. You can then have the instance calculate the current pose for all nodes + * by calling Calculate() for a given timestamp. After this you can retrieve the + * present transformation for a given node by calling GetLocalTransform() or + * GetGlobalTransform(). A full set of bone matrices can be retrieved by + * GetBoneMatrices() for a given mesh. + */ +class SceneAnimator +{ +public: + + // ---------------------------------------------------------------------------- + /** Constructor for a given scene. + * + * The object keeps a reference to the scene during its lifetime, but + * ownership stays at the caller. + * @param pScene The scene to animate. + * @param pAnimIndex [optional] Index of the animation to play. Assumed to + * be 0 if not given. + */ + SceneAnimator( const aiScene* pScene, size_t pAnimIndex = 0); + + /** Destructor */ + ~SceneAnimator(); + + // ---------------------------------------------------------------------------- + /** Sets the animation to use for playback. This also recreates the internal + * mapping structures, which might take a few cycles. + * @param pAnimIndex Index of the animation in the scene's animation array + */ + void SetAnimIndex( size_t pAnimIndex); + + // ---------------------------------------------------------------------------- + /** Calculates the node transformations for the scene. Call this to get + * uptodate results before calling one of the getters. + * @param pTime Current time. Can be an arbitrary range. + */ + void Calculate( double pTime); + + // ---------------------------------------------------------------------------- + /** Retrieves the most recent local transformation matrix for the given node. + * + * The returned matrix is in the node's parent's local space, just like the + * original node's transformation matrix. If the node is not animated, the + * node's original transformation is returned so that you can safely use or + * assign it to the node itsself. If there is no node with the given name, + * the identity matrix is returned. All transformations are updated whenever + * Calculate() is called. + * @param pNodeName Name of the node + * @return A reference to the node's most recently calculated local + * transformation matrix. + */ + const aiMatrix4x4& GetLocalTransform( const aiNode* node) const; + + // ---------------------------------------------------------------------------- + /** Retrieves the most recent global transformation matrix for the given node. + * + * The returned matrix is in world space, which is the same coordinate space + * as the transformation of the scene's root node. If the node is not animated, + * the node's original transformation is returned so that you can safely use or + * assign it to the node itsself. If there is no node with the given name, the + * identity matrix is returned. All transformations are updated whenever + * Calculate() is called. + * @param pNodeName Name of the node + * @return A reference to the node's most recently calculated global + * transformation matrix. + */ + const aiMatrix4x4& GetGlobalTransform( const aiNode* node) const; + + // ---------------------------------------------------------------------------- + /** Calculates the bone matrices for the given mesh. + * + * Each bone matrix transforms from mesh space in bind pose to mesh space in + * skinned pose, it does not contain the mesh's world matrix. Thus the usual + * matrix chain for using in the vertex shader is + * @code + * boneMatrix * worldMatrix * viewMatrix * projMatrix + * @endcode + * @param pNode The node carrying the mesh. + * @param pMeshIndex Index of the mesh in the node's mesh array. The NODE's + * mesh array, not the scene's mesh array! Leave out to use the first mesh + * of the node, which is usually also the only one. + * @return A reference to a vector of bone matrices. Stays stable till the + * next call to GetBoneMatrices(); + */ + const std::vector<aiMatrix4x4>& GetBoneMatrices( const aiNode* pNode, + size_t pMeshIndex = 0); + + + // ---------------------------------------------------------------------------- + /** @brief Get the current animation index + */ + size_t CurrentAnimIndex() const { + return mCurrentAnimIndex; + } + + // ---------------------------------------------------------------------------- + /** @brief Get the current animation or NULL + */ + aiAnimation* CurrentAnim() const { + return mCurrentAnimIndex < mScene->mNumAnimations ? mScene->mAnimations[ mCurrentAnimIndex ] : NULL; + } + +protected: + + /** Recursively creates an internal node structure matching the + * current scene and animation. + */ + SceneAnimNode* CreateNodeTree( aiNode* pNode, SceneAnimNode* pParent); + + /** Recursively updates the internal node transformations from the + * given matrix array + */ + void UpdateTransforms( SceneAnimNode* pNode, const std::vector<aiMatrix4x4>& pTransforms); + + /** Calculates the global transformation matrix for the given internal node */ + void CalculateGlobalTransform( SceneAnimNode* pInternalNode); + +protected: + /** The scene we're operating on */ + const aiScene* mScene; + + /** Current animation index */ + size_t mCurrentAnimIndex; + + /** The AnimEvaluator we use to calculate the current pose for the current animation */ + AnimEvaluator* mAnimEvaluator; + + /** Root node of the internal scene structure */ + SceneAnimNode* mRootNode; + + /** Name to node map to quickly find nodes by their name */ + typedef std::map<const aiNode*, SceneAnimNode*> NodeMap; + NodeMap mNodesByName; + + /** Name to node map to quickly find nodes for given bones by their name */ + typedef std::map<const char*, const aiNode*> BoneMap; + BoneMap mBoneNodesByName; + + /** Array to return transformations results inside. */ + std::vector<aiMatrix4x4> mTransforms; + + /** Identity matrix to return a reference to in case of error */ + aiMatrix4x4 mIdentityMatrix; +}; + +} // end of namespace AssimpView + #endif // AV_SCENEANIMATOR_H_INCLUDED \ No newline at end of file diff --git a/tools/assimp_view/Shaders.h b/tools/assimp_view/Shaders.h index e716a50a2..59a45ce13 100644 --- a/tools/assimp_view/Shaders.h +++ b/tools/assimp_view/Shaders.h @@ -1,63 +1,63 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2012, assimp 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 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_SHADERS_H_INCLUDED) -#define AV_SHADERS_H_INCLUDED - -// Shader used for rendering a skybox background -extern std::string g_szSkyboxShader; - -// Shader used for visualizing normal vectors -extern std::string g_szNormalsShader; - -// Default shader -extern std::string g_szDefaultShader; - -// Material shader -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 +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2012, assimp 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 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_SHADERS_H_INCLUDED) +#define AV_SHADERS_H_INCLUDED + +// Shader used for rendering a skybox background +extern std::string g_szSkyboxShader; + +// Shader used for visualizing normal vectors +extern std::string g_szNormalsShader; + +// Default shader +extern std::string g_szDefaultShader; + +// Material shader +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.h b/tools/assimp_view/assimp_view.h index d18148dc5..26bde344a 100644 --- a/tools/assimp_view/assimp_view.h +++ b/tools/assimp_view/assimp_view.h @@ -1,286 +1,286 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2012, assimp 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 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_MAIN_H_INCLUDED) -#define AV_MAIN_H_INCLUDED - -#define AI_SHADER_COMPILE_FLAGS D3DXSHADER_USE_LEGACY_D3DX9_31_DLL - -// include resource definitions -#include "resource.h" - -#include <assert.h> -#include <stdlib.h> -#include <malloc.h> -#include <memory.h> -#include <tchar.h> -#include <stdio.h> -#include <time.h> - -// Include ASSIMP headers (XXX: do we really need all of them?) -#include <assimp/cimport.h> -#include <assimp/Importer.hpp> -#include <assimp/ai_assert.h> -#include <assimp/cfileio.h> -#include <assimp/postprocess.h> -#include <assimp/scene.h> -#include <assimp/IOSystem.hpp> -#include <assimp/IOStream.hpp> -#include <assimp/LogStream.hpp> -#include <assimp/DefaultLogger.hpp> - - -#include "../../code/MaterialSystem.h" // aiMaterial class -#include "../../code/StringComparison.h" // ASSIMP_stricmp and ASSIMP_strincmp - -// in order for std::min and std::max to behave properly -#ifndef max -#define max(a,b) (((a) > (b)) ? (a) : (b)) -#endif // max -#ifndef min -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif // min - -#include <time.h> - -// default movement speed -#define MOVE_SPEED 3.f - -#include "AssetHelper.h" -#include "Camera.h" -#include "RenderOptions.h" -#include "Shaders.h" -#include "Background.h" -#include "LogDisplay.h" -#include "LogWindow.h" -#include "Display.h" -#include "MeshRenderer.h" -#include "MaterialManager.h" - - -// outside of namespace, to help Intellisense and solve boost::metatype_stuff_miracle -#include "AnimEvaluator.h" -#include "SceneAnimator.h" - -namespace AssimpView -{ - -//------------------------------------------------------------------------------- -// Function prototypes -//------------------------------------------------------------------------------- -int InitD3D(void); -int ShutdownD3D(void); -int CreateDevice (bool p_bMultiSample,bool p_bSuperSample, bool bHW = true); -int CreateDevice (void); -int ShutdownDevice(void); -int GetProjectionMatrix (aiMatrix4x4& p_mOut); -int LoadAsset(void); -int CreateAssetData(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); - -void HandleMouseInputFPS( void ); -void HandleMouseInputLightRotate( void ); -void HandleMouseInputLocal( void ); -void HandleKeyboardInputFPS( void ); -void HandleMouseInputLightIntensityAndColor( void ); -void HandleMouseInputSkyBox( void ); -void HandleKeyboardInputTextureView( void ); -void HandleMouseInputTextureView( void ); - - -//------------------------------------------------------------------------------- -// -// Dialog procedure for the progress bar window -// -//------------------------------------------------------------------------------- -INT_PTR CALLBACK ProgressMessageProc(HWND hwndDlg,UINT uMsg, - WPARAM wParam,LPARAM lParam); - -//------------------------------------------------------------------------------- -// Main message procedure of the application -// -// The function handles all incoming messages for the main window. -// However, if does not directly process input commands. -// NOTE: Due to the impossibility to process WM_CHAR messages in dialogs -// properly the code for all hotkeys has been moved to the WndMain -//------------------------------------------------------------------------------- -INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, - WPARAM wParam,LPARAM lParam); - -//------------------------------------------------------------------------------- -// -// Dialog procedure for the about dialog -// -//------------------------------------------------------------------------------- -INT_PTR CALLBACK AboutMessageProc(HWND hwndDlg,UINT uMsg, - WPARAM wParam,LPARAM lParam); - -//------------------------------------------------------------------------------- -// -// Dialog procedure for the help dialog -// -//------------------------------------------------------------------------------- -INT_PTR CALLBACK HelpDialogProc(HWND hwndDlg,UINT uMsg, - WPARAM wParam,LPARAM lParam); - - -//------------------------------------------------------------------------------- -// Handle command line parameters -// -// The function loads an asset specified on the command line as first argument -// Other command line parameters are not handled -//------------------------------------------------------------------------------- -void HandleCommandLine(char* p_szCommand); - - -//------------------------------------------------------------------------------- -template <class type, class intype> -type clamp(intype in) -{ - // for unsigned types only ... - intype mask = (0x1u << (sizeof(type)*8))-1; - return (type)max((intype)0,min(in,mask)); -} - - -//------------------------------------------------------------------------------- -// Position of the cursor relative to the 3ds max' like control circle -//------------------------------------------------------------------------------- -enum EClickPos -{ - // The click was inside the inner circle (x,y axis) - EClickPos_Circle, - // The click was inside one of tghe vertical snap-ins - EClickPos_CircleVert, - // The click was inside onf of the horizontal snap-ins - EClickPos_CircleHor, - // the cklick was outside the circle (z-axis) - EClickPos_Outside -}; - -#if (!defined AI_VIEW_CAPTION_BASE) -# define AI_VIEW_CAPTION_BASE "Open Asset Import Library : Viewer " -#endif // !! AI_VIEW_CAPTION_BASE - -//------------------------------------------------------------------------------- -// Evil globals -//------------------------------------------------------------------------------- - extern HINSTANCE g_hInstance /*= NULL*/; - extern HWND g_hDlg /*= NULL*/; - extern IDirect3D9* g_piD3D /*= NULL*/; - extern IDirect3DDevice9* g_piDevice /*= NULL*/; - extern IDirect3DVertexDeclaration9* gDefaultVertexDecl /*= NULL*/; - extern double g_fFPS /*= 0.0f*/; - extern char g_szFileName[MAX_PATH]; - 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*/; - extern bool g_bMousePressedBoth /*= false*/; - extern float g_fElpasedTime /*= 0.0f*/; - extern D3DCAPS9 g_sCaps; - extern bool g_bLoadingFinished /*= false*/; - extern HANDLE g_hThreadHandle /*= NULL*/; - extern float g_fWheelPos /*= -10.0f*/; - extern bool g_bLoadingCanceled /*= false*/; - extern IDirect3DTexture9* g_pcTexture /*= NULL*/; - - extern aiMatrix4x4 g_mWorld; - extern aiMatrix4x4 g_mWorldRotate; - extern aiVector3D g_vRotateSpeed /*= aiVector3D(0.5f,0.5f,0.5f)*/; - - extern aiVector3D g_avLightDirs[1] /* = - { aiVector3D(-0.5f,0.6f,0.2f) , - aiVector3D(-0.5f,0.5f,0.5f)} */; - - - extern POINT g_mousePos /*= {0,0};*/; - extern POINT g_LastmousePos /*= {0,0}*/; - extern bool g_bFPSView /*= false*/; - extern bool g_bInvert /*= false*/; - 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 D3DCOLOR g_avLightColors[3]; - - extern RenderOptions g_sOptions; - extern Camera g_sCamera; - extern AssetHelper *g_pcAsset /*= NULL*/; - - - // - // Contains the mask image for the HUD - // (used to determine the position of a click) - // - // The size of the image is identical to the size of the main - // HUD texture - // - extern unsigned char* g_szImageMask /*= NULL*/; - - - extern float g_fACMR /*= 3.0f*/; - extern IDirect3DQuery9* g_piQuery; - - extern bool g_bPlay /*= false*/; - - extern double g_dCurrent; - extern float g_smoothAngle /*= 80.f*/; - - extern unsigned int ppsteps,ppstepsdefault; - extern bool nopointslines; - } - +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2012, assimp 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 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_MAIN_H_INCLUDED) +#define AV_MAIN_H_INCLUDED + +#define AI_SHADER_COMPILE_FLAGS D3DXSHADER_USE_LEGACY_D3DX9_31_DLL + +// include resource definitions +#include "resource.h" + +#include <assert.h> +#include <stdlib.h> +#include <malloc.h> +#include <memory.h> +#include <tchar.h> +#include <stdio.h> +#include <time.h> + +// Include ASSIMP headers (XXX: do we really need all of them?) +#include <assimp/cimport.h> +#include <assimp/Importer.hpp> +#include <assimp/ai_assert.h> +#include <assimp/cfileio.h> +#include <assimp/postprocess.h> +#include <assimp/scene.h> +#include <assimp/IOSystem.hpp> +#include <assimp/IOStream.hpp> +#include <assimp/LogStream.hpp> +#include <assimp/DefaultLogger.hpp> + + +#include "../../code/MaterialSystem.h" // aiMaterial class +#include "../../code/StringComparison.h" // ASSIMP_stricmp and ASSIMP_strincmp + +// in order for std::min and std::max to behave properly +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif // max +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif // min + +#include <time.h> + +// default movement speed +#define MOVE_SPEED 3.f + +#include "AssetHelper.h" +#include "Camera.h" +#include "RenderOptions.h" +#include "Shaders.h" +#include "Background.h" +#include "LogDisplay.h" +#include "LogWindow.h" +#include "Display.h" +#include "MeshRenderer.h" +#include "MaterialManager.h" + + +// outside of namespace, to help Intellisense and solve boost::metatype_stuff_miracle +#include "AnimEvaluator.h" +#include "SceneAnimator.h" + +namespace AssimpView +{ + +//------------------------------------------------------------------------------- +// Function prototypes +//------------------------------------------------------------------------------- +int InitD3D(void); +int ShutdownD3D(void); +int CreateDevice (bool p_bMultiSample,bool p_bSuperSample, bool bHW = true); +int CreateDevice (void); +int ShutdownDevice(void); +int GetProjectionMatrix (aiMatrix4x4& p_mOut); +int LoadAsset(void); +int CreateAssetData(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); + +void HandleMouseInputFPS( void ); +void HandleMouseInputLightRotate( void ); +void HandleMouseInputLocal( void ); +void HandleKeyboardInputFPS( void ); +void HandleMouseInputLightIntensityAndColor( void ); +void HandleMouseInputSkyBox( void ); +void HandleKeyboardInputTextureView( void ); +void HandleMouseInputTextureView( void ); + + +//------------------------------------------------------------------------------- +// +// Dialog procedure for the progress bar window +// +//------------------------------------------------------------------------------- +INT_PTR CALLBACK ProgressMessageProc(HWND hwndDlg,UINT uMsg, + WPARAM wParam,LPARAM lParam); + +//------------------------------------------------------------------------------- +// Main message procedure of the application +// +// The function handles all incoming messages for the main window. +// However, if does not directly process input commands. +// NOTE: Due to the impossibility to process WM_CHAR messages in dialogs +// properly the code for all hotkeys has been moved to the WndMain +//------------------------------------------------------------------------------- +INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, + WPARAM wParam,LPARAM lParam); + +//------------------------------------------------------------------------------- +// +// Dialog procedure for the about dialog +// +//------------------------------------------------------------------------------- +INT_PTR CALLBACK AboutMessageProc(HWND hwndDlg,UINT uMsg, + WPARAM wParam,LPARAM lParam); + +//------------------------------------------------------------------------------- +// +// Dialog procedure for the help dialog +// +//------------------------------------------------------------------------------- +INT_PTR CALLBACK HelpDialogProc(HWND hwndDlg,UINT uMsg, + WPARAM wParam,LPARAM lParam); + + +//------------------------------------------------------------------------------- +// Handle command line parameters +// +// The function loads an asset specified on the command line as first argument +// Other command line parameters are not handled +//------------------------------------------------------------------------------- +void HandleCommandLine(char* p_szCommand); + + +//------------------------------------------------------------------------------- +template <class type, class intype> +type clamp(intype in) +{ + // for unsigned types only ... + intype mask = (0x1u << (sizeof(type)*8))-1; + return (type)max((intype)0,min(in,mask)); +} + + +//------------------------------------------------------------------------------- +// Position of the cursor relative to the 3ds max' like control circle +//------------------------------------------------------------------------------- +enum EClickPos +{ + // The click was inside the inner circle (x,y axis) + EClickPos_Circle, + // The click was inside one of tghe vertical snap-ins + EClickPos_CircleVert, + // The click was inside onf of the horizontal snap-ins + EClickPos_CircleHor, + // the cklick was outside the circle (z-axis) + EClickPos_Outside +}; + +#if (!defined AI_VIEW_CAPTION_BASE) +# define AI_VIEW_CAPTION_BASE "Open Asset Import Library : Viewer " +#endif // !! AI_VIEW_CAPTION_BASE + +//------------------------------------------------------------------------------- +// Evil globals +//------------------------------------------------------------------------------- + extern HINSTANCE g_hInstance /*= NULL*/; + extern HWND g_hDlg /*= NULL*/; + extern IDirect3D9* g_piD3D /*= NULL*/; + extern IDirect3DDevice9* g_piDevice /*= NULL*/; + extern IDirect3DVertexDeclaration9* gDefaultVertexDecl /*= NULL*/; + extern double g_fFPS /*= 0.0f*/; + extern char g_szFileName[MAX_PATH]; + 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*/; + extern bool g_bMousePressedBoth /*= false*/; + extern float g_fElpasedTime /*= 0.0f*/; + extern D3DCAPS9 g_sCaps; + extern bool g_bLoadingFinished /*= false*/; + extern HANDLE g_hThreadHandle /*= NULL*/; + extern float g_fWheelPos /*= -10.0f*/; + extern bool g_bLoadingCanceled /*= false*/; + extern IDirect3DTexture9* g_pcTexture /*= NULL*/; + + extern aiMatrix4x4 g_mWorld; + extern aiMatrix4x4 g_mWorldRotate; + extern aiVector3D g_vRotateSpeed /*= aiVector3D(0.5f,0.5f,0.5f)*/; + + extern aiVector3D g_avLightDirs[1] /* = + { aiVector3D(-0.5f,0.6f,0.2f) , + aiVector3D(-0.5f,0.5f,0.5f)} */; + + + extern POINT g_mousePos /*= {0,0};*/; + extern POINT g_LastmousePos /*= {0,0}*/; + extern bool g_bFPSView /*= false*/; + extern bool g_bInvert /*= false*/; + 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 D3DCOLOR g_avLightColors[3]; + + extern RenderOptions g_sOptions; + extern Camera g_sCamera; + extern AssetHelper *g_pcAsset /*= NULL*/; + + + // + // Contains the mask image for the HUD + // (used to determine the position of a click) + // + // The size of the image is identical to the size of the main + // HUD texture + // + extern unsigned char* g_szImageMask /*= NULL*/; + + + extern float g_fACMR /*= 3.0f*/; + extern IDirect3DQuery9* g_piQuery; + + extern bool g_bPlay /*= false*/; + + extern double g_dCurrent; + extern float g_smoothAngle /*= 80.f*/; + + extern unsigned int ppsteps,ppstepsdefault; + extern bool nopointslines; + } + #endif // !! AV_MAIN_H_INCLUDED \ No newline at end of file diff --git a/tools/assimp_view/stdafx.h b/tools/assimp_view/stdafx.h index f60fe0069..3c78d385c 100644 --- a/tools/assimp_view/stdafx.h +++ b/tools/assimp_view/stdafx.h @@ -1,74 +1,74 @@ -// stdafx.h : Includedatei f�r Standardsystem-Includedateien -// oder h�ufig verwendete projektspezifische Includedateien, -// die nur in unregelm��igen Abst�nden ge�ndert werden. -// - -#pragma once - -// �ndern Sie folgende Definitionen f�r Plattformen, die �lter als die unten angegebenen sind. -// In MSDN finden Sie die neuesten Informationen �ber die entsprechenden Werte f�r die unterschiedlichen Plattformen. -#ifndef WINVER // Lassen Sie die Verwendung spezifischer Features von Windows XP oder sp�ter zu. -# define WINVER 0x0501 // �ndern Sie dies in den geeigneten Wert f�r andere Versionen von Windows. -#endif - -#ifndef _WIN32_WINNT // Lassen Sie die Verwendung spezifischer Features von Windows XP oder sp�ter zu. -# define _WIN32_WINNT 0x0501 // �ndern Sie dies in den geeigneten Wert f�r andere Versionen von Windows. -#endif - -#ifndef _WIN32_WINDOWS // Lassen Sie die Verwendung spezifischer Features von Windows 98 oder sp�ter zu. -# define _WIN32_WINDOWS 0x0410 // �ndern Sie dies in den geeigneten Wert f�r Windows Me oder h�her. -#endif - -#ifndef _WIN32_IE // Lassen Sie die Verwendung spezifischer Features von IE 6.0 oder sp�ter zu. -#define _WIN32_IE 0x0600 // �ndern Sie dies in den geeigneten Wert f�r andere Versionen von IE. -#endif - -#define WIN32_LEAN_AND_MEAN // Selten verwendete Teile der Windows-Header nicht einbinden. -// Windows-Headerdateien: -#include <windows.h> - -// C RunTime-Headerdateien -#include <assert.h> -#include <stdlib.h> -#include <malloc.h> -#include <memory.h> -#include <tchar.h> -#include <stdio.h> -#include <time.h> - -// D3D9 includes - -#if (defined _DEBUG) -# define D3D_DEBUG_INFO -#endif - -#include <d3d9.h> -#include <d3dx9.h> -#include <d3dx9mesh.h> - -// ShellExecute() -#include <shellapi.h> -#include <commctrl.h> - -// GetOpenFileName() -#include <commdlg.h> -#include <algorithm> -#include <mmsystem.h> - -#include <stdlib.h> -#include <stdio.h> -#include <list> -#include <vector> - -#if defined _MSC_VER -// Windows CommonControls 6.0 Manifest Extensions -# if defined _M_IX86 -# pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") -# elif defined _M_IA64 -# pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"") -# elif defined _M_X64 -# pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") -# else -# pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") -# endif -#endif +// stdafx.h : Includedatei f�r Standardsystem-Includedateien +// oder h�ufig verwendete projektspezifische Includedateien, +// die nur in unregelm��igen Abst�nden ge�ndert werden. +// + +#pragma once + +// �ndern Sie folgende Definitionen f�r Plattformen, die �lter als die unten angegebenen sind. +// In MSDN finden Sie die neuesten Informationen �ber die entsprechenden Werte f�r die unterschiedlichen Plattformen. +#ifndef WINVER // Lassen Sie die Verwendung spezifischer Features von Windows XP oder sp�ter zu. +# define WINVER 0x0501 // �ndern Sie dies in den geeigneten Wert f�r andere Versionen von Windows. +#endif + +#ifndef _WIN32_WINNT // Lassen Sie die Verwendung spezifischer Features von Windows XP oder sp�ter zu. +# define _WIN32_WINNT 0x0501 // �ndern Sie dies in den geeigneten Wert f�r andere Versionen von Windows. +#endif + +#ifndef _WIN32_WINDOWS // Lassen Sie die Verwendung spezifischer Features von Windows 98 oder sp�ter zu. +# define _WIN32_WINDOWS 0x0410 // �ndern Sie dies in den geeigneten Wert f�r Windows Me oder h�her. +#endif + +#ifndef _WIN32_IE // Lassen Sie die Verwendung spezifischer Features von IE 6.0 oder sp�ter zu. +#define _WIN32_IE 0x0600 // �ndern Sie dies in den geeigneten Wert f�r andere Versionen von IE. +#endif + +#define WIN32_LEAN_AND_MEAN // Selten verwendete Teile der Windows-Header nicht einbinden. +// Windows-Headerdateien: +#include <windows.h> + +// C RunTime-Headerdateien +#include <assert.h> +#include <stdlib.h> +#include <malloc.h> +#include <memory.h> +#include <tchar.h> +#include <stdio.h> +#include <time.h> + +// D3D9 includes + +#if (defined _DEBUG) +# define D3D_DEBUG_INFO +#endif + +#include <d3d9.h> +#include <d3dx9.h> +#include <d3dx9mesh.h> + +// ShellExecute() +#include <shellapi.h> +#include <commctrl.h> + +// GetOpenFileName() +#include <commdlg.h> +#include <algorithm> +#include <mmsystem.h> + +#include <stdlib.h> +#include <stdio.h> +#include <list> +#include <vector> + +#if defined _MSC_VER +// Windows CommonControls 6.0 Manifest Extensions +# if defined _M_IX86 +# pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") +# elif defined _M_IA64 +# pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"") +# elif defined _M_X64 +# pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") +# else +# pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") +# endif +#endif