summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2018-08-10 22:21:44 -0700
committerGitHub <noreply@github.com>2018-08-10 22:21:44 -0700
commit56d8a752d84e984afab20de5980edf10fe6c06f5 (patch)
treeeb1491b940daebc6afd200202347191d77f76112 /tools
parent73ff6907d723003d30e400f661876e7960de574f (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.cpp21
-rw-r--r--tools/gfx/model.cpp33
-rw-r--r--tools/gfx/model.h3
-rw-r--r--tools/gfx/vector-math.h1
-rw-r--r--tools/gfx/window.cpp84
-rw-r--r--tools/gfx/window.h54
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;