
// zlib open source license
//
// Copyright (c) 2010 to 2014 David Forsgren Piuva
// 
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// 
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 
//    1. The origin of this software must not be misrepresented; you must not
//    claim that you wrote the original software. If you use this software
//    in a product, an acknowledgment in the product documentation would be
//    appreciated but is not required.
// 
//    2. Altered source versions must be plainly marked as such, and must not be
//    misrepresented as being the original software.
// 
//    3. This notice may not be removed or altered from any source
//    distribution.

#pragma once

#define _CRT_SECURE_NO_DEPRECATE // Disable a well known Visual Studio bug that would say that a method is obsolete when it is not.

#define ShadowSlope 7.5f // Set the shadow offset

#include "../stdafx.h"

#include "EngineCore.h"

#include "../GlobalConstants.h"

// Parts of the core moved to different pages
#include "Core_ModelShell.h"
#include "Core_ShaderCompiling.h"
#include "../MessageQueue.h"
#include "../ContactBuffer.h"

// Trap access violation
int EngineCore::Filter(unsigned int code, struct _EXCEPTION_POINTERS *ep) {
#ifdef _DEBUG
	return EXCEPTION_CONTINUE_SEARCH;
#else
	if (code == EXCEPTION_ACCESS_VIOLATION) {
		return EXCEPTION_EXECUTE_HANDLER;
	} else {
		return EXCEPTION_CONTINUE_SEARCH;
	};
#endif
}

// Shader compilation flags
const bool UsingVS[NumberOfShaderTypes] = {true,false,false,false};
const bool UsingPS[NumberOfShaderTypes] = {true,true,true,false};
const bool UsingGS[NumberOfShaderTypes] = {true,false,false,false};

// Constant descriptions
const D3D11_SAMPLER_DESC ConstSamDescShad = {
	D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT,// D3D11_FILTER Filter;
	D3D11_TEXTURE_ADDRESS_WRAP, //D3D11_TEXTURE_ADDRESS_MODE AddressU;
	D3D11_TEXTURE_ADDRESS_WRAP, //D3D11_TEXTURE_ADDRESS_MODE AddressV;
	D3D11_TEXTURE_ADDRESS_WRAP, //D3D11_TEXTURE_ADDRESS_MODE AddressW;
	0,//FLOAT MipLODBias;
	0,//UINT MaxAnisotropy;
	D3D11_COMPARISON_LESS , //D3D11_COMPARISON_FUNC ComparisonFunc;
	0.0,0.0,0.0,0.0,//FLOAT BorderColor[ 4 ];
	0,//FLOAT MinLOD;
	D3D11_FLOAT32_MAX //FLOAT MaxLOD;
};
const D3D11_TEXTURE2D_DESC ConstStaged1x1Desc = {
	1,//UINT Width;
	1,//UINT Height;
	1,//UINT MipLevels;
	1,//UINT ArraySize;
	DXGI_FORMAT_R32G32B32A32_FLOAT,//DXGI_FORMAT Format;
	1, 0,//DXGI_SAMPLE_DESC SampleDesc;
	D3D11_USAGE_STAGING,//D3D11_USAGE Usage;
	0,//UINT BindFlags;
	D3D11_CPU_ACCESS_READ,//UINT CPUAccessFlags;
	0//UINT MiscFlags;
};
const D3D11_TEXTURE2D_DESC ConstDynamic1x1Desc = {
	1,//UINT Width;
	1,//UINT Height;
	1,//UINT MipLevels;
	1,//UINT ArraySize;
	DXGI_FORMAT_R32G32B32A32_FLOAT,//DXGI_FORMAT Format;
	1, 0,//DXGI_SAMPLE_DESC SampleDesc;
	D3D11_USAGE_DYNAMIC,//D3D11_USAGE Usage;
	D3D11_BIND_SHADER_RESOURCE,//UINT BindFlags;
	D3D11_CPU_ACCESS_WRITE,//UINT CPUAccessFlags;
	0//UINT MiscFlags;
};

// Collection macros

#define SizeOfCollection(NAME) \
	m_numberOf##NAME

#define StartCollection(NAME) \
	m_##NAME.MQ = MQ; \
	m_##NAME.allocate(100, 0); \
	SizeOfCollection(NAME) = 0; \
	NAME##_GarbagePile = NULL;

#define IncreaseCollection(NAME) \
	SizeOfCollection(NAME)++; \
	if (m_##NAME.getSize() < SizeOfCollection(NAME)) { \
		m_##NAME.redim_preserve(m_##NAME.getSize() + 100, 0); \
	}

#define DecreaseCollection(NAME) \
	SizeOfCollection(NAME)--;

#define EndCollection(NAME) \
	while (SizeOfCollection(NAME) > 0) { \
		Delete_##NAME((NAME##_Struct*)m_##NAME.getValue_warning(SizeOfCollection(NAME) - 1)); \
	} \
	m_##NAME.deallocate(); \
	NAME##_CleanUpGarbagePile();

#define AddToCollection(NAME,VAR) \
	int newIndex; \
	VAR = NAME##_GetMemory(); \
	newIndex = SizeOfCollection(NAME); \
	IncreaseCollection(NAME); \
	m_##NAME.setValue_warning(newIndex, VAR); \
	VAR->Index = newIndex; \
	VAR->useCount = 0;

