فهرست منبع

Fixed SimpleTexturedDirectX11 sample.

- Removed OpenGL/Glut references in SimpleTexturedDirectX11 CMakeFile
- Moved UTFConverter from SimpleTexturedOpenGL to its own file to be able to reuse it.
- Added compile definition SHADER_PATH to allow to locate the shader files in CMakeFile
- Fixed compile warnings
- Made global pointers null to help prevent dangling references.
- Added missing members initialization in class constructors.
- Removed references to missing model "Models/mymodel.fbx"
- Fixed error when extracting model file directory
- Added missing device context assignment in ModelLoader Load method
- Fixed memory leak caused by variable 'ourModel' not deleted.
- Removed call to dev->Release() in ModelLoader.cpp
- Adjusted Release() calls in reverse order when cleaning up D3D
- Made Throwanerror implementation throw an error instead of displaying a message box
- Fixed leaking D3D resources
- Added a pointer to an ID3D11Debug to dump live objects.
Marc-Antoine Lortie 5 سال پیش
والد
کامیت
aa8a6122ce

+ 2 - 0
CMakeLists.txt

@@ -594,6 +594,8 @@ IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
 ENDIF ()
 
 IF ( ASSIMP_BUILD_SAMPLES)
+  SET( SAMPLES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/samples )
+  SET( SAMPLES_SHARED_CODE_DIR ${SAMPLES_DIR}/SharedCode )
   IF ( WIN32 )
     ADD_SUBDIRECTORY( samples/SimpleTexturedOpenGL/ )
     ADD_SUBDIRECTORY( samples/SimpleTexturedDirectx11 )

+ 52 - 0
samples/SharedCode/UTFConverter.cpp

@@ -0,0 +1,52 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, 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 "UTFConverter.h"
+
+namespace AssimpSamples {
+namespace SharedCode {
+
+typename UTFConverter::UTFConverterImpl UTFConverter::impl_;
+
+}
+}

+ 92 - 0
samples/SharedCode/UTFConverter.h

@@ -0,0 +1,92 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, 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 ASSIMP_SAMPLES_SHARED_CODE_UTFCONVERTER_H
+#define ASSIMP_SAMPLES_SHARED_CODE_UTFCONVERTER_H
+
+#include <string>
+#include <locale>
+#include <codecvt>
+
+namespace AssimpSamples {
+namespace SharedCode {
+
+// Used to convert between multibyte and unicode strings.
+class UTFConverter {
+    using UTFConverterImpl = std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>;
+public:
+    UTFConverter(const char* s) :
+        s_(s),
+        ws_(impl_.from_bytes(s)) {
+    }
+    UTFConverter(const wchar_t* s) :
+        s_(impl_.to_bytes(s)),
+        ws_(s) {
+    }
+    UTFConverter(const std::string& s) :
+        s_(s),
+        ws_(impl_.from_bytes(s)) {
+    }
+    UTFConverter(const std::wstring& s) :
+        s_(impl_.to_bytes(s)),
+        ws_(s) {
+    }
+    inline const char* c_str() const {
+        return s_.c_str();
+    }
+    inline const std::string& str() const {
+        return s_;
+    }
+    inline const wchar_t* c_wstr() const {
+        return ws_.c_str();
+    }
+private:
+    static UTFConverterImpl impl_;
+    std::string s_;
+    std::wstring ws_;
+};
+
+}
+}
+
+#endif // ASSIMP_SAMPLES_SHARED_CODE_UTFCONVERTER_H

+ 6 - 3
samples/SimpleTexturedDirectx11/CMakeLists.txt

@@ -10,12 +10,12 @@ if ( MSVC )
   REMOVE_DEFINITIONS( -DUNICODE -D_UNICODE )
 endif ()
 
