diff options
| author | Tim Foley <tfoleyNV@users.noreply.github.com> | 2018-08-10 22:21:44 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-08-10 22:21:44 -0700 |
| commit | 56d8a752d84e984afab20de5980edf10fe6c06f5 (patch) | |
| tree | eb1491b940daebc6afd200202347191d77f76112 /tools | |
| parent | 73ff6907d723003d30e400f661876e7960de574f (diff) | |
Improve model-viewer support for lights (#626)
* Improve model-viewer support for lights
The main visible change here is that the model-viewer example supports
multiple light sources, with a basic UI for adding new light sources to
the scene, and for manipulating the ones that are there.
Along the way I also refactored the `IMaterial` decomposition to be a
bit less naive, while still only including a completely naive
Blinn-Phong implementation.
I also went ahead and spruced up the `cube.obj` file so that it has
multiple materials, although it is still a completely uninteresting
asset.
* Fixup: Windows SDK version
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/gfx/gui.cpp | 21 | ||||
| -rw-r--r-- | tools/gfx/model.cpp | 33 | ||||
| -rw-r--r-- | tools/gfx/model.h | 3 | ||||
| -rw-r--r-- | tools/gfx/vector-math.h | 1 | ||||
| -rw-r--r-- | tools/gfx/window.cpp | 84 | ||||
| -rw-r--r-- | tools/gfx/window.h | 54 |
6 files changed, 184 insertions, 12 deletions
diff --git a/tools/gfx/gui.cpp b/tools/gfx/gui.cpp index 85a080526..cefb132fb 100644 --- a/tools/gfx/gui.cpp +++ b/tools/gfx/gui.cpp @@ -13,7 +13,24 @@ namespace gfx { #ifdef _WIN32 LRESULT CALLBACK guiWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { - return ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam); + LRESULT handled = ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam); + if(handled) return handled; + ImGuiIO& io = ImGui::GetIO(); + + switch( msg ) + { + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + if(io.WantCaptureMouse) handled = 1; + break; + + case WM_KEYDOWN: + case WM_KEYUP: + if(io.WantCaptureKeyboard) handled = 1; + break; + } + + return handled; } void setNativeWindowHook(Window* window, WNDPROC proc); #endif @@ -314,7 +331,7 @@ void GUI::endFrame() viewport.extentX = draw_data->DisplaySize.x; viewport.extentY = draw_data->DisplaySize.y; viewport.minZ = 0; - viewport.maxZ = 0; + viewport.maxZ = 1; renderer->setViewport(viewport); diff --git a/tools/gfx/model.cpp b/tools/gfx/model.cpp index c8218102e..0173ce950 100644 --- a/tools/gfx/model.cpp +++ b/tools/gfx/model.cpp @@ -205,6 +205,12 @@ Result ModelLoader::load( std::vector<tinyobj::shape_t> objShapes; std::vector<tinyobj::material_t> objMaterials; + std::string baseDir; + if( auto lastSlash = strrchr(inputPath, '/') ) + { + baseDir = std::string(inputPath, lastSlash); + } + std::string diagnostics; bool shouldTriangulate = true; bool success = tinyobj::LoadObj( @@ -213,7 +219,7 @@ Result ModelLoader::load( &objMaterials, &diagnostics, inputPath, - nullptr, + baseDir.size() ? baseDir.c_str() : nullptr, shouldTriangulate); if(!diagnostics.empty()) @@ -238,6 +244,13 @@ Result ModelLoader::load( objMaterial.diffuse[1], objMaterial.diffuse[2]); + materialData.specularColor = glm::vec3( + objMaterial.specular[0], + objMaterial.specular[1], + objMaterial.specular[2]); + + materialData.specularity = objMaterial.shininess; + // load any referenced textures here if(objMaterial.diffuse_texname.length()) { @@ -416,6 +429,8 @@ Result ModelLoader::load( std::vector<void*> meshes; + void* defaultMaterial = nullptr; + for(auto& objShape : objShapes) { size_t objIndexCounter = 0; @@ -424,7 +439,21 @@ Result ModelLoader::load( { size_t objFaceIndex = objFaceCounter++; int faceMaterialID = objShape.mesh.material_ids[objFaceIndex]; - void* faceMaterial = materials[faceMaterialID]; + void* faceMaterial = nullptr; + if( faceMaterialID < 0 ) + { + if( !defaultMaterial ) + { + MaterialData defaultMaterialData; + defaultMaterialData.diffuseColor = glm::vec3(0.5, 0.5, 0.5); + defaultMaterial = callbacks->createMaterial(defaultMaterialData); + } + faceMaterial = defaultMaterial; + } + else + { + faceMaterial = materials[faceMaterialID]; + } if(!currentMesh || (faceMaterial != currentMesh->material)) { diff --git a/tools/gfx/model.h b/tools/gfx/model.h index 046b9764b..b92dfda76 100644 --- a/tools/gfx/model.h +++ b/tools/gfx/model.h @@ -13,6 +13,9 @@ struct ModelLoader struct MaterialData { glm::vec3 diffuseColor; + glm::vec3 specularColor; + float specularity; + RefPtr<TextureResource> diffuseMap; }; diff --git a/tools/gfx/vector-math.h b/tools/gfx/vector-math.h index 88cb0c1d9..e35cb46ac 100644 --- a/tools/gfx/vector-math.h +++ b/tools/gfx/vector-math.h @@ -6,6 +6,7 @@ #include "../../external/glm/glm/glm.hpp" #include "../../external/glm/glm/gtc/matrix_transform.hpp" #include "../../external/glm/glm/gtc/constants.hpp" +#include "../../external/glm/glm/gtc/quaternion.hpp" namespace gfx { diff --git a/tools/gfx/window.cpp b/tools/gfx/window.cpp index 9bc63b896..d777dc8a6 100644 --- a/tools/gfx/window.cpp +++ b/tools/gfx/window.cpp @@ -16,6 +16,7 @@ #if _WIN32 #include <Windows.h> +#include <Windowsx.h> #else #error "The slang-graphics library currently only supports Windows platforms" #endif @@ -110,8 +111,10 @@ int runWindowsApplication( struct Window { - HWND handle; - WNDPROC nativeHook; + HWND handle; + WNDPROC nativeHook; + EventHandler eventHandler; + void* userData; }; void setNativeWindowHook(Window* window, WNDPROC proc) @@ -119,6 +122,28 @@ void setNativeWindowHook(Window* window, WNDPROC proc) window->nativeHook = proc; } +static KeyCode translateKeyCode(int vkey) +{ + switch( vkey ) + { + default: + return KeyCode::Unknown; + +#define CASE(FROM, TO) case FROM: return KeyCode::TO; + CASE('A', A); CASE('B', B); CASE('C', C); CASE('D', D); CASE('E', E); + CASE('F', F); CASE('G', G); CASE('H', H); CASE('I', I); CASE('J', J); + CASE('K', K); CASE('L', M); CASE('M', M); CASE('N', N); CASE('O', O); + CASE('P', P); CASE('Q', Q); CASE('R', R); CASE('S', S); CASE('T', T); + CASE('U', U); CASE('V', V); CASE('W', W); CASE('X', X); CASE('Y', Y); + CASE('Z', Z); +#undef CASE + +#define CASE(FROM, TO) case VK_##FROM: return KeyCode::TO; + CASE(SPACE, Space); +#undef CASE + } +} + static LRESULT CALLBACK windowProc( HWND windowHandle, UINT message, @@ -139,7 +164,8 @@ static LRESULT CALLBACK windowProc( } } - // TODO: Actually implement some reasonable logic here. + auto eventHandler = window ? window->eventHandler : nullptr; + switch (message) { case WM_CREATE: @@ -152,6 +178,51 @@ static LRESULT CALLBACK windowProc( } break; + case WM_KEYDOWN: + case WM_KEYUP: + { + int virtualKey = (int) wParam; + auto keyCode = translateKeyCode(virtualKey); + if(eventHandler) + { + Event event; + event.window = window; + event.code = message == WM_KEYDOWN ? EventCode::KeyDown : EventCode::KeyUp; + event.u.key = keyCode; + eventHandler(event); + } + } + break; + + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + { + if(eventHandler) + { + Event event; + event.window = window; + event.code = message == WM_LBUTTONDOWN ? EventCode::MouseDown : EventCode::MouseUp; + event.u.mouse.x = (float) GET_X_LPARAM(lParam); + event.u.mouse.y = (float) GET_Y_LPARAM(lParam); + eventHandler(event); + } + } + break; + + case WM_MOUSEMOVE: + { + if(eventHandler) + { + Event event; + event.window = window; + event.code = EventCode::MouseMoved; + event.u.mouse.x = (float) GET_X_LPARAM(lParam); + event.u.mouse.y = (float) GET_Y_LPARAM(lParam); + eventHandler(event); + } + } + break; + case WM_CLOSE: PostQuitMessage(0); return 0; @@ -192,6 +263,8 @@ Window* createWindow(WindowDesc const& desc) Window* window = new Window(); window->handle = nullptr; window->nativeHook = nullptr; + window->eventHandler = desc.eventHandler; + window->userData = desc.userData; OSString windowTitle(desc.title); @@ -232,6 +305,11 @@ void* getPlatformWindowHandle(Window* window) return window->handle; } +void* getUserData(Window* window) +{ + return window->userData; +} + bool dispatchEvents(ApplicationContext* context) { for(;;) diff --git a/tools/gfx/window.h b/tools/gfx/window.h index 6e557d26c..e154acec3 100644 --- a/tools/gfx/window.h +++ b/tools/gfx/window.h @@ -5,18 +5,62 @@ namespace gfx { -struct WindowDesc +typedef struct Window Window; + +enum class KeyCode { - char const* title; - int width; - int height; + Unknown, + + // TODO: extend this to cover at least a standard US-English keyboard + + A, B, C, D, E, F, G, H, I, J, + K, L, M, N, O, P, Q, R, S, T, + U, V, W, X, Y, Z, + + Space, }; -typedef struct Window Window; +enum class EventCode : uint32_t +{ + MouseDown, + MouseUp, + MouseMoved, + KeyDown, + KeyUp, +}; + +struct Event +{ + EventCode code; + Window* window; + union + { + struct + { + float x; + float y; + } mouse; + + KeyCode key; + } u; +}; + +typedef void (*EventHandler)(Event const&); + +struct WindowDesc +{ + char const* title = nullptr; + void* userData = nullptr; + int width = 0; + int height = 0; + EventHandler eventHandler = nullptr; +}; Window* createWindow(WindowDesc const& desc); void showWindow(Window* window); + void* getPlatformWindowHandle(Window* window); +void* getUserData(Window* window); /// Opaque state provided by platform for a running application. typedef struct ApplicationContext ApplicationContext; |