#define DEF_DEFAULT_METHODS(NAME) \
void EngineCore::Delete_##NAME(NAME##_Struct* Reference) { \
	NAME##_Struct* lastReference; \
	int deletedIndex;  \
	if (Reference->useCount == 0 || m_SilentTermination) { \
		deletedIndex = Reference->Index; \
		NAME##_Struct_Release(Reference); \
		NAME##_LeaveMemory(Reference); \
		if (deletedIndex != SizeOfCollection(NAME) - 1) { \
			lastReference = (NAME##_Struct*)m_##NAME.getValue_warning(SizeOfCollection(NAME) - 1); \
			m_##NAME.setValue_warning(deletedIndex, lastReference); \
			lastReference->Index = deletedIndex; \
		} \
		m_##NAME.setValue_warning(SizeOfCollection(NAME) - 1, 0); \
		DecreaseCollection(NAME); \
	} else { \
		swprintf_s( MQ->messageBuffer, L"You tried to delete a %s before deleting %i things that are using it!", L#NAME, Reference->useCount); MQ->InsertMessage(MQ->messageBuffer); \
	} \
} \
void EngineCore::NAME##_CleanUpGarbagePile(void) { \
	NAME##_Struct* Next; \
	while (NAME##_GarbagePile) { \
		Next = NAME##_GarbagePile->NextGarbage; \
		SAFE_DELETE(NAME##_GarbagePile) \
		NAME##_GarbagePile = Next; \
	} \
} \
void EngineCore::NAME##_LeaveMemory(NAME##_Struct* NewItem) { \
	if (m_CollectGarbage) { \
		m_pReferences[NewItem->ID].Valid = false; \
		NewItem->NextGarbage = NAME##_GarbagePile; \
		NAME##_GarbagePile = NewItem; \
	} else { \
		SAFE_DELETE(NewItem) \
	} \
} \
NAME##_Struct* EngineCore::NAME##_GetMemory(void) { \
	NAME##_Struct* Item; \
	int PreservedID; \
	if (NAME##_GarbagePile == NULL) { \
		Item = new NAME##_Struct; \
		if (Item == NULL) { \
			MQ->InsertMessage(L"GetMemory: Memory allocation was denied."); \
		} \
		ZeroMemory( Item, sizeof( NAME##_Struct ) ); \
		Item->ID = InsertToPointerTable((void*)Item, ColType_##NAME); \
	} else { \
		Item = (NAME##_Struct*)NAME##_GarbagePile; \
		NAME##_GarbagePile = NAME##_GarbagePile->NextGarbage; \
		PreservedID = Item->ID; \
		ZeroMemory( Item, sizeof( NAME##_Struct ) ); \
		Item->ID = PreservedID; \
	} \
	m_pReferences[Item->ID].Valid = true; \
	return Item; \
} \
NAME##_Struct* EngineCore::##NAME##_PointerFromID(int ID, bool AllowNull) { \
	if (ID == 0) { \
		if (!AllowNull) { \
			MQ->InsertMessage(L"A NULL reference was given to a method that don't allow null."); \
		} \
		return NULL; \
	} else if (ID < 0 || ID >= m_usedReferences) { \
		swprintf_s( MQ->messageBuffer, L"%i is out of bound for the reference numbers.", ID); MQ->InsertMessage(MQ->messageBuffer); \
		return NULL; \
	} else if (m_pReferences[ID].Valid == false) { \
		swprintf_s( MQ->messageBuffer, L"%i is not a valid reference number.", ID); MQ->InsertMessage(MQ->messageBuffer); \
		return NULL; \
	} else if (m_pReferences[ID].CollectionType != ColType_##NAME) { \
	swprintf_s( MQ->messageBuffer, L"%i does not refer to a %s.", ID, L#NAME); MQ->InsertMessage(MQ->messageBuffer); \
		return NULL; \
	} else { \
		return (NAME##_Struct*)m_pReferences[ID].pointer; \
	} \
}

#define INDEX_BY_NAME_DEC(NAME) \
int EngineCore::Find##NAME##IndexByName(wchar_t* filename) { \
	int i; NAME##_Struct* current##NAME; \
	LoopForwardLengthFromZero(i,SizeOfCollection(NAME)) { \
		current##NAME = (NAME##_Struct*)m_##NAME.getValue_warning(i); \
		if (CompareStrings_FileNames(current##NAME->FileName,filename)) { return i; } \
	} \
	return -1; \
}

// Takes a pointer to the reference table and returns the new external ID for it.
int EngineCore::InsertToPointerTable(void* pointer, int CollectionType) {
	int i;
	ReferenceTable* NewReferences;
	m_usedReferences++;
	if (m_usedReferences > m_lenReferences) {
		m_lenReferences = m_lenReferences * 2;
		NewReferences = new ReferenceTable[m_lenReferences];
		if (NewReferences == NULL) {
			MQ->InsertMessage(L"InsertToPointerTable: Memory allocation was denied when creating a reference table.");
		}
		
		// Preserve old references
		LoopForward(0,i,m_usedReferences-2) {
			NewReferences[i] = m_pReferences[i];
		}
		// Clear memory
		LoopForward(m_usedReferences,i,m_lenReferences-1) {
			NewReferences[i].pointer = NULL;
			NewReferences[i].Valid = false;
			NewReferences[i].CollectionType = ColType_None;
		}
		SAFE_DELETE_ARRAY(m_pReferences)
		m_pReferences = NewReferences;
	}
	m_pReferences[m_usedReferences - 1].pointer = pointer;
	m_pReferences[m_usedReferences - 1].Valid = true;
	m_pReferences[m_usedReferences - 1].CollectionType = CollectionType;
	return m_usedReferences - 1;
}

// Post condition: Returns the pointer for the given external ID.
// This allow NULL as a valid argument
void* EngineCore::VoidPointerFromID(int ID) {
	if (ID < 0 || ID >= m_usedReferences) {
		swprintf_s( MQ->messageBuffer, L"VoidPointerFromID: %i is out of bound for the reference numbers!", ID); MQ->InsertMessage(MQ->messageBuffer);
		return NULL;
	} else if (m_pReferences[ID].Valid == false) {
		swprintf_s( MQ->messageBuffer, L"VoidPointerFromID: %i is not a valid reference number!", ID); MQ->InsertMessage(MQ->messageBuffer);
		return NULL;
	} else {
		return m_pReferences[ID].pointer;
	}
}

// Post condition: Returns the type for the given external ID.
int EngineCore::TypeFromID(int ID) {
	if (ID < 0 || ID >= m_usedReferences) {
		return 0;
	} else if (m_pReferences[ID].Valid == false) {
		return 0;
	} else {
		return m_pReferences[ID].CollectionType;
	}
}

// Precondition: The ID in the struct must have the same place as in a Texture_Struct
//   If the precondition is broken, random behaviour might occur.
// Post condition: Returns the external ID from the given pointer.
int EngineCore::IDFromPointer(void* Pointer) {
	if (Pointer == NULL) {
		return 0;
	} else {
		int NewID;
		NewID = ((Abstract_Struct*)Pointer)->ID;
		if (NewID < 0 || NewID >= m_usedReferences) { // Asserting the range for initial testing
			swprintf_s( MQ->messageBuffer, L"%i is out of bound for the reference numbers but was returned from the engine as a result! You should report how you got this error so that I can add more safety.", NewID); MQ->InsertMessage(MQ->messageBuffer);
			return 0;
		} else {
			return NewID;
		}
	}
}

EngineCore::EngineCore(void) {
	int i;
	
	MQ = NULL;
	
	CORE_DATA_TABLE(INIT)
	
	// The most important pointers
	m_pd3dDevice = NULL;
	m_pImmediateContext = NULL;
	m_pSwapChain = NULL;
	ZeroMemory(&m_PhysicsCore,sizeof(PhysicsCore));
	m_D3DLineVertexBuffer = NULL;
	
	// Reset data used by the file parser for consistency and safety
	Parser_CurrentModel = NULL;
	writeIndex = -1;
	counting = false;
	GeneratorString = NULL;
	LoopForwardLengthFromZero(i,32) {
		NumberString[i] = 0;
	}
	
	// Start memory and reference manager
	m_pReferences = new ReferenceTable[m_lenReferences];
	LoopForward(0,i,m_lenReferences-1) {
		m_pReferences[i].pointer = NULL;
		m_pReferences[i].Valid = false;
		m_pReferences[i].CollectionType = ColType_None;
	}
	
	// Start collections
	COLLECTION_TABLE(StartCollection)
	
	// Reset double link lists
	LL_ModifiedCPUSurface.ResetMemory();
	LL_ModifiedShape.ResetMemory();
	
	// Input is cleaned up to enforce deterministic debugging
	PostEffect_CleanUpInput();
	Draw_CleanUpInput();
}

EngineCore::~EngineCore(void) {
	// Disable use counting when we are not testing the engine
	#ifndef _DEBUG
		m_SilentTermination = true;
	#endif
	
	CORE_DATA_TABLE(RELEASE)
	
	// The most important pointers
	Try_Start {
		if( m_pImmediateContext ) m_pImmediateContext->ClearState();
		SAFE_RELEASE( m_pd3dDevice )
		SAFE_RELEASE( m_pSwapChain )
		SAFE_RELEASE( m_pImmediateContext )
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation while releasing the Direct 3D interface. Report this error if you are using the latest version of the graphics engine so that you can get a new version without the bug.",L"Error!",NULL);
	}
	
	// Disconnect any default material shader
	DISCONNECT(m_pDefaultMaterialShader,L"Access violation while disconnecting default material shader. Report this error if you are using the latest version of the graphics engine so that you can get a new version without the bug.")
	
	// Disconnect any default texture
	DISCONNECT(m_pDefaultTexture,L"Access violation while disconnecting default texture. Report this error if you are using the latest version of the graphics engine so that you can get a new version without the bug.")
	
	// Disconnect any light projection atlas
	DISCONNECT(m_pLightProjectionAtlas,L"Access violation while disconnecting light projection atlas. Report this error if you are using the latest version of the graphics engine so that you can get a new version without the bug.")
	
	// Disconnect any sky instance
	DISCONNECT(m_pSkyInstance,L"Access violation while disconnecting sky instance. Report this error if you are using the latest version of the graphics engine so that you can get a new version without the bug.")

	// Disconnect and delete all children
	Try_Start {
		int i;
		CollisionShape_Struct* pCurrentShape;
		LoopForwardLengthFromZero(i, SizeOfCollection(CollisionShape)) {
			pCurrentShape = (CollisionShape_Struct*)m_CollisionShape.getValue_warning(i);
			CollisionShape_Compound_DeleteAllChildren(pCurrentShape);
		}
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation while deleting all compound shapes. Report this error if you are using the latest version of the graphics engine so that you can get a new version without the bug.",L"Error!",NULL);
	}
	
	Try_Start {
		// End collections
		COLLECTION_TABLE(EndCollection)
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation while terminating collections. Report this error if you are using the latest version of the graphics engine so that you can get a new version without the bug.",L"Error!",NULL);
	}
	
	Try_Start {
		// End debug drawing
		DebugLine_Terminate();
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation while terminating debug drawing. Report this error if you are using the latest version of the graphics engine so that you can get a new version without the bug.",L"Error!",NULL);
	}
	
	// End the physics engine
	Physics_Terminate(&m_PhysicsCore);
	
	Try_Start {
		// End memory and reference manager
		m_CollectGarbage = false; //No more reuse of memory
		SAFE_DELETE_ARRAY(m_pReferences)
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation while releasing the reference table. Report this error if you are using the latest version of the graphics engine so that you can get a new version without the bug.",L"Error!",NULL);
	}
	
	// These methods can't be in the table because they must be released in reverse order
	Try_Start {
		SAFE_RELEASE(m_pListener)
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation while releasing the sound engine's listener. Report this error if you are using the latest version of the graphics engine so that you can get a new version without the bug.",L"Error!",NULL);
	}
	Try_Start {
		SAFE_RELEASE(m_pMixingBuffer)
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation while releasing the sound engine's mixing buffer. Report this error if you are using the latest version of the graphics engine so that you can get a new version without the bug.",L"Error!",NULL);
	}
	Try_Start {
		SAFE_RELEASE(m_pSoundEngineInterface)
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation while releasing the sound engine's interface. Report this error if you are using the latest version of the graphics engine so that you can get a new version without the bug.",L"Error!",NULL);
	}
}

COLLECTION_TABLE(DEF_DEFAULT_METHODS)

// List all shared collections
INDEX_BY_NAME_DEC(Texture)
INDEX_BY_NAME_DEC(Shader)

void EngineCore::DrawSurface_InitEmpty(DrawSurface_Struct* Surface) {
	Surface->CurrentWidth = -1;
	Surface->CurrentHeight = -1;
	Surface->ColorInput = NULL;
	Surface->ColorOutput = NULL;
	Surface->ColorInput_Reverse = NULL;
	Surface->ColorOutput_Reverse = NULL;
	Surface->OriginalColorInput = NULL;
	Surface->OriginalColorBuffer = NULL;
	Surface->OriginalColorOutput = NULL;
	Surface->ExtraColorInput = NULL;
	Surface->ExtraColorBuffer = NULL;
	Surface->ExtraColorOutput = NULL;
	Surface->DepthBuffer = NULL;
	Surface->DepthBuffers = 0;
	Surface->DepthInputAndOutput = NULL;
	Surface->AutoSize = false;
	Surface->WidthMultiplier = 1.0f;
	Surface->HeightMultiplier = 1.0f;
	Surface->WidthAdder = 0;
	Surface->HeightAdder = 0;
	Surface->HasContent = false;
	Surface->ExtraDepthBuffer = NULL;
	Surface->DepthOutput = NULL;
	Surface->HaveValidDepthBuffer = false;
	Surface->ZWCorrection = DVector2(0.0f,0.0f);
	Surface->MaterialCount = 0;
	Surface->FinalSurface = false;
	Surface->HaveExtraColorBuffer = false;
	Surface->SwapState = false;
	Surface->ZWCorrection = DVector2(0.0f,0.0f);
}

void EngineCore::DrawSurface_SetSize_Linear(DrawSurface_Struct* Surface, float widthMultiplier, float heightMultiplier, int widthAdder, int heightAdder, bool FinalSurface, int DepthBuffers, bool HaveExtraColorBuffer, int WindowWidth, int WindowHeight) {
	DrawSurface_SetSize(Surface,(int)((float)WindowWidth * widthMultiplier) + widthAdder,(int)((float)WindowHeight * heightMultiplier) + heightAdder,FinalSurface,DepthBuffers,HaveExtraColorBuffer);
}

void EngineCore::DepthBuffer_InitEmpty(DepthBuffer_Struct* Surface) {
	Surface->CurrentWidth = -1;
	Surface->CurrentHeight = -1;
	Surface->DepthBuffer = NULL;
	Surface->DepthInputAndOutput = NULL;
	Surface->DepthOutput = NULL;
}

// Create methods

// DrawSurface
DrawSurface_Struct* EngineCore::DrawSurface_CreateFixed(int newWidth, int newHeight, int numberOfDepthBuffers, bool useExtraColorBuffer) {
	// Don't resize according to the window
	DrawSurface_Struct* newDrawSurface;
	Try_Start {
		AddToCollection(DrawSurface,newDrawSurface)
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::DrawSurface_CreateFixed: Access violation while adding to the collection.");
	}
	DrawSurface_InitEmpty(newDrawSurface);
	DrawSurface_SetSize(newDrawSurface,newWidth,newHeight,false,numberOfDepthBuffers,useExtraColorBuffer);
	newDrawSurface->FinalSurface = false;
	newDrawSurface->AutoSize = false;
	return newDrawSurface;
}
DrawSurface_Struct* EngineCore::DrawSurface_CreateAutoSized(float widthMultiplier, float heightMultiplier, int widthAdder, int heightAdder, int numberOfDepthBuffers, bool useExtraColorBuffer) {
	// Use a linear function to set the dimensions based on the window size
	DrawSurface_Struct* newDrawSurface;
	Try_Start {
		AddToCollection(DrawSurface,newDrawSurface)
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::DrawSurface_CreateAutoSized: Access violation while adding to the collection.");
	}
	DrawSurface_InitEmpty(newDrawSurface);
	RECT rc; GetClientRect( m_hWnd, &rc ); UINT width = rc.right - rc.left; UINT height = rc.bottom - rc.top;
	DrawSurface_SetSize_Linear(newDrawSurface,widthMultiplier,heightMultiplier,widthAdder,heightAdder,false,numberOfDepthBuffers,useExtraColorBuffer,width,height);
	newDrawSurface->FinalSurface = false;
	newDrawSurface->AutoSize = true;
	newDrawSurface->WidthMultiplier = widthMultiplier;
	newDrawSurface->HeightMultiplier = heightMultiplier;
	newDrawSurface->WidthAdder = widthAdder;
	newDrawSurface->HeightAdder = heightAdder;
	return newDrawSurface;
}

// CPUSurface
CPUSurface_Struct* EngineCore::CPUSurface_CreateFixed(int newWidth, int newHeight, float Red, float Green, float Blue, float Alpha) {
	CPUSurface_Struct* newCPUSurface;
	Try_Start {
		AddToCollection(CPUSurface,newCPUSurface)
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::CPUSurface_CreateFixed: Access violation while adding to the collection.");
	}
	newCPUSurface->Width = 0;
	newCPUSurface->Height = 0;
	newCPUSurface->StagingBuffer = NULL;
	newCPUSurface->CPUContent = NULL;
	newCPUSurface->LL_HeightField.ResetMemory();
	newCPUSurface->LL_ModifiedCPUSurface.ResetMemory();
	CPUSurface_SetSize(newCPUSurface,newWidth,newHeight,Red,Green,Blue,Alpha);
	return newCPUSurface;
}

// Texture
Texture_Struct* EngineCore::Texture_Load(wchar_t* filename, bool LockResource) {
	wchar_t extendedFilename[260];
	wchar_t comparisonName[260];
	wchar_t CurrentPath[260];
	int Width;
	int Height;
	ID3D11ShaderResourceView* newResource;
	int ExistingIndex;
	Try_Start {
		if (withoutPath(filename,comparisonName)) {
			ExistingIndex = FindTextureIndexByName(comparisonName);
			if (ExistingIndex > -1) {
				// Use existing texture
				Texture_Struct* Existing;
				Try_Start {
					Existing = (Texture_Struct*)m_Texture.getValue_warning(ExistingIndex);
				} Try_Else {
					swprintf_s( MQ->messageBuffer, L"EngineCore::Texture_Load: Access violation while getting an existing texture. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
					return NULL;
				}
				Try_Start {
					Existing->Locked = Existing->Locked || LockResource;
				} Try_Else {
					swprintf_s( MQ->messageBuffer, L"EngineCore::Texture_Load: Access violation while setting the lock flag. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
					return NULL;
				}
				return Existing;
			} else {
				// Check if the file exist in any of the 4 extensions and fail if nothing is found.
				Try_Start {
					if (replaceAfterDot(filename,extendedFilename,L"dds")) {
						if (!FileExist(extendedFilename)) {
							replaceAfterDot(filename,extendedFilename,L"bmp");
							if (!FileExist(extendedFilename)) {
								replaceAfterDot(filename,extendedFilename,L"png");
								if (!FileExist(extendedFilename)) {
									replaceAfterDot(filename,extendedFilename,L"jpg");
									if (!FileExist(extendedFilename)) {
										::GetCurrentDirectoryW(260,CurrentPath);
										swprintf_s( MQ->messageBuffer, L"Texture_Load: \"%s\" could not be found with the extensions dds, bmp, png and jpg from the path \"%s\".", filename, CurrentPath); MQ->InsertMessage(MQ->messageBuffer); \
										return NULL;
									}
								}
							}
						}
					} else {
						swprintf_s( MQ->messageBuffer, L"Texture_Load: The filename \"%s\" is too long.", filename); MQ->InsertMessage(MQ->messageBuffer); \
						return NULL;
					}
				} Try_Else {
					swprintf_s( MQ->messageBuffer, L"EngineCore::Texture_Load: Access violation while trying to find the file of any matching extension. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
					return NULL;
				}
				Try_Start {
					// Loading from file
					HRESULT hr = S_OK;
					D3DX11_IMAGE_LOAD_INFO ZeroInfo;
					D3DX11_IMAGE_INFO SrcInfo;
					D3DX11_IMAGE_LOAD_INFO* pLoadInfo;
					
					pLoadInfo = &ZeroInfo;
					newResource = NULL;
					Try_Start {
						D3DX11GetImageInfoFromFile( extendedFilename, NULL, &SrcInfo, NULL );
					} Try_Else {
						swprintf_s( MQ->messageBuffer, L"EngineCore::Texture_Load: Access violation while calling D3DX11GetImageInfoFromFile. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
						return NULL;
					}
					pLoadInfo->pSrcInfo = &SrcInfo;
					Width = (int)pLoadInfo->pSrcInfo->Width;
					Height = (int)pLoadInfo->pSrcInfo->Height;
					pLoadInfo->Format = pLoadInfo->pSrcInfo->Format;
					
					//Create the texture
					ID3D11Texture2D* pRes = NULL;
					Try_Start {
						hr = D3DX11CreateTextureFromFile( m_pd3dDevice, extendedFilename, pLoadInfo, NULL, ( ID3D11Resource** )&pRes, NULL );
					} Try_Else {
						swprintf_s( MQ->messageBuffer, L"EngineCore::Texture_Load: Access violation while calling D3DX11CreateTextureFromFile. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
						return NULL;
					}
					
					if( FAILED( hr ) ) {
						swprintf_s( MQ->messageBuffer, L"Texture_Load: \"%s\" was found but could not be loaded.", extendedFilename); MQ->InsertMessage(MQ->messageBuffer); \
						return NULL;
					}
					D3D11_TEXTURE2D_DESC tex_dsc;
					Try_Start {
						pRes->GetDesc(&tex_dsc);
					} Try_Else {
						swprintf_s( MQ->messageBuffer, L"EngineCore::Texture_Load: Access violation while getting the texture description. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
						return NULL;
					}
					
					D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
					
					Try_Start {
						SRVDesc.Format = ZeroInfo.Format;
						if( pLoadInfo->pSrcInfo->ResourceDimension == D3D11_RESOURCE_DIMENSION_TEXTURE1D )
						{
							SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
							SRVDesc.Texture1D.MostDetailedMip = 0;
							SRVDesc.Texture1D.MipLevels = pLoadInfo->pSrcInfo->MipLevels;
						}
						else if( pLoadInfo->pSrcInfo->ResourceDimension == D3D11_RESOURCE_DIMENSION_TEXTURE2D )
						{
							SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
							SRVDesc.Texture2D.MostDetailedMip = 0;
							SRVDesc.Texture2D.MipLevels = pLoadInfo->pSrcInfo->MipLevels;
							
							if( pLoadInfo->pSrcInfo->MiscFlags & D3D11_RESOURCE_MISC_TEXTURECUBE )
							{
								SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
								SRVDesc.TextureCube.MostDetailedMip = 0;
								SRVDesc.TextureCube.MipLevels = pLoadInfo->pSrcInfo->MipLevels;
							}
						}
						else if( pLoadInfo->pSrcInfo->ResourceDimension == D3D11_RESOURCE_DIMENSION_TEXTURE3D )
						{
							SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
							SRVDesc.Texture3D.MostDetailedMip = 0;
							SRVDesc.Texture3D.MipLevels = pLoadInfo->pSrcInfo->MipLevels;
						}
						SRVDesc.Format = tex_dsc.Format;
					} Try_Else {
						swprintf_s( MQ->messageBuffer, L"EngineCore::Texture_Load: Access violation while getting the texture format. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
						return NULL;
					}
					SRVDesc.Texture2D.MipLevels = tex_dsc.MipLevels;
					SRVDesc.Texture2D.MostDetailedMip = 0;
					Try_Start {
						hr = m_pd3dDevice->CreateShaderResourceView( pRes, &SRVDesc, &newResource );
					} Try_Else {
						swprintf_s( MQ->messageBuffer, L"EngineCore::Texture_Load: Access violation while creating the shader resource view. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
						return NULL;
					}
					if (FAILED(hr)) {
						swprintf_s( MQ->messageBuffer, L"Texture_Load: \"%s\" was loaded but the resource view could not be created.", extendedFilename); MQ->InsertMessage(MQ->messageBuffer); \
						return NULL;
					}
					Try_Start {
						pRes->Release();
					} Try_Else {
						swprintf_s( MQ->messageBuffer, L"EngineCore::Texture_Load: Access violation while releasing the resource. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
						return NULL;
					}
				} Try_Else {
					swprintf_s( MQ->messageBuffer, L"EngineCore::Texture_Load: Access violation in the outer part of the real loading code. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
					return NULL;
				}
				
				Texture_Struct* newTexture;
				Try_Start {
					AddToCollection(Texture,newTexture)
						newTexture->ColorOutput = newResource;
						newTexture->Width = Width;
						newTexture->Height = Height;
						Try_Start {
							CopyToFixedSizePath(comparisonName,newTexture->FileName);
						} Try_Else {
							swprintf_s( MQ->messageBuffer, L"EngineCore::Texture_Load: Access violation while duplicating the texture's filename. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
							return NULL;
						}
						newTexture->Locked = LockResource;
				} Try_Else {
					swprintf_s( MQ->messageBuffer, L"EngineCore::Texture_Load: Access violation while adding the texture to the collection. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
					return NULL;
				}
				return newTexture;
			}
		} else {
			swprintf_s( MQ->messageBuffer, L"Texture_Load: The filename \"%s\" is too long.", filename); MQ->InsertMessage(MQ->messageBuffer); \
			return NULL;
		}
	} Try_Else {
		swprintf_s( MQ->messageBuffer, L"EngineCore::Texture_Load: Access violation in the outer layer. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
		return NULL;
	}
}

#define CHOOSE_VERTEX_LAYOUT(NAME,BYTEARRAY) \
	UINT numElements = ARRAYSIZE(NAME); \
	hr = m_pd3dDevice->CreateInputLayout( NAME, numElements, BYTEARRAY->TheData, BYTEARRAY->GetSizeInBytes(), &pNewVertexLayout );

// Constraint
#define USE_ONE_BODY \
	newConstraint->BodyA = Body; \
	StartUsing(Body->useCount); \
	newConstraint->BodyB = NULL;
#define USE_TWO_BODIES \
	newConstraint->BodyA = BodyA; \
	StartUsing(BodyA->useCount); \
	newConstraint->BodyB = BodyB; \
	StartUsing(BodyB->useCount);
#define MAKE_CONSTRAINT_CONSTRUCTOR_CONTENT(CONSTRAINTTYPE,CONSTRUCTION,BODY_USE) \
	Constraint_Struct* newConstraint; \
	if (m_Running == true) { \
		AddToCollection(Constraint,newConstraint); \
		newConstraint->ConstraintType = CONSTRAINTTYPE; \
		CONSTRUCTION \
		m_PhysicsCore.dynamicsWorld->addConstraint(newConstraint->Constraint); \
		BODY_USE \
		return newConstraint; \
	} else { \
		MQ->InsertMessage(L"You can't create a constraint before starting the engine."); \
		return 0; \
	}
Constraint_Struct* EngineCore::Constraint_Create_PointToPoint_1(RigidBody_Struct* Body,float Point_X,float Point_Y,float Point_Z) {
	MAKE_CONSTRAINT_CONSTRUCTOR_CONTENT(
		ConstraintType_PointToPoint_1,
		newConstraint->Constraint = new btPoint2PointConstraint(*(Body->Body),btVector3(Point_X,Point_Y,Point_Z));,
		USE_ONE_BODY
	)
}
Constraint_Struct* EngineCore::Constraint_Create_PointToPoint_2(RigidBody_Struct* BodyA,RigidBody_Struct* BodyB,float PointA_X,float PointA_Y,float PointA_Z,float PointB_X,float PointB_Y,float PointB_Z) {
	MAKE_CONSTRAINT_CONSTRUCTOR_CONTENT(
		ConstraintType_PointToPoint_2,
		newConstraint->Constraint = new btPoint2PointConstraint(*(BodyA->Body),*(BodyB->Body),btVector3(PointA_X,PointA_Y,PointA_Z),btVector3(PointB_X,PointB_Y,PointB_Z));,
		USE_TWO_BODIES
	)
}
Constraint_Struct* EngineCore::Constraint_Create_Hinge_1(RigidBody_Struct* Body,float Pivot_X,float Pivot_Y,float Pivot_Z,float Axis_X,float Axis_Y,float Axis_Z) {
	MAKE_CONSTRAINT_CONSTRUCTOR_CONTENT(
		ConstraintType_Hinge_1,
		newConstraint->Constraint = new btHingeConstraint(*(Body->Body),btVector3(Pivot_X,Pivot_Y,Pivot_Z),btVector3(Axis_X,Axis_Y,Axis_Z),false);,
		USE_ONE_BODY
	)
}
Constraint_Struct* EngineCore::Constraint_Create_Hinge_2(RigidBody_Struct* BodyA,RigidBody_Struct* BodyB,float PivotA_X,float PivotA_Y,float PivotA_Z,float PivotB_X,float PivotB_Y,float PivotB_Z,float AxisA_X,float AxisA_Y,float AxisA_Z,float AxisB_X,float AxisB_Y,float AxisB_Z) {
	MAKE_CONSTRAINT_CONSTRUCTOR_CONTENT(
		ConstraintType_Hinge_2,
		newConstraint->Constraint = new btHingeConstraint(*(BodyA->Body),*(BodyB->Body),btVector3(PivotA_X,PivotA_Y,PivotA_Z),btVector3(PivotB_X,PivotB_Y,PivotB_Z),btVector3(AxisA_X,AxisA_Y,AxisA_Z),btVector3(AxisB_X,AxisB_Y,AxisB_Z),false);,
		USE_TWO_BODIES
	)
}

// Rigid body
void EngineCore::RigidBody_SetTransformation_Aux(RigidBody_Struct* RigidBody,btTransform* NewTrans) {
	RigidBody->Body->setWorldTransform(*NewTrans);
	if (!(RigidBody->Dynamic)) {
		RigidBody->Body->setInterpolationWorldTransform(*NewTrans);
	}
}
void EngineCore::RigidBody_SetTransformation(RigidBody_Struct* RigidBody,DVector3 Pos, DVector3 XAxis, DVector3 YAxis) {
	btTransform NewTrans;
	MakeOrthogonalBtTransform(&NewTrans,Pos,XAxis,YAxis);
	RigidBody_SetTransformation_Aux(RigidBody,&NewTrans);
}
RigidBody_Struct* EngineCore::RigidBody_Create(CollisionShape_Struct* CollisionShape, float Mass, DVector3 Pos, DVector3 XAxis, DVector3 YAxis, bool Dynamic, bool Kinematic) {
	RigidBody_Struct* newRigidBody;
	if (m_Running == true) {
		// Add to collection
		AddToCollection(RigidBody,newRigidBody)
		
		// Calculate the shape's local inertia if needed
		if (!(CollisionShape->HasValidLocalInertiaPerMass)) {
			CollisionShape->CollisionShape->calculateLocalInertia(1.0f,CollisionShape->LocalInertiaPerMass);
			CollisionShape->HasValidLocalInertiaPerMass = true;
		}

		// Create the body
		btRigidBody::btRigidBodyConstructionInfo cinfo(Mass,NULL,CollisionShape->CollisionShape,CollisionShape->LocalInertiaPerMass * Mass);
		newRigidBody->Body = new btRigidBody(cinfo);
		
		// Remember the linear and angular mass
		newRigidBody->LinearMass = Mass;
		newRigidBody->LocalInertia = DVector3(CollisionShape->LocalInertiaPerMass.getX() * Mass,CollisionShape->LocalInertiaPerMass.getY() * Mass,CollisionShape->LocalInertiaPerMass.getZ() * Mass);

		// Store a pointer to the graphics engine's struct
		newRigidBody->Body->setUserPointer(newRigidBody);
		
		// Add the kinematic flag if needed
		if (Kinematic) {
			newRigidBody->Body->setCollisionFlags(newRigidBody->Body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
			newRigidBody->Body->setActivationState(DISABLE_DEACTIVATION);
		}
		
		// Place the body
		RigidBody_SetTransformation(newRigidBody,Pos,XAxis,YAxis);
		
		// Remember if it is dynamic to avoid dangerous floating point comparisons
		newRigidBody->Dynamic = Dynamic;
		
		// Add it to the dynamics world
		m_PhysicsCore.dynamicsWorld->addRigidBody(newRigidBody->Body);
		
		// Add 1 use of Shape
		newRigidBody->CollisionShape = CollisionShape;
		StartUsing(CollisionShape->useCount);
		
		// Initiate the body for the use list
		newRigidBody->LL_BodyUseShape.ResetMemory();
		
		// Initiate the head for the follow list
		newRigidBody->LL_Follow.ResetMemory();
		
		// Push to a double linked list of users
		CollisionShape->LL_BodyUseShape.Insert(&(newRigidBody->LL_BodyUseShape),newRigidBody);
		
		return newRigidBody;
	} else {
		MQ->InsertMessage(L"You can't create a rigid body before starting the engine.");
		return 0;
	}
}

// Collision shape
CollisionShape_Struct* EngineCore::GeneralCollisionShapeConstructor(int ShapeType,btCollisionShape* CollisionShape,CPUSurface_Struct* CPUSurface) {
	CollisionShape_Struct* newCollisionShape;
	if (CollisionShape) {
		if (m_Running == true) {
			AddToCollection(CollisionShape,newCollisionShape)
			newCollisionShape->ShapeType = ShapeType;
			newCollisionShape->CPUSurface = CPUSurface;
			if (CPUSurface) {
				StartUsing(CPUSurface->useCount);
			}
			newCollisionShape->CollisionShape = CollisionShape;
			newCollisionShape->CollisionShape->setUserPointer(newCollisionShape);
			newCollisionShape->HasValidLocalInertiaPerMass = false;
			newCollisionShape->HasCompoundParent = false;
			newCollisionShape->LL_BodyUseShape.ResetMemory();
			newCollisionShape->LL_HeightField.ResetMemory();
			if (CPUSurface) {
				CPUSurface->LL_HeightField.Insert(&(newCollisionShape->LL_HeightField),newCollisionShape);
			}
			newCollisionShape->LL_ModifiedShape.ResetMemory();
			return newCollisionShape;
		} else {
			MQ->InsertMessage(L"You can't create a collision shape before starting the engine.");
			return 0;
		}
	} else {
		MQ->InsertMessage(L"GeneralCollisionShapeConstructor: Could not allocate memory for the shape in Bullet.");
		return 0;
	}
}
CollisionShape_Struct* EngineCore::CollisionShape_Create_Box(float HalfWidth, float HalfHeight, float HalfDepth,CPUSurface_Struct* CPUSurface) {
	if (HalfWidth < 0.0f) {
		MQ->InsertMessage(L"CollisionShape_Create_Box: HalfWidth must be greater than zero.");
		return 0;
	} else if (HalfHeight < 0.0f) {
		MQ->InsertMessage(L"CollisionShape_Create_Box: HalfHeight must be greater than zero.");
		return 0;
	} else if (HalfDepth < 0.0f) {
		MQ->InsertMessage(L"CollisionShape_Create_Box: HalfDepth must be greater than zero.");
		return 0;
	} else {
		return GeneralCollisionShapeConstructor(ShapeType_Box,new btBoxShape(btVector3(HalfWidth,HalfHeight,HalfDepth)),NULL);
	}
}
CollisionShape_Struct* EngineCore::CollisionShape_Create_Sphere(float Radius,CPUSurface_Struct* CPUSurface) {
	if (Radius < 0.0f) {
		MQ->InsertMessage(L"CollisionShape_Create_Sphere: Radius must be greater than zero.");
		return 0;
	} else {
		return GeneralCollisionShapeConstructor(ShapeType_Sphere,new btSphereShape(Radius),NULL);
	}
}
CollisionShape_Struct* EngineCore::CollisionShape_Create_StaticPlane(float NX, float NY, float NZ, float D,CPUSurface_Struct* CPUSurface) {
	return GeneralCollisionShapeConstructor(ShapeType_StaticPlane,new btStaticPlaneShape(btVector3(NX,NY,NZ),D),NULL);
}
CollisionShape_Struct* EngineCore::CollisionShape_Create_Cylinder(float HalfWidth, float HalfHeight, float HalfDepth,CPUSurface_Struct* CPUSurface) {
	if (HalfWidth < 0.0f) {
		MQ->InsertMessage(L"CollisionShape_Create_Cylinder: HalfWidth must be greater than zero.");
		return 0;
	} else if (HalfHeight < 0.0f) {
		MQ->InsertMessage(L"CollisionShape_Create_Cylinder: HalfHeight must be greater than zero.");
		return 0;
	} else if (HalfDepth < 0.0f) {
		MQ->InsertMessage(L"CollisionShape_Create_Cylinder: HalfDepth must be greater than zero.");
		return 0;
	} else {
		return GeneralCollisionShapeConstructor(ShapeType_Cylinder,new btCylinderShape(btVector3(HalfWidth,HalfHeight,HalfDepth)),NULL);
	}
}
CollisionShape_Struct* EngineCore::CollisionShape_Create_Capsule(float Radius, float Height,CPUSurface_Struct* CPUSurface) {
	if (Radius < 0.0f) {
		MQ->InsertMessage(L"CollisionShape_Create_Capsule: Radius must be greater than zero.");
		return 0;
	} else if (Height < 0.0f) {
		MQ->InsertMessage(L"CollisionShape_Create_Capsule: Height must be greater than zero.");
		return 0;
	} else {
		return GeneralCollisionShapeConstructor(ShapeType_Capsule,new btCapsuleShape(Radius,Height),NULL);
	}
}
CollisionShape_Struct* EngineCore::CollisionShape_Create_Cone(float Radius, float Height,CPUSurface_Struct* CPUSurface) {
	if (Radius < 0.0f) {
		MQ->InsertMessage(L"CollisionShape_Create_Cone: Radius must be greater than zero.");
		return 0;
	} else if (Height < 0.0f) {
		MQ->InsertMessage(L"CollisionShape_Create_Cone: Height must be greater than zero.");
		return 0;
	} else {
		return GeneralCollisionShapeConstructor(ShapeType_Cone,new btConeShape(Radius,Height),NULL);
	}
}
CollisionShape_Struct* EngineCore::CollisionShape_Create_HeightField_UsingCPUSurface(int HeightStickWidth, int HeightStickLength,void* heightfieldData,float minHeight,float maxHeight,int upDimension,int channelIndex,bool flipQuadEdges,bool diamondPattern,CPUSurface_Struct* CPUSurface) {
	// Preconditions are checked in the interface
	return GeneralCollisionShapeConstructor(ShapeType_HeightField,new FourChannelHeightField(HeightStickWidth,HeightStickLength,heightfieldData,minHeight,maxHeight,upDimension,channelIndex,flipQuadEdges,diamondPattern),CPUSurface);
}
CollisionShape_Struct* EngineCore::CollisionShape_Create_Compound(CPUSurface_Struct* CPUSurface) {
	return GeneralCollisionShapeConstructor(ShapeType_Compound,new ModifiedCompound(),NULL);
}
CollisionShape_Struct* EngineCore::CollisionShape_Create_ConvexHull(CPUSurface_Struct* CPUSurface) {
	return GeneralCollisionShapeConstructor(ShapeType_ConvexHull,new btConvexHullShape(),NULL);
}

// Model
Model_Struct* EngineCore::CreateEmptyModel(void) {
	Model_Struct* newModel;
	if (m_Running == true) {
		// Add to collection
		AddToCollection(Model,newModel)
		
		// Allocate the mesh.
		newModel->Model.Init(m_pd3dDevice, m_pImmediateContext, MQ);
		
		return newModel;
	} else {
		MQ->InsertMessage(L"You can't create a model before starting the engine.");
		return 0;
	}
}

// Instance
Instance_Struct* EngineCore::Instance_Create(Model_Struct* Model) {
	int i;
	Instance_Struct* newInstance;
	
	// Add to collection
	Try_Start {
		AddToCollection(Instance,newInstance)
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::Instance_Create: Access violation while adding to the collection.");
	}
	
	// Set values.
	newInstance->Transformation = IdentityMatrix();
	newInstance->VisualModel = Model;
	newInstance->BoneFrame = NULL;
	LoopForward(0,i,NumberOfShaderChannels-1) {
		newInstance->Visible[i] = true;
	}
	newInstance->Mirrored = false;
	newInstance->ModifiedArguments = false;
	newInstance->DetailLevel_Int = 2;
	newInstance->DetailLevel_Float = 2.0f;
	newInstance->AutoDetailLevel = false;
	LoopForwardLengthFromZero(i,NumberOfUserVectorsPerInstance) {
		newInstance->UserProperties_Instance[i] = DVector4(0.0f, 0.0f, 0.0f, 0.0f);
	}
	newInstance->Color = DVector4(1.0f, 1.0f, 1.0f, 1.0f);
	LoopForwardLengthFromZero(i,NumberOfOverrideChannels) {
		newInstance->OverrideSurfaces[i].iSurfaceType = SurfaceType_Empty;
		newInstance->OverrideSurfaces[i].pSurface = NULL;
	}
	
	// Following rigid body
	newInstance->FollowedRigidBody = NULL;
	newInstance->UseLocalScaling = false;
	newInstance->LL_Follow.ResetMemory();
	
	// Lock the model so that it can't be deleted before the instance.
	if (Model) {
		StartUsing(Model->useCount);
	}

	return newInstance;
}

// Light sources
LightSource_Struct* EngineCore::LightSource_Create_Point_Shadowless(DVector3 Pos, float Radius, DVector3 RGBIntensity) {
	LightSource_Struct* newLightSource;
	
	// Add to collection
	Try_Start {
		AddToCollection(LightSource,newLightSource)
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::LightSource_Create_Point_Shadowless: Access violation while adding to the collection.");
	}
	
	// Set values
	newLightSource->ShadowlessType = LightType_Point;
	newLightSource->ShaderData.Type = LightType_Point;
	newLightSource->ShaderData.Pos = Pos;
	newLightSource->ShaderData.Radius = Radius;
	newLightSource->ShaderData.Color = RGBIntensity;
	newLightSource->HasDepthTile = false;
	newLightSource->IsOrthogonal = false;
	newLightSource->OutsideIntensity = 1.0f;
	newLightSource->FadeSize = 1.0f;
	newLightSource->EnabledByUser = true;
	
	return newLightSource;
}
LightSource_Struct* EngineCore::LightSource_Create_Sun_Shadowless(DVector3 Direction, DVector3 RGBIntensity) {
	LightSource_Struct* newLightSource;
	
	// Add to collection
	Try_Start {
		AddToCollection(LightSource,newLightSource)
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::LightSource_Create_Sun_Shadowless: Access violation while adding to the collection.");
	}
	
	// Set values
	newLightSource->ShadowlessType = LightType_Sun;
	newLightSource->ShaderData.Type = LightType_Sun;
	newLightSource->ShaderData.ZAxis = NormalizeVec3(Direction);
	newLightSource->ShaderData.Color = RGBIntensity;
	newLightSource->HasDepthTile = false;
	newLightSource->WantDepthTile = false;
	newLightSource->IsOrthogonal = true;
	newLightSource->OutsideIntensity = 1.0f;
	newLightSource->FadeSize = 1.0f;
	newLightSource->EnabledByUser = true;
	
	return newLightSource;
}
LightSource_Struct* EngineCore::LightSource_Create_Sun_Shadowcasting_SingleLayer(DVector3 Pos, DVector3 Direction, DVector3 UpVector, float NearClip, float FarClip, DVector3 RGBIntensity, float HalfWidth, float HalfHeight, float ShadowTransparency, int ResolutionGroup, float OutsideIntensity, float FadeSize) {
	LightSource_Struct* newLightSource;
	
	// Add to collection
	Try_Start {
		AddToCollection(LightSource,newLightSource)
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::LightSource_Create_Sun_Shadowcasting_SingleLayer: Access violation while adding to the collection.");
	}
	
	// Set values
	newLightSource->ShaderData.Pos = Pos;
	DVector3 NormalizedUpVector;
	DVector3 NormalizedDirection;
	newLightSource->ShadowlessType = LightType_Sun;
	newLightSource->ShaderData.Type = LightType_Sun_Shadow_SingleLayer;
	NormalizedDirection = NormalizeVec3(Direction);
	NormalizedUpVector = NormalizeVec3(UpVector);
	newLightSource->ShaderData.ZAxis = NormalizedDirection;
	newLightSource->ShaderData.XAxis = NormalizeVec3(CrossVec3(NormalizedUpVector,NormalizedDirection));
	newLightSource->ShaderData.YAxis = NormalizeVec3(CrossVec3(NormalizedDirection,newLightSource->ShaderData.XAxis));
	newLightSource->ShaderData.NearClip = NearClip;
	newLightSource->ShaderData.ShadowOffset = 0.0f;
	newLightSource->ShaderData.ShadowTransparency = ClampFloat(0.0f,ShadowTransparency,1.0f);
	newLightSource->ShaderData.Radius = FarClip;
	newLightSource->ShaderData.Color = RGBIntensity;
	newLightSource->ShaderData.WidthSlope = HalfWidth;
	newLightSource->ShaderData.HeightSlope = HalfHeight;
	newLightSource->HasDepthTile = false;
	newLightSource->WantDepthTile = true;
	newLightSource->IsOrthogonal = true;
	newLightSource->OutsideIntensity = ClampFloat(0.0f, OutsideIntensity, 1.0f);
	newLightSource->FadeSize = ClampFloat(0.001f, FadeSize, 1.0f);
	newLightSource->EnabledByUser = true;
	newLightSource->ResolutionGroup = ClampInt(0,ResolutionGroup,QASmallestSize);
	CreateDefaultDepthAtlasIfNeeded();
	
	return newLightSource;
}
LightSource_Struct* EngineCore::LightSource_Create_Spotlight_RoundAndSoft_Shadowless(DVector3 Pos, DVector3 Direction, DVector3 UpVector, float Radius, DVector3 RGBIntensity, float WidthSlope, float HeightSlope) {
	LightSource_Struct* newLightSource;
	
	// Add to collection
	Try_Start {
		AddToCollection(LightSource,newLightSource)
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::LightSource_Create_Spotlight_RoundAndSoft_Shadowless: Access violation while adding to the collection.");
	}
	
	// Set values
	newLightSource->ShaderData.Pos = Pos;
	DVector3 NormalizedUpVector;
	DVector3 NormalizedDirection;
	newLightSource->ShadowlessType = LightType_Spot;
	newLightSource->ShaderData.Type = LightType_Spot;
	NormalizedDirection = NormalizeVec3(Direction);
	NormalizedUpVector = NormalizeVec3(UpVector);
	newLightSource->ShaderData.ZAxis = NormalizedDirection;
	newLightSource->ShaderData.XAxis = NormalizeVec3(CrossVec3(NormalizedUpVector,NormalizedDirection));
	newLightSource->ShaderData.YAxis = NormalizeVec3(CrossVec3(NormalizedDirection,newLightSource->ShaderData.XAxis));
	newLightSource->ShaderData.NearClip = 0.01f;
	newLightSource->ShaderData.ShadowOffset = 0.0f;
	newLightSource->ShaderData.Radius = Radius;
	newLightSource->ShaderData.Color = RGBIntensity;
	newLightSource->ShaderData.WidthSlope = WidthSlope;
	newLightSource->ShaderData.HeightSlope = HeightSlope;
	newLightSource->HasDepthTile = false;
	newLightSource->WantDepthTile = false;
	newLightSource->IsOrthogonal = false;
	newLightSource->OutsideIntensity = 1.0f;
	newLightSource->FadeSize = 1.0f;
	newLightSource->EnabledByUser = true;
	
	return newLightSource;
}
LightSource_Struct* EngineCore::LightSource_Create_Spotlight_Atlas_Shadowless(DVector3 Pos, DVector3 Direction, DVector3 UpVector, float Radius, DVector3 RGBIntensity, float WidthSlope, float HeightSlope, float MinU, float MaxU, float MinV, float MaxV) {
	LightSource_Struct* newLightSource;
	
	// Add to collection
	Try_Start {
		AddToCollection(LightSource,newLightSource)
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::LightSource_Create_Spotlight_Atlas_Shadowless: Access violation while adding to the collection.");
	}
	
	// Set values
	newLightSource->ShaderData.Pos = Pos;
	DVector3 NormalizedUpVector;
	DVector3 NormalizedDirection;
	newLightSource->ShadowlessType = LightType_Spot_Atlas;
	newLightSource->ShaderData.Type = LightType_Spot_Atlas;
	NormalizedDirection = NormalizeVec3(Direction);
	NormalizedUpVector = NormalizeVec3(UpVector);
	newLightSource->ShaderData.ZAxis = NormalizedDirection;
	newLightSource->ShaderData.XAxis = NormalizeVec3(CrossVec3(NormalizedUpVector,NormalizedDirection));
	newLightSource->ShaderData.YAxis = NormalizeVec3(CrossVec3(NormalizedDirection,newLightSource->ShaderData.XAxis));
	newLightSource->ShaderData.NearClip = 0.01f;
	newLightSource->ShaderData.ShadowOffset = 0.0f;
	newLightSource->ShaderData.Radius = Radius;
	newLightSource->ShaderData.Color = RGBIntensity;
	newLightSource->ShaderData.WidthSlope = WidthSlope;
	newLightSource->ShaderData.HeightSlope = HeightSlope;
	newLightSource->ShaderData.TextureAtlasRect = DVector4(MinU, MaxU, MinV, MaxV);
	newLightSource->HasDepthTile = false;
	newLightSource->WantDepthTile = false;
	newLightSource->IsOrthogonal = false;
	newLightSource->OutsideIntensity = 1.0f;
	newLightSource->FadeSize = 1.0f;
	newLightSource->EnabledByUser = true;
	
	return newLightSource;
}
LightSource_Struct* EngineCore::LightSource_Create_Spotlight_RoundAndSoft_Shadowcasting(DVector3 Pos, DVector3 Direction, DVector3 UpVector, float Radius, DVector3 RGBIntensity, float WidthSlope, float HeightSlope, float NearClip, float ShadowTransparency, int ResolutionGroup) {
	LightSource_Struct* newLightSource;
	
	// Add to collection
	Try_Start {
		AddToCollection(LightSource,newLightSource)
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::LightSource_Create_Spotlight_RoundAndSoft_Shadowcasting: Access violation while adding to the collection.");
	}
	
	// Set values
	newLightSource->ShaderData.Pos = Pos;
	DVector3 NormalizedUpVector;
	DVector3 NormalizedDirection;
	newLightSource->ShadowlessType = LightType_Spot;
	newLightSource->ShaderData.Type = LightType_Spot_Shadow;
	NormalizedDirection = NormalizeVec3(Direction);
	NormalizedUpVector = NormalizeVec3(UpVector);
	newLightSource->ShaderData.ZAxis = NormalizedDirection;
	newLightSource->ShaderData.XAxis = NormalizeVec3(CrossVec3(NormalizedUpVector,NormalizedDirection));
	newLightSource->ShaderData.YAxis = NormalizeVec3(CrossVec3(NormalizedDirection,newLightSource->ShaderData.XAxis));
	newLightSource->ShaderData.NearClip = MaxFloat(0.001f,NearClip);
	newLightSource->ShaderData.ShadowOffset = 0.0f;
	newLightSource->ShaderData.ShadowTransparency = ClampFloat(0.0f,ShadowTransparency,1.0f);
	newLightSource->ShaderData.Radius = Radius;
	newLightSource->ShaderData.Color = RGBIntensity;
	newLightSource->ShaderData.WidthSlope = WidthSlope;
	newLightSource->ShaderData.HeightSlope = HeightSlope;
	newLightSource->HasDepthTile = false;
	newLightSource->WantDepthTile = true;
	newLightSource->IsOrthogonal = false;
	newLightSource->OutsideIntensity = 1.0f;
	newLightSource->FadeSize = 1.0f;
	newLightSource->EnabledByUser = true;
	newLightSource->ResolutionGroup = ClampInt(0,ResolutionGroup,QASmallestSize);
	CreateDefaultDepthAtlasIfNeeded();
	
	return newLightSource;
}
LightSource_Struct* EngineCore::LightSource_Create_Spotlight_Atlas_Shadowcasting(DVector3 Pos, DVector3 Direction, DVector3 UpVector, float Radius, DVector3 RGBIntensity, float WidthSlope, float HeightSlope, float MinU, float MaxU, float MinV, float MaxV, float NearClip, float ShadowTransparency, int ResolutionGroup) {
	LightSource_Struct* newLightSource;
	
	// Add to collection
	Try_Start {
		AddToCollection(LightSource,newLightSource)
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::LightSource_Create_Spotlight_Atlas_Shadowcasting: Access violation while adding to the collection.");
	}
	
	// Set values
	newLightSource->ShaderData.Pos = Pos;
	DVector3 NormalizedUpVector;
	DVector3 NormalizedDirection;
	newLightSource->ShadowlessType = LightType_Spot_Atlas;
	newLightSource->ShaderData.Type = LightType_Spot_Atlas_Shadow;
	NormalizedDirection = NormalizeVec3(Direction);
	NormalizedUpVector = NormalizeVec3(UpVector);
	newLightSource->ShaderData.ZAxis = NormalizedDirection;
	newLightSource->ShaderData.XAxis = NormalizeVec3(CrossVec3(NormalizedUpVector,NormalizedDirection));
	newLightSource->ShaderData.YAxis = NormalizeVec3(CrossVec3(NormalizedDirection,newLightSource->ShaderData.XAxis));
	newLightSource->ShaderData.NearClip = MaxFloat(0.001f,NearClip);
	newLightSource->ShaderData.ShadowOffset = 0.0f;
	newLightSource->ShaderData.ShadowTransparency = ClampFloat(0.0f,ShadowTransparency,1.0f);
	newLightSource->ShaderData.Radius = Radius;
	newLightSource->ShaderData.Color = RGBIntensity;
	newLightSource->ShaderData.WidthSlope = WidthSlope;
	newLightSource->ShaderData.HeightSlope = HeightSlope;
	newLightSource->ShaderData.TextureAtlasRect = DVector4(MinU, MaxU, MinV, MaxV);
	newLightSource->HasDepthTile = false;
	newLightSource->WantDepthTile = true;
	newLightSource->IsOrthogonal = false;
	newLightSource->OutsideIntensity = 1.0f;
	newLightSource->FadeSize = 1.0f;
	newLightSource->EnabledByUser = true;
	newLightSource->ResolutionGroup = ClampInt(0,ResolutionGroup,QASmallestSize);
	CreateDefaultDepthAtlasIfNeeded();
	
	return newLightSource;
}

// Camera
// Remember that Camera_CreateStructFromLight is a secondary constructor
Camera_Struct* EngineCore::Camera_Create(void) {
	Camera_Struct* newCamera;
	
	// Add to collection
	Try_Start {
		AddToCollection(Camera,newCamera)
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::Camera_Create: Access violation while adding to the collection.");
	}
	
	// Set values
	newCamera->Eye = DVector3(0.0f,0.0f,0.0f);
	newCamera->At = DVector3(1.0f,0.0f,0.0f);
	newCamera->Up = DVector3(0.0f,1.0f,0.0f);
	newCamera->FieldOfView = 3.1415926535897932384626433832795f / 4;
	newCamera->VerticalFieldOfView = 1;
	newCamera->EnableCuttingPlane = 0;
	newCamera->CuttingPlane = DVector4(0.0f,0.0f,0.0f,0.0f);
	newCamera->RefractiveMultiplier = 1.0f;
	newCamera->IsOrthogonal = 0;
	newCamera->OrthogonalHalfWidth = 1.0f;
	newCamera->OrthogonalHalfHeight = 1.0f;
	newCamera->DebugDraw = 0;
	return newCamera;
}

// SoundBuffer
SoundBuffer_Struct* EngineCore::CreateSoundBufferFromFile(wchar_t* Filename,int NewNumberOfCopies, bool LoadAs3DSound, bool Editable) {
	SoundBuffer_Struct* newSoundBuffer;
	SoundClass* newBuffer;
	// Add to collection
	AddToCollection(SoundBuffer,newSoundBuffer)
	
	// Allocate the sound
	newBuffer = new SoundClass(m_pSoundEngineInterface,m_hWnd,Filename,NewNumberOfCopies,LoadAs3DSound,Editable,MQ,m_Sound_MetersPerDistanceUnit);
	
	if(newBuffer == NULL) {
		return NULL;
	} else if (!(newBuffer->Flag_Loaded)) {
		return NULL;
	}
	newBuffer->MQ = MQ;
	newSoundBuffer->Buffer = newBuffer;
	return newSoundBuffer;
}
SoundBuffer_Struct* EngineCore::CreateEmptySoundBuffer(int NewNumberOfCopies, bool LoadAs3DSound, int SamplesPerSecond, int NumberOfChannels, int NumberOfSamplesPerChannel) {
	SoundBuffer_Struct* newSoundBuffer;
	SoundClass* newBuffer;
	// Add to collection
	AddToCollection(SoundBuffer,newSoundBuffer)
	
	// Allocate the sound
	newBuffer = new SoundClass(m_pSoundEngineInterface,m_hWnd,SamplesPerSecond,NumberOfChannels,NumberOfSamplesPerChannel,NewNumberOfCopies,LoadAs3DSound,MQ,m_Sound_MetersPerDistanceUnit);
	
	if(newBuffer == NULL) {
		return NULL;
	} else if (!(newBuffer->Flag_Loaded)) {
		return NULL;
	}
	newBuffer->MQ = MQ;
	newSoundBuffer->Buffer = newBuffer;
	return newSoundBuffer;
}

BoneFrame_Struct* EngineCore::BoneFrame_CreateEmpty(void) {
	int i;
	BoneFrame_Struct* newBoneFrame;
	
	// Add to collection
	Try_Start {
		AddToCollection(BoneFrame,newBoneFrame)
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::BoneFrame_CreateEmpty: Access violation while adding to the collection.");
	}
	
	// Set values
	Try_Start {
		LoopForwardLengthFromZero(i,MaxNumberOfBones) {
			newBoneFrame->Content.Bone[i].Start = DVector4(0.0f,0.0f,0.0f,0.0f);
			newBoneFrame->Content.Bone[i].YAxis = DVector4(0.0f,1.0f,0.0f,0.0f);
			newBoneFrame->Content.Bone[i].ZAxis = DVector4(0.0f,0.0f,1.0f,0.0f);
		}
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::BoneFrame_CreateEmpty: Access violation while setting initial bone positions.");
	}
	return newBoneFrame;
}

BoneFrame_Struct*  EngineCore::BoneFrame_CreateFromDefaultPose(Model_Struct* Model) {
	int i;
	BoneFrame_Struct* newBoneFrame;
	
	// Add to collection
	Try_Start {
		AddToCollection(BoneFrame,newBoneFrame)
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::BoneFrame_CreateEmpty: Access violation while adding to the collection.");
	}
	
	// Set values
	int NumberOfBonesInModel;
	DVector3 DefaultYAxis;
	DVector3 DefaultZAxis;
	DVector3 DefaultStart;
	
	NumberOfBonesInModel = Model->Model.GetNumberOfBones();
	Try_Start {
		LoopForwardLengthFromZero(i,MaxNumberOfBones) {
			if (i < NumberOfBonesInModel) {
				newBoneFrame->Content.Bone[i] = Model->Model.Bone_GetBone(i);
			} else {
				newBoneFrame->Content.Bone[i].Start = DVector4(0.0f,0.0f,0.0f,0.0f);
				newBoneFrame->Content.Bone[i].YAxis = DVector4(0.0f,1.0f,0.0f,0.0f);
				newBoneFrame->Content.Bone[i].ZAxis = DVector4(0.0f,0.0f,1.0f,0.0f);
			}
		}
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::BoneFrame_CreateEmpty: Access violation while setting initial bone positions.");
	}
	return newBoneFrame;
}

// Release methods

// DrawSurface
void EngineCore::DrawSurface_Struct_Release(DrawSurface_Struct* Reference) {
	Try_Start {
		SAFE_RELEASE(Reference->OriginalColorInput)
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in DrawSurface_Struct_Release when releasing the original color input.",L"Error!",NULL);
	}
	Try_Start {
		SAFE_RELEASE(Reference->OriginalColorBuffer)
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in DrawSurface_Struct_Release when releasing the original color buffer.",L"Error!",NULL);
	}
	Try_Start {
		SAFE_RELEASE(Reference->OriginalColorOutput)
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in DrawSurface_Struct_Release when releasing the original color output.",L"Error!",NULL);
	}
	Try_Start {
		SAFE_RELEASE(Reference->ExtraColorInput)
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in DrawSurface_Struct_Release when releasing the extra color input.",L"Error!",NULL);
	}
	Try_Start {
		SAFE_RELEASE(Reference->ExtraColorBuffer)
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in DrawSurface_Struct_Release when releasing the extra color buffer.",L"Error!",NULL);
	}
	Try_Start {
		SAFE_RELEASE(Reference->ExtraColorOutput)
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in DrawSurface_Struct_Release when releasing the extra color output.",L"Error!",NULL);
	}
	Try_Start {
		SAFE_RELEASE(Reference->DepthBuffer)
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in DrawSurface_Struct_Release when releasing the depth buffer.",L"Error!",NULL);
	}
	Try_Start {
		SAFE_RELEASE(Reference->DepthInputAndOutput)
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in DrawSurface_Struct_Release when releasing the depth stencil view.",L"Error!",NULL);
	}
	Try_Start {
		SAFE_RELEASE(Reference->ExtraDepthBuffer)
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in DrawSurface_Struct_Release when releasing the extra depth buffer.",L"Error!",NULL);
	}
	Try_Start {
		SAFE_RELEASE(Reference->DepthOutput)
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in DrawSurface_Struct_Release when releasing the depth output.",L"Error!",NULL);
	}
}

// CPUSurface
void EngineCore::CPUSurface_Struct_Release(CPUSurface_Struct* Reference) {
	Try_Start {
		SAFE_RELEASE(Reference->StagingBuffer)
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in CPUSurface_Struct_Release when releasing the staging buffer.",L"Error!",NULL);
	}
	Try_Start {
		SAFE_DELETE_ARRAY(Reference->CPUContent)
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in CPUSurface_Struct_Release when releasing the array.",L"Error!",NULL);
	}
}

// Texture
void EngineCore::Texture_Struct_Release(Texture_Struct* Reference) {
	Try_Start {
		SAFE_RELEASE( Reference->ColorOutput )
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in Texture_Struct_Release when releasing the color output.",L"Error!",NULL);
	}
}

// Shader
void EngineCore::Shader_Struct_Release(Shader_Struct* Reference) {
	Try_Start {
		SAFE_RELEASE( Reference->VS.pVertexLayout )
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in Shader_Struct_Release when releasing the vertex layout.",L"Error!",NULL);
	}
	Try_Start {
		SAFE_RELEASE( Reference->VS.pVertexShader )
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in Shader_Struct_Release when releasing the vertex shader.",L"Error!",NULL);
	}
	Try_Start {
		SAFE_RELEASE( Reference->PS.pPixelShader )
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in Shader_Struct_Release when releasing the pixel shader.",L"Error!",NULL);
	}
	Try_Start {
		SAFE_RELEASE( Reference->GS.pGeometryShader )
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in Shader_Struct_Release when releasing the geometry shader.",L"Error!",NULL);
	}
}

// Model
void EngineCore::Model_Struct_Release(Model_Struct* Reference) {
	Try_Start {
		Reference->Model.Terminate();
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in Model_Struct_Release when calling the destructor in the model.",L"Error!",NULL);
	}
}

// Constraint
void EngineCore::Constraint_Struct_Release(Constraint_Struct* Reference) {
	Try_Start {
		m_PhysicsCore.dynamicsWorld->removeConstraint(Reference->Constraint);
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in CollisionShape_Struct_Release when removing the Constraint from the dynamics world.",L"Error!",NULL);
	}
	Try_Start {
		SAFE_DELETE(Reference->Constraint)
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in CollisionShape_Struct_Release when deleting the Constraint.",L"Error!",NULL);
	}
	Try_Start {
		if (Reference->BodyA) {
			StopUsing(Reference->BodyA->useCount);
			Reference->BodyA = NULL;
		}
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in CollisionShape_Struct_Release when decreasing use count for it's body A.",L"Error!",NULL);
	}
	Try_Start {
		// Body B is optional
		if (Reference->BodyB) {
			StopUsing(Reference->BodyB->useCount);
			Reference->BodyB = NULL;
		}
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in CollisionShape_Struct_Release when decreasing use count for it's body B.",L"Error!",NULL);
	}
}

// Rigid body
void EngineCore::RigidBody_Struct_Release(RigidBody_Struct* Reference) {
	Try_Start {
		m_PhysicsCore.dynamicsWorld->removeCollisionObject(Reference->Body);
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in RigidBody_Struct_Release when removing the rigid body from the dynamics world.",L"Error!",NULL);
	}
	Try_Start {
		SAFE_DELETE(Reference->Body)
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in RigidBody_Struct_Release when calling the destructor in the rigid body.",L"Error!",NULL);
	}
	if (!(Reference->CollisionShape)) {
		::MessageBoxW(NULL,L"A rigid body had no shape assigned when deleting in RigidBody_Struct_Release.",L"Error!",NULL);
	}
	Try_Start {
		Reference->CollisionShape->LL_BodyUseShape.Remove(&(Reference->LL_BodyUseShape));
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in RigidBody_Struct_Release when removed from a CPU surface's double linked list.",L"Error!",NULL);
	}
	Try_Start {
		StopUsing(Reference->CollisionShape->useCount);
		Reference->CollisionShape = NULL;
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in RigidBody_Struct_Release when decreasing use count for it's shape.",L"Error!",NULL);
	}
}

// Collision shape
void EngineCore::CollisionShape_Compound_DeleteAllChildren(CollisionShape_Struct* CollisionShape) {
	if (CollisionShape->ShapeType == ShapeType_Compound) {
		// Cast to compound after knowing it's type
		ModifiedCompound* pCurrentCompoundShape = (ModifiedCompound*)(CollisionShape->CollisionShape);
		// Look at child zero until no child remains
		int i, NumberOfChildren;
		CollisionShape->HasValidLocalInertiaPerMass = false;
		NumberOfChildren = pCurrentCompoundShape->getNumChildShapes();
		LoopForwardLengthFromZero(i, NumberOfChildren) {
			// Get the first remaining child
			btCollisionShape* pCurrentChild = pCurrentCompoundShape->getChildShape(0);
			if (pCurrentChild) {
				// Get the pointer to the shape's struct in the graphics engine
				CollisionShape_Struct* pChildStruct = (CollisionShape_Struct*)(pCurrentChild->getUserPointer());
				if (pChildStruct) {
					// Decrease use count for the child
					StopUsing(pChildStruct->useCount);
					pChildStruct->HasCompoundParent = false;
				} else {
					::MessageBoxW(NULL,L"A pointer to a child's struct was NULL in CollisionShape_Struct_Release when removing child references.",L"Error!",NULL);
				}
				
				// Remove the child from the compound
				pCurrentCompoundShape->removeChildShapeByIndex(0);
				
				// Delete the child if nothing else is using it
				if (pChildStruct) {
					if (pChildStruct->useCount <= 0) {
						CollisionShape_Struct_Release(pChildStruct);
					}
				}
			} else {
				::MessageBoxW(NULL,L"A pointer to a child was NULL in CollisionShape_Struct_Release when removing child references.",L"Error!",NULL);
			}
		}
	}
}
void EngineCore::CollisionShape_Struct_Release(CollisionShape_Struct* Reference) {
	Try_Start {
		CollisionShape_Compound_DeleteAllChildren(Reference);
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in CollisionShape_Struct_Release when removing child references.",L"Error!",NULL);
	}
	Try_Start {
		SAFE_DELETE(Reference->CollisionShape)
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in CollisionShape_Struct_Release when deleting the shape.",L"Error!",NULL);
	}
	Try_Start {
		Reference->CPUSurface->LL_HeightField.Remove(&(Reference->LL_HeightField));
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in CollisionShape_Struct_Release when removed from a CPU surface's double linked list.",L"Error!",NULL);
	}
	Try_Start {
		if (Reference->CPUSurface) {
			// Remove use
			StopUsing(Reference->CPUSurface->useCount);
			Reference->CPUSurface = NULL;
		}
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in RigidBody_Struct_Release when decreasing use count for a connected CPU surface.",L"Error!",NULL);
	}
}

// Instance
void EngineCore::Instance_Struct_Release(Instance_Struct* Reference) {
	Try_Start {
		if (Reference->FollowedRigidBody) {
			StopUsing(Reference->FollowedRigidBody->useCount);
			Reference->FollowedRigidBody->LL_Follow.Remove(&(Reference->LL_Follow));
			Reference->FollowedRigidBody = NULL;
		}
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in Instance_Struct_Release when stop following a rigid body.",L"Error!",NULL);
	}
	Try_Start {
		if (Reference->VisualModel != NULL) {
			StopUsing(Reference->VisualModel->useCount);
		}
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in Instance_Struct_Release when decreasing the model's use count.",L"Error!",NULL);
	}
	Try_Start {
		if (Reference->BoneFrame != NULL) {
			StopUsing(Reference->BoneFrame->useCount);
		}
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in Instance_Struct_Release when decreasing the bone frame's use count.",L"Error!",NULL);
	}
	Try_Start {
		int i;
		LoopForwardLengthFromZero(i,NumberOfOverrideChannels) {
			Instance_ReleaseOverride(Reference,i);
		}
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in Instance_Struct_Release when releasing the instance overrides.",L"Error!",NULL);
	}
}

// Camera
void EngineCore::Camera_Struct_Release(Camera_Struct* Reference) {
	// The camera have no pointer to release
}

// LightSource
void EngineCore::LightSource_Struct_Release(LightSource_Struct* Reference) {
	// The light source have no pointer to release
}

// SoundBuffer
void EngineCore::SoundBuffer_Struct_Release(SoundBuffer_Struct* Reference) {
	Try_Start {
		SAFE_DELETE(Reference->Buffer)
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in SoundBuffer_Struct_Release when releasing the sound class.",L"Error!",NULL);
	}
}

// Bone frame
void EngineCore::BoneFrame_Struct_Release(BoneFrame_Struct* Reference) {
	// The bone frame have no pointer to release
}

void EngineCore::Camera_Place(Camera_Struct* Camera, DVector3 Eye, DVector3 At, DVector3 Up) {
	Camera->Eye = Eye;
	Camera->At = At;
	Camera->Up = Up;
}

DMatrix EngineCore::Camera_GetAxisSystem(Camera_Struct* Camera) {
	DMatrix CameraMatrix;
	DVector3 XAxis; DVector3 YAxis; DVector3 ZAxis;
	ZAxis = NormalizeVec3(SubVec3(Camera->At,Camera->Eye));
	XAxis = NormalizeVec3(CrossVec3(Camera->Up, ZAxis));
	YAxis = CrossVec3(ZAxis, XAxis);
	CameraMatrix._11 = XAxis.x; CameraMatrix._12 = XAxis.y; CameraMatrix._13 = XAxis.z; CameraMatrix._14 = 0.0f;
	CameraMatrix._21 = YAxis.x; CameraMatrix._22 = YAxis.y; CameraMatrix._23 = YAxis.z; CameraMatrix._24 = 0.0f;
	CameraMatrix._31 = ZAxis.x; CameraMatrix._32 = ZAxis.y; CameraMatrix._33 = ZAxis.z; CameraMatrix._34 = 0.0f;
	CameraMatrix._41 = Camera->Eye.x; CameraMatrix._42 = Camera->Eye.y; CameraMatrix._43 = Camera->Eye.z; CameraMatrix._44 = 1.0f;
	return CameraMatrix;
}

void EngineCore::Camera_SetVerticalFOV_InRadians(Camera_Struct* Camera, float FieldOfView) {
	Camera->FieldOfView = FieldOfView;
	Camera->VerticalFieldOfView = true;
}

void EngineCore::Camera_SetHorizontalFOV_InRadians(Camera_Struct* Camera, float FieldOfView) {
	Camera->FieldOfView = FieldOfView;
	Camera->VerticalFieldOfView = false;
}

void EngineCore::Camera_SetVerticalFOV_InDegrees(Camera_Struct* Camera, float FieldOfView) {
	Camera_SetVerticalFOV_InRadians(Camera,FieldOfView * 0.01745329251994f);
}
void EngineCore::Camera_SetHorizontalFOV_InDegrees(Camera_Struct* Camera, float FieldOfView) {
	Camera_SetHorizontalFOV_InRadians(Camera,FieldOfView * 0.01745329251994f);
}

void EngineCore::Instance_ReplaceModel(Instance_Struct* Instance, Model_Struct* Model) {
	if (Instance->VisualModel != NULL) StopUsing(Instance->VisualModel->useCount);
	if (Model) {
		StartUsing(Model->useCount);
	}
	Instance->VisualModel = Model;
}

void EngineCore::Instance_RemoveBoneFrame(Instance_Struct* Instance) {
	if (Instance->BoneFrame != NULL) StopUsing(Instance->BoneFrame->useCount);
	Instance->BoneFrame = NULL;
}

void EngineCore::Instance_AssignBoneFrame(Instance_Struct* Instance, BoneFrame_Struct* BoneFrame) {
	if (Instance->BoneFrame != NULL) {
		StopUsing(Instance->BoneFrame->useCount);
	}
	if (BoneFrame) {
		StartUsing(BoneFrame->useCount);
	}
	Instance->BoneFrame = BoneFrame;
}

void EngineCore::DrawSurface_SetSwapState(DrawSurface_Struct* Surface, bool NewSwapState) {
	if (Surface->ExtraColorBuffer == false) {
		Surface->ColorInput = Surface->OriginalColorInput;
		Surface->ColorOutput = Surface->OriginalColorOutput;
		Surface->ColorInput_Reverse = Surface->OriginalColorInput;
		Surface->ColorOutput_Reverse = Surface->OriginalColorOutput;
	} else {
		if (NewSwapState) {
			Surface->ColorInput = Surface->ExtraColorInput;
			Surface->ColorOutput = Surface->OriginalColorOutput;
			Surface->ColorInput_Reverse = Surface->OriginalColorInput;
			Surface->ColorOutput_Reverse = Surface->ExtraColorOutput;
		} else {
			Surface->ColorInput = Surface->OriginalColorInput;
			Surface->ColorOutput = Surface->ExtraColorOutput;
			Surface->ColorInput_Reverse = Surface->ExtraColorInput;
			Surface->ColorOutput_Reverse = Surface->OriginalColorOutput;
		}
	}
	Surface->SwapState = NewSwapState;
}

void EngineCore::SetFilter(int FilterIndex) {
	float blendFactor[4] = { 1.0f,1.0f,1.0f,1.0f };
	ID3D11BlendState* BlendState;
	if (FilterIndex == Filter_Alpha) {
		BlendState = m_pBS_AlphaFilter;
	} else {
		BlendState = NULL;
	}
	m_pImmediateContext->OMSetBlendState( BlendState, blendFactor, 0xfff);
}

void EngineCore::ShowLastRender(void) {
	// Present our back buffer to our front buffer
	m_pSwapChain->Present( 0, 0 );
	m_HasRenderedToFinalSurface = true;
}

int EngineCore::GetWantedSurfaceWidth(DrawSurface_Struct* Surface) {
	RECT rc; GetClientRect( m_hWnd, &rc ); UINT width = rc.right - rc.left;
	if(Surface->FinalSurface) {
		return width;
	} else if(Surface->AutoSize) {
		return ((int)(width * Surface->WidthMultiplier) + Surface->WidthAdder);
	} else {
		return Surface->CurrentWidth;
	}
}

int EngineCore::GetWantedSurfaceHeight(DrawSurface_Struct* Surface) {
	RECT rc; GetClientRect( m_hWnd, &rc ); UINT height = rc.bottom - rc.top;
	if(Surface->FinalSurface) {
		return height;
	} else if(Surface->AutoSize) {
		return ((int)(height * Surface->HeightMultiplier) + Surface->HeightAdder);
	} else {
		return Surface->CurrentHeight;
	}
}

void EngineCore::AutoSizeSurface(DrawSurface_Struct* Surface) {
	RECT rc; GetClientRect( m_hWnd, &rc ); UINT width = rc.right - rc.left; UINT height = rc.bottom - rc.top;
	if(Surface->FinalSurface) {
		DrawSurface_SetSize(Surface,width,height,true,2,false);
	} else if(Surface->AutoSize) {
		DrawSurface_SetSize_Linear(Surface,Surface->WidthMultiplier,Surface->HeightMultiplier,Surface->WidthAdder,Surface->HeightAdder,false,Surface->DepthBuffers,Surface->HaveExtraColorBuffer,width,height);
	}
}

void EngineCore::FillInstanceConstantBuffers(Instance_Struct* Item, ModelClass* Mesh, DVector4 Color) {
	int i; int NumberOfBones; int BoneBufferIndex; DVector3 DefaultYAxis; DVector3 DefaultZAxis; DVector3 DefaultStart;
	
	// Choose a constant buffer that can fit the bones
	NumberOfBones = Mesh->GetNumberOfBones();
	if (NumberOfBones <= 8) {
		BoneBufferIndex = 0;
	} else if (NumberOfBones <= 16) {
		BoneBufferIndex = 1;
	} else if (NumberOfBones <= 32) {
		BoneBufferIndex = 2;
	} else if (NumberOfBones <= 64) {
		BoneBufferIndex = 3;
	} else {
		NumberOfBones = 64;
		BoneBufferIndex = 3;
	}
	
	// Every object's data
	CBEveryObject cbEveryObject;
	cbEveryObject.mObjectToWorld = TransposeMatrix(Item->Transformation);
	cbEveryObject.Color = Color;
	cbEveryObject.DetailLevel = Item->DetailLevel_Float;
	cbEveryObject.BoneBuffer = BoneBufferIndex;
	m_pImmediateContext->UpdateSubresource( m_pCBEveryObject, 0, NULL, &cbEveryObject, 0, 0 );
	
	// Optional bone buffers
	if (NumberOfBones > 0) {
		CBBoneFrame_8 cbBoneFrame_8;
		CBBoneFrame_16 cbBoneFrame_16;
		CBBoneFrame_32 cbBoneFrame_32;
		CBBoneFrame_64 cbBoneFrame_64;
		switch (BoneBufferIndex) {
		case 0:
			if (Item->BoneFrame != NULL) {
				LoopForwardLengthFromZero(i,NumberOfBones) {
					cbBoneFrame_8.Bone[i] = Item->BoneFrame->Content.Bone[i];
				}
			} else {
				LoopForwardLengthFromZero(i,NumberOfBones) {
					cbBoneFrame_8.Bone[i] = Mesh->Bone_GetBone(i);
				}
			}
			m_pImmediateContext->UpdateSubresource( m_pCBBoneFrame_8, 0, NULL, &cbBoneFrame_8, 0, 0 );
		break;
		case 1:
			if (Item->BoneFrame != NULL) {
				LoopForwardLengthFromZero(i,NumberOfBones) {
					cbBoneFrame_16.Bone[i] = Item->BoneFrame->Content.Bone[i];
				}
			} else {
				LoopForwardLengthFromZero(i,NumberOfBones) {
					cbBoneFrame_16.Bone[i] = Mesh->Bone_GetBone(i);
				}
			}
			m_pImmediateContext->UpdateSubresource( m_pCBBoneFrame_16, 0, NULL, &cbBoneFrame_16, 0, 0 );
		break;
		case 2:
			if (Item->BoneFrame != NULL) {
				LoopForwardLengthFromZero(i,NumberOfBones) {
					cbBoneFrame_32.Bone[i] = Item->BoneFrame->Content.Bone[i];
				}
			} else {
				LoopForwardLengthFromZero(i,NumberOfBones) {
					cbBoneFrame_32.Bone[i] = Mesh->Bone_GetBone(i);
				}
			}
			m_pImmediateContext->UpdateSubresource( m_pCBBoneFrame_32, 0, NULL, &cbBoneFrame_32, 0, 0 );
		break;
		case 3:
			if (Item->BoneFrame != NULL) {
				LoopForwardLengthFromZero(i,NumberOfBones) {
					cbBoneFrame_64.Bone[i] = Item->BoneFrame->Content.Bone[i];
				}
			} else {
				LoopForwardLengthFromZero(i,NumberOfBones) {
					cbBoneFrame_64.Bone[i] = Mesh->Bone_GetBone(i);
				}
			}
			m_pImmediateContext->UpdateSubresource( m_pCBBoneFrame_64, 0, NULL, &cbBoneFrame_64, 0, 0 );
		break;
		default:
			MQ->InsertMessage(L"EngineCore::FillInstanceConstantBuffers: BoneBufferIndex is out of bound! Report this error if you use the latest version of the graphics engine.");
		}
	}
	
	// Optional argument buffer
	CBArgBuffer cbArgBuffer;
	if (Item->ModifiedArguments == true) {
		// The instance have modified arguments
		LoopForwardLengthFromZero(i,NumberOfUserVectorsPerInstance) {
			cbArgBuffer.UserProperties_Instance[i] = Item->UserProperties_Instance[i];
		}
		m_pImmediateContext->UpdateSubresource( m_pCBArgBuffer, 0, NULL, &cbArgBuffer, 0, 0 );
		m_ArgumentBufferIsDirty = true;
	} else if (m_ArgumentBufferIsDirty == true) {
		// We have no modified arguments in the current instance but the constant buffer is dirty and the shaders might be using them
		LoopForwardLengthFromZero(i,NumberOfUserVectorsPerInstance) {
			cbArgBuffer.UserProperties_Instance[i] = DVector4(0.0f,0.0f,0.0f,0.0f);
		}
		m_pImmediateContext->UpdateSubresource( m_pCBArgBuffer, 0, NULL, &cbArgBuffer, 0, 0 );
		m_ArgumentBufferIsDirty = false;
	}
}

void EngineCore::RenderItem(Instance_Struct* Item, int ShaderChannel, Shader_Struct* ShaderOverride, int FilterIndex, int RenderingMethod, int Part, DVector4 Color) {
	ModelClass* pCurrentMesh;
	Model_Struct* pCurrentModel;
	pCurrentModel = Item->VisualModel;
	if (pCurrentModel != NULL) {
		pCurrentMesh = &(pCurrentModel->Model);
		if (pCurrentMesh != NULL) {
			// Update per object constant buffer
			FillInstanceConstantBuffers(Item,pCurrentMesh,Color);
			
			// Select how triangles will be treated
			if (RenderingMethod == RenderingMethod_Edges) {
				m_pImmediateContext->RSSetState( m_StateWireFrame );
			} else if (RenderingMethod == RenderingMethod_DoubleSidedTriangles) {
				m_pImmediateContext->RSSetState( m_StateDoubleFace );
			} else {
				// Flip faces on mirrored objects
				if (Item->Mirrored) {
					m_pImmediateContext->RSSetState( m_StateBackFace );
				} else {
					m_pImmediateContext->RSSetState( m_StateFrontFace );
				}
			}
			
			// Choose filter
			SetFilter(FilterIndex);
			
			pCurrentModel->Model.Render(ShaderChannel,m_pDefaultMaterialShader,m_pDefaultTexture,Item->OverrideSurfaces,m_pLightProjectionAtlas,Item->DetailLevel_Int,ShaderOverride,Part,false);
		}
	}
}

// Replacing RenderItem for shadows
void EngineCore::RenderShadow(Instance_Struct* Item) {
	ModelClass* pCurrentMesh;
	Model_Struct* pCurrentModel;
	Try_Start {
		pCurrentModel = Item->VisualModel;
	} Try_Else {
		MQ->InsertMessage(L"RenderShadow: Access violation was detected when getting the current model.");
	}
	Try_Start {
		if (pCurrentModel != NULL) {
			pCurrentMesh = &(pCurrentModel->Model);
			if (pCurrentMesh != NULL) {
				Try_Start {
					// Update per object constant buffer
					FillInstanceConstantBuffers(Item,pCurrentMesh,Item->Color);
				} Try_Else {
					MQ->InsertMessage(L"RenderShadow: Access violation was detected when updating per object constant buffer.");
				}
				
				Try_Start {
					// Flip faces on mirrored objects
					if (Item->Mirrored) {
						m_pImmediateContext->RSSetState( m_StateBackFace );
					} else {
						m_pImmediateContext->RSSetState( m_StateFrontFace );
					}
				} Try_Else {
					MQ->InsertMessage(L"RenderShadow: Access violation was detected when flipping faces on mirrored objects.");
				}
				
				Try_Start {
					pCurrentModel->Model.Render(1,m_pDefaultMaterialShader,m_pDefaultTexture,Item->OverrideSurfaces,m_pLightProjectionAtlas,Item->DetailLevel_Int,NULL,-1,true);
				} Try_Else {
					MQ->InsertMessage(L"RenderShadow: Access violation was detected when rendering in the model class.");
				}
			}
		}
	} Try_Else {
		MQ->InsertMessage(L"RenderShadow: Access violation was detected after getting the current model.");
	}
}

HRESULT EngineCore::CreateFullScreenQuad(ID3D11Buffer** Buffer) {
	// Create vertex buffer
	VertexStructure_Quad vertices[] = {
		{ DVector3( -1.0f, 1.0f, 0.5f ) },
		{ DVector3( 1.0f, 1.0f, 0.5f ) },
		{ DVector3( -1.0f, -1.0f, 0.5f ) },
		{ DVector3( 1.0f, 1.0f, 0.5f ) },
		{ DVector3( 1.0f, -1.0f, 0.5f ) },
		{ DVector3( -1.0f, -1.0f, 0.5f ) },
	};
	D3D11_BUFFER_DESC bd;
	ZeroMemory( &bd, sizeof(bd) );
	bd.Usage = D3D11_USAGE_DEFAULT;
	bd.ByteWidth = sizeof( VertexStructure_Quad ) * ARRAYSIZE(vertices);
	bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	bd.CPUAccessFlags = 0;
	D3D11_SUBRESOURCE_DATA InitData;
	ZeroMemory( &InitData, sizeof(InitData) );
	InitData.pSysMem = vertices;
	
	return  m_pd3dDevice->CreateBuffer( &bd, &InitData, Buffer );
}

void EngineCore::PostEffect_RenderShader(DrawSurface_Struct* OutputSurface, Shader_Struct* PostEffect) {
	int i;
	ID3D11ShaderResourceView* InputResourceViews[16];
	int	InputResourceType[16];
	DVector2 InputResourceZWCorrection[16];
	int RecievedType;
	void* SurfacePointer;
	CBPostEffect cbPostEffect;
	D3D11_VIEWPORT vp;
	
	Try_Start {
		// Convert from ID to resource view pointers
		LoopForwardLengthFromZero(i,16) {
			InputResourceZWCorrection[i] = DVector2(0.0f, 0.0f);
			if (m_PostEffect_InputTextures[i] != 0) {
				SurfacePointer = VoidPointerFromID(m_PostEffect_InputTextures[i]);
				if (SurfacePointer == NULL) {
					swprintf_s( MQ->messageBuffer, L"PostEffect_RenderShader: Input surface at index %i recieved ID %i that not is a valid reference.", i, m_PostEffect_InputTextures[i]); MQ->InsertMessage(MQ->messageBuffer);
					InputResourceType[i] = 0;
				} else {
					RecievedType = m_pReferences[m_PostEffect_InputTextures[i]].CollectionType;
					if (RecievedType == ColType_DrawSurface) {
						if (((DrawSurface_Struct*)SurfacePointer)->FinalSurface) {
							swprintf_s( MQ->messageBuffer, L"PostEffect_RenderShader: Input texture at index %i is the final draw surface that only can be written to.", i); MQ->InsertMessage(MQ->messageBuffer);
						} else if (m_PostEffect_InputTextureSubresourceTypes[i] == SubresourceType_Color) {
							InputResourceViews[i] = ((DrawSurface_Struct*)SurfacePointer)->ColorOutput;
						} else if (m_PostEffect_InputTextureSubresourceTypes[i] == SubresourceType_Depth) {
							if (((DrawSurface_Struct*)SurfacePointer)->DepthOutput == NULL) {
								swprintf_s( MQ->messageBuffer, L"PostEffect_RenderShader: The draw surface at index %i does not have a depth buffer to read from. The color buffer is used instead.", i, m_PostEffect_InputTextureSubresourceTypes[i]); MQ->InsertMessage(MQ->messageBuffer);
								InputResourceViews[i] = ((DrawSurface_Struct*)SurfacePointer)->ColorOutput;
							} else {
								if (((DrawSurface_Struct*)SurfacePointer)->HaveValidDepthBuffer == false) {
									swprintf_s( MQ->messageBuffer, L"PostEffect_RenderShader: The draw surface at index %i does not have valid content in it's depth buffer. You must render a scene to it to fill it with depth. Resizing will make it invalid again.", i, m_PostEffect_InputTextureSubresourceTypes[i]); MQ->InsertMessage(MQ->messageBuffer);
									InputResourceViews[i] = ((DrawSurface_Struct*)SurfacePointer)->ColorOutput;
								} else {
									InputResourceViews[i] = ((DrawSurface_Struct*)SurfacePointer)->DepthOutput;
									InputResourceZWCorrection[i] = ((DrawSurface_Struct*)SurfacePointer)->ZWCorrection;
								}
							}
						} else {
							swprintf_s( MQ->messageBuffer, L"PostEffect_RenderShader: The draw surface at index %i was given with the unknown subresource type %i. The color will be used instead.", i, m_PostEffect_InputTextureSubresourceTypes[i]); MQ->InsertMessage(MQ->messageBuffer);
							InputResourceViews[i] = ((DrawSurface_Struct*)SurfacePointer)->ColorOutput;
						}
					} else if (RecievedType == ColType_Texture) {
						if (((Texture_Struct*)SurfacePointer)->Locked == false) {
							swprintf_s( MQ->messageBuffer, L"PostEffect_RenderShader: Input texture at index %i was not locked and can be deleted by the engine. Only unlock resources when you are done with using them. Using unlocked resources is as bad as writing to unallocated memory.", i, m_PostEffect_InputTextures[i]); MQ->InsertMessage(MQ->messageBuffer);
						}
						InputResourceViews[i] = ((Texture_Struct*)SurfacePointer)->ColorOutput;
					}
				}
				InputResourceType[i] = 2;
			} else if (m_pDefaultTexture != NULL) {
				InputResourceType[i] = 1;
			} else {
				InputResourceType[i] = 0;
			}
		}
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::PostEffect_RenderShader: Access violation while converting reference numbers to pointers.\n");
		return;
	}
	
	Try_Start {
		// Make sure that the output is not also an input if the output don't have an extra color buffer
		if (OutputSurface->HaveExtraColorBuffer == false) {
			LoopForwardLengthFromZero(i,16) {
				if (InputResourceType[i] == 2 && m_PostEffect_InputTextureSubresourceTypes[i] == SubresourceType_Color) {
					if (((void*)OutputSurface) == VoidPointerFromID(m_PostEffect_InputTextures[i])) {
						if (OutputSurface->FinalSurface) {
							MQ->InsertMessage(L"PostEffect_RenderShader: The final draw surface is used as both input and output. The final draw surface does not have an extra color buffer because the ability would make it harder to use the engine. Use the final draw surface to store the result from the last post effect.");
						} else {
							swprintf_s( MQ->messageBuffer, L"PostEffect_RenderShader: Input surface at index %i is the same draw surface as OutputSurface. Accept the extra memory cost by creating the output draw surface with an extra color buffer.", i); MQ->InsertMessage(MQ->messageBuffer);
						}
						return;
					}
				}
			}
		}
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::PostEffect_RenderShader: Access violation while checking if double buffering is used without an extra buffer.\n");
		return;
	}
	
	Try_Start {
		// Set output surface
		AutoSizeSurface(OutputSurface);
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::PostEffect_RenderShader: Access violation while resizing the output surface.\n");
		return;
	}
	Try_Start {
		m_pImmediateContext->OMSetRenderTargets(1,&OutputSurface->ColorInput,NULL);
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::PostEffect_RenderShader: Access violation while selecting the render target.\n");
		return;
	}
	
	Try_Start {
		if (PostEffect->Locked == false) {
			MQ->InsertMessage(L"PostEffect_RenderShader: The shader is not locked and can be deleted by the engine. Only unlock resources when you are done with using them. Using unlocked resources is as bad as writing to unallocated memory.");
		}
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::PostEffect_RenderShader: Access violation while checking if the post effect shader is locked.\n");
		return;
	}
	Try_Start {
		if (PostEffect->Compiled == false) {
			MQ->InsertMessage(L"PostEffect_RenderShader: The shader is not compiled and can not be used for a post effect.");
			return;
		}
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::PostEffect_RenderShader: Access violation while checking if the post effect shader is compiled.\n");
		return;
	}
	Try_Start {
		m_pImmediateContext->IASetInputLayout( m_PostEffectVS.pVertexLayout );
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::PostEffect_RenderShader: Access violation while setting the vertex input layout.\n");
		return;
	}
	Try_Start {
		m_pImmediateContext->VSSetShader( m_PostEffectVS.pVertexShader, NULL, 0 );
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::PostEffect_RenderShader: Access violation while setting the vertex shader.\n");
		return;
	}
	Try_Start {
		m_pImmediateContext->PSSetShader( PostEffect->PS.pPixelShader, NULL, 0 );
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::PostEffect_RenderShader: Access violation while setting the pixel shader.\n");
		return;
	}
	Try_Start {
		m_pImmediateContext->GSSetShader( NULL, NULL, 0 );
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::PostEffect_RenderShader: Access violation while removing the geometry shader.\n");
		return;
	}
	
	Try_Start {
		// Set any valid input textures
		LoopForwardLengthFromZero(i,16) {
			if (InputResourceType[i] == 0) {
				Try_Start {
					m_pImmediateContext->PSSetShaderResources(i,0,NULL);
				} Try_Else {
					MQ->InsertMessage(L"EngineCore::PostEffect_RenderShader: Access violation while assigning the input surfaces. While giving a NULL surface.\n");
					return;
				}
			} else if (InputResourceType[i] == 1) {
				Try_Start {
					m_pImmediateContext->PSSetShaderResources(i,1,&(m_pDefaultTexture->ColorOutput));
				} Try_Else {
					MQ->InsertMessage(L"EngineCore::PostEffect_RenderShader: Access violation while assigning the input surfaces. While giving a default texture.\n");
					return;
				}
			} else {
				Try_Start {
					m_pImmediateContext->PSSetShaderResources(i,1,&InputResourceViews[i]);
				} Try_Else {
					MQ->InsertMessage(L"EngineCore::PostEffect_RenderShader: Access violation while assigning the input surfaces. While giving a texture or draw surface.\n");
					return;
				}
			}
		}
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::PostEffect_RenderShader: Access violation while assigning the input surfaces.\n");
		return;
	}
	
	Try_Start {
		// Set vertex buffer
		UINT stride = sizeof( VertexStructure_Quad );
		UINT offset = 0;
		m_pImmediateContext->IASetVertexBuffers( 0, 1, &m_pQuad_VertexBuffer, &stride, &offset );
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::PostEffect_RenderShader: Access violation while assigning the vertex buffer.\n");
		return;
	}
	
	Try_Start {
		// Set primitive topology
		m_pImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::PostEffect_RenderShader: Access violation while selecting a triangle list.\n");
		return;
	}
	
	Try_Start {
		// Pixel shader resources
		m_pImmediateContext->PSSetConstantBuffers( 0, 1, &m_pCBPostEffect );
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::PostEffect_RenderShader: Access violation while assigning the constant buffer.\n");
		return;
	}
	
	Try_Start {
		// Select the rectangle area to render to
		vp.MinDepth = 0.0f;
		vp.MaxDepth = 1.0f;
		vp.TopLeftX = 0.0f;
		vp.TopLeftY = 0.0f;
		vp.Width = (FLOAT)OutputSurface->CurrentWidth;
		vp.Height = (FLOAT)OutputSurface->CurrentHeight;
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::PostEffect_RenderShader: Access violation while calculating the viewport dimensions.\n");
		return;
	}
	Try_Start {
		m_pImmediateContext->RSSetViewports(1, &vp);
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::PostEffect_RenderShader: Access violation while assigning the viewport dimensions.\n");
		return;
	}
	
	Try_Start {
		// Choose filter
		SetFilter(Filter_None);
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::PostEffect_RenderShader: Access violation while choosing the default filter.\n");
		return;
	}
	
	Try_Start {
		// Give the constant buffer
		cbPostEffect.GlobalTime = m_GlobalTime;
		cbPostEffect.Dimensions.x = (FLOAT)OutputSurface->CurrentWidth;
		cbPostEffect.Dimensions.y = (FLOAT)OutputSurface->CurrentHeight;
		LoopForwardLengthFromZero(i,16) {
			cbPostEffect.ZWCorrection[i] = InputResourceZWCorrection[i];
		}
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::PostEffect_RenderShader: Access violation while giving built in arguments to the constant buffer's packet.\n");
		return;
	}
	Try_Start {
		LoopForwardLengthFromZero(i,NumberOfUserVectorsPerPostEffect) {
			cbPostEffect.PostEffectInput[i] = m_PostEffect_InputArguments[i];
		}
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::PostEffect_RenderShader: Access violation while giving input arguments to the constant buffer's packet.\n");
		return;
	}
	Try_Start {
		m_pImmediateContext->UpdateSubresource(m_pCBPostEffect, 0, NULL, &cbPostEffect, 0, 0);
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::PostEffect_RenderShader: Access violation while sending the packet to the constant buffer.\n");
		return;
	}

	// Draw 6 vertices
	Try_Start {
		m_pImmediateContext->RSSetState(m_StateDoubleFace);
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::PostEffect_RenderShader: Access violation while selecting front face culling.\n");
		return;
	}
	Try_Start {
		m_pImmediateContext->Draw(6,0);
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::PostEffect_RenderShader: Access violation while drawing the effect quad.\n");
		return;
	}
	
	Try_Start {
		// Clear resources
		ClearResourcesAfterRender();
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::PostEffect_RenderShader: Access violation while clearing resources.\n");
		return;
	}
	
	Try_Start {
		// OutputSurface has been written to
		OutputSurface->HasContent = true;
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::PostEffect_RenderShader: Access violation while telling the output surface that it has been written to.\n");
		return;
	}
	
	Try_Start {
		// Show final results
		if(OutputSurface->FinalSurface && m_AutomaticSwapChain) {
			ShowLastRender();
		}
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::PostEffect_RenderShader: Access violation while showing the final result.\n");
		return;
	}
	
	Try_Start {
		// Input is cleaned up to enforce deterministic debugging
		PostEffect_CleanUpInput();
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::PostEffect_RenderShader: Access violation while cleaning up the input.\n");
		return;
	}
	
	Try_Start {
		// Swap pointers for double draw surface output
		if (OutputSurface->HaveExtraColorBuffer) {
			DrawSurface_SetSwapState(OutputSurface,!(OutputSurface->SwapState));
		}
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::PostEffect_RenderShader: Access violation while setting the swap state for the output surface.\n");
		return;
	}
}

void EngineCore::PostEffect_CleanUpInput(void) {
	int i;
	LoopForwardLengthFromZero(i,16) {
		m_PostEffect_InputTextures[i] = 0;
		m_PostEffect_InputTextureSubresourceTypes[i] = SubresourceType_Color;
	}
	LoopForwardLengthFromZero(i,NumberOfUserVectorsPerPostEffect) {
		m_PostEffect_InputArguments[i] = DVector4(0.0f, 0.0f, 0.0f, 0.0f);
	}
}

void EngineCore::Draw_CleanUpInput(void) {
	int i;
	LoopForwardLengthFromZero(i,16) {
		m_Draw_InputTextures[i] = 0;
	}
	LoopForwardLengthFromZero(i,NumberOfUserVectorsPerDrawing) {
		m_Draw_InputArguments[i] = DVector4(0.0f, 0.0f, 0.0f, 0.0f);
	}
	m_Draw_Color = DVector4(1.0f, 1.0f, 1.0f, 1.0f);
	m_Draw_SrcRectUV1 = DVector4(0.0f, 1.0f, 0.0f, 1.0f);
	m_Draw_SrcRectUV2 = DVector4(0.0f, 1.0f, 0.0f, 1.0f);
}

void EngineCore::ClearResourcesAfterRender(void) {
	void* nv_19[] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
	FLOAT blendFactor[4] = {1.0f,1.0f,1.0f,1.0f};
	ID3D11RenderTargetView* pnullView = NULL;
	m_pImmediateContext->OMSetRenderTargets(1, &pnullView, NULL);
	m_pImmediateContext->VSSetShaderResources(0, 19, (ID3D11ShaderResourceView**)nv_19);
	m_pImmediateContext->PSSetShaderResources(0, 19, (ID3D11ShaderResourceView**)nv_19);
	m_pImmediateContext->GSSetShaderResources(0, 19, (ID3D11ShaderResourceView**)nv_19);
	m_pImmediateContext->OMSetBlendState(NULL, blendFactor, 0xfff);
}

int EngineCore::DrawSurface_GetWidth(DrawSurface_Struct* Surface) {
	return GetWantedSurfaceWidth(Surface);
}

int EngineCore::DrawSurface_GetHeight(DrawSurface_Struct* Surface) {
	return GetWantedSurfaceHeight(Surface);
}

D3D11_BUFFER_DESC EngineCore::MakeBufferDesc(int Size) {
	D3D11_BUFFER_DESC bd;
	ZeroMemory( &bd, sizeof(bd) );
	bd.Usage = D3D11_USAGE_DEFAULT;
	bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
	bd.CPUAccessFlags = 0;
	bd.ByteWidth = Size;
	return bd;
}
D3D11_RASTERIZER_DESC EngineCore::MakeRasterizerDesc(D3D11_CULL_MODE CullMode,bool DepthClipEnable,D3D11_FILL_MODE FillMode) {
	D3D11_RASTERIZER_DESC StateDesc = {
		FillMode,	//D3D11_FILL_MODE FillMode;
		CullMode,			//D3D11_CULL_MODE CullMode;
		true,				//BOOL FrontCounterClockwise;
		0,					//INT DepthBias;
		0.0,				//FLOAT DepthBiasClamp;
		0.0,				//FLOAT SlopeScaledDepthBias;
		DepthClipEnable,	//BOOL DepthClipEnable;
		false,				//BOOL ScissorEnable;
		false,				//BOOL MultisampleEnable;
		false				//BOOL AntialiasedLineEnable;
	};
	return StateDesc;
}
D3D11_DEPTH_STENCIL_DESC EngineCore::MakeDepthStencilDesc(D3D11_DEPTH_WRITE_MASK DepthWriteMask) {
	D3D11_DEPTH_STENCIL_DESC DepthStencilDesc;
	ZeroMemory( &DepthStencilDesc, sizeof(D3D11_DEPTH_STENCIL_DESC) );
	DepthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
	DepthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
	DepthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
	DepthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
	DepthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
	DepthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
	DepthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
	DepthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
	DepthStencilDesc.DepthEnable = TRUE;
	DepthStencilDesc.DepthWriteMask = DepthWriteMask;
	DepthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS;
	DepthStencilDesc.StencilEnable = FALSE;
	DepthStencilDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
	DepthStencilDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
	return DepthStencilDesc;
}
D3D11_BLEND_DESC EngineCore::MakeBlendDesc(void) {
	D3D11_BLEND_DESC BlendDesc;
	ZeroMemory( &BlendDesc, sizeof(D3D11_BLEND_DESC) );
	BlendDesc.RenderTarget[0].BlendEnable			= true;
	BlendDesc.RenderTarget[0].BlendOp				= D3D11_BLEND_OP_ADD;
	BlendDesc.RenderTarget[0].BlendOpAlpha			= D3D11_BLEND_OP_ADD;
	BlendDesc.RenderTarget[0].SrcBlend				= D3D11_BLEND_SRC_ALPHA;
	BlendDesc.RenderTarget[0].SrcBlendAlpha			= D3D11_BLEND_ONE; //D3D11_BLEND_SRC_ALPHA;
	BlendDesc.RenderTarget[0].DestBlend				= D3D11_BLEND_INV_SRC_ALPHA;
	BlendDesc.RenderTarget[0].DestBlendAlpha		= D3D11_BLEND_INV_SRC_ALPHA; //D3D11_BLEND_INV_SRC_ALPHA;
	BlendDesc.RenderTarget[0].RenderTargetWriteMask	= D3D11_COLOR_WRITE_ENABLE_ALL;
	return BlendDesc;
}

bool EngineCore::InitDevice(HWND new_hWnd) {
	if (m_Running) {
		MQ->InsertMessage(L"InitDevice: The engine is already running.");
		return false;
	} else {
		m_hWnd = new_hWnd;
		
		if (!InitiateSound()) {
			MQ->InsertMessage(L"InitDevice: The sound engine could not be initiated.");
			return false;
		}
		
		UINT createDeviceFlags = 0;
		#ifdef _DEBUG
			createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
		#endif
		
		RECT rc; GetClientRect( m_hWnd, &rc ); UINT width = rc.right - rc.left; UINT height = rc.bottom - rc.top;
		
		if (m_hWnd == NULL) {
			MQ->InsertMessage(L"The window handle is NULL.");
		} else if (!IsWindow(m_hWnd)) {
			MQ->InsertMessage(L"The window handle is invalid.");
		} else {
			if (width < 1 || height < 1 || width > 8192 || height > 8192) { width = 1; height = 1; }
			
			D3D_FEATURE_LEVEL featureLevels[] = {
				D3D_FEATURE_LEVEL_11_0,
				D3D_FEATURE_LEVEL_10_1,
				D3D_FEATURE_LEVEL_10_0,
			};
			UINT numFeatureLevels = ARRAYSIZE( featureLevels );
			
			DXGI_SWAP_CHAIN_DESC sd;
			ZeroMemory( &sd, sizeof( sd ) );
			sd.BufferCount = 1;
			sd.BufferDesc.Width = width;
			sd.BufferDesc.Height = height;
			sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
			sd.BufferDesc.RefreshRate.Numerator = 0;
			sd.BufferDesc.RefreshRate.Denominator = 1;
			sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
			sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
			sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
			sd.OutputWindow = m_hWnd;
			sd.SampleDesc.Count = 1;
			sd.SampleDesc.Quality = 0;
			sd.Windowed = TRUE;
			
			if (FAILED(D3D11CreateDeviceAndSwapChain( NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, createDeviceFlags, featureLevels, numFeatureLevels, D3D11_SDK_VERSION, &sd, &m_pSwapChain, &m_pd3dDevice, &m_featureLevel, &m_pImmediateContext ))) {
				MQ->InsertMessage(L"Could not create the swap chain. Installing the DirectX SDK from february 2010 should make sure that you have the right version of DirectX 11 installed.");
				return false;
			}
			
			// Prepare all draw surfaces
			DrawSurface_SetSize(&m_SurfaceScreen,width,height,true,2,false);
			m_SurfaceScreen.FinalSurface = true;
			
			// Allocate data in the table using bd for the constant buffers
			CORE_DATA_TABLE(ALLOCATE)
			
			// Allow access to the final draw surface
			m_usedReferences = 2;
			m_pReferences[1].pointer = &m_SurfaceScreen; m_SurfaceScreen.ID = 1;
			m_pReferences[1].Valid = true;
			m_pReferences[1].CollectionType = ColType_DrawSurface;
			
			// Assign samplers
			m_pImmediateContext->VSSetSamplers( 0, 1, &m_pSamConstant );
			//m_pImmediateContext->VSSetSamplers( 1, 1, &m_pSamSharp );
			m_pImmediateContext->VSSetSamplers( 2, 1, &m_pSamClampedConstant );
			//m_pImmediateContext->VSSetSamplers( 3, 1, &m_pSamClampedSharp );
			//m_pImmediateContext->VSSetSamplers( 4, 1, &m_pSamAnisotropicMipmap );
			//m_pImmediateContext->VSSetSamplers( 5, 1, &m_pSamMipmap );
			//m_pImmediateContext->VSSetSamplers( 6, 1, &m_pSamShadow );
			m_pImmediateContext->GSSetSamplers( 0, 1, &m_pSamConstant );
			//m_pImmediateContext->GSSetSamplers( 1, 1, &m_pSamSharp );
			m_pImmediateContext->GSSetSamplers( 2, 1, &m_pSamClampedConstant );
			//m_pImmediateContext->GSSetSamplers( 3, 1, &m_pSamClampedSharp );
			//m_pImmediateContext->GSSetSamplers( 4, 1, &m_pSamAnisotropicMipmap );
			//m_pImmediateContext->GSSetSamplers( 5, 1, &m_pSamMipmap );
			//m_pImmediateContext->GSSetSamplers( 6, 1, &m_pSamShadow );
			m_pImmediateContext->PSSetSamplers( 0, 1, &m_pSamConstant );
			m_pImmediateContext->PSSetSamplers( 1, 1, &m_pSamSharp );
			m_pImmediateContext->PSSetSamplers( 2, 1, &m_pSamClampedConstant );
			m_pImmediateContext->PSSetSamplers( 3, 1, &m_pSamClampedSharp );
			m_pImmediateContext->PSSetSamplers( 4, 1, &m_pSamAnisotropicMipmap );
			m_pImmediateContext->PSSetSamplers( 5, 1, &m_pSamMipmap );
			m_pImmediateContext->PSSetSamplers( 6, 1, &m_pSamShadow );
			
			// Start the physics engine
			Physics_Init(&m_PhysicsCore, this);
			
			// Start debug drawing
			DebugLine_Init();
			
			m_Running = true;
		}
	}
	return true;
}

void EngineCore::CreateDefaultDepthAtlasIfNeeded(void) {
	if (m_DepthAtlas.CurrentWidth < 1) {
		DepthBuffer_SetSize(&m_DepthAtlas, 1024, 1024);
		ClearShadows();
	}
}

HRESULT EngineCore::CreateSampler(bool Clamp, bool Linear, int ExtraSamples, boolean MipMap, ID3D11SamplerState** Sampler) {
	D3D11_SAMPLER_DESC SD = {
		D3D11_FILTER_MIN_MAG_MIP_LINEAR,// D3D11_FILTER Filter;
		D3D11_TEXTURE_ADDRESS_WRAP, //D3D11_TEXTURE_ADDRESS_MODE AddressU;
		D3D11_TEXTURE_ADDRESS_WRAP, //D3D11_TEXTURE_ADDRESS_MODE AddressV;
		D3D11_TEXTURE_ADDRESS_WRAP, //D3D11_TEXTURE_ADDRESS_MODE AddressW;
		0,//FLOAT MipLODBias; Decides the offset in resolution. Positive gives low resolution textures.
		0,//UINT MaxAnisotropy;
		D3D11_COMPARISON_ALWAYS , //D3D11_COMPARISON_FUNC ComparisonFunc;
		1.0,1.0,1.0,1.0,//FLOAT BorderColor[ 4 ];
		0,//FLOAT MinLOD;
		8 //FLOAT MaxLOD; How much will the resolution be degraded at the worst sizes.
	};
	if (MipMap) {
		SD.MaxLOD = 30.0f;
	} else {
		SD.MaxLOD = 0.0f;
	}
	if (Clamp) {
		SD.AddressU = SD.AddressV = SD.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
	} else {
		SD.AddressU = SD.AddressV = SD.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
	}
	SD.MaxAnisotropy = ExtraSamples;
	if (ExtraSamples > 0) {
		SD.Filter = D3D11_FILTER_ANISOTROPIC;
	} else {
		if (Linear) {
			SD.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
		} else {
			SD.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
		}
	}
	return m_pd3dDevice->CreateSamplerState( &SD, Sampler );
}

#define CleanUpCollection(NAME) \
	NAME##_Struct* pCurrent##NAME; \
	LoopBackwardLengthFromZero(i, SizeOfCollection(NAME)) { \
		pCurrent##NAME = (NAME##_Struct*)m_##NAME##.getValue_warning(i); \
		if (pCurrent##NAME##->Locked == false && pCurrent##NAME##->useCount <= 0) { \
			Delete_##NAME(pCurrent##NAME); \
		} \
	}

void EngineCore::RemoveUnusedResources(void) {
	int i;
	CleanUpCollection(Texture)
	CleanUpCollection(Shader)
}

void EngineCore::SetDefaultMaterialShader(Shader_Struct* MaterialShader) {
	if (m_pDefaultMaterialShader != NULL) { StopUsing(m_pDefaultMaterialShader->useCount); }
	if (MaterialShader) {
		StartUsing(MaterialShader->useCount);
	}
	m_pDefaultMaterialShader = MaterialShader;
}

void EngineCore::SetDefaultTexture(Texture_Struct* Texture) {
	if (m_pDefaultTexture != NULL) { StopUsing(m_pDefaultTexture->useCount); }
	if (Texture) {
		StartUsing(Texture->useCount);
	}
	m_pDefaultTexture = Texture;
}

void EngineCore::SetLightProjectionAtlas(Texture_Struct* Texture) {
	if (m_pLightProjectionAtlas != NULL) { StopUsing(m_pLightProjectionAtlas->useCount); }
	if (Texture) {
		StartUsing(Texture->useCount);
	}
	m_pLightProjectionAtlas = Texture;
}

void EngineCore::SetSkyInstance(Instance_Struct* Instance) {
	if (m_pSkyInstance != NULL) { StopUsing(m_pSkyInstance->useCount); }
	if (Instance) {
		StartUsing(Instance->useCount);
	}
	m_pSkyInstance = Instance;
}

void EngineCore::Instance_ReleaseOverride(Instance_Struct* Instance, int OverrideChannel) {
	// Decrease use
	if (Instance->OverrideSurfaces[OverrideChannel].iSurfaceType == SurfaceType_Texture) {
		StopUsing(((Texture_Struct*)Instance->OverrideSurfaces[OverrideChannel].pSurface)->useCount);
	} else if (Instance->OverrideSurfaces[OverrideChannel].iSurfaceType == SurfaceType_DrawSurface) {
		StopUsing(((DrawSurface_Struct*)Instance->OverrideSurfaces[OverrideChannel].pSurface)->useCount);
		StopUsing(((DrawSurface_Struct*)Instance->OverrideSurfaces[OverrideChannel].pSurface)->MaterialCount);
	}
	
	// Remove the reference
	Instance->OverrideSurfaces[OverrideChannel].iSurfaceType = SurfaceType_Empty;
	Instance->OverrideSurfaces[OverrideChannel].pSurface = NULL;
}

// Returns any ID to the override channel
int EngineCore::Instance_GetIDFromOverride(Instance_Struct* Instance, int OverrideChannel) {
	if (Instance->OverrideSurfaces[OverrideChannel].iSurfaceType == SurfaceType_Texture) {
		return ((Texture_Struct*)Instance->OverrideSurfaces[OverrideChannel].pSurface)->ID;
	} else if (Instance->OverrideSurfaces[OverrideChannel].iSurfaceType == SurfaceType_DrawSurface) {
		return ((DrawSurface_Struct*)Instance->OverrideSurfaces[OverrideChannel].pSurface)->ID;
	} else {
		return 0;
	}
}

void EngineCore::Instance_SetOverrideUsingTexture(Instance_Struct* Instance, int OverrideChannel, Texture_Struct* Texture) {
	// Release any old override
	Instance_ReleaseOverride(Instance,OverrideChannel);
	
	// Assign the new override
	Instance->OverrideSurfaces[OverrideChannel].iSurfaceType = SurfaceType_Texture;
	Instance->OverrideSurfaces[OverrideChannel].pSurface = Texture;
	
	// Increase use
	if (Texture) {
		StartUsing(Texture->useCount);
	}
}

void EngineCore::Instance_SetOverrideUsingDrawSurface(Instance_Struct* Instance, int OverrideChannel, DrawSurface_Struct* DrawSurface) {
	// Release any old override
	Instance_ReleaseOverride(Instance,OverrideChannel);
	
	// Assign the new override
	Instance->OverrideSurfaces[OverrideChannel].iSurfaceType = SurfaceType_DrawSurface;
	Instance->OverrideSurfaces[OverrideChannel].pSurface = DrawSurface;
	
	// Increase use
	if (DrawSurface) {
		StartUsing(DrawSurface->useCount);
		StartUsing(DrawSurface->MaterialCount);
	}
}

void EngineCore::UpdateAutomaticDetailLevels(DVector3 Center) {
	int i;
	Instance_Struct* pCurrentInstance;
	DVector3 cameraToObjectOffset;
	float Dist;

	// Used for fading the last iteration of mesh smoothing in geometry shaders
	float MediumHighFallOff = Lerp(m_MediumHighDetailLimit,0.0f,0.2f);
	float LowMediumFallOff = Lerp(m_LowMediumDetailLimit,m_MediumHighDetailLimit,0.2f);

	LoopForwardLengthFromZero(i, SizeOfCollection(Instance)) {
		pCurrentInstance = (Instance_Struct*)m_Instance.getValue_warning(i);
		if (pCurrentInstance->AutoDetailLevel) {
			cameraToObjectOffset = SubVec3(DVector3(pCurrentInstance->Transformation._41,pCurrentInstance->Transformation._42,pCurrentInstance->Transformation._43),Center);
			Dist = AbsVec3(cameraToObjectOffset);
			if (Dist < m_MediumHighDetailLimit) {
				pCurrentInstance->DetailLevel_Int = 2;
			} else if (Dist < m_LowMediumDetailLimit) {
				pCurrentInstance->DetailLevel_Int = 1;
			} else {
				pCurrentInstance->DetailLevel_Int = 0;
			}
			if (Dist < MediumHighFallOff) {
				// 0 to MediumHighFallOff -> 2
				pCurrentInstance->DetailLevel_Float = 2.0f;
			} else if (Dist < m_MediumHighDetailLimit) {
				// MediumHighFallOff to m_MediumHighDetailLimit -> 1 to 2
				pCurrentInstance->DetailLevel_Float = 1.0f + InverseLerp(m_MediumHighDetailLimit,MediumHighFallOff,Dist);
			} else if (Dist < LowMediumFallOff) {
				// m_MediumHighDetailLimit to LowMediumFallOff -> 1
				pCurrentInstance->DetailLevel_Float = 1.0f;
			} else if (Dist < m_LowMediumDetailLimit) {
				// LowMediumFallOff to m_LowMediumDetailLimit -> 0 to 1
				pCurrentInstance->DetailLevel_Float = InverseLerp(m_LowMediumDetailLimit,LowMediumFallOff,Dist);
			} else {
				// m_LowMediumDetailLimit to infinity -> 0
				pCurrentInstance->DetailLevel_Float = 0.0f;
			}
		}
	}
}

bool EngineCore::CanLightBeSeenFromCamera(Camera_Struct* InputCamera, LightSource* TheLight) {
	DVector3 CameraPos[5];
	int i;
	if (TheLight->Color.x < 0.000001f && TheLight->Color.x > -0.000001f && TheLight->Color.y < 0.000001f && TheLight->Color.y > -0.000001f && TheLight->Color.z < 0.000001f && TheLight->Color.z > -0.000001f) {
		// Culled by light intensity
		return false;
	} else if (TheLight->Type == LightType_Point) {
		if ( DistVec3(InputCamera->Eye,TheLight->Pos) < (InputCamera->FarClipPlane + TheLight->Radius) ) {
			CameraPos[0] = TransformVec3Mat4(TheLight->Pos,InputCamera->RefractedWorldToCamera);
			if (InputCamera->IsOrthogonal) {
				// Orthogonal
				if (CameraPos[0].z < InputCamera->NearClipPlane - TheLight->Radius) {
					return false;
				} else if (AbsFloat(CameraPos[0].x) - TheLight->Radius > InputCamera->OrthogonalHalfWidth) {
					return false;
				} else if (AbsFloat(CameraPos[0].y) - TheLight->Radius > InputCamera->OrthogonalHalfHeight) {
					return false;
				} else {
					return true;
				}
			} else {
				// Perspective
				if (CameraPos[0].z < InputCamera->NearClipPlane - TheLight->Radius) {
					return false;
				} else {
					if (AbsFloat(CameraPos[0].x) - (sqrtf(1 + pow(InputCamera->WidthSlope, 2.0f)) * TheLight->Radius) > CameraPos[0].z * InputCamera->WidthSlope) {
						return false;
					} else {
						if (AbsFloat(CameraPos[0].y) - (sqrtf(1 + pow(InputCamera->HeightSlope, 2.0f)) * TheLight->Radius) > CameraPos[0].z * InputCamera->HeightSlope) {
							return false;
						} else {
							return true;
						}
					}
				}
			}
		} else {
			return false;
		}
	} else if (TheLight->Type == LightType_Sun || TheLight->Type == LightType_Sun_Shadow_SingleLayer) {
		return true;
	} else if (TheLight->Type == LightType_Spot || TheLight->Type == LightType_Spot_Atlas || TheLight->Type == LightType_Spot_Shadow || TheLight->Type == LightType_Spot_Atlas_Shadow) {
		if (TheLight->WidthSlope <= 0 || TheLight->HeightSlope <= 0) {
			// Culled by slopes
			return false;
		} else if ( DistVec3(InputCamera->Eye,TheLight->Pos) < (InputCamera->FarClipPlane + TheLight->Radius) ) {
			CameraPos[0] = TransformVec3Mat4(TheLight->Pos,InputCamera->RefractedWorldToCamera);
			if (CameraPos[0].z < InputCamera->NearClipPlane - TheLight->Radius) {
				return false;
			} else {
				if (AbsFloat(CameraPos[0].x) - (sqrtf(1 + pow(InputCamera->WidthSlope, 2.0f)) * TheLight->Radius) > CameraPos[0].z * InputCamera->WidthSlope) {
					return false;
				} else {
					if (AbsFloat(CameraPos[0].y) - (sqrtf(1 + pow(InputCamera->HeightSlope, 2.0f)) * TheLight->Radius) > CameraPos[0].z * InputCamera->HeightSlope) {
						return false;
					} else {
						DVector3 EndPoint;
						DVector3 WidthVector;
						DVector3 HeightVector;
						DVector3 SpotFrustum_WorldSpace[5];
						// Generate points in world space.
						EndPoint = AddVec3(TheLight->Pos,ScaleVec3(TheLight->ZAxis,TheLight->Radius));
						WidthVector = ScaleVec3(TheLight->XAxis,TheLight->WidthSlope * TheLight->Radius);
						HeightVector = ScaleVec3(TheLight->YAxis,TheLight->HeightSlope * TheLight->Radius);
						SpotFrustum_WorldSpace[0] = TheLight->Pos;
						SpotFrustum_WorldSpace[1] = AddVec3(AddVec3(EndPoint,WidthVector),HeightVector);
						SpotFrustum_WorldSpace[2] = SubVec3(AddVec3(EndPoint,WidthVector),HeightVector);
						SpotFrustum_WorldSpace[3] = AddVec3(SubVec3(EndPoint,WidthVector),HeightVector);
						SpotFrustum_WorldSpace[4] = SubVec3(SubVec3(EndPoint,WidthVector),HeightVector);
						// Convert to camera space.
						LoopForward(0,i,4) {
							CameraPos[i] = TransformVec3Mat4(SpotFrustum_WorldSpace[i],InputCamera->RefractedWorldToCamera);
						}
						// Return false when a plane is excluding all points.
						if (CameraPos[0].z < 0
						 && CameraPos[1].z < 0
						 && CameraPos[2].z < 0
						 && CameraPos[3].z < 0
						 && CameraPos[4].z < 0) return false;
						
						if (InputCamera->IsOrthogonal) {
							// Orthogonal
							if (CameraPos[0].x > InputCamera->OrthogonalHalfWidth
							 && CameraPos[1].x > InputCamera->OrthogonalHalfWidth
							 && CameraPos[2].x > InputCamera->OrthogonalHalfWidth
							 && CameraPos[3].x > InputCamera->OrthogonalHalfWidth
							 && CameraPos[4].x > InputCamera->OrthogonalHalfWidth) return false;
							if (CameraPos[0].x < -InputCamera->OrthogonalHalfWidth
							 && CameraPos[1].x < -InputCamera->OrthogonalHalfWidth
							 && CameraPos[2].x < -InputCamera->OrthogonalHalfWidth
							 && CameraPos[3].x < -InputCamera->OrthogonalHalfWidth
							 && CameraPos[4].x < -InputCamera->OrthogonalHalfWidth) return false;
							if (CameraPos[0].y > InputCamera->OrthogonalHalfHeight
							 && CameraPos[1].y > InputCamera->OrthogonalHalfHeight
							 && CameraPos[2].y > InputCamera->OrthogonalHalfHeight
							 && CameraPos[3].y > InputCamera->OrthogonalHalfHeight
							 && CameraPos[4].y > InputCamera->OrthogonalHalfHeight) return false;
							if (CameraPos[0].y < -InputCamera->OrthogonalHalfHeight
							 && CameraPos[1].y < -InputCamera->OrthogonalHalfHeight
							 && CameraPos[2].y < -InputCamera->OrthogonalHalfHeight
							 && CameraPos[3].y < -InputCamera->OrthogonalHalfHeight
							 && CameraPos[4].y < -InputCamera->OrthogonalHalfHeight) return false;
						} else {
							// Perspective
							if (CameraPos[0].x > CameraPos[0].z * InputCamera->WidthSlope
							 && CameraPos[1].x > CameraPos[1].z * InputCamera->WidthSlope
							 && CameraPos[2].x > CameraPos[2].z * InputCamera->WidthSlope
							 && CameraPos[3].x > CameraPos[3].z * InputCamera->WidthSlope
							 && CameraPos[4].x > CameraPos[4].z * InputCamera->WidthSlope) return false;
							if (CameraPos[0].x < CameraPos[0].z * -InputCamera->WidthSlope
							 && CameraPos[1].x < CameraPos[1].z * -InputCamera->WidthSlope
							 && CameraPos[2].x < CameraPos[2].z * -InputCamera->WidthSlope
							 && CameraPos[3].x < CameraPos[3].z * -InputCamera->WidthSlope
							 && CameraPos[4].x < CameraPos[4].z * -InputCamera->WidthSlope) return false;
							if (CameraPos[0].y > CameraPos[0].z * InputCamera->HeightSlope
							 && CameraPos[1].y > CameraPos[1].z * InputCamera->HeightSlope
							 && CameraPos[2].y > CameraPos[2].z * InputCamera->HeightSlope
							 && CameraPos[3].y > CameraPos[3].z * InputCamera->HeightSlope
							 && CameraPos[4].y > CameraPos[4].z * InputCamera->HeightSlope) return false;
							if (CameraPos[0].y < CameraPos[0].z * -InputCamera->HeightSlope
							 && CameraPos[1].y < CameraPos[1].z * -InputCamera->HeightSlope
							 && CameraPos[2].y < CameraPos[2].z * -InputCamera->HeightSlope
							 && CameraPos[3].y < CameraPos[3].z * -InputCamera->HeightSlope
							 && CameraPos[4].y < CameraPos[4].z * -InputCamera->HeightSlope) return false;
						}
						
						return true;
					}
				}
			}
		} else {
			return false;
		}
	}
	return false;
}

float EngineCore::GetBoundingSphereRadius(DMatrix Transformation, ModelClass* Model) {
	float XAxisLength; float YAxisLength; float ZAxisLength;
	
	// Measure each axis
	XAxisLength = AbsVec3(DVector3(Transformation._11,Transformation._12,Transformation._13));
	YAxisLength = AbsVec3(DVector3(Transformation._21,Transformation._22,Transformation._23));
	ZAxisLength = AbsVec3(DVector3(Transformation._31,Transformation._32,Transformation._33));
	
	// Multiply the radius with the length of the longest axis assuming that the axis system is orthogonal
	// This allow non uniform scaling but not tilting
	return (Model->Radius * Model->ModelProperties.BoundMultiplier) * MaxFloat(MaxFloat(XAxisLength,YAxisLength),ZAxisLength);
}
void EngineCore::GetBoundingBoxCorners(DMatrix Transformation, ModelClass* Model, DVector3* EightWorldSpaceOutputPositions) {
	DVector3 PointZero;
	DVector3 PlusX; DVector3 MinusX;
	DVector3 PlusY; DVector3 MinusY;
	DVector3 PlusZ; DVector3 MinusZ;
	
	// Get the center of the axis system
	PointZero = DVector3(Transformation._41,Transformation._42,Transformation._43);
	
	// Multiply axis system with bounding box dimensions
	PlusX = DVector3(Transformation._11 * (Model->ObjectSpaceMax.x * Model->ModelProperties.BoundMultiplier),Transformation._12 * (Model->ObjectSpaceMax.x * Model->ModelProperties.BoundMultiplier),Transformation._13 * (Model->ObjectSpaceMax.x * Model->ModelProperties.BoundMultiplier));
	MinusX = DVector3(Transformation._11 * (Model->ObjectSpaceMin.x * Model->ModelProperties.BoundMultiplier),Transformation._12 * (Model->ObjectSpaceMin.x * Model->ModelProperties.BoundMultiplier),Transformation._13 * (Model->ObjectSpaceMin.x * Model->ModelProperties.BoundMultiplier));
	PlusY = DVector3(Transformation._21 * (Model->ObjectSpaceMax.y * Model->ModelProperties.BoundMultiplier),Transformation._22 * (Model->ObjectSpaceMax.y * Model->ModelProperties.BoundMultiplier),Transformation._23 * (Model->ObjectSpaceMax.y * Model->ModelProperties.BoundMultiplier));
	MinusY = DVector3(Transformation._21 * (Model->ObjectSpaceMin.y * Model->ModelProperties.BoundMultiplier),Transformation._22 * (Model->ObjectSpaceMin.y * Model->ModelProperties.BoundMultiplier),Transformation._23 * (Model->ObjectSpaceMin.y * Model->ModelProperties.BoundMultiplier));
	PlusZ = DVector3(Transformation._31 * (Model->ObjectSpaceMax.z * Model->ModelProperties.BoundMultiplier),Transformation._32 * (Model->ObjectSpaceMax.z * Model->ModelProperties.BoundMultiplier),Transformation._33 * (Model->ObjectSpaceMax.z * Model->ModelProperties.BoundMultiplier));
	MinusZ = DVector3(Transformation._31 * (Model->ObjectSpaceMin.z * Model->ModelProperties.BoundMultiplier),Transformation._32 * (Model->ObjectSpaceMin.z * Model->ModelProperties.BoundMultiplier),Transformation._33 * (Model->ObjectSpaceMin.z * Model->ModelProperties.BoundMultiplier));
	
	// Generate world space coordinates
	EightWorldSpaceOutputPositions[0] = AddVec3(AddVec3(AddVec3(PointZero,PlusX),PlusY),PlusZ);
	EightWorldSpaceOutputPositions[1] = AddVec3(AddVec3(AddVec3(PointZero,PlusX),PlusY),MinusZ);
	EightWorldSpaceOutputPositions[2] = AddVec3(AddVec3(AddVec3(PointZero,PlusX),MinusY),PlusZ);
	EightWorldSpaceOutputPositions[3] = AddVec3(AddVec3(AddVec3(PointZero,PlusX),MinusY),MinusZ);
	EightWorldSpaceOutputPositions[4] = AddVec3(AddVec3(AddVec3(PointZero,MinusX),PlusY),PlusZ);
	EightWorldSpaceOutputPositions[5] = AddVec3(AddVec3(AddVec3(PointZero,MinusX),PlusY),MinusZ);
	EightWorldSpaceOutputPositions[6] = AddVec3(AddVec3(AddVec3(PointZero,MinusX),MinusY),PlusZ);
	EightWorldSpaceOutputPositions[7] = AddVec3(AddVec3(AddVec3(PointZero,MinusX),MinusY),MinusZ);
}

bool EngineCore::CanInstanceBeSeenFromCamera(Camera_Struct* InputCamera, Instance_Struct* Instance,bool CullUsingFarClip,bool CullUsingCuttingPlane) {
	ModelClass* Model;
	DVector3 Points_CameraSpace[8];
	int i;
	Model = &(Instance->VisualModel->Model);
	if (Model->ModelProperties.CullingMethod == Culling_AABB) {
		DVector3 Points_WorldSpace[8];
		
		// Get the world space corners
		GetBoundingBoxCorners(Instance->Transformation,Model,Points_WorldSpace);
		
		// Do optional cutting plane culling
		if (InputCamera->EnableCuttingPlane && CullUsingCuttingPlane) {
			if ( (Points_WorldSpace[0].x * InputCamera->CuttingPlane.x) + (Points_WorldSpace[0].y * InputCamera->CuttingPlane.y) + (Points_WorldSpace[0].z * InputCamera->CuttingPlane.z) < InputCamera->CuttingPlane.w
			  && (Points_WorldSpace[1].x * InputCamera->CuttingPlane.x) + (Points_WorldSpace[1].y * InputCamera->CuttingPlane.y) + (Points_WorldSpace[1].z * InputCamera->CuttingPlane.z) < InputCamera->CuttingPlane.w
			  && (Points_WorldSpace[2].x * InputCamera->CuttingPlane.x) + (Points_WorldSpace[2].y * InputCamera->CuttingPlane.y) + (Points_WorldSpace[2].z * InputCamera->CuttingPlane.z) < InputCamera->CuttingPlane.w
			  && (Points_WorldSpace[3].x * InputCamera->CuttingPlane.x) + (Points_WorldSpace[3].y * InputCamera->CuttingPlane.y) + (Points_WorldSpace[3].z * InputCamera->CuttingPlane.z) < InputCamera->CuttingPlane.w
			  && (Points_WorldSpace[4].x * InputCamera->CuttingPlane.x) + (Points_WorldSpace[4].y * InputCamera->CuttingPlane.y) + (Points_WorldSpace[4].z * InputCamera->CuttingPlane.z) < InputCamera->CuttingPlane.w
			  && (Points_WorldSpace[5].x * InputCamera->CuttingPlane.x) + (Points_WorldSpace[5].y * InputCamera->CuttingPlane.y) + (Points_WorldSpace[5].z * InputCamera->CuttingPlane.z) < InputCamera->CuttingPlane.w
			  && (Points_WorldSpace[6].x * InputCamera->CuttingPlane.x) + (Points_WorldSpace[6].y * InputCamera->CuttingPlane.y) + (Points_WorldSpace[6].z * InputCamera->CuttingPlane.z) < InputCamera->CuttingPlane.w
			  && (Points_WorldSpace[7].x * InputCamera->CuttingPlane.x) + (Points_WorldSpace[7].y * InputCamera->CuttingPlane.y) + (Points_WorldSpace[7].z * InputCamera->CuttingPlane.z) < InputCamera->CuttingPlane.w ) return false;
		}
		
		// Convert to camera space
		LoopForward(0,i,7) {
			Points_CameraSpace[i] = TransformVec3Mat4(Points_WorldSpace[i],InputCamera->RefractedWorldToCamera);
		}
		
		// Do camera view frustum culling
		if (Points_CameraSpace[0].z < InputCamera->NearClipPlane
		 && Points_CameraSpace[1].z < InputCamera->NearClipPlane
		 && Points_CameraSpace[2].z < InputCamera->NearClipPlane
		 && Points_CameraSpace[3].z < InputCamera->NearClipPlane
		 && Points_CameraSpace[4].z < InputCamera->NearClipPlane
		 && Points_CameraSpace[5].z < InputCamera->NearClipPlane
		 && Points_CameraSpace[6].z < InputCamera->NearClipPlane
		 && Points_CameraSpace[7].z < InputCamera->NearClipPlane) return false;
		if (CullUsingFarClip) {
			if (Points_CameraSpace[0].z > InputCamera->FarClipPlane
			 && Points_CameraSpace[1].z > InputCamera->FarClipPlane
			 && Points_CameraSpace[2].z > InputCamera->FarClipPlane
			 && Points_CameraSpace[3].z > InputCamera->FarClipPlane
			 && Points_CameraSpace[4].z > InputCamera->FarClipPlane
			 && Points_CameraSpace[5].z > InputCamera->FarClipPlane
			 && Points_CameraSpace[6].z > InputCamera->FarClipPlane
			 && Points_CameraSpace[7].z > InputCamera->FarClipPlane) return false;
		}
		if (InputCamera->IsOrthogonal) {
			// Orthogonal
			if (Points_CameraSpace[0].x > InputCamera->OrthogonalHalfWidth 
			 && Points_CameraSpace[1].x > InputCamera->OrthogonalHalfWidth
			 && Points_CameraSpace[2].x > InputCamera->OrthogonalHalfWidth
			 && Points_CameraSpace[3].x > InputCamera->OrthogonalHalfWidth
			 && Points_CameraSpace[4].x > InputCamera->OrthogonalHalfWidth
			 && Points_CameraSpace[5].x > InputCamera->OrthogonalHalfWidth
			 && Points_CameraSpace[6].x > InputCamera->OrthogonalHalfWidth
			 && Points_CameraSpace[7].x > InputCamera->OrthogonalHalfWidth) return false;
			if (Points_CameraSpace[0].x < -InputCamera->OrthogonalHalfWidth
			 && Points_CameraSpace[1].x < -InputCamera->OrthogonalHalfWidth
			 && Points_CameraSpace[2].x < -InputCamera->OrthogonalHalfWidth
			 && Points_CameraSpace[3].x < -InputCamera->OrthogonalHalfWidth
			 && Points_CameraSpace[4].x < -InputCamera->OrthogonalHalfWidth
			 && Points_CameraSpace[5].x < -InputCamera->OrthogonalHalfWidth
			 && Points_CameraSpace[6].x < -InputCamera->OrthogonalHalfWidth
			 && Points_CameraSpace[7].x < -InputCamera->OrthogonalHalfWidth) return false;
			if (Points_CameraSpace[0].y > InputCamera->OrthogonalHalfHeight
			 && Points_CameraSpace[1].y > InputCamera->OrthogonalHalfHeight
			 && Points_CameraSpace[2].y > InputCamera->OrthogonalHalfHeight
			 && Points_CameraSpace[3].y > InputCamera->OrthogonalHalfHeight
			 && Points_CameraSpace[4].y > InputCamera->OrthogonalHalfHeight
			 && Points_CameraSpace[5].y > InputCamera->OrthogonalHalfHeight
			 && Points_CameraSpace[6].y > InputCamera->OrthogonalHalfHeight
			 && Points_CameraSpace[7].y > InputCamera->OrthogonalHalfHeight) return false;
			if (Points_CameraSpace[0].y < -InputCamera->OrthogonalHalfHeight
			 && Points_CameraSpace[1].y < -InputCamera->OrthogonalHalfHeight
			 && Points_CameraSpace[2].y < -InputCamera->OrthogonalHalfHeight
			 && Points_CameraSpace[3].y < -InputCamera->OrthogonalHalfHeight
			 && Points_CameraSpace[4].y < -InputCamera->OrthogonalHalfHeight
			 && Points_CameraSpace[5].y < -InputCamera->OrthogonalHalfHeight
			 && Points_CameraSpace[6].y < -InputCamera->OrthogonalHalfHeight
			 && Points_CameraSpace[7].y < -InputCamera->OrthogonalHalfHeight) return false;
		} else {
			// Perspective
			if (Points_CameraSpace[0].x > Points_CameraSpace[0].z * InputCamera->WidthSlope
			 && Points_CameraSpace[1].x > Points_CameraSpace[1].z * InputCamera->WidthSlope
			 && Points_CameraSpace[2].x > Points_CameraSpace[2].z * InputCamera->WidthSlope
			 && Points_CameraSpace[3].x > Points_CameraSpace[3].z * InputCamera->WidthSlope
			 && Points_CameraSpace[4].x > Points_CameraSpace[4].z * InputCamera->WidthSlope
			 && Points_CameraSpace[5].x > Points_CameraSpace[5].z * InputCamera->WidthSlope
			 && Points_CameraSpace[6].x > Points_CameraSpace[6].z * InputCamera->WidthSlope
			 && Points_CameraSpace[7].x > Points_CameraSpace[7].z * InputCamera->WidthSlope) return false;
			if (Points_CameraSpace[0].x < Points_CameraSpace[0].z * -InputCamera->WidthSlope
			 && Points_CameraSpace[1].x < Points_CameraSpace[1].z * -InputCamera->WidthSlope
			 && Points_CameraSpace[2].x < Points_CameraSpace[2].z * -InputCamera->WidthSlope
			 && Points_CameraSpace[3].x < Points_CameraSpace[3].z * -InputCamera->WidthSlope
			 && Points_CameraSpace[4].x < Points_CameraSpace[4].z * -InputCamera->WidthSlope
			 && Points_CameraSpace[5].x < Points_CameraSpace[5].z * -InputCamera->WidthSlope
			 && Points_CameraSpace[6].x < Points_CameraSpace[6].z * -InputCamera->WidthSlope
			 && Points_CameraSpace[7].x < Points_CameraSpace[7].z * -InputCamera->WidthSlope) return false;
			if (Points_CameraSpace[0].y > Points_CameraSpace[0].z * InputCamera->HeightSlope
			 && Points_CameraSpace[1].y > Points_CameraSpace[1].z * InputCamera->HeightSlope
			 && Points_CameraSpace[2].y > Points_CameraSpace[2].z * InputCamera->HeightSlope
			 && Points_CameraSpace[3].y > Points_CameraSpace[3].z * InputCamera->HeightSlope
			 && Points_CameraSpace[4].y > Points_CameraSpace[4].z * InputCamera->HeightSlope
			 && Points_CameraSpace[5].y > Points_CameraSpace[5].z * InputCamera->HeightSlope
			 && Points_CameraSpace[6].y > Points_CameraSpace[6].z * InputCamera->HeightSlope
			 && Points_CameraSpace[7].y > Points_CameraSpace[7].z * InputCamera->HeightSlope) return false;
			if (Points_CameraSpace[0].y < Points_CameraSpace[0].z * -InputCamera->HeightSlope
			 && Points_CameraSpace[1].y < Points_CameraSpace[1].z * -InputCamera->HeightSlope
			 && Points_CameraSpace[2].y < Points_CameraSpace[2].z * -InputCamera->HeightSlope
			 && Points_CameraSpace[3].y < Points_CameraSpace[3].z * -InputCamera->HeightSlope
			 && Points_CameraSpace[4].y < Points_CameraSpace[4].z * -InputCamera->HeightSlope
			 && Points_CameraSpace[5].y < Points_CameraSpace[5].z * -InputCamera->HeightSlope
			 && Points_CameraSpace[6].y < Points_CameraSpace[6].z * -InputCamera->HeightSlope
			 && Points_CameraSpace[7].y < Points_CameraSpace[7].z * -InputCamera->HeightSlope) return false;
		}
		return true;
	} else if (Model->ModelProperties.CullingMethod == Culling_Radius) {
		float Radius;
		DVector3 PointZero;
		Radius = GetBoundingSphereRadius(Instance->Transformation,Model);
		
		// Get the position
		PointZero = DVector3(Instance->Transformation._41,Instance->Transformation._42,Instance->Transformation._43);
		
		// Do optional cutting plane culling without refraction
		if (InputCamera->EnableCuttingPlane && CullUsingCuttingPlane) {
			if ( (PointZero.x * InputCamera->CuttingPlane.x) + (PointZero.y * InputCamera->CuttingPlane.y) + (PointZero.z * InputCamera->CuttingPlane.z) + Radius < InputCamera->CuttingPlane.w ) return false;
		}
		
		// If refractive multiplier is above 1, multiply the radius with the refractive multiplier
		if (InputCamera->EnableCuttingPlane && InputCamera->RefractiveMultiplier > 1.0f) {
			Radius = Radius * InputCamera->RefractiveMultiplier;
		}
		
		// Transform to camera space
		Points_CameraSpace[0] = TransformVec3Mat4(PointZero,InputCamera->RefractedWorldToCamera);
		
		// Do camera view frustum culling
		if (Points_CameraSpace[0].z < InputCamera->NearClipPlane - Radius) return false;
		if (CullUsingFarClip) {
			if (Points_CameraSpace[0].z > InputCamera->FarClipPlane + Radius) return false;
		}
		if (InputCamera->IsOrthogonal) {
			// Orthogonal
			if (AbsFloat(Points_CameraSpace[0].x) - Radius > InputCamera->OrthogonalHalfWidth) return false;
			if (AbsFloat(Points_CameraSpace[0].y) - Radius > InputCamera->OrthogonalHalfHeight) return false;
		} else {
			// Perspective
			if (AbsFloat(Points_CameraSpace[0].x) - (sqrtf(1 + pow(InputCamera->WidthSlope, 2.0f)) * Radius) > Points_CameraSpace[0].z * InputCamera->WidthSlope) return false;
			if (AbsFloat(Points_CameraSpace[0].y) - (sqrtf(1 + pow(InputCamera->HeightSlope, 2.0f)) * Radius) > Points_CameraSpace[0].z * InputCamera->HeightSlope) return false;
		}
		return true;
	} else {
		return true;
	}
}

DVector4 EngineCore::CPUSurface_GetPixelColor_Clamped(CPUSurface_Struct* Surface, int X, int Y) {
	if (X < 0) {
		X = 0;
	} else if (X > Surface->Width - 1) {
		X = Surface->Width - 1;
	}
	if (Y < 0) {
		Y = 0;
	} else if (Y > Surface->Height - 1) {
		Y = Surface->Height - 1;
	}
	return Surface->CPUContent[X + (Y * Surface->Width)];
}

DVector4 EngineCore::CPUSurface_GetPixelColor_Border(CPUSurface_Struct* Surface, int X, int Y, float DefaultRed, float DefaultGreen, float DefaultBlue, float DefaultAlpha) {
	if (X < 0 || Y < 0 || X > Surface->Width - 1 || Y > Surface->Height - 1) {
		return DVector4(DefaultRed,DefaultGreen,DefaultBlue,DefaultAlpha);
	} else {
		return Surface->CPUContent[X + (Y * Surface->Width)];
	}
}

void EngineCore::CPUSurface_SetPixelColor(CPUSurface_Struct* Surface, int X, int Y, float Red, float Green, float Blue, float Alpha, bool GiveWarning) {
	if (X < 0 || Y < 0 || X > Surface->Width - 1 || Y > Surface->Height - 1) {
		if (GiveWarning) {
			swprintf_s( MQ->messageBuffer, L"CPUSurface_SetPixelColor_Warning: The pixel coordinate (%i,%i) is out of the bound ([0..%i],[0..%i]). Use CPUSurface_SetPixelColor_Ignore if you think that this is not an error in your code.",X,Y,Surface->Width - 1,Surface->Height - 1); MQ->InsertMessage(MQ->messageBuffer);
		}
	} else {
		Surface->CPUContent[X + (Y * Surface->Width)] = DVector4(Red,Green,Blue,Alpha);
			
		// Tell physics that height fields might need to clear proxy
		Physics_CPUSurfaceHasChanged(Surface);
	}
}

void EngineCore::CPUSurface_SetSize(CPUSurface_Struct* Surface, int NewWidth, int NewHeight, float Red, float Green, float Blue, float Alpha) {
	if (NewWidth < 1 || NewHeight < 1) {
		MQ->InsertMessage(L"CPUSurface_SetSize: A CPU surface can't have non positive dimensions.");
	} else if (NewWidth > 8192 || NewHeight > 8192) {
		MQ->InsertMessage(L"CPUSurface_SetSize: A CPU surface can't have dimensions larger than 8192.");
	} else {
		
		// Release any old data to avoid memory leaks
		CPUSurface_Struct_Release(Surface);
		
		// Store dimensions
		Surface->Width = NewWidth;
		Surface->Height = NewHeight;
		
		// Allocate the CPU array
		int Size = NewWidth * NewHeight;
		Surface->CPUContent = new DVector4[Size];
		
		if (Surface->CPUContent == NULL) {
			MQ->InsertMessage(L"CPUSurface_SetSize: Could not allocate the CPU surface.");
		} else {
			// Fill the CPU array with a default value for deterministic behaviour.
			CPUSurface_FillWithColor(Surface,Red, Green, Blue, Alpha);
			
			// Create staging buffer
			D3D11_TEXTURE2D_DESC StagedDesc = {
				NewWidth,//UINT Width;
				NewHeight,//UINT Height;
				1,//UINT MipLevels;
				1,//UINT ArraySize;
				DXGI_FORMAT_R32G32B32A32_FLOAT,//DXGI_FORMAT Format;
				1, 0,//DXGI_SAMPLE_DESC SampleDesc;
				D3D11_USAGE_STAGING,//D3D11_USAGE Usage;
				0,//UINT BindFlags;
				D3D11_CPU_ACCESS_READ,//UINT CPUAccessFlags;
				0//UINT MiscFlags;
			};
			m_pd3dDevice->CreateTexture2D( &StagedDesc, NULL, &Surface->StagingBuffer );
		}
	}
}

void EngineCore::CPUSurface_FillWithColor(CPUSurface_Struct* Surface, float Red, float Green, float Blue, float Alpha) {
	int i, length;
	length = Surface->Width * Surface->Height;
	LoopForwardLengthFromZero(i,length) {
		Surface->CPUContent[i] = DVector4(Red, Green, Blue, Alpha);
	}
	
	// Tell physics that height fields might need to clear proxy
	Physics_CPUSurfaceHasChanged(Surface);
}

void EngineCore::CPUSurface_CopyRectFromDrawSurface(DrawSurface_Struct* Input_DrawSurface, CPUSurface_Struct* Output_CPUSurface, int SourceLeft, int SourceTop, int DestLeft, int DestTop, int Width, int Height) {
	int X; int Y;
	ID3D11Texture2D* InputResource;
	if (Input_DrawSurface->FinalSurface == true) {
		MQ->InsertMessage(L"CPUSurface_CopyRectFromDrawSurface: The final draw surface can not be used with this method because it does not work like a regular draw surface.");
	} else if (DestLeft < 0) {
		swprintf_s( MQ->messageBuffer, L"CPUSurface_CopyRectFromDrawSurface: DestLeft = %i < 0.",DestLeft); MQ->InsertMessage(MQ->messageBuffer);
	} else if (DestTop < 0) {
		swprintf_s( MQ->messageBuffer, L"CPUSurface_CopyRectFromDrawSurface: DestTop = %i < 0.",DestTop); MQ->InsertMessage(MQ->messageBuffer);
	} else if (SourceLeft < 0) {
		swprintf_s( MQ->messageBuffer, L"CPUSurface_CopyRectFromDrawSurface: SourceLeft = %i < 0.",SourceLeft); MQ->InsertMessage(MQ->messageBuffer);
	} else if (SourceTop < 0) {
		swprintf_s( MQ->messageBuffer, L"CPUSurface_CopyRectFromDrawSurface: SourceTop = %i < 0.",SourceTop); MQ->InsertMessage(MQ->messageBuffer);
	} else if (SourceLeft + Width > Input_DrawSurface->CurrentWidth) {
		swprintf_s( MQ->messageBuffer, L"CPUSurface_CopyRectFromDrawSurface: SourceLeft + Width = %i > %i.",SourceLeft + Width,Input_DrawSurface->CurrentWidth); MQ->InsertMessage(MQ->messageBuffer);
	} else if (SourceTop + Height > Input_DrawSurface->CurrentHeight) {
		swprintf_s( MQ->messageBuffer, L"CPUSurface_CopyRectFromDrawSurface: SourceTop + Height = %i > %i.",SourceTop + Height,Input_DrawSurface->CurrentHeight); MQ->InsertMessage(MQ->messageBuffer);
	} else if (DestLeft + Width > Output_CPUSurface->Width) {
		swprintf_s( MQ->messageBuffer, L"CPUSurface_CopyRectFromDrawSurface: DestLeft + Width = %i > %i.",DestLeft + Width,Output_CPUSurface->Width); MQ->InsertMessage(MQ->messageBuffer);
	} else if (DestTop + Height > Output_CPUSurface->Height ) {
		swprintf_s( MQ->messageBuffer, L"CPUSurface_CopyRectFromDrawSurface: DestTop + Height = %i > %i.",DestLeft + Height,Output_CPUSurface->Height); MQ->InsertMessage(MQ->messageBuffer);
	} else if (Input_DrawSurface->HasContent == false) {
		// Save time if we already know the result
		LoopForward(DestTop,Y,DestTop + Height - 1) {
			LoopForward(DestLeft,X,DestLeft + Width - 1) {
				Output_CPUSurface->CPUContent[X + (Y * Output_CPUSurface->Width)] = DVector4(0.0f, 0.0f, 0.0f, 0.0f);
			}
		}
		
		// Tell physics that height fields might need to clear proxy
		Physics_CPUSurfaceHasChanged(Output_CPUSurface);
	} else {
		// Select all pixels
		D3D11_BOX SrcBox;
		SrcBox.left = SourceLeft; // Minimum X
		SrcBox.right = SourceLeft + Width; // Maximum X
		SrcBox.top = SourceTop; // Minimum Y
		SrcBox.bottom = SourceTop + Height; // Maximum Y
		SrcBox.front = 0; // Always 0 for 2D textures
		SrcBox.back = 1; // Always 1 for 2D textures
		
		// Get the texture pointer
		if (Input_DrawSurface->HaveExtraColorBuffer == false || Input_DrawSurface->SwapState == true) {
			InputResource = Input_DrawSurface->OriginalColorBuffer;
		} else {
			InputResource = Input_DrawSurface->ExtraColorBuffer;
		}
		
		// Copy the draw surface to the staging buffer
		m_pImmediateContext->CopySubresourceRegion(Output_CPUSurface->StagingBuffer,0,0,0,0,InputResource,0,&SrcBox);
		
		// Lock the memory
		D3D11_MAPPED_SUBRESOURCE MappingResult;
		if (FAILED(m_pImmediateContext->Map(Output_CPUSurface->StagingBuffer,0,D3D11_MAP_READ,0,&MappingResult))) {
			swprintf_s( MQ->messageBuffer, L"CPUSurface_CopyRectFromDrawSurface: Mapping from staging buffer failed.",DestLeft + Height,Output_CPUSurface->Height); MQ->InsertMessage(MQ->messageBuffer);
		} else {
			// Get the data
			if (MappingResult.pData == NULL) {
				MQ->InsertMessage(L"CPUSurface_CopyRectFromDrawSurface: Could not read the texture because the mapped subresource returned NULL.");
			} else {
				LoopForward(DestTop,Y,DestTop + Height - 1) {
					LoopForward(DestLeft,X,DestLeft + Width - 1) {
						Output_CPUSurface->CPUContent[X + (Y * Output_CPUSurface->Width)] = ((DVector4*)MappingResult.pData)[(X - DestLeft) + ((Y - DestTop) * MappingResult.RowPitch / sizeof(DVector4))];
					}
				}
			}
		}

		// Unlock the memory
		m_pImmediateContext->Unmap(Output_CPUSurface->StagingBuffer,0);
		
		// Tell physics that height fields might need to clear proxy
		Physics_CPUSurfaceHasChanged(Output_CPUSurface);
	}
}

void EngineCore::DepthBuffer_Release(DepthBuffer_Struct* Reference) {
	Try_Start {
		SAFE_RELEASE(Reference->DepthBuffer)
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in DepthBuffer_Release when releasing the depth buffer.",L"Error!",NULL);
	}
	Try_Start {
		SAFE_RELEASE(Reference->DepthInputAndOutput)
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in DepthBuffer_Release when releasing the depth stencil view.",L"Error!",NULL);
	}
	Try_Start {
		SAFE_RELEASE(Reference->DepthOutput)
	} Try_Else {
		::MessageBoxW(NULL,L"Access violation in DepthBuffer_Release when releasing the shader resource view.",L"Error!",NULL);
	}
}

void EngineCore::DepthBuffer_Clear(DepthBuffer_Struct* Reference) {
	m_pImmediateContext->ClearDepthStencilView( Reference->DepthInputAndOutput, D3D11_CLEAR_DEPTH, 1.0f, 0 );
}

void EngineCore::ClearShadows(void) {
	int l; LightSource_Struct* pCurrentLightSource;
	m_DepthAtlas_PartUsed = 0;
	m_DepthAtlas_DeniedAllocation = 0;
	if (m_DepthAtlas.DepthBuffer != NULL) {
		// Clear the depth atlas
		DepthBuffer_Clear(&m_DepthAtlas);
		
		// Deallocate every depth tile
		m_pDepthAltasQuadAllocator->Reset();
		LoopForwardLengthFromZero(l, SizeOfCollection(LightSource)) {
			pCurrentLightSource = (LightSource_Struct*)m_LightSource.getValue_warning(l);
			pCurrentLightSource->HasDepthTile = false;
		}
	}
}

void EngineCore::DrawSurface_Clear(DrawSurface_Struct* Surface) {
	// Clear the color buffer
	DrawSurface_ClearColor(Surface);
	
	// Clear the depth buffer
	DrawSurface_ClearDepthBuffer(Surface);
}

void EngineCore::DrawSurface_ClearColor(DrawSurface_Struct* Surface) {
	// Clear the color buffer
	if (Surface->ColorInput != NULL) {
		m_pImmediateContext->ClearRenderTargetView( Surface->ColorInput, ToFloatArray(&m_vBackgroundColor) );
	}
}

void EngineCore::DrawSurface_ClearDepthBuffer(DrawSurface_Struct* Surface) {
	// Clear the depth buffer
	if (Surface->DepthInputAndOutput != NULL) {
		m_pImmediateContext->ClearDepthStencilView( Surface->DepthInputAndOutput, D3D11_CLEAR_DEPTH, 1.0f, 0 );
	}
}

void EngineCore::DrawSurface_Swap(DrawSurface_Struct* Surface) {
	if (Surface->HaveExtraColorBuffer) {
		DrawSurface_SetSwapState(Surface,!(Surface->SwapState));
	}
}

void EngineCore::SetDefaultShaderResources(void) {
	// Geometry shader resources
	m_pImmediateContext->GSSetConstantBuffers( 0, 1, &m_pCBEveryRender );
	m_pImmediateContext->GSSetConstantBuffers( 1, 1, &m_pCBEveryObject );
	m_pImmediateContext->GSSetConstantBuffers( 2, 1, &m_pCBBoneFrame_8 );
	m_pImmediateContext->GSSetConstantBuffers( 3, 1, &m_pCBBoneFrame_16 );
	m_pImmediateContext->GSSetConstantBuffers( 4, 1, &m_pCBBoneFrame_32 );
	m_pImmediateContext->GSSetConstantBuffers( 5, 1, &m_pCBBoneFrame_64 );
	m_pImmediateContext->GSSetConstantBuffers( 6, 1, &m_pCBArgBuffer );

	// Vertex shader resources
	m_pImmediateContext->VSSetConstantBuffers( 0, 1, &m_pCBEveryRender );
	m_pImmediateContext->VSSetConstantBuffers( 1, 1, &m_pCBEveryObject );
	m_pImmediateContext->VSSetConstantBuffers( 2, 1, &m_pCBBoneFrame_8 );
	m_pImmediateContext->VSSetConstantBuffers( 3, 1, &m_pCBBoneFrame_16 );
	m_pImmediateContext->VSSetConstantBuffers( 4, 1, &m_pCBBoneFrame_32 );
	m_pImmediateContext->VSSetConstantBuffers( 5, 1, &m_pCBBoneFrame_64 );
	m_pImmediateContext->VSSetConstantBuffers( 6, 1, &m_pCBArgBuffer );
	
	// Pixel shader resources
	m_pImmediateContext->PSSetConstantBuffers( 0, 1, &m_pCBEveryRender );
	m_pImmediateContext->PSSetConstantBuffers( 1, 1, &m_pCBEveryObject );
	//m_pImmediateContext->PSSetConstantBuffers( 2, 1, &m_pCBBoneFrame_8 );
	//m_pImmediateContext->PSSetConstantBuffers( 3, 1, &m_pCBBoneFrame_16 );
	//m_pImmediateContext->PSSetConstantBuffers( 4, 1, &m_pCBBoneFrame_32 );
	//m_pImmediateContext->PSSetConstantBuffers( 5, 1, &m_pCBBoneFrame_64 );
	m_pImmediateContext->PSSetConstantBuffers( 6, 1, &m_pCBArgBuffer );
}

void EngineCore::SortInstances(Camera_Struct* Camera) {
	// Write the distance to the sort value for each object instance
	DVector3 objectWorldCenter;
	DVector3 cameraToObjectOffset;
	DVector3 cameraDirection;
	int i; float Dist;
	Instance_Struct* pCurrentInstance;
	LoopForwardLengthFromZero(i, SizeOfCollection(Instance)) {
		pCurrentInstance = (Instance_Struct*)m_Instance.getValue_warning(i);
		objectWorldCenter = TransformVec3Mat4(pCurrentInstance->VisualModel->Model.ObjectSpaceCenter, pCurrentInstance->Transformation);
		
		// Distance
		cameraToObjectOffset = SubVec3(objectWorldCenter,Camera->Eye);
		Dist = AbsVec3(cameraToObjectOffset);
		
		// Depth
		/*cameraDirection = Camera->At - Camera->Eye;
		cameraDirection = NormalizeVec3(cameraDirection);
		Dist = D3DXVec3Dot(&objectWorldCenter,&cameraDirection);
		*/
		
		m_Instance.setSortValue_warning(i, Dist);
	}
	// Use the sort values to sort the instance list
	m_Instance.heapSort(SizeOfCollection(Instance));
	// Update the index for references
	LoopForwardLengthFromZero(i, SizeOfCollection(Instance)) {
		pCurrentInstance = (Instance_Struct*)m_Instance.getValue_warning(i);
		pCurrentInstance->Index = i;
	}
}

void EngineCore::SetRenderTargetRect(float left, float top, float width, float height) {
	D3D11_VIEWPORT vp;
	vp.MinDepth = 0.0f;
	vp.MaxDepth = 1.0f;
	vp.TopLeftX = left;
	vp.TopLeftY = top;
	vp.Width = width;
	vp.Height = height;
	m_pImmediateContext->RSSetViewports( 1, &vp );
}

DMatrix EngineCore::Camera_GetRefractedWorldTransformation(Camera_Struct* Camera) {
	// Transform this so that the camera's refractive multiplier is scaling along the cutting plane
	DMatrix RFT;
	RFT = IdentityMatrix();
	DVector4 Plane = Camera->CuttingPlane;
	float Refraction = Camera->RefractiveMultiplier;
	
	// Scale the X axis along the plane
	float XAxisOffset = ((RFT._11 * Plane.x) + (RFT._12 * Plane.y) + (RFT._13 * Plane.z)) * (Refraction - 1.0f);
	RFT._11 += (Camera->CuttingPlane.x * XAxisOffset);
	RFT._12 += (Camera->CuttingPlane.y * XAxisOffset);
	RFT._13 += (Camera->CuttingPlane.z * XAxisOffset);
	// Scale the Y axis along the plane
	float YAxisOffset = ((RFT._21 * Plane.x) + (RFT._22 * Plane.y) + (RFT._23 * Plane.z)) * (Refraction - 1.0f);
	RFT._21 += (Camera->CuttingPlane.x * YAxisOffset);
	RFT._22 += (Camera->CuttingPlane.y * YAxisOffset);
	RFT._23 += (Camera->CuttingPlane.z * YAxisOffset);
	// Scale the Z axis along the plane
	float ZAxisOffset = ((RFT._31 * Plane.x) + (RFT._32 * Plane.y) + (RFT._33 * Plane.z)) * (Refraction - 1.0f);
	RFT._31 += (Camera->CuttingPlane.x * ZAxisOffset);
	RFT._32 += (Camera->CuttingPlane.y * ZAxisOffset);
	RFT._33 += (Camera->CuttingPlane.z * ZAxisOffset);
	
	// Subtract from the position to keep things on the plane at the same place
	RFT._41 -= (Camera->CuttingPlane.x * Camera->CuttingPlane.w * (Refraction - 1.0f));
	RFT._42 -= (Camera->CuttingPlane.y * Camera->CuttingPlane.w * (Refraction - 1.0f));
	RFT._43 -= (Camera->CuttingPlane.z * Camera->CuttingPlane.w * (Refraction - 1.0f));
	return RFT;
}

void EngineCore::LoadGlobalTextures(DrawSurface_Struct* ResultSurface) {
	ID3D11ShaderResourceView* NoTexture = NULL;
	
	// Load light projection atlas to it's register
	if (m_pLightProjectionAtlas == NULL) {
		if (m_pDefaultTexture == NULL) {
			// NULL texture
			m_pImmediateContext->PSSetShaderResources(LightProjectionTextureChannel,1,&NoTexture);
		} else {
			// Default texture
			m_pImmediateContext->PSSetShaderResources(LightProjectionTextureChannel,1,&(m_pDefaultTexture->ColorOutput));
		}
	} else {
		// Light projection atlas
		m_pImmediateContext->PSSetShaderResources(LightProjectionTextureChannel,1,&(m_pLightProjectionAtlas->ColorOutput));
	}
	
	// Load depth atlas to it's register
	if (m_DepthAtlas.DepthBuffer == NULL) {
		// NULL texture
		m_pImmediateContext->PSSetShaderResources(DepthAtlasTextureChannel,1,&NoTexture);
	} else {
		// Depth atlas
		m_pImmediateContext->PSSetShaderResources(DepthAtlasTextureChannel,1,&(m_DepthAtlas.DepthOutput));
	}
	
	// Load depth copy to it's register
	if (m_DepthAtlas.DepthBuffer == NULL) {
		// NULL texture
		m_pImmediateContext->PSSetShaderResources(DepthCopyTextureChannel,1,&NoTexture);
	} else {
		// Depth atlas
		m_pImmediateContext->PSSetShaderResources(DepthCopyTextureChannel,1,&(ResultSurface->DepthOutput));
	}
}

void EngineCore::Camera_Prepare(Camera_Struct* InputCamera, float AspectRatio) {
	// Create a view matrix
	InputCamera->WorldToCamera = LookAtLH(InputCamera->Eye, InputCamera->At, InputCamera->Up );
	
	// Create the refracted view matrix
	if (InputCamera->EnableCuttingPlane) {
		InputCamera->RefractedWorldToCamera = MulMat(Camera_GetRefractedWorldTransformation(InputCamera),InputCamera->WorldToCamera);
	} else {
		InputCamera->RefractedWorldToCamera = InputCamera->WorldToCamera;
	}
	
	// Load global settings
	InputCamera->FarClipPlane = m_FarClipPlane;
	InputCamera->NearClipPlane = m_NearClipPlane;
	
	// Create a projection matrix
	if (InputCamera->IsOrthogonal) {
		// Orthogonal
		InputCamera->CameraToImage = OrthoLH( InputCamera->OrthogonalHalfWidth * 2.0f, InputCamera->OrthogonalHalfHeight * 2.0f, m_NearClipPlane, m_FarClipPlane );
		InputCamera->HeightSlope = 0.0f;
		InputCamera->WidthSlope = 0.0f;
	} else {
		// Perspective
		if (InputCamera->VerticalFieldOfView) {
			// Vertical FOV
			InputCamera->CameraToImage = PerspectiveFovLH(InputCamera->FieldOfView, AspectRatio, m_NearClipPlane, m_FarClipPlane );
			InputCamera->HeightSlope = tanf(InputCamera->FieldOfView * 0.5f);
			InputCamera->WidthSlope = InputCamera->HeightSlope * AspectRatio;
		} else {
			// Horizontal FOV
			InputCamera->CameraToImage = PerspectiveFovLH(2 * atanf(tanf(InputCamera->FieldOfView * 0.5f) / AspectRatio), AspectRatio, m_NearClipPlane, m_FarClipPlane );
			InputCamera->WidthSlope = tanf(InputCamera->FieldOfView * 0.5f);
			InputCamera->HeightSlope = InputCamera->WidthSlope / AspectRatio;
		}
	}
}

void EngineCore::Camera_CreateStructFromLight(Camera_Struct* InputCamera, LightSource_Struct* InputLight) {
	float AspectRatio;
	DVector3 At;
	At = AddVec3(InputLight->ShaderData.Pos,InputLight->ShaderData.ZAxis);
	
	AspectRatio = InputLight->ShaderData.WidthSlope / InputLight->ShaderData.HeightSlope;
	
	// Create a view matrix
	InputCamera->WorldToCamera = LookAtLH(InputLight->ShaderData.Pos, At, InputLight->ShaderData.YAxis);
	
	// Assign it as the refracted view matrix
	InputCamera->RefractedWorldToCamera = InputCamera->WorldToCamera;
	
	InputCamera->IsOrthogonal = InputLight->IsOrthogonal;
	if (InputLight->IsOrthogonal) {
		// Create orthogonal projection matrix
		InputCamera->WidthSlope = 0.0f;
		InputCamera->HeightSlope = 0.0f;
		InputCamera->FieldOfView = 0.0f;
		InputCamera->OrthogonalHalfWidth = InputLight->ShaderData.WidthSlope;
		InputCamera->OrthogonalHalfHeight = InputLight->ShaderData.HeightSlope;
		InputCamera->CameraToImage = OrthoLH( InputCamera->OrthogonalHalfWidth * 2.0f, InputCamera->OrthogonalHalfHeight * 2.0f, InputLight->ShaderData.NearClip, InputLight->ShaderData.Radius);
	} else {
		// Create projection matrix and calculate vertical FOV
		InputCamera->WidthSlope = InputLight->ShaderData.WidthSlope;
		InputCamera->HeightSlope = InputLight->ShaderData.HeightSlope;
		InputCamera->FieldOfView = atanf(InputCamera->HeightSlope) * 2.0f;
		InputCamera->OrthogonalHalfWidth = 0.0f;
		InputCamera->OrthogonalHalfHeight = 0.0f;
		InputCamera->CameraToImage = PerspectiveFovLH(InputCamera->FieldOfView, AspectRatio, InputLight->ShaderData.NearClip, InputLight->ShaderData.Radius);
	}
	// Set some remaining values
	InputCamera->Eye = InputLight->ShaderData.Pos;
	InputCamera->At = At;
	InputCamera->Up = InputLight->ShaderData.YAxis;
	InputCamera->VerticalFieldOfView = true;
	InputCamera->EnableCuttingPlane = false;
	InputCamera->CuttingPlane = DVector4(0.0f,0.0f,0.0f,0.0f);
	InputCamera->RefractiveMultiplier = 1.0f;
	InputCamera->FarClipPlane = InputLight->ShaderData.Radius;
	InputCamera->NearClipPlane = InputLight->ShaderData.NearClip;
}

void EngineCore::Camera_Render(Camera_Struct* InputCamera, DrawSurface_Struct* ResultSurface, int ShaderChannel, Instance_Struct* OptionalSingleInstance, Shader_Struct* ShaderOverride, int FilterIndex, int RenderingMethod, bool UseDepthBuffer, DVector4 InstanceColor, int Part) {
	int l; int i;
	LightSource_Struct* pCurrentLightSource;
	Camera_Struct TempCamera;
	CBEveryRender cbEveryRender;
	
	Try_Start {
		// Assign constant buffers
		SetDefaultShaderResources();
	} Try_Else {
		MQ->InsertMessage(L"Camera_Render: Access violation was detected when assigning default resources.");
	}
	
	Try_Start {
		// Update geometry if needed
		if (OptionalSingleInstance) {
			OptionalSingleInstance->VisualModel->Model.UpdateEverythingIfNeeded();
		} else {
			UpdateModels();
		}
	} Try_Else {
		MQ->InsertMessage(L"Camera_Render: Access violation was detected when updating geometry.");
	}
	
	Try_Start {
		// Make sure that the result surface has the right size.
		AutoSizeSurface(ResultSurface);
	} Try_Else {
		MQ->InsertMessage(L"Camera_Render: Access violation was detected when resizing the result surface.");
	}
	
	Try_Start {
		if (OptionalSingleInstance == NULL) {
			// Clear color and depth buffers
			DrawSurface_Clear(ResultSurface);
		}
	} Try_Else {
		MQ->InsertMessage(L"Camera_Render: Access violation was detected when clearing the draw surface.");
	}
	
	Try_Start {
		// Calculate some data needed to use the camera
		Camera_Prepare(InputCamera,ResultSurface->CurrentWidth / (FLOAT)ResultSurface->CurrentHeight);
	} Try_Else {
		MQ->InsertMessage(L"Camera_Render: Access violation was detected when preparing the camera.");
	}
	
	Try_Start {
		if (OptionalSingleInstance == NULL) {
			// Calculate what light sources we see this render
			l = 0;
			while (l < SizeOfCollection(LightSource)) {
				pCurrentLightSource = (LightSource_Struct*)m_LightSource.getValue_warning(l);
				if (pCurrentLightSource->EnabledByUser) {
					if (CanLightBeSeenFromCamera(InputCamera,&pCurrentLightSource->ShaderData)) {
						pCurrentLightSource->SeenThisRender = true;
						if (pCurrentLightSource->ShaderData.ShadowTransparency < 0.999f) {
							if (pCurrentLightSource->WantDepthTile == true && pCurrentLightSource->HasDepthTile == false) {
								// Try to allocate and continue if it works
								QARect NextArea;
								NextArea = m_pDepthAltasQuadAllocator->Allocate(pCurrentLightSource->ResolutionGroup);
								if (NextArea.MaxU < -0.5f) {
									m_DepthAtlas_DeniedAllocation = 1;
								} else {
									// Count use
									m_DepthAtlas_PartUsed += pow(0.25f,(float)pCurrentLightSource->ResolutionGroup);
								
									// Calculate the new tile's area in the depth atlas
									pCurrentLightSource->ShaderData.DepthAtlasRect.x = NextArea.MinU; // MinU
									pCurrentLightSource->ShaderData.DepthAtlasRect.y = NextArea.MaxU; // MaxU
									pCurrentLightSource->ShaderData.DepthAtlasRect.z = NextArea.MinV; // MinV
									pCurrentLightSource->ShaderData.DepthAtlasRect.w = NextArea.MaxV; // MaxV
								
									// Tell the light source that it has an allocation
									pCurrentLightSource->HasDepthTile = true;
								
									// Render depth map
										// Create a temporary camera
										Camera_CreateStructFromLight(&TempCamera,pCurrentLightSource);
									
										// Use these values to convert the depth tile's non-linear value to the real depth.
										if (pCurrentLightSource->IsOrthogonal) {
											pCurrentLightSource->ShaderData.ZWCorrection = DVector2(pCurrentLightSource->OutsideIntensity,pCurrentLightSource->FadeSize);
										} else {
											pCurrentLightSource->ShaderData.ZWCorrection = DVector2(TempCamera.CameraToImage._33,TempCamera.CameraToImage._43);
										}
									
										// Update constant buffer for this render
											// Give global settings
											cbEveryRender.FogColor = m_vBackgroundColor;
											cbEveryRender.SceneSettingsA.x = pCurrentLightSource->ShaderData.Radius;
											cbEveryRender.SceneSettingsA.y = 0.0f;
											cbEveryRender.SceneSettingsA.z = pCurrentLightSource->ShaderData.NearClip;
											cbEveryRender.AmbientLight = DVector3(1.0f, 1.0f, 1.0f);
											cbEveryRender.GlobalTime = m_GlobalTime;
										
											// Give surface settings
											cbEveryRender.Dimensions = DVector2((float)m_DepthAtlas.CurrentWidth * (NextArea.MaxU - NextArea.MinU),(float)m_DepthAtlas.CurrentHeight * (NextArea.MaxV - NextArea.MinV));
										
											// Give camera settings
											cbEveryRender.mCameraToImage = TransposeMatrix(TempCamera.CameraToImage);
											cbEveryRender.CameraPos_WorldSpace = TempCamera.Eye;
											cbEveryRender.EnableCuttingPlane = 0.0f;
											cbEveryRender.mWorldToCamera_NoRefraction = TransposeMatrix(TempCamera.WorldToCamera);
											cbEveryRender.mWorldToCamera = TransposeMatrix(TempCamera.RefractedWorldToCamera);
											cbEveryRender.mWorldToImage = MulMat(cbEveryRender.mCameraToImage,cbEveryRender.mWorldToCamera);
										
											// Don't use any light in this render
											cbEveryRender.NumberOfLights = 0;
										m_pImmediateContext->UpdateSubresource( m_pCBEveryRender, 0, NULL, &cbEveryRender, 0, 0 );
									
										float TileResolutionInPixels;
										TileResolutionInPixels = (float)m_DepthAtlas.CurrentWidth * (NextArea.MaxU - NextArea.MinU);
									
										// Calculate the optimal shadow offset
										pCurrentLightSource->ShaderData.ShadowOffset = MaxFloat(pCurrentLightSource->ShaderData.WidthSlope,pCurrentLightSource->ShaderData.HeightSlope) * ShadowSlope / TileResolutionInPixels;
									
										// Tell Direct3D where to draw
										ID3D11RenderTargetView* pnullView = NULL;
										m_pImmediateContext->OMSetRenderTargets(1,&pnullView,m_DepthAtlas.DepthInputAndOutput);
										SetRenderTargetRect(pCurrentLightSource->ShaderData.DepthAtlasRect.x * (float)m_DepthAtlas.CurrentWidth,
															pCurrentLightSource->ShaderData.DepthAtlasRect.z * (float)m_DepthAtlas.CurrentHeight,
															TileResolutionInPixels,
															TileResolutionInPixels);
									
										// Render the depth tile
										RenderOneStep(&TempCamera);
									// Finished rendering
								}
							}
						}
					} else {
						pCurrentLightSource->SeenThisRender = false;
					}
				} else {
					pCurrentLightSource->SeenThisRender = false;
				}
				l++;
			}
		}
	} Try_Else {
		MQ->InsertMessage(L"Camera_Render: Access violation was detected when rendering depth maps for light sources.");
	}
	
	// Update constant buffer for this render
	Try_Start {
		// Give global settings
		cbEveryRender.FogColor = m_vBackgroundColor;
		cbEveryRender.SceneSettingsA.x = m_FarClipPlane;
		cbEveryRender.SceneSettingsA.y = m_MaxFogIntensity;
		cbEveryRender.SceneSettingsA.z = m_NearClipPlane;
		if (OptionalSingleInstance) {
			cbEveryRender.AmbientLight = DVector3(1.0f, 1.0f, 1.0f);
		} else {
			cbEveryRender.AmbientLight = m_AmbientLight;
		}
		cbEveryRender.GlobalTime = m_GlobalTime;
	} Try_Else {
		MQ->InsertMessage(L"Camera_Render: Access violation was detected when filling the constant buffer with global settings.");
	}
	
	Try_Start {
		// Give surface settings
		cbEveryRender.Dimensions = DVector2((float)ResultSurface->CurrentWidth,(float)ResultSurface->CurrentHeight);
	} Try_Else {
		MQ->InsertMessage(L"Camera_Render: Access violation was detected when filling the constant buffer with surface settings.");
	}
	
	Try_Start {
		// Give camera settings
		cbEveryRender.mCameraToImage = TransposeMatrix(InputCamera->CameraToImage);
		cbEveryRender.CameraPos_WorldSpace = InputCamera->Eye;
		if (InputCamera->EnableCuttingPlane) {
			cbEveryRender.EnableCuttingPlane = 1.0f;
			cbEveryRender.CuttingPlane = InputCamera->CuttingPlane;
		} else {
			cbEveryRender.EnableCuttingPlane = 0.0f;
		}
		cbEveryRender.mWorldToCamera_NoRefraction = TransposeMatrix(InputCamera->WorldToCamera);
		cbEveryRender.mWorldToCamera = TransposeMatrix(InputCamera->RefractedWorldToCamera);
		cbEveryRender.mWorldToImage = MulMat(cbEveryRender.mCameraToImage,cbEveryRender.mWorldToCamera);
	} Try_Else {
		MQ->InsertMessage(L"Camera_Render: Access violation was detected when filling the constant buffer with camera settings.");
	}
	
	Try_Start {
		if (OptionalSingleInstance) {
			// Don't use light for single instances.
			cbEveryRender.NumberOfLights = 0;
		} else {
			// Insert visible light sources for this render.
			l = 0; i = 0;
			while (l < SizeOfCollection(LightSource) && i < MaxNumberOfLights) {
				pCurrentLightSource = (LightSource_Struct*)m_LightSource.getValue_warning(l);
				if (pCurrentLightSource->SeenThisRender) {
					if (pCurrentLightSource->HasDepthTile == true || pCurrentLightSource->WantDepthTile == false) {
						cbEveryRender.Lights[i] = pCurrentLightSource->ShaderData;
						i++;
					} else if (pCurrentLightSource->WantDepthTile == true) {
						cbEveryRender.Lights[i] = pCurrentLightSource->ShaderData;
						cbEveryRender.Lights[i].Type = pCurrentLightSource->ShadowlessType;
						i++;
					}
				}
				l++;
			}
			cbEveryRender.NumberOfLights = i;
			m_SeenLightSources = cbEveryRender.NumberOfLights;
			m_CulledLightSources = SizeOfCollection(LightSource) - cbEveryRender.NumberOfLights;
		}
	} Try_Else {
		MQ->InsertMessage(L"Camera_Render: Access violation was detected when filling the constant buffer with light sources.");
	}
	
	Try_Start {
		m_pImmediateContext->UpdateSubresource( m_pCBEveryRender, 0, NULL, &cbEveryRender, 0, 0 );
	} Try_Else {
		MQ->InsertMessage(L"Camera_Render: Access violation was detected when updating the constant buffer.");
	}
	
	Try_Start {
		// Tell Direct 3D that we will render to the selected output.
		ID3D11DepthStencilView* DepthBuffer;
		if (UseDepthBuffer) {
			DepthBuffer = ResultSurface->DepthInputAndOutput;
		} else {
			DepthBuffer = NULL;
		}
		
		if (OptionalSingleInstance == NULL) {
			m_pImmediateContext->OMSetRenderTargets(1,&ResultSurface->ColorInput,DepthBuffer);
		} else {
			m_pImmediateContext->OMSetRenderTargets(1,&ResultSurface->ColorInput_Reverse,DepthBuffer);
		}
	} Try_Else {
		MQ->InsertMessage(L"Camera_Render: Access violation was detected when choosing render target.");
	}
	
	Try_Start {
		// Set up the viewport
		SetRenderTargetRect(0.0,0.0,(FLOAT)ResultSurface->CurrentWidth,(FLOAT)ResultSurface->CurrentHeight);
	} Try_Else {
		MQ->InsertMessage(L"Camera_Render: Access violation was detected when defining the viewport.");
	}
	
	Try_Start {
		if (OptionalSingleInstance == NULL) {
			// Sort by distance to the eye
			SortInstances(InputCamera);
		}
	} Try_Else {
		MQ->InsertMessage(L"Camera_Render: Access violation was detected when sorting instances by distance.");
	}
	
	Try_Start {
		// Load all global textures
		LoadGlobalTextures(ResultSurface);
	} Try_Else {
		MQ->InsertMessage(L"Camera_Render: Access violation was detected when loading global textures.");
	}
	
	Try_Start {
		if (OptionalSingleInstance) {
			// Render single instance
			if (FilterIndex) {
				m_pImmediateContext->OMSetDepthStencilState(m_pDepthStencilDisableDepthWrite, 0); // Disable depth write
			} else {
				m_pImmediateContext->OMSetDepthStencilState(m_pDepthStencilDefault, 0); // Enable depth write
			}
			RenderItem(OptionalSingleInstance, ShaderChannel, ShaderOverride, FilterIndex, RenderingMethod, Part, InstanceColor);
		} else {
			// Render opaque and filtered instances
			RenderTwoSteps(InputCamera,ShaderChannel,ResultSurface);
		}
	} Try_Else {
		MQ->InsertMessage(L"Camera_Render: Access violation was detected when rendering instances in 2 steps.");
	}
	
	Try_Start {
		if (OptionalSingleInstance == NULL) {
			//Debug draw
			if (InputCamera->DebugDraw) {
				m_pImmediateContext->OMSetRenderTargets(1,&ResultSurface->ColorInput,NULL);
				DebugDraw(InputCamera);
			}
		}
	} Try_Else {
		MQ->InsertMessage(L"Camera_Render: Access violation was detected when debug drawing.");
	}
	
	Try_Start {
		// Clear resources
		ClearResourcesAfterRender();
	} Try_Else {
		MQ->InsertMessage(L"Camera_Render: Access violation was detected when clearing old resources.");
	}
	
	Try_Start {
		// ResultSurface has been written to
		ResultSurface->HasContent = true;
		ResultSurface->HaveValidDepthBuffer = true;
		ResultSurface->ZWCorrection = DVector2(InputCamera->CameraToImage._33,InputCamera->CameraToImage._43);
	} Try_Else {
		MQ->InsertMessage(L"Camera_Render: Access violation was detected when updating the output surface's status.");
	}
	
	Try_Start {
		// Show final results
		if(ResultSurface->FinalSurface && m_AutomaticSwapChain) {
			ShowLastRender();
		}
	} Try_Else {
		MQ->InsertMessage(L"Camera_Render: Access violation was detected when updating the swap chain.");
	}
	
	Try_Start {
		if (OptionalSingleInstance == NULL) {
			// Swap pointers for double draw surface output
			DrawSurface_Swap(ResultSurface);
		}
	} Try_Else {
		MQ->InsertMessage(L"Camera_Render: Access violation was detected when swapping color buffers in the output surface.");
	}
}

int EngineCore::DrawSurface_SaveToFile(DrawSurface_Struct* Surface, wchar_t* Filename) {
	ID3D11Resource* Texture;
	D3DX11_IMAGE_FILE_FORMAT Format;
	Try_Start {
		if (Surface->HaveExtraColorBuffer == false || Surface->SwapState == true) {
			Texture = Surface->OriginalColorBuffer;
		} else {
			Texture = Surface->ExtraColorBuffer;
		}
		int L = lengthOfString_wide(Filename);
		if (L >= 4) {
			if (Filename[L-4] == '.') {
				if ((Filename[L-3] == 'd' || Filename[L-3] == 'D') &&(Filename[L-2] == 'd' || Filename[L-2] == 'D') && (Filename[L-1] == 's' || Filename[L-1] == 'S')) {
					Format = D3DX11_IFF_DDS;
				} else if ((Filename[L-3] == 'p' || Filename[L-3] == 'P') &&(Filename[L-2] == 'n' || Filename[L-2] == 'N') && (Filename[L-1] == 'g' || Filename[L-1] == 'G')) {
					Format = D3DX11_IFF_PNG;
				} else if ((Filename[L-3] == 'b' || Filename[L-3] == 'B') &&(Filename[L-2] == 'm' || Filename[L-2] == 'M') && (Filename[L-1] == 'p' || Filename[L-1] == 'P')) {
					Format = D3DX11_IFF_BMP;
				} else if ((Filename[L-3] == 'j' || Filename[L-3] == 'J') &&(Filename[L-2] == 'p' || Filename[L-2] == 'P') && (Filename[L-1] == 'g' || Filename[L-1] == 'G')) {
					Format = D3DX11_IFF_JPG;
				} else {
					return 2; // Unknown file extension
				}
			} else {
				return 2; // Unknown file extension
			}
		} else {
			return 2; // Too short filename
		}
		if (FAILED(D3DX11SaveTextureToFile(m_pImmediateContext,Texture,Format,Filename))) {
			return 0;
		} else {
			return 1;
		}
	} Try_Else {
		MQ->InsertMessage(L"Internal error in DrawSurface_SaveToFile: Access violation was detected.");
		return 0;
	}
}

void EngineCore::DrawSurface_FillWithColor(DrawSurface_Struct* Surface, float Red, float Green, float Blue, float Alpha) {
	AutoSizeSurface(Surface);
	if (Surface->OriginalColorInput != NULL) {
		m_pImmediateContext->ClearRenderTargetView( Surface->OriginalColorInput, ToFloatArray(&DVector4(Red, Green, Blue, Alpha)) );
	}
	if (Surface->ExtraColorInput != NULL) {
		m_pImmediateContext->ClearRenderTargetView( Surface->ExtraColorInput, ToFloatArray(&DVector4(Red, Green, Blue, Alpha)) );
	}
}

DVector4 EngineCore::DrawSurface_GetPixelColor(DrawSurface_Struct* Surface, int X, int Y) {
	DVector4 Result;
	ID3D11Texture2D* InputResource;
	if (Surface->FinalSurface == true) {
		MQ->InsertMessage(L"DrawSurface_GetPixelColor: The final draw surface can not be used with this method because it does not work like a regular draw surface.");
		return DVector4(0.0f, 0.0f, 0.0f, 0.0f);
	} else if (Surface->HasContent == false) {
		// Save time if we already know the result
		return DVector4(0.0f, 0.0f, 0.0f, 0.0f);
	} else if (X >= 0 && X < Surface->CurrentWidth && Y >= 0 && Y < Surface->CurrentHeight) {
		// Select the only pixel in the dynamic buffer
		D3D11_BOX SrcBox;
		SrcBox.left = X; // Minimum X
		SrcBox.right = X+1; // Maximum X
		SrcBox.top = Y; // Minimum Y
		SrcBox.bottom = Y+1; // Maximum Y
		SrcBox.front = 0; // Always 0 for 2D textures
		SrcBox.back = 1; // Always 1 for 2D textures
		
		// Get the texture pointer
		if (Surface->HaveExtraColorBuffer == false || Surface->SwapState == true) {
			InputResource = Surface->OriginalColorBuffer;
		} else {
			InputResource = Surface->ExtraColorBuffer;
		}
		
		// Copy the pixel to the staging buffer
		m_pImmediateContext->CopySubresourceRegion(m_pSinglePixelCPUOutput,0,0,0,0,InputResource,0,&SrcBox);
		
		// Lock the memory
		D3D11_MAPPED_SUBRESOURCE MappingResult;
		if (m_pImmediateContext->Map(m_pSinglePixelCPUOutput,0,D3D11_MAP_READ,0,&MappingResult) != S_OK) {
			MQ->InsertMessage(L"DrawSurface_GetPixelColor: Could not map the output buffer.");
		}
			
			// Get the data
			if (MappingResult.pData == NULL) {
				MQ->InsertMessage(L"DrawSurface_GetPixelColor: Could not read the pixel color because the mapped subresource returned NULL.");
			} else {
				Result = *((DVector4*)MappingResult.pData);
			}
			
		// Unlock the memory
		m_pImmediateContext->Unmap(m_pSinglePixelCPUOutput,0);
		
		return Result;
	} else {
		swprintf_s( MQ->messageBuffer, L"DrawSurface_GetPixelColor: The pixel coordinate is out of bound. X=%i, Y=%i, Width=%i, Height=%i", X, Y, Surface->CurrentWidth, Surface->CurrentHeight); MQ->InsertMessage(MQ->messageBuffer);
		return DVector4(0.0f, 0.0f, 0.0f, 0.0f);
	}
}

void EngineCore::DrawSurface_SetPixelColor(DrawSurface_Struct* Surface, int X, int Y, DVector4 Color) {
	ID3D11Texture2D* OutputResource;
	if (Surface->FinalSurface == true) {
		MQ->InsertMessage(L"DrawSurface_SetPixelColor: The final draw surface can not be used with this method because it does not work like a regular draw surface.");
	} else {
		// Make sure that we have a surface of the correct dimensions
		AutoSizeSurface(Surface);
		
		if (X >= 0 && X < Surface->CurrentWidth && Y >= 0 && Y < Surface->CurrentHeight) {
			D3D11_MAPPED_SUBRESOURCE MappingResult;
			if (m_pImmediateContext->Map(m_pSinglePixelCPUInput, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappingResult) != S_OK) {
				MQ->InsertMessage(L"DrawSurface_SetPixelColor: Could not map the input buffer.");
			}
				memcpy(MappingResult.pData, &Color, 16);
				MappingResult.RowPitch = 16;
				MappingResult.DepthPitch = 0;
			m_pImmediateContext->Unmap(m_pSinglePixelCPUInput, 0);
			
			// Select the pixel
			D3D11_BOX SrcBox;
			SrcBox.left = 0; // Minimum X
			SrcBox.right = 1; // Maximum X
			SrcBox.top = 0; // Minimum Y
			SrcBox.bottom = 1; // Maximum Y
			SrcBox.front = 0; // Always 0 for 2D textures
			SrcBox.back = 1; // Always 1 for 2D textures
			
			// Get the texture pointer
			if (Surface->HaveExtraColorBuffer == false || Surface->SwapState == true) {
				OutputResource = Surface->OriginalColorBuffer;
			} else {
				OutputResource = Surface->ExtraColorBuffer;
			}
			
			// Copy the pixel to the draw surface
			m_pImmediateContext->CopySubresourceRegion(OutputResource,0,X,Y,0,m_pSinglePixelCPUInput,0,&SrcBox);
			
			// Remember that we have content now
			Surface->HasContent = true;
		} else {
			swprintf_s( MQ->messageBuffer, L"DrawSurface_SetPixelColor: The pixel coordinate is out of bound. X=%i, Y=%i, Width=%i, Height=%i", X, Y, Surface->CurrentWidth, Surface->CurrentHeight); MQ->InsertMessage(MQ->messageBuffer);
		}
	}
}

void EngineCore::DepthBuffer_SetSize(DepthBuffer_Struct* Surface, int NewWidth, int NewHeight) {
	Try_Start {
		if (NewWidth < 1 || NewHeight < 1) {
			MQ->InsertMessage(L"DepthBuffer_SetSize: A depth buffer can't have non positive dimensions.");
		} else if (Surface->CurrentWidth != NewWidth || Surface->CurrentHeight != NewHeight) {
			// Release any old data to avoid memory leaks
			Try_Start {
				DepthBuffer_Release(Surface);
			} Try_Else {
				MQ->InsertMessage(L"DepthBuffer_SetSize: Access violation was detected while releasing old memory.\n");
				return;
			}
			
			// Store dimensions
			Try_Start {
				Surface->CurrentWidth = NewWidth;
				Surface->CurrentHeight = NewHeight;
			} Try_Else {
				MQ->InsertMessage(L"DepthBuffer_SetSize: Access violation was detected while giving the draw surface it's new dimensions.\n");
				return;
			}
			
			// Depth buffer
			D3D11_TEXTURE2D_DESC DepthTextureDescription = {
				NewWidth,//UINT Width;
				NewHeight,//UINT Height;
				1,//UINT MipLevels;
				1,//UINT ArraySize;
				DXGI_FORMAT_R32_TYPELESS,//DXGI_FORMAT Format;
				1, 0,//DXGI_SAMPLE_DESC SampleDesc;
				D3D11_USAGE_DEFAULT,//D3D11_USAGE Usage;
				D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE,//UINT BindFlags;
				0,//UINT CPUAccessFlags;
				0//UINT MiscFlags;
			};
			
			// Depth buffer
			Try_Start {
				if (m_pd3dDevice->CreateTexture2D( &DepthTextureDescription, NULL, &Surface->DepthBuffer ) != S_OK) {
					MQ->InsertMessage(L"DepthBuffer_SetSize: Could not create the depth atlas.");
				}
			} Try_Else {
				MQ->InsertMessage(L"DepthBuffer_SetSize: Access violation was detected while creating the depth buffer.\n");
				return;
			}
			
			// Depth I/O
			D3D11_DEPTH_STENCIL_VIEW_DESC DepthIODescription = {
				DXGI_FORMAT_D32_FLOAT,
				D3D11_DSV_DIMENSION_TEXTURE2D,
				0
			};
			Try_Start {
				if (m_pd3dDevice->CreateDepthStencilView( Surface->DepthBuffer, &DepthIODescription, &Surface->DepthInputAndOutput ) != S_OK) {
					MQ->InsertMessage(L"DepthBuffer_SetSize: Could not create depth stencil view for the depth atlas.");
				}
			} Try_Else {
				MQ->InsertMessage(L"DepthBuffer_SetSize: Access violation was detected while creating the depth stencil view.\n");
				return;
			}
			
			// Depth output
			D3D11_SHADER_RESOURCE_VIEW_DESC TextureOutputDescription = {
				DXGI_FORMAT_R32_FLOAT,
				D3D11_SRV_DIMENSION_TEXTURE2D,
				0,
				0
			};
			TextureOutputDescription.Texture2D.MipLevels = 1;
			Try_Start {
				if (m_pd3dDevice->CreateShaderResourceView( Surface->DepthBuffer, &TextureOutputDescription, &Surface->DepthOutput ) != S_OK) {
					MQ->InsertMessage(L"DepthBuffer_SetSize: Could not create shader resource view for the depth atlas.");
				}
			} Try_Else {
				MQ->InsertMessage(L"DepthBuffer_SetSize: Access violation was detected while creating the depth output.\n");
				return;
			}
		}
	} Try_Else {
		MQ->InsertMessage(L"DepthBuffer_SetSize: Access violation was detected.\n");
		return;
	}
}

void EngineCore::DrawSurface_SetSize(DrawSurface_Struct* Surface, int NewWidth, int NewHeight, bool FinalSurface, int DepthBuffers, bool HaveExtraColorBuffer) {
	Try_Start {
		if (NewWidth < 1 || NewHeight < 1) {
			MQ->InsertMessage(L"DrawSurface_SetSize: A draw surface can't have non positive dimensions.");
		} else if (Surface->CurrentWidth != NewWidth || Surface->CurrentHeight != NewHeight) {
			// Release any old data to avoid memory leaks
			Try_Start {
				DrawSurface_Struct_Release(Surface);
			} Try_Else {
				MQ->InsertMessage(L"DrawSurface_SetSize: Access violation was detected while releasing old memory.\n");
				return;
			}
			
			// Remember that it was cleared
			Try_Start {
				Surface->HasContent = false;
				Surface->HaveValidDepthBuffer = false;
			} Try_Else {
				MQ->InsertMessage(L"DrawSurface_SetSize: Access violation was detected while telling the draw surface that it is empty.\n");
				return;
			}
			
			// Store dimensions
			Try_Start {
				Surface->CurrentWidth = NewWidth;
				Surface->CurrentHeight = NewHeight;
			} Try_Else {
				MQ->InsertMessage(L"DrawSurface_SetSize: Access violation was detected while giving the draw surface it's new dimensions.\n");
				return;
			}
			
			Try_Start {
				if (FinalSurface == true) {
					// Use the swap chain
					if ( m_pSwapChain->ResizeBuffers(1,NewWidth,NewHeight,DXGI_FORMAT_R8G8B8A8_UNORM,0) != S_OK) {
						MQ->InsertMessage(L"DrawSurface_SetSize: Could not resize the swap chain buffers.");
					}
					if (HaveExtraColorBuffer) {
						MQ->InsertMessage(L"DrawSurface_SetSize: The final draw surface may not have an extra color buffer.");
					}
				}
			} Try_Else {
				MQ->InsertMessage(L"DrawSurface_SetSize: Access violation was detected while resizing the swap chain's buffers.\n");
				return;
			}
			
			Try_Start {
				Surface->HaveExtraColorBuffer = HaveExtraColorBuffer;
			} Try_Else {
				MQ->InsertMessage(L"DrawSurface_SetSize: Access violation was detected while telling the draw surface if it has an extra color buffer.\n");
				return;
			}
			
			// Color buffer
			D3D11_TEXTURE2D_DESC TextureDescription = {
				NewWidth,//UINT Width;
				NewHeight,//UINT Height;
				1,//UINT MipLevels;
				1,//UINT ArraySize;
				DXGI_FORMAT_R32G32B32A32_FLOAT,//DXGI_FORMAT Format;
				1, 0,//DXGI_SAMPLE_DESC SampleDesc;
				D3D11_USAGE_DEFAULT,//D3D11_USAGE Usage;
				D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET,//UINT BindFlags;
				0,//UINT CPUAccessFlags;
				0//UINT MiscFlags;
			};
			Try_Start {
				// Color buffer
				if ( m_pd3dDevice->CreateTexture2D( &TextureDescription, NULL, &Surface->OriginalColorBuffer ) != S_OK) {
					MQ->InsertMessage(L"DrawSurface_SetSize: Could not create the color buffer.");
				}
			} Try_Else {
				MQ->InsertMessage(L"DrawSurface_SetSize: Access violation was detected while creating the color buffer.\n");
				return;
			}
			Try_Start {
				// Extra color buffer
				if (HaveExtraColorBuffer) {
					if ( m_pd3dDevice->CreateTexture2D( &TextureDescription, NULL, &Surface->ExtraColorBuffer ) != S_OK) {
						MQ->InsertMessage(L"DrawSurface_SetSize: Could not create the extra color buffer.");
					}
				}
			} Try_Else {
				MQ->InsertMessage(L"DrawSurface_SetSize: Access violation was detected while creating the extra color buffer.\n");
				return;
			}
			
			// Color output
			D3D11_SHADER_RESOURCE_VIEW_DESC TextureOutputDescription = { TextureDescription.Format, D3D11_SRV_DIMENSION_TEXTURE2D, 0, 0 };
			TextureOutputDescription.Texture2D.MipLevels = 1;
			Try_Start {
				if ( m_pd3dDevice->CreateShaderResourceView( Surface->OriginalColorBuffer, &TextureOutputDescription, &Surface->OriginalColorOutput ) != S_OK) {
					MQ->InsertMessage(L"DrawSurface_SetSize: Could not create the color output.");
				}
			} Try_Else {
				MQ->InsertMessage(L"DrawSurface_SetSize: Access violation was detected while creating the color output.\n");
				return;
			}
			Try_Start {
				if (HaveExtraColorBuffer) { // Extra surface
					if ( m_pd3dDevice->CreateShaderResourceView( Surface->ExtraColorBuffer, &TextureOutputDescription, &Surface->ExtraColorOutput ) != S_OK) {
						MQ->InsertMessage(L"DrawSurface_SetSize: Could not create the extra color output.");
					}
				}
			} Try_Else {
				MQ->InsertMessage(L"DrawSurface_SetSize: Access violation was detected while creating the extra color output.\n");
				return;
			}
			
			// Color input
			if (FinalSurface) {
				ID3D11Texture2D* pBackBuffer = NULL;
				Try_Start {
					if (m_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), ( LPVOID* )&pBackBuffer ) != S_OK) {
						MQ->InsertMessage(L"DrawSurface_SetSize: Could not get the back buffer.");
					}
				} Try_Else {
					MQ->InsertMessage(L"DrawSurface_SetSize: Access violation was detected while getting the back buffer.\n");
					return;
				}
				Try_Start {
					if ( m_pd3dDevice->CreateRenderTargetView( pBackBuffer, NULL, &Surface->OriginalColorInput ) != S_OK) {
						MQ->InsertMessage(L"DrawSurface_SetSize: Could not create the color input for the final draw surface.");
					}
				} Try_Else {
					// ¤¤¤¤ This happen then trying to run PIX
					MQ->InsertMessage(L"DrawSurface_SetSize: Access violation was detected while creating the color input for the final draw surface.\n");
					return;
				}
				Try_Start {
					pBackBuffer->Release();
				} Try_Else {
					MQ->InsertMessage(L"DrawSurface_SetSize: Access violation was detected while releasing the back buffer.\n");
					return;
				}
			} else {
				D3D11_RENDER_TARGET_VIEW_DESC TextureInputDescription;
				TextureInputDescription.Format = TextureDescription.Format;
				TextureInputDescription.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
				TextureInputDescription.Texture2D.MipSlice = 0;
				Try_Start {
					if ( m_pd3dDevice->CreateRenderTargetView(Surface->OriginalColorBuffer, &TextureInputDescription, &Surface->OriginalColorInput ) != S_OK) {
						MQ->InsertMessage(L"DrawSurface_SetSize: Could not create the color input.");
					}
				} Try_Else {
					MQ->InsertMessage(L"DrawSurface_SetSize: Access violation was detected while creating the color input.\n");
					return;
				}
				Try_Start {
					if (HaveExtraColorBuffer) { // Extra surface
						if ( m_pd3dDevice->CreateRenderTargetView(Surface->ExtraColorBuffer, &TextureInputDescription, &Surface->ExtraColorInput ) != S_OK) {
							MQ->InsertMessage(L"DrawSurface_SetSize: Could not create the extra color input.");
						}
					}
				} Try_Else {
					MQ->InsertMessage(L"DrawSurface_SetSize: Access violation was detected while creating the extra color input.\n");
					return;
				}
			}
			
			Try_Start {
				Surface->DepthBuffers = DepthBuffers;
			} Try_Else {
				MQ->InsertMessage(L"DrawSurface_SetSize: Access violation was detected while setting the number of depth buffers.\n");
				return;
			}
			
			if (DepthBuffers > 0) {
				// Allow rendering scene
				
				// Depth buffer
				D3D11_TEXTURE2D_DESC DepthTextureDescription = TextureDescription;
				DepthTextureDescription.Format = DXGI_FORMAT_R32_TYPELESS;
				DepthTextureDescription.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
				Try_Start {
					if ( m_pd3dDevice->CreateTexture2D( &DepthTextureDescription, NULL, &Surface->DepthBuffer ) != S_OK) {
							MQ->InsertMessage(L"DrawSurface_SetSize: Could not create the depth buffer.");
						}
				} Try_Else {
					MQ->InsertMessage(L"DrawSurface_SetSize: Access violation was detected while creating the depth buffer.\n");
					return;
				}
				
				// Depth I/O
				D3D11_DEPTH_STENCIL_VIEW_DESC DepthIODescription = {
					DXGI_FORMAT_D32_FLOAT,
					D3D11_DSV_DIMENSION_TEXTURE2D,
					0
				};
				Try_Start {
					if ( m_pd3dDevice->CreateDepthStencilView( Surface->DepthBuffer, &DepthIODescription, &Surface->DepthInputAndOutput ) != S_OK) {
							MQ->InsertMessage(L"DrawSurface_SetSize: Could not create the depth stencil view.");
						}
				} Try_Else {
					MQ->InsertMessage(L"DrawSurface_SetSize: Access violation was detected while creating the depth stencil view.\n");
					return;
				}
				
				D3D11_SHADER_RESOURCE_VIEW_DESC TextureOutputDescription = {
					DXGI_FORMAT_R32_FLOAT,
					D3D11_SRV_DIMENSION_TEXTURE2D,
					0,
					0
				};
				TextureOutputDescription.Texture2D.MipLevels = 1;
				if (DepthBuffers > 1) {
					// Allow soft particles
					
					// Extra depth buffer
					DepthTextureDescription.BindFlags = D3D11_BIND_SHADER_RESOURCE;
					Try_Start {
						if (m_pd3dDevice->CreateTexture2D( &DepthTextureDescription, NULL, &Surface->ExtraDepthBuffer ) != S_OK) {
							MQ->InsertMessage(L"DrawSurface_SetSize: Could not create the extra depth buffer.");
						}
					} Try_Else {
						MQ->InsertMessage(L"DrawSurface_SetSize: Access violation was detected while creating the extra depth buffer.\n");
						return;
					}
					
					// Depth output
					Try_Start {
						if (m_pd3dDevice->CreateShaderResourceView( Surface->ExtraDepthBuffer, &TextureOutputDescription, &Surface->DepthOutput ) != S_OK) {
							MQ->InsertMessage(L"DepthBuffer_SetSize: Could not create shader resource view for the extra depth buffer.");
						}
					} Try_Else {
						MQ->InsertMessage(L"DrawSurface_SetSize: Access violation was detected while creating the depth output for the extra depth buffer.\n");
						return;
					}
				} else {
					// Give the only depth buffer to post effects
					
					// Depth output
					Try_Start {
						if (m_pd3dDevice->CreateShaderResourceView( Surface->DepthBuffer, &TextureOutputDescription, &Surface->DepthOutput ) != S_OK) {
							MQ->InsertMessage(L"DepthBuffer_SetSize: Could not create shader resource view for the original depth buffer.");
						}
					} Try_Else {
						MQ->InsertMessage(L"DrawSurface_SetSize: Access violation was detected while creating the depth output for the only depth buffer.\n");
						return;
					}
				}
			}
			Try_Start {
				DrawSurface_SetSwapState(Surface,false);
			} Try_Else {
				MQ->InsertMessage(L"DrawSurface_SetSize: Access violation was detected while setting the initial swap state.\n");
				return;
			}
		}
	} Try_Else {
		MQ->InsertMessage(L"DrawSurface_SetSize: Access violation was detected.\n");
		return;
	}
}

void EngineCore::RenderTwoSteps(Camera_Struct* InputCamera, int ShaderChannel, DrawSurface_Struct* Surface) {
	int i;
	
	// Reset counting
	m_SeenInstances = 0;
	m_CulledInstances = 0;

	Try_Start {
		// Render the sky
		if (m_pSkyInstance) {
			if (m_pSkyInstance->Visible[ShaderChannel]) {
				m_pImmediateContext->OMSetDepthStencilState(m_pDepthStencilDisableDepthWrite, 0);
				RenderItem(m_pSkyInstance,ShaderChannel,NULL,m_pSkyInstance->VisualModel->Model.ModelProperties.FilterType,RenderingMethod_Triangles,-1,m_pSkyInstance->Color);
			}
		}
	} Try_Else {
		MQ->InsertMessage(L"RenderTwoSteps: Access violation was detected when rendering the sky instances.");
	}

	{ // Block for local access to uninitialized pointer
		Instance_Struct* pCurrentInstance;

		Try_Start {
			// Render each visible solid instance's model
			m_pImmediateContext->OMSetDepthStencilState(m_pDepthStencilDefault, 0);
			LoopForwardLengthFromZero(i, SizeOfCollection(Instance)) {
				pCurrentInstance = (Instance_Struct*)m_Instance.getValue_warning(i);
				if (pCurrentInstance != m_pSkyInstance && pCurrentInstance->Visible[ShaderChannel] && pCurrentInstance->VisualModel->Model.ModelProperties.FilterType == Filter_None) {
					if (CanInstanceBeSeenFromCamera(InputCamera,pCurrentInstance,true,true)) {
						RenderItem(pCurrentInstance,ShaderChannel,NULL,pCurrentInstance->VisualModel->Model.ModelProperties.FilterType,RenderingMethod_Triangles,-1,pCurrentInstance->Color);
						m_SeenInstances++;
					} else {
						m_CulledInstances++;
					}
				}
			}
		} Try_Else {
			MQ->InsertMessage(L"RenderTwoSteps: Access violation was detected when rendering solid instances.");
		}
	
		Try_Start {
			// If an extra depth buffer exist, copy to it
			if (Surface->ExtraDepthBuffer != NULL && Surface->DepthBuffer != NULL) {
				Try_Start {
					m_pImmediateContext->CopyResource(Surface->ExtraDepthBuffer,Surface->DepthBuffer);
				} Try_Else {
					MQ->InsertMessage(L"EngineCore::RenderTwoSteps: Access violation while duplicating the depth buffer.\n");
				}
			}
		} Try_Else {
			MQ->InsertMessage(L"RenderTwoSteps: Access violation was detected when duplicating the depth buffer.");
		}
	
		Try_Start {
			// Render each visible filtered instance's model
			m_pImmediateContext->OMSetDepthStencilState(m_pDepthStencilDisableDepthWrite, 0);
			LoopBackwardLengthFromZero(i, SizeOfCollection(Instance)) {
				pCurrentInstance = (Instance_Struct*)m_Instance.getValue_warning(i);
				if (pCurrentInstance != m_pSkyInstance && pCurrentInstance->Visible[ShaderChannel] && pCurrentInstance->VisualModel->Model.ModelProperties.FilterType > Filter_None) {
					if (CanInstanceBeSeenFromCamera(InputCamera,pCurrentInstance,true,true)) {
						RenderItem(pCurrentInstance,ShaderChannel,NULL,pCurrentInstance->VisualModel->Model.ModelProperties.FilterType,RenderingMethod_Triangles,-1,pCurrentInstance->Color);
						m_SeenInstances++;
					} else {
						m_CulledInstances++;
					}
				}
			}
		} Try_Else {
			MQ->InsertMessage(L"RenderTwoSteps: Access violation was detected when rendering filtered instances.");
		}
	}
}

void EngineCore::RenderOneStep(Camera_Struct* InputCamera) {
	int i;
	Instance_Struct* pCurrentInstance;
	Try_Start {
		SetFilter(Filter_None);
	} Try_Else {
		MQ->InsertMessage(L"RenderOneStep: Access violation was detected when choosing the filter.");
	}
	
	Try_Start {
		// Render each visible solid instance's model
		m_pImmediateContext->OMSetDepthStencilState(m_pDepthStencilDefault, 0);
		LoopForwardLengthFromZero(i, SizeOfCollection(Instance)) {
			pCurrentInstance = (Instance_Struct*)m_Instance.getValue_warning(i);
			if (pCurrentInstance->Visible[1]) {
				if (CanInstanceBeSeenFromCamera(InputCamera,pCurrentInstance,true,true)) {
					Try_Start {
						RenderShadow(pCurrentInstance);
					} Try_Else {
						MQ->InsertMessage(L"RenderOneStep: Access violation was detected when rendering a shadow.");
					}
				}
			}
		}
	} Try_Else {
		MQ->InsertMessage(L"RenderOneStep: Access violation was detected when rendering shadows.");
	}
}

bool EngineCore::InitiateSound(void) {
	HRESULT hr;
	
	// Initialize the direct sound interface pointer for the default sound device.
	Try_Start {
		hr = DirectSoundCreate8(NULL, &m_pSoundEngineInterface, NULL);
		if(FAILED(hr)) {
			MQ->InsertMessage(L"InitSound: Could not initialize direct sound 8.");
			return false;
		}
	} Try_Else {
		MQ->InsertMessage(L"InitSound: Access violation while initializing direct sound 8.");
	}
	
	// Set the cooperative level to priority so the format of the primary sound buffer can be modified.
	Try_Start {
		hr = m_pSoundEngineInterface->SetCooperativeLevel(m_hWnd, DSSCL_PRIORITY);
		if(FAILED(hr)) {
			MQ->InsertMessage(L"InitSound: Could not set the cooperative level.");
			return false;
		}
	} Try_Else {
		MQ->InsertMessage(L"InitSound: Access violation while setting the cooperative level.");
	}
	
	// Setup the primary buffer description.
	DSBUFFERDESC bufferDesc;
	bufferDesc.dwSize = sizeof(DSBUFFERDESC);
	bufferDesc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRL3D;
	bufferDesc.dwBufferBytes = 0;
	bufferDesc.dwReserved = 0;
	bufferDesc.lpwfxFormat = NULL;
	bufferDesc.guid3DAlgorithm = GUID_NULL;
	
	// Get control of the primary sound buffer on the default sound device.
	Try_Start {
		hr = m_pSoundEngineInterface->CreateSoundBuffer(&bufferDesc, &m_pMixingBuffer, NULL);
		if(FAILED(hr)) {
			MQ->InsertMessage(L"InitSound: Could not create the mixing buffer.");
			return false;
		}
	} Try_Else {
		MQ->InsertMessage(L"InitSound: Access violation while creating the mixing buffer.");
	}
	
	// Obtain a listener interface.
	Try_Start {
		hr = m_pMixingBuffer->QueryInterface(IID_IDirectSound3DListener8, (LPVOID*)&m_pListener);
		if(FAILED(hr)) {
			MQ->InsertMessage(L"InitSound: Could not get the listener interface.");
			return false;
		}
	} Try_Else {
		MQ->InsertMessage(L"InitSound: Access violation while getting the listener interface.");
	}
	
	// Set the initial position of the listener.
	PlaceListener(DVector3(0,0,0),DVector3(0,0,1),DVector3(0,1,0));
	Try_Start {
		hr = m_pListener->SetPosition(0.0f, 0.0f, 0.0f, DS3D_IMMEDIATE);
		if(FAILED(hr)) {
			MQ->InsertMessage(L"InitSound: Could not set the initial listener position.");
			return false;
		}
	} Try_Else {
		MQ->InsertMessage(L"InitSound: Access violation while setting the initial listener position.");
	}
	return true;
}

void EngineCore::PlaceListener(DVector3 Pos, DVector3 Front, DVector3 Up) {
	DVector3 Top;
	m_Sound_ListenerPosition = Pos;
	Top = NormalizeVec3(CrossVec3(NormalizeVec3(CrossVec3(NormalizeVec3(Front),NormalizeVec3(Up))),NormalizeVec3(Front)));
	if (FAILED(m_pListener->SetPosition(
	  m_Sound_ListenerPosition.x * m_Sound_MetersPerDistanceUnit,
	  m_Sound_ListenerPosition.y * m_Sound_MetersPerDistanceUnit,
	  m_Sound_ListenerPosition.z * m_Sound_MetersPerDistanceUnit,
	  DS3D_DEFERRED))) {
		MQ->InsertMessage(L"Sound_PlaceGlobalListener: Could not set the position.");
	}
	if (FAILED(m_pListener->SetOrientation(Front.x,Front.y,Front.z,Top.x,Top.y,Top.z,DS3D_DEFERRED))) {
		MQ->InsertMessage(L"Sound_PlaceGlobalListener: Could not set the orientation.");
	}
	if (FAILED(m_pListener->CommitDeferredSettings())) {
		MQ->InsertMessage(L"Sound_PlaceGlobalListener: Could not commit deferred settings.");
	}
}

void EngineCore::SetMetersPerDistanceUnit(float Meters) {
	int i;
	SoundBuffer_Struct* pCurrentSoundBuffer;
	if (m_Sound_MetersPerDistanceUnit != Meters) {
		m_Sound_MetersPerDistanceUnit = Meters;
		LoopForwardLengthFromZero(i, SizeOfCollection(SoundBuffer)) {
			pCurrentSoundBuffer = (SoundBuffer_Struct*)m_SoundBuffer.getValue_warning(i);
			if (pCurrentSoundBuffer->Buffer) {
				if (pCurrentSoundBuffer->Buffer->Flag_3DSound ) {
					pCurrentSoundBuffer->Buffer->SetMetersPerDistanceUnit(Meters);
				}
			}
		}
		if (FAILED(m_pListener->SetPosition(
		  m_Sound_ListenerPosition.x * m_Sound_MetersPerDistanceUnit,
		  m_Sound_ListenerPosition.y * m_Sound_MetersPerDistanceUnit,
		  m_Sound_ListenerPosition.z * m_Sound_MetersPerDistanceUnit,
		  DS3D_IMMEDIATE))) {
			MQ->InsertMessage(L"Sound_PlaceGlobalListener: Could not set the position.");
		}
	}
}

const D3D11_INPUT_ELEMENT_DESC MaterialLayout[] = {
	INPUT_ELEMENT(POSITION,DXGI_FORMAT_R32G32B32_FLOAT),
	INPUT_ELEMENT(TEXCOORD,DXGI_FORMAT_R32G32B32A32_FLOAT),
	INPUT_ELEMENT(COLOR,DXGI_FORMAT_R32G32B32A32_FLOAT),
	INPUT_ELEMENT(NORMAL,DXGI_FORMAT_R32G32B32_FLOAT),
	INPUT_ELEMENT(PSIZE,DXGI_FORMAT_R32_FLOAT),
	INPUT_ELEMENT(BINORMAL,DXGI_FORMAT_R32G32B32A32_FLOAT),
	INPUT_ELEMENT(TANGENT,DXGI_FORMAT_R32G32B32A32_FLOAT),
	INPUT_ELEMENT(TEXTURE,DXGI_FORMAT_R32G32B32A32_FLOAT),
};

const D3D11_INPUT_ELEMENT_DESC QuadLayout[] = {
	INPUT_ELEMENT(POSITION,DXGI_FORMAT_R32G32B32_FLOAT),
};

const D3D11_INPUT_ELEMENT_DESC LineLayout[] = {
	INPUT_ELEMENT(POSITION,DXGI_FORMAT_R32G32B32_FLOAT),
	INPUT_ELEMENT(COLOR,DXGI_FORMAT_R32G32B32_FLOAT),
};

// Shader
Shader_Struct* EngineCore::Shader_Load(wchar_t* filename, int ShaderType, bool LockResource) {
	HRESULT hr = S_OK;
	ID3D11InputLayout* pNewVertexLayout;
	ID3D11VertexShader* pNewVertexShader;
	ID3D11PixelShader* pNewPixelShader;
	ID3D11GeometryShader* pNewGeometryShader;
	Shader_Struct* newShader;
	wchar_t extendedFilename[260];
	wchar_t comparisonName[260];
	wchar_t CurrentPath[260];
	int ExistingIndex;
	ByteArray* pVSByteArray;
	ByteArray* pPSByteArray;
	ByteArray* pGSByteArray;
	Shader_Struct* Existing;
	Try_Start {
		if (withoutPath(filename,comparisonName)) {
			ExistingIndex = FindShaderIndexByName(comparisonName);
			if (ExistingIndex > -1) {
				// Use existing shader
				Try_Start {
					Existing = (Shader_Struct*)m_Shader.getValue_warning(ExistingIndex);
				} Try_Else {
					swprintf_s( MQ->messageBuffer, L"EngineCore::Shader_Load: Access violation while getting the existing shader. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
					return NULL;
				}
				Try_Start {
					Existing->Locked = Existing->Locked || LockResource;
				} Try_Else {
					swprintf_s( MQ->messageBuffer, L"EngineCore::Shader_Load: Access violation while setting the lock flag. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
					return NULL;
				}
				return Existing;
			} else {
				Try_Start {
					if (replaceAfterDot(filename,extendedFilename,L"hlsl")) {
						if (!FileExist(extendedFilename)) {
							::GetCurrentDirectoryW(260,CurrentPath);
							swprintf_s( MQ->messageBuffer, L"Shader_Load: The shader \"%s\" could not be found from the path \"%s\".", extendedFilename, CurrentPath); MQ->InsertMessage(MQ->messageBuffer);
							return NULL;
						} else {
							pVSByteArray = NULL;
							pNewVertexLayout = NULL;
							pNewVertexShader = NULL;
							if (UsingVS[ShaderType]) {
								// Compile the vertex shader
								Try_Start {
									if (CompileShaderFromFile( ShaderType,extendedFilename, L"VSO", "VS", "vs_4_0", &pVSByteArray, false ) == CompilationResult_Failed) {
										// On Error
										AddToCollection(Shader,newShader)
											newShader->VS.pVertexLayout = NULL;
											newShader->VS.pVertexShader = NULL;
											newShader->PS.pPixelShader = NULL;
											newShader->GS.pGeometryShader = NULL;
											newShader->ShaderType = ShaderType;
											newShader->Compiled = false;
											CopyToFixedSizePath(comparisonName,newShader->FileName);
											newShader->Locked = LockResource;
										return newShader;
									}
								} Try_Else {
									swprintf_s( MQ->messageBuffer, L"EngineCore::Shader_Load: Access violation while calling CompileShaderFromFile for the vertex shader. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
									return NULL;
								}
								Try_Start {
									if (pVSByteArray == NULL) {
										swprintf_s( MQ->messageBuffer, L"EngineCore::Shader_Load: NULL returned from CompileShaderFromFile for the vertex shader. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
										return NULL;
									} else {
										hr = m_pd3dDevice->CreateVertexShader( pVSByteArray->TheData, pVSByteArray->GetSizeInBytes(), NULL, &pNewVertexShader );
									}
								} Try_Else {
									swprintf_s( MQ->messageBuffer, L"EngineCore::Shader_Load: Access violation while calling CreateVertexShader. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
									return NULL;
								}
								if (FAILED(hr)) {
									Try_Start {
										SAFE_DELETE(pVSByteArray)
									} Try_Else {
										swprintf_s( MQ->messageBuffer, L"EngineCore::Shader_Load: Access violation while releasing a failed vertex shader ByteArray. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
										return NULL;
									}
									MQ->InsertMessage(L"Shader_Load: Failed to create a vertex shader.");
									return NULL;
								}
								
								// Select the input layout
								if (ShaderType == ShaderType_Material) {
									Try_Start {
										CHOOSE_VERTEX_LAYOUT(MaterialLayout,pVSByteArray)
									} Try_Else {
										swprintf_s( MQ->messageBuffer, L"EngineCore::Shader_Load: Access violation while choosing the material input layout. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
										return NULL;
									}
								} else if (ShaderType == ShaderType_PostEffect) {
									Try_Start {
										CHOOSE_VERTEX_LAYOUT(QuadLayout,pVSByteArray)
									} Try_Else {
										swprintf_s( MQ->messageBuffer, L"EngineCore::Shader_Load: Access violation while choosing the quad input layout. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
										return NULL;
									}
								} else if (ShaderType == ShaderType_Draw) {
									Try_Start {
										CHOOSE_VERTEX_LAYOUT(QuadLayout,pVSByteArray)
									} Try_Else {
										swprintf_s( MQ->messageBuffer, L"EngineCore::Shader_Load: Access violation while choosing the draw input layout. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
										return NULL;
									}
								} else if (ShaderType == ShaderType_Line) {
									Try_Start {
										CHOOSE_VERTEX_LAYOUT(LineLayout,pVSByteArray)
									} Try_Else {
										swprintf_s( MQ->messageBuffer, L"EngineCore::Shader_Load: Access violation while choosing the line input layout. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
										return NULL;
									}
								} else {
									swprintf_s( MQ->messageBuffer, L"EngineCore::Shader_Load: Unknown shader type. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
									return NULL;
								}
							}
							
							pPSByteArray = NULL;
							pNewPixelShader = NULL;
							if (UsingPS[ShaderType]) {
								// Compile the pixel shader
								Try_Start {
									if (CompileShaderFromFile(ShaderType, extendedFilename, L"PSO", "PS", "ps_4_0", &pPSByteArray, false ) == CompilationResult_Failed) {
										// On Error
										AddToCollection(Shader,newShader)
											newShader->VS.pVertexLayout = NULL;
											newShader->VS.pVertexShader = NULL;
											newShader->PS.pPixelShader = NULL;
											newShader->GS.pGeometryShader = NULL;
											newShader->ShaderType = ShaderType;
											newShader->Compiled = false;
											CopyToFixedSizePath(comparisonName,newShader->FileName);
											newShader->Locked = LockResource;
										return newShader;
									}
								} Try_Else {
									swprintf_s( MQ->messageBuffer, L"EngineCore::Shader_Load: Access violation while calling CompileShaderFromFile for the pixel shader. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
									return NULL;
								}
								Try_Start {
									if (pPSByteArray == NULL) {
										swprintf_s( MQ->messageBuffer, L"EngineCore::Shader_Load: NULL returned from CompileShaderFromFile for the pixel shader. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
										return NULL;
									} else {
										hr = m_pd3dDevice->CreatePixelShader( pPSByteArray->TheData, pPSByteArray->GetSizeInBytes(), NULL, &pNewPixelShader );
									}
								} Try_Else {
									swprintf_s( MQ->messageBuffer, L"EngineCore::Shader_Load: Access violation while calling CreatePixelShader. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
									return NULL;
								}
								if (FAILED(hr)) {
									Try_Start {
										SAFE_DELETE(pPSByteArray)
									} Try_Else {
										swprintf_s( MQ->messageBuffer, L"EngineCore::Shader_Load: Access violation while releasing a failed pixel shader ByteArray. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
										return NULL;
									}
									MQ->InsertMessage(L"Shader_Load: Failed to create a pixel shader.");
									return NULL;
								}
							}
							
							pGSByteArray = NULL;
							pNewGeometryShader = NULL;
							if (UsingGS[ShaderType]) {
								// Compile any geometry shader
								Try_Start {
									int ErrorCode;
									ErrorCode = CompileShaderFromFile(ShaderType, extendedFilename, L"GSO", "GS", "gs_4_0", &pGSByteArray, true);
									if (ErrorCode == CompilationResult_Failed) {
										// On Error
										AddToCollection(Shader,newShader)
											newShader->VS.pVertexLayout = NULL;
											newShader->VS.pVertexShader = NULL;
											newShader->PS.pPixelShader = NULL;
											newShader->GS.pGeometryShader = NULL;
											newShader->ShaderType = ShaderType;
											newShader->Compiled = false;
											CopyToFixedSizePath(comparisonName,newShader->FileName);
											newShader->Locked = LockResource;
										return newShader;
									} else if (ErrorCode != CompilationResult_OptionalEntryNotFound) {
										Try_Start {
											if (pGSByteArray == NULL) {
												swprintf_s( MQ->messageBuffer, L"EngineCore::Shader_Load: NULL returned from CompileShaderFromFile for the geometry shader. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
												return NULL;
											} else {
												hr = m_pd3dDevice->CreateGeometryShader( pGSByteArray->TheData, pGSByteArray->GetSizeInBytes(), NULL, &pNewGeometryShader );
											}
										} Try_Else {
											swprintf_s( MQ->messageBuffer, L"EngineCore::Shader_Load: Access violation while calling CreateGeometryShader. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
											return NULL;
										}
										if (FAILED(hr)) {
											Try_Start {
												SAFE_DELETE(pGSByteArray)
											} Try_Else {
												swprintf_s( MQ->messageBuffer, L"EngineCore::Shader_Load: Access violation while releasing a failed geometry shader ByteArray. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
												return NULL;
											}
											MQ->InsertMessage(L"Shader_Load: Failed to create a geometry shader.");
											return NULL;
										}
									}
								} Try_Else {
									swprintf_s( MQ->messageBuffer, L"EngineCore::Shader_Load: Access violation while calling CompileShaderFromFile for the geometry shader. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
									return NULL;
								}
							}

							// Release temporary data
							Try_Start {
								SAFE_DELETE(pPSByteArray)
							} Try_Else {
								swprintf_s( MQ->messageBuffer, L"EngineCore::Shader_Load: Access violation while releasing a good pixel shader ByteArray. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
								return NULL;
							}
							Try_Start {
								SAFE_DELETE(pVSByteArray)
							} Try_Else {
								swprintf_s( MQ->messageBuffer, L"EngineCore::Shader_Load: Access violation while releasing a good vertex shader ByteArray. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
								return NULL;
							}
							Try_Start {
								SAFE_DELETE(pGSByteArray)
							} Try_Else {
								swprintf_s( MQ->messageBuffer, L"EngineCore::Shader_Load: Access violation while releasing a good geometry shader ByteArray. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
								return NULL;
							}
							
							Try_Start {
								AddToCollection(Shader,newShader)
									newShader->VS.pVertexLayout = pNewVertexLayout;
									newShader->VS.pVertexShader = pNewVertexShader;
									newShader->PS.pPixelShader = pNewPixelShader;
									newShader->GS.pGeometryShader = pNewGeometryShader;
									newShader->ShaderType = ShaderType;
									newShader->Compiled = true;
									Try_Start {
										CopyToFixedSizePath(comparisonName,newShader->FileName);
									} Try_Else {
										swprintf_s( MQ->messageBuffer, L"EngineCore::Shader_Load: Access violation while duplicating the shader's filename. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
										return NULL;
									}
									newShader->Locked = LockResource;
							} Try_Else {
								swprintf_s( MQ->messageBuffer, L"EngineCore::Shader_Load: Access violation while adding the shader to the collection. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
								return NULL;
							}
							return newShader;
						}
					} else {
						swprintf_s( MQ->messageBuffer, L"EngineCore::Shader_Load: The filename \"%s\" is too long.", filename); MQ->InsertMessage(MQ->messageBuffer); \
						return NULL;
					}
				} Try_Else {
					swprintf_s( MQ->messageBuffer, L"EngineCore::Shader_Load: Access violation in the outer part of the real shader loading code. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
					return NULL;
				}
			}
		} else {
			swprintf_s( MQ->messageBuffer, L"EngineCore::Shader_Load: The filename \"%s\" is too long.", filename); MQ->InsertMessage(MQ->messageBuffer); \
			return NULL;
		}
	} Try_Else {
		swprintf_s( MQ->messageBuffer, L"EngineCore::Shader_Load: Access violation in the outer part of the code. Filename = \"%s\".\n",filename); MQ->InsertMessage(MQ->messageBuffer);
		return NULL;
	}
}

VertexShader EngineCore::Shader_CreateVSFromString(char* content, int ShaderType) {
	HRESULT hr = S_OK;
	VertexShader NewShader;
	ByteArray* pCompiledShader;
	ID3D11VertexShader* pNewVertexShader = NULL;
	ID3D11InputLayout* pNewVertexLayout = NULL;
	NewShader.pVertexLayout = NULL;
	NewShader.pVertexShader = NULL;
	
	// Compile the vertex shader
	pCompiledShader = NULL;
	Try_Start {
		if (CompileShaderFromString( ShaderType, content, "VS", "vs_4_0", &pCompiledShader, false ) == CompilationResult_Failed) {
			return NewShader;
		}
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::Shader_CreateVSFromString: Access violation while calling CompileShaderFromString.\n");
		return NewShader;
	}
	Try_Start {
		hr = m_pd3dDevice->CreateVertexShader( pCompiledShader->TheData, pCompiledShader->GetSizeInBytes(), NULL, &pNewVertexShader );
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::Shader_CreateVSFromString: Access violation while calling CreateVertexShader.\n");
		return NewShader;
	}
	if (FAILED(hr)) {
		Try_Start {
			SAFE_DELETE(pCompiledShader)
		} Try_Else {
			MQ->InsertMessage(L"EngineCore::Shader_CreateVSFromString: Access violation while releasing a failed vertex shader ByteArray.\n");
			return NewShader;
		}
		MQ->InsertMessage(L"EngineCore::Shader_CreateVSFromString: Failed to create a vertex shader.");
		return NewShader;
	}
	
	// Select the input layout
	if (ShaderType == ShaderType_Material) {
		Try_Start {
			CHOOSE_VERTEX_LAYOUT(MaterialLayout,pCompiledShader)
		} Try_Else {
			MQ->InsertMessage(L"EngineCore::Shader_CreateVSFromString: Access violation while choosing the material input layout.\n");
			return NewShader;
		}
	} else if (ShaderType == ShaderType_PostEffect) {
		Try_Start {
			CHOOSE_VERTEX_LAYOUT(QuadLayout,pCompiledShader)
		} Try_Else {
			MQ->InsertMessage(L"EngineCore::Shader_CreateVSFromString: Access violation while choosing the quad input layout.\n");
			return NewShader;
		}
	} else if (ShaderType == ShaderType_Draw) {
		Try_Start {
			CHOOSE_VERTEX_LAYOUT(QuadLayout,pCompiledShader)
		} Try_Else {
			MQ->InsertMessage(L"EngineCore::Shader_CreateVSFromString: Access violation while choosing the quad input layout.\n");
			return NewShader;
		}
	} else if (ShaderType == ShaderType_Line) {
		Try_Start {
			CHOOSE_VERTEX_LAYOUT(LineLayout,pCompiledShader)
		} Try_Else {
			MQ->InsertMessage(L"EngineCore::Shader_CreateVSFromString: Access violation while choosing the line input layout.\n");
			return NewShader;
		}
	} else {
		MQ->InsertMessage(L"EngineCore::Shader_CreateVSFromString:  Unknown shader type.\n");
		return NewShader;
	}
	
	Try_Start {
		SAFE_DELETE(pCompiledShader)
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::Shader_CreateVSFromString: Access violation while releasing a good vertex shader ByteArray.\n");
		return NewShader;
	}
	
	NewShader.pVertexLayout = pNewVertexLayout;
	NewShader.pVertexShader = pNewVertexShader;
	return NewShader;
}

PixelShader EngineCore::Shader_CreatePSFromString(char* content, int ShaderType) {
	HRESULT hr = S_OK;
	PixelShader NewShader;
	ByteArray* pCompiledShader;
	ID3D11PixelShader* pNewPixelShader = NULL;
	NewShader.pPixelShader = NULL;
	
	// Compile the pixel shader
	pCompiledShader = NULL;
	Try_Start {
		if (CompileShaderFromString( ShaderType, content, "PS", "ps_4_0", &pCompiledShader, false ) == CompilationResult_Failed) {
			return NewShader;
		}
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::Shader_CreatePSFromString: Access violation while calling CompileShaderFromString for the pixel shader.\n");
		return NewShader;
	}
	Try_Start {
		hr = m_pd3dDevice->CreatePixelShader( pCompiledShader->TheData, pCompiledShader->GetSizeInBytes(), NULL, &pNewPixelShader );
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::Shader_CreatePSFromString: Access violation while calling CreatePixelShader.\n");
		return NewShader;
	}
	
	if (FAILED(hr)) {
		Try_Start {
			SAFE_DELETE(pCompiledShader)
		} Try_Else {
			MQ->InsertMessage(L"EngineCore::Shader_CreatePSFromString: Access violation while releasing a failed pixel shader ByteArray.\n");
			return NewShader;
		}
		MQ->InsertMessage(L"EngineCore::Shader_CreatePSFromString: Failed to create a pixel shader.");
		return NewShader;
	}
	
	Try_Start {
		SAFE_DELETE(pCompiledShader)
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::Shader_CreatePSFromString: Access violation while releasing a good pixel shader ByteArray.\n");
		return NewShader;
	}
	
	NewShader.pPixelShader = pNewPixelShader;
	return NewShader;
}

void EngineCore::UpdateModels(void) {
	Try_Start {
		// Safe but slow method
		// Update each model who has changed using the complete list of models
		int i; Model_Struct* pCurrentModel;
		LoopForwardLengthFromZero(i, SizeOfCollection(Model)) {
			pCurrentModel = (Model_Struct*)m_Model.getValue_warning(i);
			pCurrentModel->Model.UpdateEverythingIfNeeded();
		}
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::UpdateModels: Access violation was detected when updating geometry for each model.");
	}
}

void EngineCore::Draw_RenderQuad(DrawSurface_Struct* OutputSurface, Shader_Struct* DrawShader, DVector2 Center, DVector2 XAxis, DVector2 YAxis, int FilterType) {
	if( OutputSurface->FinalSurface && m_AutomaticSwapChain) {
		MQ->InsertMessage(L"EngineCore::Draw_RenderQuad: You can not draw directly on the final draw surface with automatic swap chain enabled because that might show the final image before it is complete.\nTurn it off using Engine_SetAutomaticSwapChain and update the swap chain manually using Engine_UpdateSwapChain.\n");
	} else if ( (Center.x + XAxis.x + YAxis.x > -1 || Center.x + XAxis.x - YAxis.x > -1 || Center.x - XAxis.x + YAxis.x > -1 || Center.x - XAxis.x - YAxis.x > -1)
			&& (Center.x + XAxis.x + YAxis.x < 1 || Center.x + XAxis.x - YAxis.x < 1 || Center.x - XAxis.x + YAxis.x < 1 || Center.x - XAxis.x - YAxis.x < 1)
			&& (Center.y + XAxis.y + YAxis.y > -1 || Center.y + XAxis.y - YAxis.y > -1 || Center.y - XAxis.y + YAxis.y > -1 || Center.y - XAxis.y - YAxis.y > -1)
			&& (Center.y + XAxis.y + YAxis.y < 1 || Center.y + XAxis.y - YAxis.y < 1 || Center.y - XAxis.y + YAxis.y < 1 || Center.y - XAxis.y - YAxis.y < 1)) {
			// Culling test passed
		
		int i;
		ID3D11ShaderResourceView* InputResourceViews[16];
		int	InputResourceType[16];
		int RecievedType;
		void* SurfacePointer;
		CBDraw cbDraw;
		D3D11_VIEWPORT vp;
		
		Try_Start {
			// Convert from ID to resource view pointers
			LoopForwardLengthFromZero(i,16) {
				if (m_Draw_InputTextures[i] != 0) {
					SurfacePointer = VoidPointerFromID(m_Draw_InputTextures[i]);
					if (SurfacePointer == NULL) {
						swprintf_s( MQ->messageBuffer, L"Draw_RenderQuad: Input surface at index %i recieved ID %i that not is a valid reference.", i, m_Draw_InputTextures[i]); MQ->InsertMessage(MQ->messageBuffer);
						InputResourceType[i] = 0;
					} else {
						RecievedType = m_pReferences[m_Draw_InputTextures[i]].CollectionType;
						if (RecievedType == ColType_DrawSurface) {
							if (((DrawSurface_Struct*)SurfacePointer)->FinalSurface) {
								swprintf_s( MQ->messageBuffer, L"Draw_RenderQuad: Input texture at index %i is the final draw surface that only can be written to.", i); MQ->InsertMessage(MQ->messageBuffer);
							} else {
								InputResourceViews[i] = ((DrawSurface_Struct*)SurfacePointer)->ColorOutput;
							}
						} else if (RecievedType == ColType_Texture) {
							if (((Texture_Struct*)SurfacePointer)->Locked == false) {
								swprintf_s( MQ->messageBuffer, L"Draw_RenderQuad: Input surface at index %i was not locked and can be deleted by the engine. Only unlock resources when you are done with using them. Using unlocked resources is as bad as writing to unallocated memory.", i, m_Draw_InputTextures[i]); MQ->InsertMessage(MQ->messageBuffer);
							}
							InputResourceViews[i] = ((Texture_Struct*)SurfacePointer)->ColorOutput;
						}
					}
					InputResourceType[i] = 2;
				} else if (m_pDefaultTexture != NULL) {
					InputResourceType[i] = 1;
				} else {
					InputResourceType[i] = 0;
				}
			}
		} Try_Else {
			MQ->InsertMessage(L"EngineCore::Draw_RenderQuad: Access violation while converting reference numbers to pointers.\n");
			return;
		}
		
		Try_Start {
			// Make sure that the output is not also an input
			LoopForwardLengthFromZero(i,16) {
				if (InputResourceType[i] == 2) {
					if (((void*)OutputSurface) == VoidPointerFromID(m_Draw_InputTextures[i])) {
						swprintf_s( MQ->messageBuffer, L"Draw_RenderQuad: Input surface at index %i is the same draw surface as OutputSurface. This is not possible to do with resonable performance because the output is already seen as the background and would force the entire color buffer to be duplicated. Use post effects if you want to treat the background as just another input surface.", i); MQ->InsertMessage(MQ->messageBuffer);
						return;
					}
				}
			}
		} Try_Else {
			MQ->InsertMessage(L"EngineCore::Draw_RenderQuad: Access violation while checking if the output is used as input.\n");
			return;
		}
		
		Try_Start {
			// Set output surface
			AutoSizeSurface(OutputSurface);
		} Try_Else {
			MQ->InsertMessage(L"EngineCore::Draw_RenderQuad: Access violation while resizing the output surface.\n");
			return;
		}
		Try_Start {
			// Select rendering target
			m_pImmediateContext->OMSetRenderTargets(1,&OutputSurface->ColorInput_Reverse,NULL);
		} Try_Else {
			MQ->InsertMessage(L"EngineCore::Draw_RenderQuad: Access violation while selecting the render target.\n");
			return;
		}
		
		Try_Start {
			if (DrawShader->Locked == false) {
				MQ->InsertMessage(L"Draw_RenderQuad: The shader is not locked and can be deleted by the engine. Only unlock resources when you are done with using them. Using unlocked resources is as bad as writing to unallocated memory.");
			}
		} Try_Else {
			MQ->InsertMessage(L"EngineCore::Draw_RenderQuad: Access violation while checking if the draw shader is locked.\n");
			return;
		}
		Try_Start {
			if (DrawShader->Compiled == false) {
				MQ->InsertMessage(L"Draw_RenderQuad: The shader is not compiled and can not be used for drawing.");
				return;
			}
		} Try_Else {
			MQ->InsertMessage(L"EngineCore::Draw_RenderQuad: Access violation while checking if the draw shader is compiled.\n");
			return;
		}
		Try_Start {
			m_pImmediateContext->IASetInputLayout( m_DrawVS.pVertexLayout );
		} Try_Else {
			MQ->InsertMessage(L"EngineCore::Draw_RenderQuad: Access violation while setting the vertex input layout.\n");
			return;
		}
		Try_Start {
			m_pImmediateContext->VSSetShader( m_DrawVS.pVertexShader, NULL, 0 );
		} Try_Else {
			MQ->InsertMessage(L"EngineCore::Draw_RenderQuad: Access violation while setting the vertex shader.\n");
			return;
		}
		Try_Start {
			m_pImmediateContext->PSSetShader( DrawShader->PS.pPixelShader, NULL, 0 );
		} Try_Else {
			MQ->InsertMessage(L"EngineCore::Draw_RenderQuad: Access violation while setting the pixel shader.\n");
			return;
		}
		Try_Start {
			m_pImmediateContext->GSSetShader( NULL, NULL, 0 );
		} Try_Else {
			MQ->InsertMessage(L"EngineCore::Draw_RenderQuad: Access violation while removing the geometry shader.\n");
			return;
		}
		
		Try_Start {
			// Set any valid input textures
			LoopForwardLengthFromZero(i,16) {
				if (InputResourceType[i] == 0) {
					Try_Start {
						m_pImmediateContext->PSSetShaderResources(i,0,NULL);
					} Try_Else {
						MQ->InsertMessage(L"EngineCore::Draw_RenderQuad: Access violation while assigning the input surfaces. While giving a NULL surface.\n");
						return;
					}
				} else if (InputResourceType[i] == 1) {
					Try_Start {
						m_pImmediateContext->PSSetShaderResources(i,1,&(m_pDefaultTexture->ColorOutput));
					} Try_Else {
						MQ->InsertMessage(L"EngineCore::Draw_RenderQuad: Access violation while assigning the input surfaces. While giving a default texture.\n");
						return;
					}
				} else {
					Try_Start {
						m_pImmediateContext->PSSetShaderResources(i,1,&InputResourceViews[i]);
					} Try_Else {
						MQ->InsertMessage(L"EngineCore::Draw_RenderQuad: Access violation while assigning the input surfaces. While giving a texture or draw surface.\n");
						return;
					}
				}
			}
		} Try_Else {
			MQ->InsertMessage(L"EngineCore::Draw_RenderQuad: Access violation while assigning the input surfaces.\n");
			return;
		}
		
		Try_Start {
			// Set vertex buffer
			UINT stride = sizeof( VertexStructure_Quad );
			UINT offset = 0;
			m_pImmediateContext->IASetVertexBuffers( 0, 1, &m_pQuad_VertexBuffer, &stride, &offset );
		} Try_Else {
			MQ->InsertMessage(L"EngineCore::Draw_RenderQuad: Access violation while assigning the vertex buffer.\n");
			return;
		}
		
		Try_Start {
			// Set primitive topology
			m_pImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
		} Try_Else {
			MQ->InsertMessage(L"EngineCore::Draw_RenderQuad: Access violation while selecting a triangle list.\n");
			return;
		}
		
		Try_Start {
			// Shader resources
			m_pImmediateContext->VSSetConstantBuffers( 0, 1, &m_pCBDraw );
			m_pImmediateContext->PSSetConstantBuffers( 0, 1, &m_pCBDraw );
		} Try_Else {
			MQ->InsertMessage(L"EngineCore::Draw_RenderQuad: Access violation while assigning the constant buffer.\n");
			return;
		}
		
		Try_Start {
			// Select the rectangle area to render to
			vp.MinDepth = 0.0f;
			vp.MaxDepth = 1.0f;
			vp.TopLeftX = 0.0f;
			vp.TopLeftY = 0.0f;
			vp.Width = (FLOAT)OutputSurface->CurrentWidth;
			vp.Height = (FLOAT)OutputSurface->CurrentHeight;
		} Try_Else {
			MQ->InsertMessage(L"EngineCore::Draw_RenderQuad: Access violation while calculating the viewport dimensions.\n");
			return;
		}
		Try_Start {
			m_pImmediateContext->RSSetViewports(1, &vp);
		} Try_Else {
			MQ->InsertMessage(L"EngineCore::Draw_RenderQuad: Access violation while assigning the viewport dimensions.\n");
			return;
		}
		
		Try_Start {
			// Choose filter
			if (FilterType < 0 || FilterType > NumberOfFilterTypes - 1) {
				swprintf_s( MQ->messageBuffer, L"EngineCore::Draw_RenderQuad: %i is not a valid filter type index. Use 0 for fully visible or 1 for alpha filtering.", FilterType); MQ->InsertMessage(MQ->messageBuffer); \
				SetFilter(Filter_None);
			} else {
				SetFilter(FilterType);
			}
		} Try_Else {
			MQ->InsertMessage(L"EngineCore::Draw_RenderQuad: Access violation while choosing the default filter.\n");
			return;
		}
		
		Try_Start {
			// Give the constant buffer
			cbDraw.GlobalTime = m_GlobalTime;
			cbDraw.Dimensions.x = (FLOAT)OutputSurface->CurrentWidth;
			cbDraw.Dimensions.y = (FLOAT)OutputSurface->CurrentHeight;
			cbDraw.Color = m_Draw_Color;
			cbDraw.SrcRectUV1 = m_Draw_SrcRectUV1;
			cbDraw.SrcRectUV2 = m_Draw_SrcRectUV2;
			cbDraw.Center = Center;
			cbDraw.XAxis = XAxis;
			cbDraw.YAxis = YAxis;
		} Try_Else {
			MQ->InsertMessage(L"EngineCore::Draw_RenderQuad: Access violation while giving built in arguments to the constant buffer's packet.\n");
			return;
		}
		Try_Start {
			LoopForwardLengthFromZero(i,NumberOfUserVectorsPerDrawing) {
				cbDraw.Arg[i] = m_Draw_InputArguments[i];
			}
		} Try_Else {
			MQ->InsertMessage(L"EngineCore::Draw_RenderQuad: Access violation while giving input arguments to the constant buffer's packet.\n");
			return;
		}
		Try_Start {
			m_pImmediateContext->UpdateSubresource(m_pCBDraw, 0, NULL, &cbDraw, 0, 0);
		} Try_Else {
			MQ->InsertMessage(L"EngineCore::Draw_RenderQuad: Access violation while sending the packet to the constant buffer.\n");
			return;
		}
		
		// Draw 6 vertices
		Try_Start {
			m_pImmediateContext->RSSetState(m_StateDoubleFace);
		} Try_Else {
			MQ->InsertMessage(L"EngineCore::Draw_RenderQuad: Access violation while disabling face culling.\n");
			return;
		}
		Try_Start {
			m_pImmediateContext->Draw(6,0);
		} Try_Else {
			MQ->InsertMessage(L"EngineCore::Draw_RenderQuad: Access violation while drawing the effect quad.\n");
			return;
		}
		
		Try_Start {
			// Clear resources
			ClearResourcesAfterRender();
		} Try_Else {
			MQ->InsertMessage(L"EngineCore::Draw_RenderQuad: Access violation while clearing resources.\n");
			return;
		}
		
		Try_Start {
			// OutputSurface has been written to
			OutputSurface->HasContent = true;
		} Try_Else {
			MQ->InsertMessage(L"EngineCore::Draw_RenderQuad: Access violation while telling the output surface that it has been written to.\n");
			return;
		}
	}
	Try_Start {
		// Input is cleaned up to enforce deterministic debugging
		Draw_CleanUpInput();
	} Try_Else {
		MQ->InsertMessage(L"EngineCore::Draw_RenderQuad: Access violation while cleaning up the input.\n");
		return;
	}
}

void EngineCore::Physics_CPUSurfaceHasChanged(CPUSurface_Struct* CPUSurface) {
	if (CPUSurface->useCount > 0) {
		LL_ModifiedCPUSurface.Insert(&(CPUSurface->LL_ModifiedCPUSurface),CPUSurface);
	}
}

void EngineCore::Physics_CollisionShapeHasChanged(CollisionShape_Struct* CollisionShape) {
	if (CollisionShape->useCount > 0) {
		LL_ModifiedShape.Insert(&(CollisionShape->LL_ModifiedShape),CollisionShape);
	}
}

void EngineCore::RigidBody_ClearProxy(RigidBody_Struct* RigidBody) {
	// Remove the rigid body and insert it again
	//DGE.m_PhysicsCore.dynamicsWorld->removeCollisionObject(pRigidBody->Body); DGE.m_PhysicsCore.dynamicsWorld->addRigidBody(pRigidBody->Body);
	
	// Flush contact points
	m_PhysicsCore.dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(RigidBody->Body->getBroadphaseHandle(),m_PhysicsCore.dynamicsWorld->getDispatcher());
}

void EngineCore::Physics_Step(float TimeStep) {
	DoubleLinkListBody<CPUSurface_Struct>* CPUSurfaceIterator;
	DoubleLinkListBody<CPUSurface_Struct>* NextCPUSurfaceIterator;
	
	DoubleLinkListBody<CollisionShape_Struct>* CollisionShapeIterator;
	DoubleLinkListBody<CollisionShape_Struct>* NextCollisionShapeIterator;
	
	DoubleLinkListBody<RigidBody_Struct>* RigidBodyIterator;
	
	// Clear proxy for rigid bodies connected to the CPU surface
	Try_Start {
		CPUSurfaceIterator = LL_ModifiedCPUSurface.Head;
		while (CPUSurfaceIterator) {
 			NextCPUSurfaceIterator = CPUSurfaceIterator->Next;
			CollisionShapeIterator = CPUSurfaceIterator->Content->LL_HeightField.Head;
			while (CollisionShapeIterator) {
				RigidBodyIterator = CollisionShapeIterator->Content->LL_BodyUseShape.Head;
				while (RigidBodyIterator) {
					RigidBody_ClearProxy(RigidBodyIterator->Content);
					RigidBodyIterator = RigidBodyIterator->Next;
				}
				CollisionShapeIterator = CollisionShapeIterator->Next;
			}
			LL_ModifiedCPUSurface.Remove(&(CPUSurfaceIterator->Content->LL_ModifiedCPUSurface));
			CPUSurfaceIterator = NextCPUSurfaceIterator;
		}
	} Try_Else {
		MQ->InsertMessage(L"Access violation in Physics_Step while iterating the double link list of modified CPU surfaces. Report how you got this error if you found it in the latest version of the graphics engine.");
	}
	
	// Clear proxy for rigid bodies connected to the collision shape
	Try_Start {
		CollisionShapeIterator = LL_ModifiedShape.Head;
		while (CollisionShapeIterator) {
			NextCollisionShapeIterator = CollisionShapeIterator->Next;
			RigidBodyIterator = CollisionShapeIterator->Content->LL_BodyUseShape.Head;
			while (RigidBodyIterator) {
				RigidBody_ClearProxy(RigidBodyIterator->Content);
				RigidBodyIterator = RigidBodyIterator->Next;
			}
			LL_ModifiedShape.Remove(&(CollisionShapeIterator->Content->LL_ModifiedShape));
			CollisionShapeIterator = NextCollisionShapeIterator;
		}
	} Try_Else {
		MQ->InsertMessage(L"Access violation in Physics_Step while iterating the double link list of modified collision shapes. Report how you got this error if you found it in the latest version of the graphics engine.");
	}
	
	Try_Start {
		m_PhysicsCore.dynamicsWorld->stepSimulation(TimeStep, 0);
	} Try_Else {
		MQ->InsertMessage(L"Access violation in Physics_Step while calling stepSimulation in the Bullet physics engine. Report how you got this error if you found it in the latest version of the graphics engine.");
	}
}

// This may only be called directly after rendering the world
void EngineCore::DebugDraw(Camera_Struct* InputCamera) {
	int i;
	
	// Fill the every debug draw constant buffer
	Try_Start {
		CBEveryDebugRender cbEveryDebugRender;
			DMatrix WorldToImage = MulMat(InputCamera->WorldToCamera,InputCamera->CameraToImage);
			cbEveryDebugRender.mWorldToImage = TransposeMatrix(WorldToImage);
		m_pImmediateContext->UpdateSubresource( m_pCBEveryDebugRender, 0, NULL, &cbEveryDebugRender, 0, 0 );
	} Try_Else {
		MQ->InsertMessage(L"Access violation in DrawLine while updating the every debug draw constant buffer. Report how you got this error if you found it in the latest version of the graphics engine.");
	}
	
	Try_Start {
		m_pImmediateContext->VSSetConstantBuffers( 0, 1, &m_pCBEveryDebugRender );
	} Try_Else {
		MQ->InsertMessage(L"Access violation in DrawLine while assigning the every debug draw constant buffer to the vertex shader. Report how you got this error if you found it in the latest version of the graphics engine.");
	}
	
	Try_Start {
		m_pImmediateContext->PSSetConstantBuffers( 0, 1, &m_pCBEveryDebugRender );
	} Try_Else {
		MQ->InsertMessage(L"Access violation in DrawLine while assigning the every debug draw constant buffer to the pixel shader. Report how you got this error if you found it in the latest version of the graphics engine.");
	}
	
	Try_Start {
		m_pImmediateContext->IASetInputLayout( m_LineVS.pVertexLayout );
	} Try_Else {
		MQ->InsertMessage(L"Access violation in DrawLine while selecting the input layout. Report how you got this error if you found it in the latest version of the graphics engine.");
	}
	
	Try_Start {
		m_pImmediateContext->VSSetShader( m_LineVS.pVertexShader, NULL, 0 );
	} Try_Else {
		MQ->InsertMessage(L"Access violation in DrawLine while selecting the vertex shader. Report how you got this error if you found it in the latest version of the graphics engine.");
	}
	
	Try_Start {
		m_pImmediateContext->PSSetShader( m_LinePS.pPixelShader, NULL, 0 );
	} Try_Else {
		MQ->InsertMessage(L"Access violation in DrawLine while selecting the pixel shader. Report how you got this error if you found it in the latest version of the graphics engine.");
	}
	
	Try_Start {
		m_pImmediateContext->GSSetShader( NULL, NULL, 0 );
	} Try_Else {
		MQ->InsertMessage(L"Access violation in DrawLine while removing the geometry shader. Report how you got this error if you found it in the latest version of the graphics engine.\n");
		return;
	}

	Try_Start {
		m_pImmediateContext->RSSetState(m_StateDoubleFaceNoDepthClip);
	} Try_Else {
		MQ->InsertMessage(L"Access violation in DrawLine while selecting the double face raster state. Report how you got this error if you found it in the latest version of the graphics engine.");
	}
	
	Try_Start {
		// Set primitive topology
		m_pImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_LINELIST );
	} Try_Else {
		MQ->InsertMessage(L"Access violation while selecting a triangle list. Report how you got this error if you found it in the latest version of the graphics engine.\n");
		return;
	}
	
	if (InputCamera->DebugDraw & DebugDraw_WorldCenter ) {
		DrawLine(DVector3(0.0f,0.0f,0.0f),DVector3(1.0f,0.0f,0.0f),DVector3(0.7f,0.0f,0.0f),DVector3(0.7f,0.0f,0.0f));
		DrawLine(DVector3(0.0f,0.0f,0.0f),DVector3(0.0f,1.0f,0.0f),DVector3(0.0f,0.7f,0.0f),DVector3(0.0f,0.7f,0.0f));
		DrawLine(DVector3(0.0f,0.0f,0.0f),DVector3(0.0f,0.0f,1.0f),DVector3(0.0f,0.0f,0.7f),DVector3(0.0f,0.0f,0.7f));
	}
	
	if (InputCamera->DebugDraw & DebugDraw_Instances) {
		Instance_Struct* pCurrentInstance;
		ModelClass* Model;
		Try_Start {
			LoopForwardLengthFromZero(i, SizeOfCollection(Instance)) {
				pCurrentInstance = (Instance_Struct*)m_Instance.getValue_warning(i);
				if (CanInstanceBeSeenFromCamera(InputCamera,pCurrentInstance,false,false)) {
					// Draw axis system
					DVector3 XAxis;
					DVector3 YAxis;
					DVector3 ZAxis;
					DVector3 Center;
					XAxis = DVector3(pCurrentInstance->Transformation._11,pCurrentInstance->Transformation._12,pCurrentInstance->Transformation._13);
					YAxis = DVector3(pCurrentInstance->Transformation._21,pCurrentInstance->Transformation._22,pCurrentInstance->Transformation._23);
					ZAxis = DVector3(pCurrentInstance->Transformation._31,pCurrentInstance->Transformation._32,pCurrentInstance->Transformation._33);
					Center = DVector3(pCurrentInstance->Transformation._41,pCurrentInstance->Transformation._42,pCurrentInstance->Transformation._43);
					DrawLine(
						DVector3(Center.x,Center.y,Center.z),
						DVector3(Center.x + XAxis.x,Center.y + XAxis.y,Center.z + XAxis.z),
						DVector3(0.7f,0.0f,0.0f),
						DVector3(0.7f,0.0f,0.0f));
					DrawLine(
						DVector3(Center.x,Center.y,Center.z),
						DVector3(Center.x + YAxis.x,Center.y + YAxis.y,Center.z + YAxis.z),
						DVector3(0.0f,0.7f,0.0f),
						DVector3(0.0f,0.7f,0.0f));
					DrawLine(
						DVector3(Center.x,Center.y,Center.z),
						DVector3(Center.x + ZAxis.x,Center.y + ZAxis.y,Center.z + ZAxis.z),
						DVector3(0.0f,0.0f,0.7f),
						DVector3(0.0f,0.0f,0.7f));
					
					// Draw bounding shapes
					Model = &(pCurrentInstance->VisualModel->Model);
					if (Model->ModelProperties.CullingMethod == Culling_AABB) {
						DVector3 Points_WorldSpace[8];
						GetBoundingBoxCorners(pCurrentInstance->Transformation,Model,Points_WorldSpace);
						DrawLine(Points_WorldSpace[0],Points_WorldSpace[2],DVector3(1.0f,1.0f,1.0f),DVector3(1.0f,1.0f,1.0f));
						DrawLine(Points_WorldSpace[2],Points_WorldSpace[6],DVector3(1.0f,1.0f,1.0f),DVector3(1.0f,1.0f,1.0f));
						DrawLine(Points_WorldSpace[6],Points_WorldSpace[4],DVector3(1.0f,1.0f,1.0f),DVector3(1.0f,1.0f,1.0f));
						DrawLine(Points_WorldSpace[4],Points_WorldSpace[0],DVector3(1.0f,1.0f,1.0f),DVector3(1.0f,1.0f,1.0f));
						DrawLine(Points_WorldSpace[1],Points_WorldSpace[3],DVector3(1.0f,1.0f,1.0f),DVector3(1.0f,1.0f,1.0f));
						DrawLine(Points_WorldSpace[3],Points_WorldSpace[7],DVector3(1.0f,1.0f,1.0f),DVector3(1.0f,1.0f,1.0f));
						DrawLine(Points_WorldSpace[7],Points_WorldSpace[5],DVector3(1.0f,1.0f,1.0f),DVector3(1.0f,1.0f,1.0f));
						DrawLine(Points_WorldSpace[5],Points_WorldSpace[1],DVector3(1.0f,1.0f,1.0f),DVector3(1.0f,1.0f,1.0f));
						DrawLine(Points_WorldSpace[0],Points_WorldSpace[1],DVector3(1.0f,1.0f,1.0f),DVector3(1.0f,1.0f,1.0f));
						DrawLine(Points_WorldSpace[2],Points_WorldSpace[3],DVector3(1.0f,1.0f,1.0f),DVector3(1.0f,1.0f,1.0f));
						DrawLine(Points_WorldSpace[6],Points_WorldSpace[7],DVector3(1.0f,1.0f,1.0f),DVector3(1.0f,1.0f,1.0f));
						DrawLine(Points_WorldSpace[4],Points_WorldSpace[5],DVector3(1.0f,1.0f,1.0f),DVector3(1.0f,1.0f,1.0f));
					} else if (Model->ModelProperties.CullingMethod == Culling_Radius) {
						float Radius; float CameraDistance; int DetailLevel;
						Radius = GetBoundingSphereRadius(pCurrentInstance->Transformation,Model);
						CameraDistance = m_Instance.getSortValue_warning(i); // Reuse the distance calculation from the last rendering
						if (InputCamera->IsOrthogonal) {
							DetailLevel = 4;
						} else {
							DetailLevel = ClampInt(2,(int)((Radius * 40) / MaxFloat(0.001f,CameraDistance)),8);
						}
						DrawSphere(Center,Radius,DVector3(1.0f,1.0f,1.0f),DetailLevel);
					}
				}
			}
		} Try_Else {
			MQ->InsertMessage(L"DebugDraw: Access violation was detected when debug drawing instances.");
		}
	}
	
	if (InputCamera->DebugDraw & (DebugDraw_RigidBodies | DebugDraw_Constraints | DebugDraw_Collisions) ) {
		// Set the bitmask for physical debug drawing
		int DebugMode;
		DebugMode = 0;
		if (InputCamera->DebugDraw & DebugDraw_RigidBodies) { DebugMode = DebugMode | btIDebugDraw::DBG_DrawWireframe; }
		if (InputCamera->DebugDraw & DebugDraw_Constraints) { DebugMode = DebugMode | (btIDebugDraw::DBG_DrawConstraints | btIDebugDraw::DBG_DrawConstraintLimits); }
		if (InputCamera->DebugDraw & DebugDraw_Collisions) { DebugMode = DebugMode | btIDebugDraw::DBG_DrawContactPoints; }
		
		//Using btIDebugDraw::DBG_DrawAabb causes btCompoundCollisionAlgorithm to make draw calls during physical simulation and crashes my engine.
		
		m_PhysicsCore.debugDrawer->setDebugMode(DebugMode);
		
		// Set the visible volume
		DVector3 Points_WorldSpace[8];
		if (InputCamera->IsOrthogonal) {
			Camera_GetViewFrustum(InputCamera,Points_WorldSpace,-m_DebugDrawRadius,m_DebugDrawRadius);
		} else {
			Camera_GetViewFrustum(InputCamera,Points_WorldSpace,0.0f,m_DebugDrawRadius);
		}
		DVector3 AABBMin; DVector3 AABBMax;
		GetBoundingBoxFromPoints(Points_WorldSpace,8,&AABBMin,&AABBMax);
		m_PhysicsCore.dynamicsWorld->m_DebugCenter = btVector3(InputCamera->Eye.x, InputCamera->Eye.y, InputCamera->Eye.z);
		m_PhysicsCore.dynamicsWorld->m_DebugRadius = m_DebugDrawRadius;
		m_PhysicsCore.dynamicsWorld->m_DebugDrawMin = btVector3(MaxFloat(AABBMin.x,InputCamera->Eye.x - m_DebugDrawRadius),MaxFloat(AABBMin.y,InputCamera->Eye.y - m_DebugDrawRadius),MaxFloat(AABBMin.z,InputCamera->Eye.z - m_DebugDrawRadius));
		m_PhysicsCore.dynamicsWorld->m_DebugDrawMax = btVector3(MinFloat(AABBMax.x,InputCamera->Eye.x + m_DebugDrawRadius),MinFloat(AABBMax.y,InputCamera->Eye.y + m_DebugDrawRadius),MinFloat(AABBMax.z,InputCamera->Eye.z + m_DebugDrawRadius));
		
		// Debug draw physics
		m_PhysicsCore.dynamicsWorld->debugDrawWorld();
		
		// Just in case of being used while simulating
		m_PhysicsCore.debugDrawer->setDebugMode(0);
	}
	
}

// Precondition: NumberOfPoints <= the number of vectors in the array pointed to by Points and NumberOfPoints > 0.
void EngineCore::GetBoundingBoxFromPoints(DVector3* Points,int NumberOfPoints,DVector3* AABBMinOut,DVector3* AABBMaxOut) {
	int P;
	ASSERT(NumberOfPoints > 0);
	(*AABBMinOut) = Points[0];
	(*AABBMaxOut) = Points[0];
	LoopForward(1,P,NumberOfPoints - 1) {
		if (Points[P].x < AABBMinOut->x) {
			AABBMinOut->x = Points[P].x;
		} else if (Points[P].x > AABBMaxOut->x) {
			AABBMaxOut->x = Points[P].x;
		}
		if (Points[P].y < AABBMinOut->y) {
			AABBMinOut->y = Points[P].y;
		} else if (Points[P].y > AABBMaxOut->y) {
			AABBMaxOut->y = Points[P].y;
		}
		if (Points[P].z < AABBMinOut->z) {
			AABBMinOut->z = Points[P].z;
		} else if (Points[P].z > AABBMaxOut->z) {
			AABBMaxOut->z = Points[P].z;
		}
	}
}

// Assumes that Camera_Prepare has been called since the last modification
void EngineCore::Camera_GetViewFrustum(Camera_Struct* InputCamera,DVector3* EightWorldSpaceOutputPositions,float Near,float Far) {
	DVector3 XAxis;
	DVector3 YAxis;
	DVector3 ZAxis;
	DVector3 Center;
	float Width;
	float Height;
	
	// Get information about the camera from the last generated WorldToCamera matrix
	XAxis = DVector3(InputCamera->WorldToCamera._11,InputCamera->WorldToCamera._21,InputCamera->WorldToCamera._31);
	YAxis = DVector3(InputCamera->WorldToCamera._12,InputCamera->WorldToCamera._22,InputCamera->WorldToCamera._32);
	ZAxis = DVector3(InputCamera->WorldToCamera._13,InputCamera->WorldToCamera._23,InputCamera->WorldToCamera._33);
	Center = InputCamera->Eye;
	Width = InputCamera->WidthSlope;
	Height = InputCamera->HeightSlope;
	
	if (InputCamera->IsOrthogonal) {
		// Generate world space coordinates for orthogonal view frustum
		EightWorldSpaceOutputPositions[0] = AddVec3(Center,AddVec3(AddVec3(ScaleVec3(ZAxis,Near),ScaleVec3(XAxis,Width)),ScaleVec3(YAxis,Height)));
		EightWorldSpaceOutputPositions[1] = AddVec3(Center,SubVec3(AddVec3(ScaleVec3(ZAxis,Near),ScaleVec3(XAxis,Width)),ScaleVec3(YAxis,Height)));
		EightWorldSpaceOutputPositions[2] = AddVec3(Center,AddVec3(SubVec3(ScaleVec3(ZAxis,Near),ScaleVec3(XAxis,Width)),ScaleVec3(YAxis,Height)));
		EightWorldSpaceOutputPositions[3] = AddVec3(Center,SubVec3(SubVec3(ScaleVec3(ZAxis,Near),ScaleVec3(XAxis,Width)),ScaleVec3(YAxis,Height)));
		EightWorldSpaceOutputPositions[4] = AddVec3(Center,AddVec3(AddVec3(ScaleVec3(ZAxis,Far),ScaleVec3(XAxis,Width)),ScaleVec3(YAxis,Height)));
		EightWorldSpaceOutputPositions[5] = AddVec3(Center,SubVec3(AddVec3(ScaleVec3(ZAxis,Far),ScaleVec3(XAxis,Width)),ScaleVec3(YAxis,Height)));
		EightWorldSpaceOutputPositions[6] = AddVec3(Center,AddVec3(SubVec3(ScaleVec3(ZAxis,Far),ScaleVec3(XAxis,Width)),ScaleVec3(YAxis,Height)));
		EightWorldSpaceOutputPositions[7] = AddVec3(Center,SubVec3(SubVec3(ScaleVec3(ZAxis,Far),ScaleVec3(XAxis,Width)),ScaleVec3(YAxis,Height)));
	} else {
		// Generate world space coordinates for perspective view frustum
		EightWorldSpaceOutputPositions[0] = AddVec3(Center,AddVec3(AddVec3(ScaleVec3(ZAxis,Near),ScaleVec3(XAxis,Near * Width)),ScaleVec3(YAxis,Near * Height)));
		EightWorldSpaceOutputPositions[1] = AddVec3(Center,SubVec3(AddVec3(ScaleVec3(ZAxis,Near),ScaleVec3(XAxis,Near * Width)),ScaleVec3(YAxis,Near * Height)));
		EightWorldSpaceOutputPositions[2] = AddVec3(Center,AddVec3(SubVec3(ScaleVec3(ZAxis,Near),ScaleVec3(XAxis,Near * Width)),ScaleVec3(YAxis,Near * Height)));
		EightWorldSpaceOutputPositions[3] = AddVec3(Center,SubVec3(SubVec3(ScaleVec3(ZAxis,Near),ScaleVec3(XAxis,Near * Width)),ScaleVec3(YAxis,Near * Height)));
		EightWorldSpaceOutputPositions[4] = AddVec3(Center,AddVec3(AddVec3(ScaleVec3(ZAxis,Far),ScaleVec3(XAxis,Far * Width)),ScaleVec3(YAxis,Far * Height)));
		EightWorldSpaceOutputPositions[5] = AddVec3(Center,SubVec3(AddVec3(ScaleVec3(ZAxis,Far),ScaleVec3(XAxis,Far * Width)),ScaleVec3(YAxis,Far * Height)));
		EightWorldSpaceOutputPositions[6] = AddVec3(Center,AddVec3(SubVec3(ScaleVec3(ZAxis,Far),ScaleVec3(XAxis,Far * Width)),ScaleVec3(YAxis,Far * Height)));
		EightWorldSpaceOutputPositions[7] = AddVec3(Center,SubVec3(SubVec3(ScaleVec3(ZAxis,Far),ScaleVec3(XAxis,Far * Width)),ScaleVec3(YAxis,Far * Height)));
	}
}

void EngineCore::DrawSphere(DVector3 Center,float Radius,DVector3 Color,int DetailLevel) {
	int I;
	int LinesPerCircle;
	float StartAngle;
	float EndAngle;
	if (DetailLevel < 1) {DetailLevel = 1;}
	LinesPerCircle = DetailLevel * 4;
	LoopForwardLengthFromZero(I,LinesPerCircle) {
		StartAngle = (((float)I) / ((float)LinesPerCircle)) * 6.283185307179586476925286766559f;
		EndAngle = (((float)(I + 1)) / ((float)LinesPerCircle)) * 6.283185307179586476925286766559f;
		DrawLine(AddVec3(Center,DVector3(sinf(StartAngle) * Radius,cosf(StartAngle) * Radius,0)),AddVec3(Center,DVector3(sinf(EndAngle) * Radius,cosf(EndAngle) * Radius,0)),Color,Color);
		DrawLine(AddVec3(Center,DVector3(sinf(StartAngle) * Radius,0,cosf(StartAngle) * Radius)),AddVec3(Center,DVector3(sinf(EndAngle) * Radius,0,cosf(EndAngle) * Radius)),Color,Color);
		DrawLine(AddVec3(Center,DVector3(0,sinf(StartAngle) * Radius,cosf(StartAngle) * Radius)),AddVec3(Center,DVector3(0,sinf(EndAngle) * Radius,cosf(EndAngle) * Radius)),Color,Color);
	}
}

void EngineCore::DrawLine(DVector3 from,DVector3 to, DVector3 fromColor, DVector3 toColor) {
	Try_Start {
		m_LineVertexBuffer[0].Pos = from;
		m_LineVertexBuffer[0].Color = fromColor;
		m_LineVertexBuffer[1].Pos = to;
		m_LineVertexBuffer[1].Color = toColor;
	} Try_Else {
		MQ->InsertMessage(L"Access violation in DrawLine while filling the CPU vertex buffer. Report how you got this error if you found it in the latest version of the graphics engine.");
	}
	
	Try_Start {
		D3D11_MAPPED_SUBRESOURCE MappedSubresource;
		m_pImmediateContext->Map(m_D3DLineVertexBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &MappedSubresource);
			memcpy(MappedSubresource.pData, m_LineVertexBuffer, sizeof(m_LineVertexBuffer));
		m_pImmediateContext->Unmap(m_D3DLineVertexBuffer, NULL);
	} Try_Else {
		MQ->InsertMessage(L"Access violation in DrawLine while moving the vertex buffer to the graphics card. Report how you got this error if you found it in the latest version of the graphics engine.");
	}
	
	Try_Start {
		m_pImmediateContext->IASetVertexBuffers( 0, 1, &m_D3DLineVertexBuffer, &DebugLine_VertexStructureSize, &DebugLine_NoOffset );
	} Try_Else {
		MQ->InsertMessage(L"Access violation in DrawLine while assigning the vertex buffer. Report how you got this error if you found it in the latest version of the graphics engine.");
	}
	
	Try_Start {
		m_pImmediateContext->Draw(2,0);
	} Try_Else {
		MQ->InsertMessage(L"Access violation in DrawLine while drawing the line. Report how you got this error if you found it in the latest version of the graphics engine.");
	}
}

void EngineCore::DebugLine_Init(void) {
	// Initiate some data
	DebugLine_VertexStructureSize = sizeof(VertexStructure_Line);
	DebugLine_NoOffset = 0;
	
	// Create a dynamic vertex buffer for debug drawing
	D3D11_BUFFER_DESC bd;
	Try_Start {
		ZeroMemory( &bd, sizeof(bd) );
		bd.Usage = D3D11_USAGE_DYNAMIC;
		bd.ByteWidth = sizeof(VertexStructure_Line) * 2;
		bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
		bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
		bd.MiscFlags = 0;
	} Try_Else {
		MQ->InsertMessage(L"Access violation in DebugLine_Init while creating the vertex buffer description. Report how you got this error if you found it in the latest version of the graphics engine.");
	}
	Try_Start {
		if (m_pd3dDevice) {
			m_pd3dDevice->CreateBuffer( &bd, NULL, &m_D3DLineVertexBuffer );
		} else {
			MQ->InsertMessage(L"m_pd3dDevice was NULL when trying to create a dynamic vertex buffer in DebugLine_Init. Report how you got this error if you found it in the latest version of the graphics engine.");
		}
	} Try_Else {
		MQ->InsertMessage(L"Access violation in DebugLine_Init while creating a dynamic vertex buffer for drawing lines. Report how you got this error if you found it in the latest version of the graphics engine.");
	}
}

void EngineCore::DebugLine_Terminate(void) {
	// Release the debug drawing's dynamic vertex buffer
	SAFE_RELEASE(m_D3DLineVertexBuffer)
}

void Physics_Init(PhysicsCore* Core, EngineCore* NewEngineCore) {
	// Create the classes
	Core->collisionConfiguration = new btDefaultCollisionConfiguration();
	Core->dispatcher = new btCollisionDispatcher(Core->collisionConfiguration);
	Core->overlappingPairCache = new btDbvtBroadphase();
	Core->solver = new btSequentialImpulseConstraintSolver();
	Core->dynamicsWorld = new ModifiedWorld(Core->dispatcher,Core->overlappingPairCache,Core->solver,Core->collisionConfiguration);
	Core->debugDrawer = new DebugDrawer(NewEngineCore);
		Core->dynamicsWorld->setDebugDrawer(Core->debugDrawer);
}

void Physics_Terminate(PhysicsCore* Core) {
	// Terminate the classes
	SAFE_DELETE(Core->debugDrawer)
	SAFE_DELETE(Core->dynamicsWorld)
	SAFE_DELETE(Core->solver)
	SAFE_DELETE(Core->overlappingPairCache)
	SAFE_DELETE(Core->dispatcher)
	SAFE_DELETE(Core->collisionConfiguration)
}

DebugDrawer::DebugDrawer(EngineCore* NewEngineCore) {
	TheEngineCore = NewEngineCore;
}
DebugDrawer::~DebugDrawer(void) {
	
}
#define BULLET_TO_D3D_Vector3(VAR) DVector3(VAR##.getX(),VAR##.getY(),VAR##.getZ())
void DebugDrawer::drawLine(const btVector3& from,const btVector3& to,const btVector3& color) {
	TheEngineCore->DrawLine(BULLET_TO_D3D_Vector3(from),BULLET_TO_D3D_Vector3(to),BULLET_TO_D3D_Vector3(color),BULLET_TO_D3D_Vector3(color));
}
void DebugDrawer::drawLine(const btVector3& from,const btVector3& to, const btVector3& fromColor, const btVector3& toColor) {
	TheEngineCore->DrawLine(BULLET_TO_D3D_Vector3(from),BULLET_TO_D3D_Vector3(to),BULLET_TO_D3D_Vector3(fromColor),BULLET_TO_D3D_Vector3(toColor));
}
void DebugDrawer::drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,float distance,int lifeTime,const btVector3& color) {
	DVector3 EndPoint = DVector3(PointOnB.getX() + normalOnB.getX(),PointOnB.getY() + normalOnB.getY(),PointOnB.getZ() + normalOnB.getZ());
	TheEngineCore->DrawLine(BULLET_TO_D3D_Vector3(PointOnB),EndPoint,BULLET_TO_D3D_Vector3(color),DVector3(0,0,0));
}
void DebugDrawer::reportErrorWarning(const char* warningString) { /*An error message from Bullet won't help much since the user don't know what calls are made to Bullet*/ }
void DebugDrawer::draw3dText(const btVector3& location,const char* textString) { /*Do nothing*/ }
void DebugDrawer::setDebugMode(int debugMode) {
	DebugMode = debugMode;
}
int DebugDrawer::getDebugMode() const {
	return DebugMode;
}