+ADD_COMPILE_DEFINITIONS(SHADER_PATH="${CMAKE_CURRENT_SOURCE_DIR}/SimpleTexturedDirectx11/")
+
 INCLUDE_DIRECTORIES(
   ${Assimp_SOURCE_DIR}/include
   ${Assimp_SOURCE_DIR}/code
-  ${OPENGL_INCLUDE_DIR}
-  ${GLUT_INCLUDE_DIR}
-  ${Assimp_SOURCE_DIR}/samples/freeglut/include
+  ${SAMPLES_SHARED_CODE_DIR}
 )
 
 LINK_DIRECTORIES(
@@ -32,6 +32,9 @@ ADD_EXECUTABLE( assimp_simpletextureddirectx11 WIN32
   SimpleTexturedDirectx11/TextureLoader.h 
   #SimpleTexturedDirectx11/VertexShader.hlsl  
   SimpleTexturedDirectx11/main.cpp
+  SimpleTexturedDirectx11/SafeRelease.hpp
+  ${SAMPLES_SHARED_CODE_DIR}/UTFConverter.cpp
+  ${SAMPLES_SHARED_CODE_DIR}/UTFConverter.h
 )
 
 SET_PROPERTY(TARGET assimp_simpletextureddirectx11 PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})

+ 29 - 18
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h

@@ -6,6 +6,7 @@
 #include <sstream>
 #include <iostream>
 #include <vector>
+#include <stdexcept>
 using namespace std;
 
 #include <vector>
@@ -13,6 +14,8 @@ using namespace std;
 #include <DirectXMath.h>
 using namespace DirectX;
 
+#include "SafeRelease.hpp"
+
 struct VERTEX {
 	FLOAT X, Y, Z;
 	XMFLOAT2 texcoord;
@@ -22,6 +25,10 @@ struct Texture {
 	string type;
 	string path;
 	ID3D11ShaderResourceView *texture;
+
+	inline void Release() {
+		SafeRelease(texture);
+	}
 };
 
 class Mesh {
@@ -31,15 +38,15 @@ public:
 	vector<Texture> textures;
 	ID3D11Device *dev;
 
-	Mesh(ID3D11Device *dev, vector<VERTEX> vertices, vector<UINT> indices, vector<Texture> textures)
+	Mesh(ID3D11Device *dev, const vector<VERTEX>& vertices, const vector<UINT>& indices, const vector<Texture>& textures) :
+		vertices(vertices),
+		indices(indices),
+		textures(textures),
+		dev(dev),
+		VertexBuffer(nullptr),
+		IndexBuffer(nullptr)
 	{
-		this->vertices = vertices;
-		this->indices = indices;
-		this->textures = textures;
-
-		this->dev = dev;
-
-		this->setupMesh(dev);
+		this->setupMesh(this->dev);
 	}
 
 	void Draw(ID3D11DeviceContext *devcon)
@@ -52,13 +59,13 @@ public:
 
 		devcon->PSSetShaderResources(0, 1, &textures[0].texture);
 
-		devcon->DrawIndexed(indices.size(), 0, 0);
+		devcon->DrawIndexed(static_cast<UINT>(indices.size()), 0, 0);
 	}
 
 	void Close()
 	{
-		VertexBuffer->Release();
-		IndexBuffer->Release();
+		SafeRelease(VertexBuffer);
+		SafeRelease(IndexBuffer);
 	}
 private:
 	/*  Render data  */
@@ -66,13 +73,13 @@ private:
 
 	/*  Functions    */
 	// Initializes all the buffer objects/arrays
-	bool setupMesh(ID3D11Device *dev)
+	void setupMesh(ID3D11Device *dev)
 	{
 		HRESULT hr;
 
 		D3D11_BUFFER_DESC vbd;
 		vbd.Usage = D3D11_USAGE_IMMUTABLE;
-		vbd.ByteWidth = sizeof(VERTEX) * vertices.size();
+		vbd.ByteWidth = static_cast<UINT>(sizeof(VERTEX) * vertices.size());
 		vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
 		vbd.CPUAccessFlags = 0;
 		vbd.MiscFlags = 0;
@@ -81,12 +88,14 @@ private:
 		initData.pSysMem = &vertices[0];
 
 		hr = dev->CreateBuffer(&vbd, &initData, &VertexBuffer);
-		if (FAILED(hr))
-			return false;
+		if (FAILED(hr)) {
+			Close();
+			throw std::runtime_error("Failed to create vertex buffer.");
+		}
 
 		D3D11_BUFFER_DESC ibd;
 		ibd.Usage = D3D11_USAGE_IMMUTABLE;
-		ibd.ByteWidth = sizeof(UINT) * indices.size();
+		ibd.ByteWidth = static_cast<UINT>(sizeof(UINT) * indices.size());
 		ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
 		ibd.CPUAccessFlags = 0;
 		ibd.MiscFlags = 0;
@@ -94,8 +103,10 @@ private:
 		initData.pSysMem = &indices[0];
 
 		hr = dev->CreateBuffer(&ibd, &initData, &IndexBuffer);
-		if (FAILED(hr))
-			return false;
+		if (FAILED(hr)) {
+			Close();
+			throw std::runtime_error("Failed to create index buffer.");
+		}
 	}
 };
 

