aboutsummaryrefslogtreecommitdiff
path: root/APEX_1.4/externals/extensions/src
diff options
context:
space:
mode:
authorgit perforce import user <a@b>2016-10-25 12:29:14 -0600
committerSheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees>2016-10-25 18:56:37 -0500
commit3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch)
treefa6485c169e50d7415a651bf838f5bcd0fd3bfbd /APEX_1.4/externals/extensions/src
downloadphysx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz
physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip
Initial commit:
PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167]
Diffstat (limited to 'APEX_1.4/externals/extensions/src')
-rw-r--r--APEX_1.4/externals/extensions/src/nvidiautils/DeviceManager.cpp784
-rw-r--r--APEX_1.4/externals/extensions/src/nvsimplemesh/NvSimpleMesh.cpp225
-rw-r--r--APEX_1.4/externals/extensions/src/nvsimplemesh/NvSimpleMeshLoader.cpp256
-rw-r--r--APEX_1.4/externals/extensions/src/nvsimplemesh/NvSimpleRawMesh.cpp221
4 files changed, 1486 insertions, 0 deletions
diff --git a/APEX_1.4/externals/extensions/src/nvidiautils/DeviceManager.cpp b/APEX_1.4/externals/extensions/src/nvidiautils/DeviceManager.cpp
new file mode 100644
index 00000000..e695e5e6
--- /dev/null
+++ b/APEX_1.4/externals/extensions/src/nvidiautils/DeviceManager.cpp
@@ -0,0 +1,784 @@
+// TAGRELEASE: PUBLIC
+
+#include "DeviceManager.h"
+#include <WinUser.h>
+#include <Windows.h>
+#include <assert.h>
+#include <sstream>
+#include <algorithm>
+
+#ifndef SAFE_RELEASE
+#define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p)=NULL; } }
+#endif
+
+#define WINDOW_CLASS_NAME L"NvDX11"
+
+#define WINDOW_STYLE_NORMAL (WS_OVERLAPPEDWINDOW | WS_VISIBLE)
+#define WINDOW_STYLE_FULLSCREEN (WS_POPUP | WS_SYSMENU | WS_VISIBLE)
+
+// A singleton, sort of... To pass the events from WindowProc to the object.
+DeviceManager* g_DeviceManagerInstance = NULL;
+
+#undef min
+#undef max
+
+LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ if(g_DeviceManagerInstance)
+ return g_DeviceManagerInstance->MsgProc(hWnd, uMsg, wParam, lParam);
+ else
+ return DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+DeviceManager* GetDeviceManager()
+{
+ return g_DeviceManagerInstance;
+}
+
+namespace
+{
+ bool IsNvDeviceID(UINT id)
+ {
+ return id == 0x10DE;
+ }
+
+ // Find an adapter whose name contains the given string.
+ IDXGIAdapter* FindAdapter(const WCHAR* targetName, bool& isNv)
+ {
+ IDXGIAdapter* targetAdapter = NULL;
+ IDXGIFactory* IDXGIFactory_0001 = NULL;
+ HRESULT hres = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&IDXGIFactory_0001);
+ if (hres != S_OK)
+ {
+ printf("ERROR in CreateDXGIFactory, %s@%d.\nFor more info, get log from debug D3D runtime: (1) Install DX SDK, and enable Debug D3D from DX Control Panel Utility. (2) Install and start DbgView. (3) Try running the program again.\n",__FILE__,__LINE__);
+ return targetAdapter;
+ }
+
+ unsigned int adapterNo = 0;
+ while (SUCCEEDED(hres))
+ {
+ IDXGIAdapter* pAdapter = NULL;
+ hres = IDXGIFactory_0001->EnumAdapters(adapterNo, (IDXGIAdapter**)&pAdapter);
+
+ if (SUCCEEDED(hres))
+ {
+ DXGI_ADAPTER_DESC aDesc;
+ pAdapter->GetDesc(&aDesc);
+
+ // If no name is specified, return the first adapater. This is the same behaviour as the
+ // default specified for D3D11CreateDevice when no adapter is specified.
+ if (wcslen(targetName) == 0)
+ {
+ targetAdapter = pAdapter;
+ isNv = IsNvDeviceID(aDesc.VendorId);
+ break;
+ }
+
+ std::wstring aName = aDesc.Description;
+ if (aName.find(targetName) != std::string::npos)
+ {
+ targetAdapter = pAdapter;
+ isNv = IsNvDeviceID(aDesc.VendorId);
+ }
+ else
+ {
+ pAdapter->Release();
+ }
+ }
+
+ adapterNo++;
+ }
+
+ if (IDXGIFactory_0001)
+ IDXGIFactory_0001->Release();
+
+ return targetAdapter;
+ }
+
+ // Adjust window rect so that it is centred on the given adapter. Clamps to fit if it's too big.
+ RECT MoveWindowOntoAdapter(IDXGIAdapter* targetAdapter, const RECT& rect)
+ {
+ assert(targetAdapter != NULL);
+
+ RECT result = rect;
+ HRESULT hres = S_OK;
+ unsigned int outputNo = 0;
+ while (SUCCEEDED(hres))
+ {
+ IDXGIOutput* pOutput = NULL;
+ hres = targetAdapter->EnumOutputs(outputNo++, &pOutput);
+
+ if (SUCCEEDED(hres) && pOutput)
+ {
+ DXGI_OUTPUT_DESC OutputDesc;
+ pOutput->GetDesc( &OutputDesc );
+ const RECT desktop = OutputDesc.DesktopCoordinates;
+ const int centreX = (int) desktop.left + (int)(desktop.right - desktop.left) / 2;
+ const int centreY = (int) desktop.top + (int)(desktop.bottom - desktop.top) / 2;
+ const int winW = rect.right - rect.left;
+ const int winH = rect.bottom - rect.top;
+ int left = centreX - winW/2;
+ int right = left + winW;
+ int top = centreY - winH/2;
+ int bottom = top + winH;
+ result.left = std::max(left, (int) desktop.left);
+ result.right = std::min(right, (int) desktop.right);
+ result.bottom = std::min(bottom, (int) desktop.bottom);
+ result.top = std::max(top, (int) desktop.top);
+ pOutput->Release();
+
+ // If there is more than one output, go with the first found. Multi-monitor support could go here.
+ break;
+ }
+ }
+ return result;
+ }
+}
+
+HRESULT
+DeviceManager::CreateWindowDeviceAndSwapChain(const DeviceCreationParameters& params, LPWSTR title)
+{
+ g_DeviceManagerInstance = this;
+ m_WindowTitle = title;
+
+ HINSTANCE hInstance = GetModuleHandle(NULL);
+ WNDCLASSEX windowClass = { sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, WindowProc,
+ 0L, 0L, hInstance, NULL, NULL, NULL, NULL, WINDOW_CLASS_NAME, NULL };
+
+ windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
+
+ RegisterClassEx(&windowClass);
+
+ UINT windowStyle = params.startFullscreen
+ ? WINDOW_STYLE_FULLSCREEN
+ : params.startMaximized
+ ? (WINDOW_STYLE_NORMAL | WS_MAXIMIZE)
+ : WINDOW_STYLE_NORMAL;
+
+ RECT rect = { 0, 0, params.backBufferWidth, params.backBufferHeight };
+ AdjustWindowRect(&rect, windowStyle, FALSE);
+
+ IDXGIAdapter* targetAdapter = FindAdapter(params.adapterNameSubstring, m_IsNvidia);
+ if (targetAdapter)
+ {
+ rect = MoveWindowOntoAdapter(targetAdapter, rect);
+ }
+ else
+ {
+ // We could silently use a default adapter in this case. I think it's better to choke.
+ std::wostringstream ostr;
+ ostr << L"Could not find an adapter matching \"" << params.adapterNameSubstring << "\"" << std::ends;
+ MessageBox(NULL, ostr.str().c_str(), m_WindowTitle.c_str(), MB_OK | MB_ICONERROR);
+ return E_FAIL;
+ }
+
+ m_hWnd = CreateWindowEx(
+ 0,
+ WINDOW_CLASS_NAME,
+ title,
+ windowStyle,
+ rect.left,
+ rect.top,
+ rect.right - rect.left,
+ rect.bottom - rect.top,
+ GetDesktopWindow(),
+ NULL,
+ hInstance,
+ NULL
+ );
+
+ if(!m_hWnd)
+ {
+#ifdef DEBUG
+ DWORD errorCode = GetLastError();
+ printf("CreateWindowEx error code = 0x%x\n", errorCode);
+#endif
+
+ MessageBox(NULL, L"Cannot create window", m_WindowTitle.c_str(), MB_OK | MB_ICONERROR);
+ return E_FAIL;
+ }
+
+ UpdateWindow(m_hWnd);
+
+ HRESULT hr = E_FAIL;
+
+ RECT clientRect;
+ GetClientRect(m_hWnd, &clientRect);
+ UINT width = clientRect.right - clientRect.left;
+ UINT height = clientRect.bottom - clientRect.top;
+
+ ZeroMemory(&m_SwapChainDesc, sizeof(m_SwapChainDesc));
+ m_SwapChainDesc.BufferCount = params.swapChainBufferCount;
+ m_SwapChainDesc.BufferDesc.Width = width;
+ m_SwapChainDesc.BufferDesc.Height = height;
+ m_SwapChainDesc.BufferDesc.Format = params.swapChainFormat;
+ m_SwapChainDesc.BufferDesc.RefreshRate.Numerator = params.refreshRate;
+ m_SwapChainDesc.BufferDesc.RefreshRate.Denominator = 0;
+ m_SwapChainDesc.BufferUsage = params.swapChainUsage;
+ m_SwapChainDesc.OutputWindow = m_hWnd;
+ m_SwapChainDesc.SampleDesc.Count = params.swapChainSampleCount;
+ m_SwapChainDesc.SampleDesc.Quality = params.swapChainSampleQuality;
+ m_SwapChainDesc.Windowed = !params.startFullscreen;
+ m_SwapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
+
+ // The D3D documentation says that if adapter is non-null, driver type must be unknown. Why not put
+ // this logic in the CreateDevice fns then?!?
+ const D3D_DRIVER_TYPE dType = (targetAdapter)? D3D_DRIVER_TYPE_UNKNOWN: params.driverType;
+
+ hr = D3D11CreateDeviceAndSwapChain(
+ targetAdapter, // pAdapter
+ dType, // DriverType
+ NULL, // Software
+ params.createDeviceFlags, // Flags
+ &params.featureLevel, // pFeatureLevels
+ 1, // FeatureLevels
+ D3D11_SDK_VERSION, // SDKVersion
+ &m_SwapChainDesc, // pSwapChainDesc
+ &m_SwapChain, // ppSwapChain
+ &m_Device, // ppDevice
+ NULL, // pFeatureLevel
+ &m_ImmediateContext // ppImmediateContext
+ );
+
+ if (targetAdapter)
+ targetAdapter->Release();
+
+ if(FAILED(hr))
+ return hr;
+
+ m_DepthStencilDesc.ArraySize = 1;
+ m_DepthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
+ m_DepthStencilDesc.CPUAccessFlags = 0;
+ m_DepthStencilDesc.Format = params.depthStencilFormat;
+ m_DepthStencilDesc.Width = width;
+ m_DepthStencilDesc.Height = height;
+ m_DepthStencilDesc.MipLevels = 1;
+ m_DepthStencilDesc.MiscFlags = 0;
+ m_DepthStencilDesc.SampleDesc.Count = params.swapChainSampleCount;
+ m_DepthStencilDesc.SampleDesc.Quality = 0;
+ m_DepthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
+
+ hr = CreateRenderTargetAndDepthStencil();
+
+ if(FAILED(hr))
+ return hr;
+
+ DeviceCreated();
+ BackBufferResized();
+
+ return S_OK;
+}
+
+void
+DeviceManager::Shutdown()
+{
+ if(m_SwapChain && GetWindowState() == kWindowFullscreen)
+ m_SwapChain->SetFullscreenState(false, NULL);
+
+ DeviceDestroyed();
+
+ SAFE_RELEASE(m_BackBufferRTV);
+ SAFE_RELEASE(m_DepthStencilDSV);
+ SAFE_RELEASE(m_DepthStencilBuffer);
+
+ g_DeviceManagerInstance = NULL;
+ SAFE_RELEASE(m_ImmediateContext);
+ SAFE_RELEASE(m_SwapChain);
+
+ ID3D11Debug * d3dDebug = nullptr;
+ if (nullptr != m_Device)
+ {
+ ID3D11DeviceContext* pCtx;
+ m_Device->GetImmediateContext(&pCtx);
+ pCtx->ClearState();
+ pCtx->Flush();
+ pCtx->Release();
+ if (SUCCEEDED(m_Device->QueryInterface(__uuidof(ID3D11Debug), reinterpret_cast<void**>(&d3dDebug))))
+ {
+ d3dDebug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL);
+ d3dDebug->Release();
+ }
+ }
+ SAFE_RELEASE(m_Device);
+
+ if(m_hWnd)
+ {
+ DestroyWindow(m_hWnd);
+ m_hWnd = NULL;
+ }
+}
+
+HRESULT
+DeviceManager::CreateRenderTargetAndDepthStencil()
+{
+ HRESULT hr;
+
+ ID3D11Texture2D *backBuffer = NULL;
+ hr = m_SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backBuffer);
+ if (FAILED(hr))
+ return hr;
+
+ hr = m_Device->CreateRenderTargetView(backBuffer, NULL, &m_BackBufferRTV);
+ backBuffer->Release();
+ if (FAILED(hr))
+ return hr;
+
+ if(m_DepthStencilDesc.Format != DXGI_FORMAT_UNKNOWN)
+ {
+ hr = m_Device->CreateTexture2D(&m_DepthStencilDesc, NULL, &m_DepthStencilBuffer);
+ if (FAILED(hr))
+ return hr;
+
+ hr = m_Device->CreateDepthStencilView(m_DepthStencilBuffer, NULL, &m_DepthStencilDSV);
+ if (FAILED(hr))
+ return hr;
+ }
+
+ return S_OK;
+}
+
+void
+DeviceManager::MessageLoop()
+{
+ MSG msg = {0};
+
+ LARGE_INTEGER perfFreq, previousTime;
+ QueryPerformanceFrequency(&perfFreq);
+ QueryPerformanceCounter(&previousTime);
+
+ while (WM_QUIT != msg.message)
+ {
+ if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ else
+ {
+ LARGE_INTEGER newTime;
+ QueryPerformanceCounter(&newTime);
+
+ double elapsedSeconds = (m_FixedFrameInterval >= 0)
+ ? m_FixedFrameInterval
+ : (double)(newTime.QuadPart - previousTime.QuadPart) / (double)perfFreq.QuadPart;
+
+ if(m_SwapChain && GetWindowState() != kWindowMinimized)
+ {
+ Animate(elapsedSeconds);
+ Render();
+ m_SwapChain->Present(m_SyncInterval, 0);
+ Sleep(0);
+ }
+ else
+ {
+ // Release CPU resources when idle
+ Sleep(1);
+ }
+
+ {
+ m_vFrameTimes.push_back(elapsedSeconds);
+ double timeSum = 0;
+ for(auto it = m_vFrameTimes.begin(); it != m_vFrameTimes.end(); it++)
+ timeSum += *it;
+
+ if(timeSum > m_AverageTimeUpdateInterval)
+ {
+ m_AverageFrameTime = timeSum / (double)m_vFrameTimes.size();
+ m_vFrameTimes.clear();
+ }
+ }
+
+ previousTime = newTime;
+ }
+ }
+}
+
+LRESULT
+DeviceManager::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch(uMsg)
+ {
+ case WM_DESTROY:
+ case WM_CLOSE:
+ PostQuitMessage(0);
+ return 0;
+
+ case WM_SYSKEYDOWN:
+ if(wParam == VK_F4)
+ {
+ PostQuitMessage(0);
+ return 0;
+ }
+ break;
+
+ case WM_ENTERSIZEMOVE:
+ m_InSizingModalLoop = true;
+ m_NewWindowSize.cx = m_SwapChainDesc.BufferDesc.Width;
+ m_NewWindowSize.cy = m_SwapChainDesc.BufferDesc.Height;
+ break;
+
+ case WM_EXITSIZEMOVE:
+ m_InSizingModalLoop = false;
+ ResizeSwapChain();
+ break;
+
+ case WM_SIZE:
+ // Ignore the WM_SIZE event if there is no device,
+ // or if the window has been minimized (size == 0),
+ // or if it has been restored to the previous size (this part is tested inside ResizeSwapChain)
+ if (m_Device && (lParam != 0))
+ {
+ m_NewWindowSize.cx = LOWORD(lParam);
+ m_NewWindowSize.cy = HIWORD(lParam);
+
+ if(!m_InSizingModalLoop)
+ ResizeSwapChain();
+ }
+ }
+
+ if( uMsg >= WM_MOUSEFIRST && uMsg <= WM_MOUSELAST ||
+ uMsg >= WM_KEYFIRST && uMsg <= WM_KEYLAST )
+ {
+ // processing messages front-to-back
+ for(auto it = m_vControllers.begin(); it != m_vControllers.end(); it++)
+ {
+ if((*it)->IsEnabled())
+ {
+ // for kb/mouse messages, 0 means the message has been handled
+ if(0 == (*it)->MsgProc(hWnd, uMsg, wParam, lParam))
+ return 0;
+ }
+ }
+ }
+
+ return DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+void
+DeviceManager::ResizeSwapChain()
+{
+ if(m_NewWindowSize.cx == (LONG)m_SwapChainDesc.BufferDesc.Width &&
+ m_NewWindowSize.cy == (LONG)m_SwapChainDesc.BufferDesc.Height)
+ return;
+
+ m_SwapChainDesc.BufferDesc.Width = m_NewWindowSize.cx;
+ m_SwapChainDesc.BufferDesc.Height = m_NewWindowSize.cy;
+
+ ID3D11RenderTargetView *nullRTV = NULL;
+ m_ImmediateContext->OMSetRenderTargets(1, &nullRTV, NULL);
+ SAFE_RELEASE(m_BackBufferRTV);
+ SAFE_RELEASE(m_DepthStencilDSV);
+ SAFE_RELEASE(m_DepthStencilBuffer);
+
+ if (m_SwapChain)
+ {
+ // Resize the swap chain
+ m_SwapChain->ResizeBuffers(m_SwapChainDesc.BufferCount, m_SwapChainDesc.BufferDesc.Width,
+ m_SwapChainDesc.BufferDesc.Height, m_SwapChainDesc.BufferDesc.Format,
+ m_SwapChainDesc.Flags);
+
+ m_DepthStencilDesc.Width = m_NewWindowSize.cx;
+ m_DepthStencilDesc.Height = m_NewWindowSize.cy;
+
+ CreateRenderTargetAndDepthStencil();
+
+ BackBufferResized();
+ }
+}
+
+void
+DeviceManager::Render()
+{
+ D3D11_VIEWPORT viewport = { 0.0f, 0.0f, (float)m_SwapChainDesc.BufferDesc.Width, (float)m_SwapChainDesc.BufferDesc.Height, 0.0f, 1.0f };
+
+ // rendering back-to-front
+ for(auto it = m_vControllers.rbegin(); it != m_vControllers.rend(); it++)
+ {
+ if((*it)->IsEnabled())
+ {
+ m_ImmediateContext->OMSetRenderTargets(1, &m_BackBufferRTV, m_DepthStencilDSV);
+ m_ImmediateContext->RSSetViewports(1, &viewport);
+
+ (*it)->Render(m_Device, m_ImmediateContext, m_BackBufferRTV, m_DepthStencilDSV);
+ }
+ }
+
+ m_ImmediateContext->OMSetRenderTargets(0, NULL, NULL);
+}
+
+void
+DeviceManager::Animate(double fElapsedTimeSeconds)
+{
+ // front-to-back, but the order shouldn't matter
+ for(auto it = m_vControllers.begin(); it != m_vControllers.end(); it++)
+ {
+ if((*it)->IsEnabled())
+ {
+ (*it)->Animate(fElapsedTimeSeconds);
+ }
+ }
+}
+
+void
+DeviceManager::DeviceCreated()
+{
+ // creating resources front-to-back
+ for(auto it = m_vControllers.begin(); it != m_vControllers.end(); it++)
+ {
+ (*it)->DeviceCreated(m_Device);
+ }
+}
+
+void
+DeviceManager::DeviceDestroyed()
+{
+ // releasing resources back-to-front
+ for(auto it = m_vControllers.rbegin(); it != m_vControllers.rend(); it++)
+ {
+ (*it)->DeviceDestroyed();
+ }
+}
+
+void
+DeviceManager::BackBufferResized()
+{
+ if(m_SwapChain == NULL)
+ return;
+
+ DXGI_SURFACE_DESC backSD;
+ backSD.Format = m_SwapChainDesc.BufferDesc.Format;
+ backSD.Width = m_SwapChainDesc.BufferDesc.Width;
+ backSD.Height = m_SwapChainDesc.BufferDesc.Height;
+ backSD.SampleDesc = m_SwapChainDesc.SampleDesc;
+
+ for(auto it = m_vControllers.begin(); it != m_vControllers.end(); it++)
+ {
+ (*it)->BackBufferResized(m_Device, &backSD);
+ }
+}
+
+HRESULT
+DeviceManager::ChangeBackBufferFormat(DXGI_FORMAT format, UINT sampleCount)
+{
+ HRESULT hr = E_FAIL;
+
+ if((format == DXGI_FORMAT_UNKNOWN || format == m_SwapChainDesc.BufferDesc.Format) &&
+ (sampleCount == 0 || sampleCount == m_SwapChainDesc.SampleDesc.Count))
+ return S_FALSE;
+
+ if(m_Device)
+ {
+ bool fullscreen = (GetWindowState() == kWindowFullscreen);
+ if(fullscreen)
+ m_SwapChain->SetFullscreenState(false, NULL);
+
+ IDXGISwapChain* newSwapChain = NULL;
+ DXGI_SWAP_CHAIN_DESC newSwapChainDesc = m_SwapChainDesc;
+
+ if(format != DXGI_FORMAT_UNKNOWN)
+ newSwapChainDesc.BufferDesc.Format = format;
+ if(sampleCount != 0)
+ newSwapChainDesc.SampleDesc.Count = sampleCount;
+
+ IDXGIAdapter* pDXGIAdapter = GetDXGIAdapter();
+
+ IDXGIFactory* pDXGIFactory = NULL;
+ pDXGIAdapter->GetParent(__uuidof(IDXGIFactory), reinterpret_cast<void**>(&pDXGIFactory));
+
+ hr = pDXGIFactory->CreateSwapChain(m_Device, &newSwapChainDesc, &newSwapChain);
+
+ pDXGIFactory->Release();
+ pDXGIAdapter->Release();
+
+ if (FAILED(hr))
+ {
+ if(fullscreen)
+ m_SwapChain->SetFullscreenState(true, NULL);
+
+ return hr;
+ }
+
+ SAFE_RELEASE(m_BackBufferRTV);
+ SAFE_RELEASE(m_SwapChain);
+ SAFE_RELEASE(m_DepthStencilBuffer);
+ SAFE_RELEASE(m_DepthStencilDSV);
+
+ m_SwapChain = newSwapChain;
+ m_SwapChainDesc = newSwapChainDesc;
+
+ m_DepthStencilDesc.SampleDesc.Count = sampleCount;
+
+ if(fullscreen)
+ m_SwapChain->SetFullscreenState(true, NULL);
+
+ CreateRenderTargetAndDepthStencil();
+ BackBufferResized();
+ }
+
+ return S_OK;
+}
+
+void
+DeviceManager::AddControllerToFront(IVisualController* pController)
+{
+ m_vControllers.remove(pController);
+ m_vControllers.push_front(pController);
+}
+
+void
+DeviceManager::AddControllerToBack(IVisualController* pController)
+{
+ m_vControllers.remove(pController);
+ m_vControllers.push_back(pController);
+}
+
+void
+DeviceManager::RemoveController(IVisualController* pController)
+{
+ m_vControllers.remove(pController);
+}
+
+HRESULT
+DeviceManager::ResizeWindow(int width, int height)
+{
+ if(m_SwapChain == NULL)
+ return E_FAIL;
+
+ RECT rect;
+ GetWindowRect(m_hWnd, &rect);
+
+ ShowWindow(m_hWnd, SW_RESTORE);
+
+ if(!MoveWindow(m_hWnd, rect.left, rect.top, width, height, true))
+ return E_FAIL;
+
+ // No need to call m_SwapChain->ResizeBackBuffer because MoveWindow will send WM_SIZE, which calls that function.
+
+ return S_OK;
+}
+
+HRESULT
+DeviceManager::EnterFullscreenMode(int width, int height)
+{
+ if(m_SwapChain == NULL)
+ return E_FAIL;
+
+ if(GetWindowState() == kWindowFullscreen)
+ return S_FALSE;
+
+ if(width <= 0 || height <= 0)
+ {
+ width = m_SwapChainDesc.BufferDesc.Width;
+ height = m_SwapChainDesc.BufferDesc.Height;
+ }
+
+ SetWindowLong(m_hWnd, GWL_STYLE, WINDOW_STYLE_FULLSCREEN);
+ MoveWindow(m_hWnd, 0, 0, width, height, true);
+
+ HRESULT hr = m_SwapChain->SetFullscreenState(true, NULL);
+
+ if(FAILED(hr))
+ {
+ SetWindowLong(m_hWnd, GWL_STYLE, WINDOW_STYLE_NORMAL);
+ return hr;
+ }
+
+ UpdateWindow(m_hWnd);
+ m_SwapChain->GetDesc(&m_SwapChainDesc);
+
+ return S_OK;
+}
+
+HRESULT
+DeviceManager::LeaveFullscreenMode(int windowWidth, int windowHeight)
+{
+ if(m_SwapChain == NULL)
+ return E_FAIL;
+
+ if(GetWindowState() != kWindowFullscreen)
+ return S_FALSE;
+
+ HRESULT hr = m_SwapChain->SetFullscreenState(false, NULL);
+ if(FAILED(hr)) return hr;
+
+ SetWindowLong(m_hWnd, GWL_STYLE, WINDOW_STYLE_NORMAL);
+
+ if(windowWidth <= 0 || windowHeight <= 0)
+ {
+ windowWidth = m_SwapChainDesc.BufferDesc.Width;
+ windowHeight = m_SwapChainDesc.BufferDesc.Height;
+ }
+
+ RECT rect = { 0, 0, windowWidth, windowHeight };
+ AdjustWindowRect(&rect, WINDOW_STYLE_NORMAL, FALSE);
+ MoveWindow(m_hWnd, 0, 0, rect.right - rect.left, rect.bottom - rect.top, true);
+ UpdateWindow(m_hWnd);
+
+ m_SwapChain->GetDesc(&m_SwapChainDesc);
+
+ return S_OK;
+}
+
+HRESULT
+DeviceManager::ToggleFullscreen()
+{
+ if(GetWindowState() == kWindowFullscreen)
+ return LeaveFullscreenMode();
+ else
+ return EnterFullscreenMode();
+}
+
+DeviceManager::WindowState
+DeviceManager::GetWindowState()
+{
+ if(m_SwapChain && !m_SwapChainDesc.Windowed)
+ return kWindowFullscreen;
+
+ if(m_hWnd == INVALID_HANDLE_VALUE)
+ return kWindowNone;
+
+ if(IsZoomed(m_hWnd))
+ return kWindowMaximized;
+
+ if(IsIconic(m_hWnd))
+ return kWindowMinimized;
+
+ return kWindowNormal;
+}
+
+HRESULT
+DeviceManager::GetDisplayResolution(int& width, int& height)
+{
+ if(m_hWnd != INVALID_HANDLE_VALUE)
+ {
+ HMONITOR monitor = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTOPRIMARY);
+ MONITORINFO info;
+ info.cbSize = sizeof(MONITORINFO);
+
+ if(GetMonitorInfo(monitor, &info))
+ {
+ width = info.rcMonitor.right - info.rcMonitor.left;
+ height = info.rcMonitor.bottom - info.rcMonitor.top;
+ return S_OK;
+ }
+ }
+
+ return E_FAIL;
+}
+
+IDXGIAdapter*
+DeviceManager::GetDXGIAdapter()
+{
+ if(!m_Device)
+ return NULL;
+
+ IDXGIDevice* pDXGIDevice = NULL;
+ m_Device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&pDXGIDevice));
+
+ IDXGIAdapter* pDXGIAdapter = NULL;
+ pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&pDXGIAdapter));
+
+ pDXGIDevice->Release();
+
+ return pDXGIAdapter;
+}
diff --git a/APEX_1.4/externals/extensions/src/nvsimplemesh/NvSimpleMesh.cpp b/APEX_1.4/externals/extensions/src/nvsimplemesh/NvSimpleMesh.cpp
new file mode 100644
index 00000000..522b426f
--- /dev/null
+++ b/APEX_1.4/externals/extensions/src/nvsimplemesh/NvSimpleMesh.cpp
@@ -0,0 +1,225 @@
+// TAGRELEASE: PUBLIC
+#include <assert.h>
+
+// Direct3D9 includes
+#include <d3d9.h>
+
+// Direct3D11 includes
+#include <d3dcommon.h>
+#include <dxgi.h>
+#include <d3d11.h>
+#include <d3dcompiler.h>
+
+// XInput includes
+#include <xinput.h>
+
+#ifndef V
+#define V(x) { hr = (x); }
+#endif
+#ifndef V_RETURN
+#define V_RETURN(x) { hr = (x); if( FAILED(hr) ) { return hr; } }
+#endif
+
+#ifndef SAFE_DELETE
+#define SAFE_DELETE(p) { if (p) { delete (p); (p)=NULL; } }
+#endif
+#ifndef SAFE_DELETE_ARRAY
+#define SAFE_DELETE_ARRAY(p) { if (p) { delete[] (p); (p)=NULL; } }
+#endif
+#ifndef SAFE_RELEASE
+#define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p)=NULL; } }
+#endif
+
+
+#include "strsafe.h"
+#include <string>
+
+#include "NvSimpleRawMesh.h"
+#include "NvSimpleMesh.h"
+#include "NvSimpleMeshLoader.h"
+
+NvSimpleMesh::NvSimpleMesh() :
+ iNumVertices(0),
+ iNumIndices(0),
+ IndexFormat(DXGI_FORMAT_R16_UINT),
+ VertexStride(0),
+ pVB(NULL),
+ pIB(NULL),
+ pDiffuseTexture(NULL),
+ pDiffuseSRV(NULL),
+ pNormalsTexture(NULL),
+ pNormalsSRV(NULL),
+ pInputLayout(NULL)
+{
+ memset(szName,0,260);
+}
+
+inline ID3D11ShaderResourceView * UtilCreateTexture2DSRV(ID3D11Device *pd3dDevice,ID3D11Texture2D *pTex)
+{
+ HRESULT hr;
+ ID3D11ShaderResourceView *pSRV = NULL;
+
+ D3D11_TEXTURE2D_DESC TexDesc;
+ ((ID3D11Texture2D*)pTex)->GetDesc(&TexDesc);
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
+ ::ZeroMemory(&SRVDesc,sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));
+ SRVDesc.Texture2D.MipLevels = TexDesc.MipLevels;
+ SRVDesc.Texture2D.MostDetailedMip = 0;
+ SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ SRVDesc.Format = TexDesc.Format;
+
+ hr = pd3dDevice->CreateShaderResourceView(pTex,&SRVDesc,&pSRV);
+
+ return pSRV;
+}
+
+HRESULT NvSimpleMesh::Initialize(ID3D11Device *pd3dDevice,NvSimpleRawMesh *pRawMesh)
+{
+ HRESULT hr = S_OK;
+
+ if(pRawMesh)
+ {
+ memcpy(&Extents,pRawMesh->GetExtents(),3*sizeof(float));
+ memcpy(&Center,pRawMesh->GetCenter(),3*sizeof(float));
+
+ // Copy out d3d buffers and data for rendering and add references input mesh can be cleaned.
+ pVB = pRawMesh->CreateD3D11VertexBufferFor(pd3dDevice);
+ pIB = pRawMesh->CreateD3D11IndexBufferFor(pd3dDevice);
+ IndexFormat = pRawMesh->GetIndexSize()==2?DXGI_FORMAT_R16_UINT:DXGI_FORMAT_R32_UINT;
+ iNumIndices = pRawMesh->GetNumIndices();
+ iNumVertices = pRawMesh->GetNumVertices();
+ VertexStride = pRawMesh->GetVertexStride();
+
+ // Make a texture object and SRV for it.
+ pDiffuseTexture = pRawMesh->CreateD3D11DiffuseTextureFor(pd3dDevice);
+ if(pDiffuseTexture)
+ pDiffuseSRV = UtilCreateTexture2DSRV(pd3dDevice,pDiffuseTexture);
+ pNormalsTexture = pRawMesh->CreateD3D11NormalsTextureFor(pd3dDevice);
+ if(pNormalsTexture)
+ pNormalsSRV = UtilCreateTexture2DSRV(pd3dDevice,pNormalsTexture);
+ }
+
+ return hr;
+}
+
+HRESULT NvSimpleMesh::InitializeWithInputLayout(ID3D11Device *pd3dDevice,NvSimpleRawMesh *pRawMesh,BYTE*pIAsig, SIZE_T pIAsigSize)
+{
+ HRESULT hr = S_OK;
+ V_RETURN(CreateInputLayout(pd3dDevice,pIAsig,pIAsigSize));
+ V_RETURN(Initialize(pd3dDevice,pRawMesh));
+ return hr;
+}
+
+HRESULT NvSimpleMesh::CreateInputLayout(ID3D11Device *pd3dDevice,BYTE*pIAsig, SIZE_T pIAsigSize)
+{
+ HRESULT hr = S_OK;
+ SAFE_RELEASE(pInputLayout);
+ V_RETURN( pd3dDevice->CreateInputLayout( NvSimpleRawMesh::D3D11InputElements, NvSimpleRawMesh::D3D11ElementsSize, pIAsig, pIAsigSize, &pInputLayout ) );
+ return hr;
+}
+
+void NvSimpleMesh::Release()
+{
+ SAFE_RELEASE(pVB);
+ SAFE_RELEASE(pIB);
+ SAFE_RELEASE(pDiffuseTexture);
+ SAFE_RELEASE(pDiffuseSRV);
+ SAFE_RELEASE(pNormalsTexture);
+ SAFE_RELEASE(pNormalsSRV);
+ SAFE_RELEASE(pInputLayout);
+}
+
+void NvSimpleMesh::SetupDraw(ID3D11DeviceContext *pd3dContext, int iDiffuseTexSlot, int iNormalsTexSlot)
+{
+ if(iDiffuseTexSlot >= 0)
+ pd3dContext->PSSetShaderResources(iDiffuseTexSlot,1,&pDiffuseSRV);
+ if(iNormalsTexSlot >= 0)
+ pd3dContext->PSSetShaderResources(iNormalsTexSlot,1,&pNormalsSRV);
+
+ D3D11_PRIMITIVE_TOPOLOGY topology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
+
+ UINT Offsets[1];
+ UINT Strides[1];
+ ID3D11Buffer *ppVB[1];
+ Offsets[0] = 0;
+ Strides[0] = VertexStride;
+ ppVB[0] = pVB;
+
+ if(pInputLayout) // optionally set an input layout if we have one
+ pd3dContext->IASetInputLayout(pInputLayout);
+ pd3dContext->IASetVertexBuffers(0,1,ppVB,Strides,Offsets);
+ pd3dContext->IASetIndexBuffer( pIB,IndexFormat, 0 );
+ pd3dContext->IASetPrimitiveTopology(topology);
+}
+
+void NvSimpleMesh::Draw(ID3D11DeviceContext *pd3dContext)
+{
+ if(!pVB)
+ {
+ return;
+ }
+
+ pd3dContext->DrawIndexed(iNumIndices,0,0);
+}
+
+
+void NvSimpleMesh::DrawInstanced(ID3D11DeviceContext *pd3dContext, int iNumInstances)
+{
+ pd3dContext->DrawIndexedInstanced(iNumIndices,iNumInstances,0,0,0);
+}
+
+NvAggregateSimpleMesh::NvAggregateSimpleMesh()
+{
+ pSimpleMeshes = NULL;
+ NumSimpleMeshes = 0;
+}
+
+NvAggregateSimpleMesh::~NvAggregateSimpleMesh()
+{
+ SAFE_DELETE_ARRAY(pSimpleMeshes);
+}
+
+HRESULT NvAggregateSimpleMesh::Initialize(ID3D11Device *pd3dDevice,NvSimpleMeshLoader *pMeshLoader)
+{
+ HRESULT hr = S_OK;
+ if(pMeshLoader->pMeshes == NULL) return E_FAIL;
+ NumSimpleMeshes = pMeshLoader->NumMeshes;
+ pSimpleMeshes = new NvSimpleMesh[NumSimpleMeshes];
+ for(int iMesh=0;iMesh<NumSimpleMeshes;iMesh++)
+ {
+ V_RETURN(pSimpleMeshes[iMesh].Initialize(pd3dDevice,&pMeshLoader->pMeshes[iMesh]));
+ }
+ return hr;
+}
+HRESULT NvAggregateSimpleMesh::InitializeWithInputLayout(ID3D11Device *pd3dDevice,NvSimpleMeshLoader *pMeshLoader,BYTE*pIAsig, SIZE_T pIAsigSize)
+{
+ HRESULT hr = S_OK;
+ if(pMeshLoader->pMeshes == NULL) return E_FAIL;
+ NumSimpleMeshes = pMeshLoader->NumMeshes;
+ pSimpleMeshes = new NvSimpleMesh[NumSimpleMeshes];
+ for(int iMesh=0;iMesh<NumSimpleMeshes;iMesh++)
+ {
+ V_RETURN(pSimpleMeshes[iMesh].InitializeWithInputLayout(pd3dDevice,&pMeshLoader->pMeshes[iMesh],pIAsig,pIAsigSize));
+ }
+ return hr;
+}
+
+void NvAggregateSimpleMesh::Release()
+{
+ if(pSimpleMeshes == NULL) return;
+ for(int iMesh=0;iMesh<NumSimpleMeshes;iMesh++)
+ {
+ pSimpleMeshes[iMesh].Release();
+ }
+}
+
+void NvAggregateSimpleMesh::Draw(ID3D11DeviceContext *pd3dContext, int iDiffuseTexSlot, int iNormalsTexSlot)
+{
+ if(pSimpleMeshes == NULL) return;
+ for(int iMesh=0;iMesh<NumSimpleMeshes;iMesh++)
+ {
+ pSimpleMeshes[iMesh].SetupDraw(pd3dContext,iDiffuseTexSlot,iNormalsTexSlot);
+ pSimpleMeshes[iMesh].Draw(pd3dContext);
+ }
+}
diff --git a/APEX_1.4/externals/extensions/src/nvsimplemesh/NvSimpleMeshLoader.cpp b/APEX_1.4/externals/extensions/src/nvsimplemesh/NvSimpleMeshLoader.cpp
new file mode 100644
index 00000000..12a6152d
--- /dev/null
+++ b/APEX_1.4/externals/extensions/src/nvsimplemesh/NvSimpleMeshLoader.cpp
@@ -0,0 +1,256 @@
+// TAGRELEASE: PUBLIC
+#include <assert.h>
+
+// Direct3D9 includes
+#include <d3d9.h>
+
+// Direct3D11 includes
+#include <d3dcommon.h>
+#include <dxgi.h>
+#include <d3d11.h>
+#include <d3dcompiler.h>
+
+// XInput includes
+#include <xinput.h>
+
+#ifndef V
+#define V(x) { hr = (x); }
+#endif
+#ifndef V_RETURN
+#define V_RETURN(x) { hr = (x); if( FAILED(hr) ) { return hr; } }
+#endif
+
+#ifndef SAFE_DELETE
+#define SAFE_DELETE(p) { if (p) { delete (p); (p)=NULL; } }
+#endif
+#ifndef SAFE_DELETE_ARRAY
+#define SAFE_DELETE_ARRAY(p) { if (p) { delete[] (p); (p)=NULL; } }
+#endif
+#ifndef SAFE_RELEASE
+#define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p)=NULL; } }
+#endif
+
+
+#include "strsafe.h"
+#include <string>
+
+#pragma warning(push)
+#pragma warning(disable: 4100) // unreferenced formal parameter
+#include "assimp\assimp.hpp"
+#pragma warning(pop)
+#include "assimp\aiScene.h"
+#include "assimp\DefaultLogger.h"
+#include "assimp\aiPostProcess.h"
+#include "assimp\aiMesh.h"
+
+using namespace Assimp;
+
+#include "NvSimpleRawMesh.h"
+#include "NvSimpleMeshLoader.h"
+
+
+NvSimpleMeshLoader::NvSimpleMeshLoader()
+{
+ pMeshes = NULL;
+ NumMeshes = 0;
+}
+
+NvSimpleMeshLoader::~NvSimpleMeshLoader()
+{
+ SAFE_DELETE_ARRAY(pMeshes);
+}
+
+bool NvSimpleMeshLoader::LoadFile(LPWSTR szFilename)
+{
+ bool bLoaded = false;
+ (void)bLoaded;
+
+ // Create a logger instance
+ Assimp::DefaultLogger::create("",Logger::VERBOSE);
+
+ // Create an instance of the Importer class
+ Assimp::Importer importer;
+
+ CHAR szFilenameA[MAX_PATH];
+ WideCharToMultiByte(CP_ACP,0,szFilename,MAX_PATH,szFilenameA,MAX_PATH,NULL,false);
+
+ mediaPath = szFilenameA;
+ auto index = mediaPath.find_last_of('\\');
+ if(index != -1)
+ mediaPath = mediaPath.substr(0,index) + "\\";
+ else
+ mediaPath = ".\\";
+
+ // Set some flags for the removal of various data that we don't use
+ importer.SetPropertyInteger("AI_CONFIG_PP_RVC_FLAGS",aiComponent_ANIMATIONS | aiComponent_BONEWEIGHTS | aiComponent_COLORS | aiComponent_LIGHTS | aiComponent_CAMERAS);
+ //importer.SetPropertyInteger("AI_CONFIG_PP_SBP_REMOVE",aiPrimitiveType_POINTS | aiPrimitiveType_LINES );
+
+ // load the scene and preprocess it into the form we want
+ const aiScene *scene = importer.ReadFile(szFilenameA,
+ aiProcess_Triangulate| // only higher order primitives will be triangulated
+ aiProcess_GenNormals| // if normals exist, will not be generated
+ aiProcess_CalcTangentSpace|
+ aiProcess_PreTransformVertices| // rolls all node hierarchy(if existant) into the local space of meshes
+ //aiProcess_RemoveRedundantMaterials|
+ //aiProcess_FixInfacingNormals|
+ aiProcess_FindDegenerates|
+ aiProcess_SortByPType|
+ aiProcess_RemoveComponent| // processes the above flags set to remove data we don't want
+ aiProcess_FindInvalidData|
+ aiProcess_GenUVCoords|
+ aiProcess_TransformUVCoords|
+ aiProcess_OptimizeMeshes |
+
+ aiProcessPreset_TargetRealtime_Quality
+ );
+
+ // can't load?
+ if(!scene)
+ return false;
+
+ if(scene->HasMeshes())
+ {
+ pMeshes = new NvSimpleRawMesh[scene->mNumMeshes];
+ NumMeshes = scene->mNumMeshes;
+
+ DirectX::XMMATRIX identity = DirectX::XMMatrixIdentity();
+
+ RecurseAddMeshes(scene,scene->mRootNode,identity,true);
+ }
+
+ // cleanup
+ Assimp::DefaultLogger::kill();
+
+ return NumMeshes > 0;
+}
+
+void XM_CALLCONV NvSimpleMeshLoader::RecurseAddMeshes(const aiScene *scene, aiNode*pNode, DirectX::FXMMATRIX parentCompositeTransformD3D, bool bFlattenTransforms)
+{
+ // Convert the scene node's transform into DirectXMath, transposing it as we go
+ aiMatrix4x4* paiNodeTrans = &(pNode->mTransformation);
+ DirectX::XMFLOAT4X4 LocalFrameTransformXM(paiNodeTrans->a1, paiNodeTrans->b1, paiNodeTrans->c1, paiNodeTrans->d1,
+ paiNodeTrans->a2, paiNodeTrans->b2, paiNodeTrans->c2, paiNodeTrans->d2,
+ paiNodeTrans->a3, paiNodeTrans->b3, paiNodeTrans->c3, paiNodeTrans->d3,
+ paiNodeTrans->a4, paiNodeTrans->b4, paiNodeTrans->c4, paiNodeTrans->d4);
+
+ DirectX::XMMATRIX LocalFrameTransformD3D = DirectX::XMLoadFloat4x4(&LocalFrameTransformXM);
+ DirectX::XMMATRIX LocalCompositeTransformD3D = DirectX::XMMatrixMultiply(LocalFrameTransformD3D, parentCompositeTransformD3D);
+
+
+ DirectX::XMMATRIX* pActiveTransform = &LocalFrameTransformD3D;
+ if(bFlattenTransforms) pActiveTransform = &LocalCompositeTransformD3D;
+
+ if(pNode->mNumMeshes > 0)
+ {
+ for(int iSubMesh=0;iSubMesh < (int)pNode->mNumMeshes;iSubMesh++)
+ {
+ aiMesh *pMesh = scene->mMeshes[pNode->mMeshes[iSubMesh]];
+ NvSimpleRawMesh &activeMesh = pMeshes[pNode->mMeshes[iSubMesh]]; // we'll use the same ordering as the aiScene
+
+ float emin[3]; ::ZeroMemory(emin,3*sizeof(float));
+ float emax[3]; ::ZeroMemory(emax,3*sizeof(float));
+
+ if(pMesh->HasPositions() && pMesh->HasNormals() && pMesh->HasTextureCoords(0) && pMesh->HasTangentsAndBitangents())
+ {
+ activeMesh.m_iNumIndices = pMesh->mNumFaces*3;
+ activeMesh.m_iNumVertices = pMesh->mNumVertices;
+
+ // copy loaded mesh data into our vertex struct
+ activeMesh.m_pVertexData = new NvSimpleRawMesh::Vertex[pMesh->mNumVertices];
+ for(unsigned int i=0;i<pMesh->mNumVertices;i++)
+ {
+ memcpy((void*)&(activeMesh.m_pVertexData[i].Position),(void*)&(pMesh->mVertices[i]),sizeof(aiVector3D));
+ memcpy((void*)&(activeMesh.m_pVertexData[i].Normal),(void*)&(pMesh->mNormals[i]),sizeof(aiVector3D));
+ memcpy((void*)&(activeMesh.m_pVertexData[i].Tangent),(void*)&(pMesh->mTangents[i]),sizeof(aiVector3D));
+ memcpy((void*)&(activeMesh.m_pVertexData[i].UV),(void*)&(pMesh->mTextureCoords[0][i]),sizeof(aiVector2D));
+
+ for(int m=0;m<3;m++)
+ {
+ emin[m] = min(emin[m],activeMesh.m_pVertexData[i].Position[m]);
+ emax[m] = max(emin[m],activeMesh.m_pVertexData[i].Position[m]);
+ }
+ }
+
+ // create an index buffer
+ activeMesh.m_IndexSize = sizeof(UINT16);
+ if(pMesh->mNumFaces > MAXINT16)
+ activeMesh.m_IndexSize = sizeof(UINT32);
+
+ activeMesh.m_pIndexData = new BYTE[pMesh->mNumFaces * 3 * activeMesh.m_IndexSize];
+ for(unsigned int i=0;i<pMesh->mNumFaces;i++)
+ {
+ assert(pMesh->mFaces[i].mNumIndices == 3);
+ if(activeMesh.m_IndexSize == sizeof(UINT32))
+ {
+ memcpy((void*)&(activeMesh.m_pIndexData[i*3*activeMesh.m_IndexSize]),(void*)pMesh->mFaces[i].mIndices,sizeof(3*activeMesh.m_IndexSize));
+ }
+ else // 16 bit indices
+ {
+ UINT16*pFaceIndices = (UINT16*)&(activeMesh.m_pIndexData[i*3*activeMesh.m_IndexSize]);
+ pFaceIndices[0] = (UINT16)pMesh->mFaces[i].mIndices[0];
+ pFaceIndices[1] = (UINT16)pMesh->mFaces[i].mIndices[1];
+ pFaceIndices[2] = (UINT16)pMesh->mFaces[i].mIndices[2];
+ }
+ }
+
+ // assign extents
+ activeMesh.m_extents[0] = (emax[0] - emin[0]) * 0.5f;
+ activeMesh.m_extents[1] = (emax[1] - emin[1]) * 0.5f;
+ activeMesh.m_extents[2] = (emax[2] - emin[2]) * 0.5f;
+
+ // get the center
+ activeMesh.m_center[0] = emin[0] + activeMesh.m_extents[0];
+ activeMesh.m_center[1] = emin[1] + activeMesh.m_extents[1];
+ activeMesh.m_center[2] = emin[2] + activeMesh.m_extents[2];
+
+ // materials
+ if(scene->HasMaterials())
+ {
+ aiMaterial *pMaterial = scene->mMaterials[pMesh->mMaterialIndex];
+
+ if(pMaterial->GetTextureCount(aiTextureType_DIFFUSE) > 0)
+ {
+ aiString texPath;
+ pMaterial->GetTexture(aiTextureType_DIFFUSE,0,&texPath);
+
+ CHAR szFilenameA[MAX_PATH];
+ StringCchCopyA(szFilenameA,MAX_PATH,texPath.data);
+ MultiByteToWideChar(CP_ACP,0,szFilenameA,MAX_PATH,activeMesh.m_szDiffuseTexture,MAX_PATH);
+
+ //WCHAR szFullPath[MAX_PATH];
+ //if(DXUTFindDXSDKMediaFileCch(szFullPath,MAX_PATH,activeMesh.m_szDiffuseTexture) != S_OK)
+ {
+ std::string qualifiedPath = mediaPath + texPath.data;
+
+ StringCchCopyA(szFilenameA,MAX_PATH,qualifiedPath.c_str());
+ MultiByteToWideChar(CP_ACP,0,szFilenameA,MAX_PATH,activeMesh.m_szDiffuseTexture,MAX_PATH);
+ }
+ }
+ if(pMaterial->GetTextureCount(aiTextureType_NORMALS) > 0)
+ {
+ aiString texPath;
+ pMaterial->GetTexture(aiTextureType_NORMALS,0,&texPath);
+
+ CHAR szFilenameA[MAX_PATH];
+ StringCchCopyA(szFilenameA,MAX_PATH,texPath.data);
+ MultiByteToWideChar(CP_ACP,0,szFilenameA,MAX_PATH,activeMesh.m_szNormalTexture,MAX_PATH);
+
+ //WCHAR szFullPath[MAX_PATH];
+ //if(DXUTFindDXSDKMediaFileCch(szFullPath,MAX_PATH,activeMesh.m_szNormalTexture) != S_OK)
+ {
+ std::string qualifiedPath = mediaPath + texPath.data;
+
+ StringCchCopyA(szFilenameA,MAX_PATH,qualifiedPath.c_str());
+ MultiByteToWideChar(CP_ACP,0,szFilenameA,MAX_PATH,activeMesh.m_szNormalTexture,MAX_PATH);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ for(int iChild=0;iChild<(int)pNode->mNumChildren;iChild++)
+ {
+ RecurseAddMeshes(scene, pNode->mChildren[iChild],LocalCompositeTransformD3D,bFlattenTransforms);
+ }
+}
diff --git a/APEX_1.4/externals/extensions/src/nvsimplemesh/NvSimpleRawMesh.cpp b/APEX_1.4/externals/extensions/src/nvsimplemesh/NvSimpleRawMesh.cpp
new file mode 100644
index 00000000..feaa11ac
--- /dev/null
+++ b/APEX_1.4/externals/extensions/src/nvsimplemesh/NvSimpleRawMesh.cpp
@@ -0,0 +1,221 @@
+// TAGRELEASE: PUBLIC
+
+#include <assert.h>
+
+// Direct3D9 includes
+#include <d3d9.h>
+
+// Direct3D11 includes
+#include <d3dcommon.h>
+#include <dxgi.h>
+#include <d3d11.h>
+#include <d3dcompiler.h>
+
+// DXUT Includes
+#include "dxut\Core\DDSTextureLoader.h"
+
+// XInput includes
+#include <xinput.h>
+
+#ifndef V
+#define V(x) { hr = (x); }
+#endif
+#ifndef V_RETURN
+#define V_RETURN(x) { hr = (x); if( FAILED(hr) ) { return hr; } }
+#endif
+
+#ifndef SAFE_DELETE
+#define SAFE_DELETE(p) { if (p) { delete (p); (p)=NULL; } }
+#endif
+#ifndef SAFE_DELETE_ARRAY
+#define SAFE_DELETE_ARRAY(p) { if (p) { delete[] (p); (p)=NULL; } }
+#endif
+#ifndef SAFE_RELEASE
+#define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p)=NULL; } }
+#endif
+#include "strsafe.h"
+#include <string>
+#include "NvSimpleRawMesh.h"
+
+const D3D11_INPUT_ELEMENT_DESC NvSimpleRawMesh::D3D11InputElements[] =
+{
+ { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ { "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 32, D3D11_INPUT_PER_VERTEX_DATA, 0 }
+};
+
+const int NvSimpleRawMesh::D3D11ElementsSize = sizeof(NvSimpleRawMesh::D3D11InputElements)/sizeof(D3D11_INPUT_ELEMENT_DESC);
+
+
+NvSimpleRawMesh::NvSimpleRawMesh() :
+ m_pVertexData(NULL),
+ m_pIndexData(NULL),
+ m_iNumVertices(0),
+ m_iNumIndices(0),
+ m_IndexSize(sizeof(UINT16))
+{
+ m_szMeshFilename[0] = 0;
+ m_szDiffuseTexture[0] = 0;
+ m_szNormalTexture[0] = 0;
+
+ m_extents[0] = m_extents[1] = m_extents[2] = 0.f;
+ m_center[0] = m_center[1] = m_center[2] = 0.f;
+}
+
+
+NvSimpleRawMesh::~NvSimpleRawMesh()
+{
+ SAFE_DELETE_ARRAY(m_pVertexData);
+ SAFE_DELETE_ARRAY(m_pIndexData);
+}
+
+UINT NvSimpleRawMesh::GetIndexSize()
+{
+ return m_IndexSize;
+}
+
+INT NvSimpleRawMesh::GetVertexStride()
+{
+ return sizeof(Vertex);
+}
+INT NvSimpleRawMesh::GetNumVertices()
+{
+ return m_iNumVertices;
+}
+INT NvSimpleRawMesh::GetNumIndices()
+{
+ return m_iNumIndices;
+}
+
+BYTE * NvSimpleRawMesh::GetRawVertices()
+{
+ return (BYTE*)m_pVertexData;
+}
+
+NvSimpleRawMesh::Vertex * NvSimpleRawMesh::GetVertices()
+{
+ return m_pVertexData;
+}
+
+BYTE * NvSimpleRawMesh::GetRawIndices()
+{
+ return m_pIndexData;
+}
+
+HRESULT NvSimpleRawMesh::TryGuessFilename(WCHAR* /*szDestBuffer*/,WCHAR* /*szMeshFilename*/, WCHAR* /*szGuessSuffix*/)
+{
+ HRESULT hr = E_FAIL;
+
+/*
+ WCHAR szBaseFilename[MAX_PATH];
+ WCHAR szGuessFilename[MAX_PATH];
+ // Start with mesh file
+ StringCchCopyW(szBaseFilename,MAX_PATH,szMeshFilename);
+ size_t len = 0;
+ StringCchLength(szBaseFilename,MAX_PATH,&len);
+
+ // work backwards to first "." and null which strips extension
+ for(int i=(int)len-1;i>=0;i--)
+ {
+ if(szBaseFilename[i] == L'.') {szBaseFilename[i] = 0; break;}
+ }
+
+ StringCchCopy(szGuessFilename,MAX_PATH,szBaseFilename);
+ StringCchCat(szGuessFilename,MAX_PATH,szGuessSuffix);
+
+ hr = DXUTFindDXSDKMediaFileCch(szDestBuffer,MAX_PATH,szGuessFilename);
+ */
+ return hr;
+}
+
+ID3D11Texture2D *NvSimpleRawMesh::CreateD3D11DiffuseTextureFor(ID3D11Device *pd3dDevice)
+{
+ HRESULT hr = S_OK;
+ //if(m_szDiffuseTexture[0] == 0) return NULL;
+/*
+ WCHAR szTextureFilename[MAX_PATH];
+
+ if(m_szDiffuseTexture[0] != 0)
+ {
+ hr = DXUTFindDXSDKMediaFileCch(szTextureFilename,MAX_PATH,m_szDiffuseTexture);
+ }
+
+ // Try to guess a file name in same location
+ if(hr != S_OK)
+ {
+ hr = TryGuessFilename(szTextureFilename,m_szMeshFilename,L"_diffuse.dds");
+ }
+ */
+ ID3D11Resource *pTexture = NULL;
+ hr = DirectX::CreateDDSTextureFromFile(pd3dDevice, m_szDiffuseTexture, &pTexture, nullptr);
+
+ return (ID3D11Texture2D*)pTexture;
+}
+
+ID3D11Texture2D *NvSimpleRawMesh::CreateD3D11NormalsTextureFor(ID3D11Device *pd3dDevice)
+{
+ HRESULT hr = S_OK;
+ //if(m_szNormalTexture[0] == 0) return NULL;
+/*
+ WCHAR szTextureFilename[MAX_PATH];
+
+
+ if(m_szNormalTexture[0] != 0)
+ {
+ hr = DXUTFindDXSDKMediaFileCch(szTextureFilename,MAX_PATH,m_szNormalTexture);
+ }
+
+ // Try to guess a file name in same location for normals
+ if(hr != S_OK)
+ {
+ hr = TryGuessFilename(szTextureFilename,m_szMeshFilename,L"_normals.dds");
+ }
+ if(hr != S_OK)
+ {
+ hr = TryGuessFilename(szTextureFilename,m_szDiffuseTexture,L"_nm.dds");
+ }
+ */
+ ID3D11Resource *pTexture = NULL;
+ hr = DirectX::CreateDDSTextureFromFile(pd3dDevice, m_szNormalTexture, &pTexture, nullptr);
+
+ return (ID3D11Texture2D*)pTexture;
+
+}
+
+ID3D11Buffer *NvSimpleRawMesh::CreateD3D11IndexBufferFor(ID3D11Device *pd3dDevice)
+{
+ ID3D11Buffer *pIB = NULL;
+
+ D3D11_BUFFER_DESC Desc;
+ ::ZeroMemory(&Desc,sizeof(D3D11_BUFFER_DESC));
+ Desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
+ Desc.ByteWidth = GetNumIndices() * GetIndexSize();
+ Desc.Usage = D3D11_USAGE_DEFAULT;
+
+ D3D11_SUBRESOURCE_DATA SubResData;
+ ::ZeroMemory(&SubResData,sizeof(D3D11_SUBRESOURCE_DATA));
+ SubResData.pSysMem = (void*)GetRawIndices();
+
+ pd3dDevice->CreateBuffer(&Desc,&SubResData,&pIB);
+
+ return pIB;
+}
+ID3D11Buffer *NvSimpleRawMesh::CreateD3D11VertexBufferFor(ID3D11Device *pd3dDevice)
+{
+ ID3D11Buffer *pVB = NULL;
+
+ D3D11_BUFFER_DESC Desc;
+ ::ZeroMemory(&Desc,sizeof(D3D11_BUFFER_DESC));
+ Desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ Desc.ByteWidth = GetNumVertices() * GetVertexStride();
+ Desc.Usage = D3D11_USAGE_DEFAULT;
+
+ D3D11_SUBRESOURCE_DATA SubResData;
+ ::ZeroMemory(&SubResData,sizeof(D3D11_SUBRESOURCE_DATA));
+ SubResData.pSysMem = (void*)GetRawVertices();
+
+ pd3dDevice->CreateBuffer(&Desc,&SubResData,&pVB);
+
+ return pVB;
+} \ No newline at end of file