diff options
| author | git perforce import user <a@b> | 2016-10-25 12:29:14 -0600 |
|---|---|---|
| committer | Sheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees> | 2016-10-25 18:56:37 -0500 |
| commit | 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch) | |
| tree | fa6485c169e50d7415a651bf838f5bcd0fd3bfbd /APEX_1.4/externals/extensions/src | |
| download | physx-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')
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 + ¶ms.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 |