+ 12 - 4
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp

@@ -1,6 +1,12 @@
 #include "ModelLoader.h"
 
-ModelLoader::ModelLoader()
+ModelLoader::ModelLoader() : 
+	dev(nullptr),
+	devcon(nullptr),
+	meshes(),
+	directory(),
+	textures_loaded(),
+	hwnd(nullptr)
 {
 }
 
@@ -20,9 +26,10 @@ bool ModelLoader::Load(HWND hwnd, ID3D11Device * dev, ID3D11DeviceContext * devc
 	if (pScene == NULL)
 		return false;
 
-	this->directory = filename.substr(0, filename.find_last_of('/'));
+	this->directory = filename.substr(0, filename.find_last_of("/\\"));
 
 	this->dev = dev;
+	this->devcon = devcon;
 	this->hwnd = hwnd;
 
 	processNode(pScene->mRootNode, pScene);
@@ -138,12 +145,13 @@ vector<Texture> ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextureTyp
 
 void ModelLoader::Close()
 {
+	for (auto& t : textures_loaded)
+		t.Release();
+
 	for (int i = 0; i < meshes.size(); i++)
 	{
 		meshes[i].Close();
 	}
-
-	dev->Release();
 }
 
 void ModelLoader::processNode(aiNode * node, const aiScene * scene)

+ 57 - 0
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SafeRelease.hpp

@@ -0,0 +1,57 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, 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.
+---------------------------------------------------------------------------
+*/
+
+#ifdef _MSC_VER
+#pragma once
+#endif
+
+/* Used to reduce to reduce the number of lines when calling Release()
+   on a D3D interface. Implemented as a template instead of a 'SAFE_RELEASE'
+   MACRO to ease debugging. */
+template<typename T>
+inline void SafeRelease(T*& x) {
+    if (x) {
+        x->Release();
+        x = nullptr;
+    }
+}

+ 132 - 53
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp

@@ -14,12 +14,16 @@
 // ---------------------------------------------------------------------------
 
 #include <Windows.h>
+#include <shellapi.h>
+#include <stdexcept>
 #include <windowsx.h>
 #include <d3d11_1.h>
 #include <dxgi1_2.h>
 #include <DirectXMath.h>
 #include <d3dcompiler.h>
 #include "ModelLoader.h"
+#include "UTFConverter.h"
+#include "SafeRelease.hpp"
 
 #pragma comment (lib, "d3d11.lib")
 #pragma comment (lib, "Dxgi.lib")
@@ -27,6 +31,10 @@
 #pragma comment (lib, "dxguid.lib")
 
 using namespace DirectX;
+using namespace AssimpSamples::SharedCode;
+
+#define VERTEX_SHADER_FILE L"VertexShader.hlsl"
+#define PIXEL_SHADER_FILE L"PixelShader.hlsl"
 
 // ------------------------------------------------------------
 //                        Structs
@@ -45,29 +53,32 @@ struct ConstantBuffer {
 
 const char g_szClassName[] = "directxWindowClass";
 
+static std::string g_ModelPath;
 
 UINT width, height;
-HWND hwnd;
+HWND hwnd = nullptr;
 
 // ------------------------------------------------------------
 //                        DirectX Variables
 // ------------------------------------------------------------
 D3D_DRIVER_TYPE g_driverType = D3D_DRIVER_TYPE_NULL;
 D3D_FEATURE_LEVEL g_featureLevel = D3D_FEATURE_LEVEL_11_0;
-ID3D11Device *dev;
-ID3D11Device1 *dev1;
-ID3D11DeviceContext *devcon;
-ID3D11DeviceContext1 *devcon1;
-IDXGISwapChain *swapchain;
-IDXGISwapChain1 *swapchain1;
-ID3D11RenderTargetView *backbuffer;
-ID3D11VertexShader *pVS;
-ID3D11PixelShader *pPS;
-ID3D11InputLayout *pLayout;
-ID3D11Buffer *pConstantBuffer;
-ID3D11Texture2D *g_pDepthStencil;
-ID3D11DepthStencilView *g_pDepthStencilView;
-ID3D11SamplerState *TexSamplerState;
+ID3D11Device *dev = nullptr;
+ID3D11Device1 *dev1 = nullptr;
+ID3D11DeviceContext *devcon = nullptr;
+ID3D11DeviceContext1 *devcon1 = nullptr;
+IDXGISwapChain *swapchain = nullptr;
+IDXGISwapChain1 *swapchain1 = nullptr;
+ID3D11RenderTargetView *backbuffer = nullptr;
+ID3D11VertexShader *pVS = nullptr;
+ID3D11PixelShader *pPS = nullptr;
+ID3D11InputLayout *pLayout = nullptr;
+ID3D11Buffer *pConstantBuffer = nullptr;
+ID3D11Texture2D *g_pDepthStencil = nullptr;
+ID3D11DepthStencilView *g_pDepthStencilView = nullptr;
+ID3D11SamplerState *TexSamplerState = nullptr;
+ID3D11RasterizerState *rasterstate = nullptr;
+ID3D11Debug* d3d11debug = nullptr;
 
 XMMATRIX m_World;
 XMMATRIX m_View;
@@ -91,7 +102,7 @@ void Throwanerror(LPCSTR errormessage);
 //                        Our Model
 // ------------------------------------------------------------
 
-ModelLoader *ourModel;
+ModelLoader *ourModel = nullptr;
 
 LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
@@ -109,9 +120,42 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 	return 0;
 }
 
-int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
-	LPSTR lpCmdLine, int nCmdShow)
+int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
+	LPWSTR lpCmdLine, int nCmdShow)
 {
+	int argc;
+	LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc);
+	if (!argv) {
+		MessageBox(NULL, 
+			TEXT("An error occured while reading command line arguments."),
+			TEXT("Error!"),
+			MB_ICONERROR | MB_OK);
+		return EXIT_FAILURE;
+	}
+
+	// Free memory allocated from CommandLineToArgvW.
+	auto free_command_line_allocated_memory = [&argv]() {
+		if (argv) {
+			LocalFree(argv);
+			argv = nullptr;
+		}
+	};
+
+	// Ensure that a model file has been specified.
+	if (argc < 2) {
+		MessageBox(NULL, 
+			TEXT("No model file specified. The program will now close."), 
+			TEXT("Error!"),
+			MB_ICONERROR | MB_OK);
+		free_command_line_allocated_memory();
+		return EXIT_FAILURE;
+	}
+
+	// Retrieve the model file path.
+	g_ModelPath = UTFConverter(argv[1]).str();
+
+	free_command_line_allocated_memory();
+	
 	WNDCLASSEX wc;
 	MSG msg;
 
