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(&current.first,4,1,ctx.get_expect());
-		res|=fread(&current.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(&current.first,4,1,ctx.get_expect());
+        res|=fread(&current.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