@@ -160,26 +204,35 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
 	width = wr.right - wr.left;
 	height = wr.bottom - wr.top;
 
-	InitD3D(hInstance, hwnd);
+	try {
+		InitD3D(hInstance, hwnd);
 
-	while (true)
-	{
-
-		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+		while (true)
 		{
-			TranslateMessage(&msg);
-			DispatchMessage(&msg);
 
-			if (msg.message == WM_QUIT)
-				break;
-		}
+			if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+			{
+				TranslateMessage(&msg);
+				DispatchMessage(&msg);
 
-		RenderFrame();
-	}
+				if (msg.message == WM_QUIT)
+					break;
+			}
 
-	CleanD3D();
+			RenderFrame();
+		}
 
-	return msg.wParam;
+		CleanD3D();
+		return static_cast<int>(msg.wParam);
+	} catch (const std::exception& e) {
+		MessageBox(hwnd, e.what(), TEXT("Error!"), MB_ICONERROR | MB_OK);
+		CleanD3D();
+		return EXIT_FAILURE;
+	} catch (...) {
+		MessageBox(hwnd, TEXT("Caught an unknown exception."), TEXT("Error!"), MB_ICONERROR | MB_OK);
+		CleanD3D();
+		return EXIT_FAILURE;
+	}
 }
 
 void InitD3D(HINSTANCE hinstance, HWND hWnd)
@@ -227,6 +280,12 @@ void InitD3D(HINSTANCE hinstance, HWND hWnd)
 	if (FAILED(hr))
 		Throwanerror("Directx Device Creation Failed!");
 
+#if _DEBUG
+	hr = dev->QueryInterface(IID_PPV_ARGS(&d3d11debug));
+	if (FAILED(hr))
+		OutputDebugString(TEXT("Failed to retrieve DirectX 11 debug interface.\n"));
+#endif
+
 	UINT m4xMsaaQuality;
 	dev->CheckMultisampleQualityLevels(
 		DXGI_FORMAT_R8G8B8A8_UNORM, 4, &m4xMsaaQuality);
@@ -348,7 +407,6 @@ void InitD3D(HINSTANCE hinstance, HWND hWnd)
 	devcon->OMSetRenderTargets(1, &backbuffer, g_pDepthStencilView);
 
 	D3D11_RASTERIZER_DESC rasterDesc;
-	ID3D11RasterizerState *rasterState;
 	rasterDesc.AntialiasedLineEnable = false;
 	rasterDesc.CullMode = D3D11_CULL_BACK;
 	rasterDesc.DepthBias = 0;
@@ -360,8 +418,8 @@ void InitD3D(HINSTANCE hinstance, HWND hWnd)
 	rasterDesc.ScissorEnable = false;
 	rasterDesc.SlopeScaledDepthBias = 0.0f;
 
-	dev->CreateRasterizerState(&rasterDesc, &rasterState);
-	devcon->RSSetState(rasterState);
+	dev->CreateRasterizerState(&rasterDesc, &rasterstate);
+	devcon->RSSetState(rasterstate);
 
 	D3D11_VIEWPORT viewport;
 	ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
@@ -381,19 +439,38 @@ void InitD3D(HINSTANCE hinstance, HWND hWnd)
 
 void CleanD3D(void)
 {
-	swapchain->SetFullscreenState(FALSE, NULL);
-
-	ourModel->Close();
-	g_pDepthStencil->Release();
-	g_pDepthStencilView->Release();
-	pLayout->Release();
-	pVS->Release();
-	pPS->Release();
-	pConstantBuffer->Release();
-	swapchain->Release();
-	backbuffer->Release();
-	dev->Release();
-	devcon->Release();
+	if (swapchain)
+		swapchain->SetFullscreenState(FALSE, NULL);
+
+	if (ourModel) {
+		ourModel->Close();
+		delete ourModel;
+		ourModel = nullptr;
+	}
+	SafeRelease(TexSamplerState);
+	SafeRelease(pConstantBuffer);
+	SafeRelease(pLayout);
+	SafeRelease(pVS);
+	SafeRelease(pPS);
+	SafeRelease(rasterstate);
+	SafeRelease(g_pDepthStencilView);
+	SafeRelease(g_pDepthStencil);
+	SafeRelease(backbuffer);
+	SafeRelease(swapchain);
+	SafeRelease(swapchain1);
+	SafeRelease(devcon1);
+	SafeRelease(dev1);
+	SafeRelease(devcon);
+#if _DEBUG
+	if (d3d11debug) {
+		OutputDebugString(TEXT("Dumping DirectX 11 live objects.\n"));
+		d3d11debug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL);
+		SafeRelease(d3d11debug);
+	} else {
+		OutputDebugString(TEXT("Unable to dump live objects: no DirectX 11 debug interface available.\n"));
+	}
+#endif
+	SafeRelease(dev);
 }
 
 void RenderFrame(void)
@@ -431,8 +508,10 @@ void RenderFrame(void)
 void InitPipeline()
 {
 	ID3DBlob *VS, *PS;
-	CompileShaderFromFile(L"VertexShader.hlsl", 0, "main", "vs_4_0", &VS);
-	CompileShaderFromFile(L"PixelShader.hlsl", 0, "main", "ps_4_0", &PS);
+	if(FAILED(CompileShaderFromFile(SHADER_PATH VERTEX_SHADER_FILE, 0, "main", "vs_4_0", &VS)))
+		Throwanerror(UTFConverter(L"Failed to compile shader from file " VERTEX_SHADER_FILE).c_str());
+	if(FAILED(CompileShaderFromFile(SHADER_PATH PIXEL_SHADER_FILE, 0, "main", "ps_4_0", &PS)))
+		Throwanerror(UTFConverter(L"Failed to compile shader from file " PIXEL_SHADER_FILE).c_str());
 
 	dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS);
 	dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS);
@@ -485,7 +564,7 @@ void InitGraphics()
 	m_View = XMMatrixLookAtLH(Eye, At, Up);
 
 	ourModel = new ModelLoader;
-	if (!ourModel->Load(hwnd, dev, devcon, "Models/myModel.fbx"))
+	if (!ourModel->Load(hwnd, dev, devcon, g_ModelPath))
 		Throwanerror("Model couldn't be loaded");
 }
 
@@ -514,5 +593,5 @@ HRESULT	CompileShaderFromFile(LPCWSTR pFileName, const D3D_SHADER_MACRO* pDefine
 
 void Throwanerror(LPCSTR errormessage)
 {
-	MessageBox(hwnd, errormessage, "Error!", MB_ICONERROR | MB_OK);
-}
+	throw std::runtime_error(errormessage);
+}

+ 3 - 0
samples/SimpleTexturedOpenGL/CMakeLists.txt

@@ -21,6 +21,7 @@ INCLUDE_DIRECTORIES(
   ${Assimp_SOURCE_DIR}/code
   ${OPENGL_INCLUDE_DIR}
   ${GLUT_INCLUDE_DIR}
+  ${SAMPLES_SHARED_CODE_DIR}
 )
 
 LINK_DIRECTORIES(
@@ -31,6 +32,8 @@ LINK_DIRECTORIES(
 ADD_EXECUTABLE( assimp_simpletexturedogl WIN32
   SimpleTexturedOpenGL/include/boost_includes.h
   SimpleTexturedOpenGL/src/model_loading.cpp
+  ${SAMPLES_SHARED_CODE_DIR}/UTFConverter.cpp
+  ${SAMPLES_SHARED_CODE_DIR}/UTFConverter.h
 )
 
 SET_PROPERTY(TARGET assimp_simpletexturedogl PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})

+ 2 - 32
samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp

@@ -21,8 +21,6 @@
 #define STB_IMAGE_IMPLEMENTATION
 #include "contrib/stb_image/stb_image.h"
 
-#include <locale>
-#include <codecvt>
 #include <fstream>
 
 //to map image filenames to textureIds
@@ -35,7 +33,7 @@
 #include <assimp/scene.h>
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/LogStream.hpp>
-
+#include "UTFConverter.h"
 
 // The default hard-coded path. Can be overridden by supplying a path through the command line.
 static std::string modelpath = "../../test/models/OBJ/spider.obj";
@@ -77,35 +75,7 @@ GLuint*		textureIds;							// pointer to texture Array
 // Create an instance of the Importer class
 Assimp::Importer importer;
 
-// Used to convert between multibyte and unicode strings.
-class UTFConverter {
-	using UTFConverterImpl = std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>;
-public:
-	UTFConverter(const char* s) :
-		s_(s),
-		ws_(impl_.from_bytes(s)) {
-	}
-	UTFConverter(const std::string& s) :
-		s_(s),
-		ws_(impl_.from_bytes(s)) {
-	}
-	UTFConverter(const std::wstring& s) :
-		s_(impl_.to_bytes(s)),
-		ws_(s) {
-	}
-	inline const std::string& str() const {
-		return s_;
-	}
-	inline const wchar_t* c_wstr() const {
-		return ws_.c_str();
-	}
-private:
-	static UTFConverterImpl impl_;
-	std::string s_;
-	std::wstring ws_;
-};
-
-typename UTFConverter::UTFConverterImpl UTFConverter::impl_;
+using namespace AssimpSamples::SharedCode;
 
 void createAILogger()
 {