From 503dc30aee9c7614b87602ca2fd0b410d65b814d Mon Sep 17 00:00:00 2001 From: John Chapman Date: Fri, 15 May 2020 14:46:40 +0100 Subject: [PATCH] Style fixes, general code cleanup. --- examples/DirectX11/im3d_directx11.cpp | 78 +- examples/MultiContext/im3d_multicontext.cpp | 42 +- examples/OpenGL31/im3d_opengl31.cpp | 78 +- examples/OpenGL31/im3d_opengl31_debug.exp | Bin 951 -> 0 bytes examples/OpenGL31/im3d_opengl31_debug.lib | Bin 2176 -> 0 bytes examples/OpenGL33/im3d_opengl33.cpp | 56 +- examples/common/im3d_example.cpp | 497 +++++----- examples/common/main.cpp | 168 ++-- im3d.cpp | 961 +++++++++++++------- im3d.h | 521 ++++++----- im3d_math.h | 23 +- 11 files changed, 1513 insertions(+), 911 deletions(-) delete mode 100644 examples/OpenGL31/im3d_opengl31_debug.exp delete mode 100644 examples/OpenGL31/im3d_opengl31_debug.lib diff --git a/examples/DirectX11/im3d_directx11.cpp b/examples/DirectX11/im3d_directx11.cpp index f3b1a41..22008eb 100644 --- a/examples/DirectX11/im3d_directx11.cpp +++ b/examples/DirectX11/im3d_directx11.cpp @@ -43,76 +43,85 @@ bool Im3d_Init() ID3D11Device* d3d = g_Example->m_d3dDevice; { // points shader g_Im3dShaderPoints.m_vsBlob = LoadCompileShader("vs_" IM3D_DX11_VSHADER, "im3d.hlsl", "VERTEX_SHADER\0POINTS\0"); - if (!g_Im3dShaderPoints.m_vsBlob) { + if (!g_Im3dShaderPoints.m_vsBlob) + { return false; } dxAssert(d3d->CreateVertexShader((DWORD*)g_Im3dShaderPoints.m_vsBlob->GetBufferPointer(), g_Im3dShaderPoints.m_vsBlob->GetBufferSize(), nullptr, &g_Im3dShaderPoints.m_vs)); g_Im3dShaderPoints.m_gsBlob = LoadCompileShader("gs_" IM3D_DX11_VSHADER, "im3d.hlsl", "GEOMETRY_SHADER\0POINTS\0"); - if (!g_Im3dShaderPoints.m_gsBlob) { + if (!g_Im3dShaderPoints.m_gsBlob) + { return false; } dxAssert(d3d->CreateGeometryShader((DWORD*)g_Im3dShaderPoints.m_gsBlob->GetBufferPointer(), g_Im3dShaderPoints.m_gsBlob->GetBufferSize(), nullptr, &g_Im3dShaderPoints.m_gs)); g_Im3dShaderPoints.m_psBlob = LoadCompileShader("ps_" IM3D_DX11_VSHADER, "im3d.hlsl", "PIXEL_SHADER\0POINTS\0"); - if (!g_Im3dShaderPoints.m_psBlob) { + if (!g_Im3dShaderPoints.m_psBlob) + { return false; } dxAssert(d3d->CreatePixelShader((DWORD*)g_Im3dShaderPoints.m_psBlob->GetBufferPointer(), g_Im3dShaderPoints.m_psBlob->GetBufferSize(), nullptr, &g_Im3dShaderPoints.m_ps)); } + { // lines shader g_Im3dShaderLines.m_vsBlob = LoadCompileShader("vs_" IM3D_DX11_VSHADER, "im3d.hlsl", "VERTEX_SHADER\0LINES\0"); - if (!g_Im3dShaderLines.m_vsBlob) { + if (!g_Im3dShaderLines.m_vsBlob) + { return false; } dxAssert(d3d->CreateVertexShader((DWORD*)g_Im3dShaderLines.m_vsBlob->GetBufferPointer(), g_Im3dShaderLines.m_vsBlob->GetBufferSize(), nullptr, &g_Im3dShaderLines.m_vs)); g_Im3dShaderLines.m_gsBlob = LoadCompileShader("gs_" IM3D_DX11_VSHADER, "im3d.hlsl", "GEOMETRY_SHADER\0LINES\0"); - if (!g_Im3dShaderLines.m_gsBlob) { + if (!g_Im3dShaderLines.m_gsBlob) + { return false; } dxAssert(d3d->CreateGeometryShader((DWORD*)g_Im3dShaderLines.m_gsBlob->GetBufferPointer(), g_Im3dShaderLines.m_gsBlob->GetBufferSize(), nullptr, &g_Im3dShaderLines.m_gs)); g_Im3dShaderLines.m_psBlob = LoadCompileShader("ps_" IM3D_DX11_VSHADER, "im3d.hlsl", "PIXEL_SHADER\0LINES\0"); - if (!g_Im3dShaderLines.m_psBlob) { + if (!g_Im3dShaderLines.m_psBlob) + { return false; } dxAssert(d3d->CreatePixelShader((DWORD*)g_Im3dShaderLines.m_psBlob->GetBufferPointer(), g_Im3dShaderLines.m_psBlob->GetBufferSize(), nullptr, &g_Im3dShaderLines.m_ps)); } + { // triangles shader g_Im3dShaderTriangles.m_vsBlob = LoadCompileShader("vs_" IM3D_DX11_VSHADER, "im3d.hlsl", "VERTEX_SHADER\0TRIANGLES\0"); - if (!g_Im3dShaderTriangles.m_vsBlob) { + if (!g_Im3dShaderTriangles.m_vsBlob) + { return false; } dxAssert(d3d->CreateVertexShader((DWORD*)g_Im3dShaderTriangles.m_vsBlob->GetBufferPointer(), g_Im3dShaderTriangles.m_vsBlob->GetBufferSize(), nullptr, &g_Im3dShaderTriangles.m_vs)); g_Im3dShaderTriangles.m_psBlob = LoadCompileShader("ps_" IM3D_DX11_VSHADER, "im3d.hlsl", "PIXEL_SHADER\0TRIANGLES\0"); - if (!g_Im3dShaderTriangles.m_psBlob) { + if (!g_Im3dShaderTriangles.m_psBlob) + { return false; } dxAssert(d3d->CreatePixelShader((DWORD*)g_Im3dShaderTriangles.m_psBlob->GetBufferPointer(), g_Im3dShaderTriangles.m_psBlob->GetBufferSize(), nullptr, &g_Im3dShaderTriangles.m_ps)); } - { - D3D11_INPUT_ELEMENT_DESC desc[] = { - { "POSITION_SIZE", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, (UINT)offsetof(Im3d::VertexData, m_positionSize), D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)offsetof(Im3d::VertexData, m_color), D3D11_INPUT_PER_VERTEX_DATA, 0 }, - }; + { D3D11_INPUT_ELEMENT_DESC desc[] = + { + { "POSITION_SIZE", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, (UINT)offsetof(Im3d::VertexData, m_positionSize), D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)offsetof(Im3d::VertexData, m_color), D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; dxAssert(d3d->CreateInputLayout(desc, 2, g_Im3dShaderPoints.m_vsBlob->GetBufferPointer(), g_Im3dShaderPoints.m_vsBlob->GetBufferSize(), &g_Im3dInputLayout)); } - { - D3D11_RASTERIZER_DESC desc = {}; + { D3D11_RASTERIZER_DESC desc = {}; desc.FillMode = D3D11_FILL_SOLID; desc.CullMode = D3D11_CULL_NONE; // culling invalid for points/lines (they are view-aligned), valid but optional for triangles dxAssert(d3d->CreateRasterizerState(&desc, &g_Im3dRasterizerState)); } - { - D3D11_DEPTH_STENCIL_DESC desc = {}; + + { D3D11_DEPTH_STENCIL_DESC desc = {}; dxAssert(d3d->CreateDepthStencilState(&desc, &g_Im3dDepthStencilState)); } - { - D3D11_BLEND_DESC desc = {}; + + { D3D11_BLEND_DESC desc = {}; desc.RenderTarget[0].BlendEnable = true; desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; @@ -168,14 +177,17 @@ void Im3d_NewFrame() cursorPos = (cursorPos / ad.m_viewportSize) * 2.0f - 1.0f; cursorPos.y = -cursorPos.y; // window origin is top-left, ndc is bottom-left Vec3 rayOrigin, rayDirection; - if (g_Example->m_camOrtho) { + if (g_Example->m_camOrtho) + { rayOrigin.x = cursorPos.x / g_Example->m_camProj(0, 0); rayOrigin.y = cursorPos.y / g_Example->m_camProj(1, 1); rayOrigin.z = 0.0f; rayOrigin = g_Example->m_camWorld * Vec4(rayOrigin, 1.0f); rayDirection = g_Example->m_camWorld * Vec4(0.0f, 0.0f, -1.0f, 0.0f); - } else { + } + else + { rayOrigin = ad.m_viewOrigin; rayDirection.x = cursorPos.x / g_Example->m_camProj(0, 0); rayDirection.y = cursorPos.y / g_Example->m_camProj(1, 1); @@ -224,20 +236,23 @@ void Im3d_EndFrame() ID3D11Device* d3d = g_Example->m_d3dDevice; ID3D11DeviceContext* ctx = g_Example->m_d3dDeviceCtx; - D3D11_VIEWPORT viewport = { - 0.0f, 0.0f, // TopLeftX, TopLeftY - (float)g_Example->m_width, (float)g_Example->m_height, - 0.0f, 1.0f // MinDepth, MaxDepth + D3D11_VIEWPORT viewport = + { + 0.0f, 0.0f, // TopLeftX, TopLeftY + (float)g_Example->m_width, (float)g_Example->m_height, + 0.0f, 1.0f // MinDepth, MaxDepth }; ctx->RSSetViewports(1, &viewport); ctx->OMSetBlendState(g_Im3dBlendState, nullptr, 0xffffffff); ctx->OMSetDepthStencilState(g_Im3dDepthStencilState, 0); ctx->RSSetState(g_Im3dRasterizerState); - for (U32 i = 0, n = Im3d::GetDrawListCount(); i < n; ++i) { + for (U32 i = 0, n = Im3d::GetDrawListCount(); i < n; ++i) + { auto& drawList = Im3d::GetDrawLists()[i]; - if (drawList.m_layerId == Im3d::MakeId("NamedLayer")) { + if (drawList.m_layerId == Im3d::MakeId("NamedLayer")) + { // The application may group primitives into layers, which can be used to change the draw state (e.g. enable depth testing, use a different shader) } @@ -250,8 +265,10 @@ void Im3d_EndFrame() // upload vertex data static U32 s_vertexBufferSize = 0; - if (!g_Im3dVertexBuffer || s_vertexBufferSize < drawList.m_vertexCount) { - if (g_Im3dVertexBuffer) { + if (!g_Im3dVertexBuffer || s_vertexBufferSize < drawList.m_vertexCount) + { + if (g_Im3dVertexBuffer) + { g_Im3dVertexBuffer->Release(); g_Im3dVertexBuffer = nullptr; } @@ -262,7 +279,8 @@ void Im3d_EndFrame() UnmapBuffer(g_Im3dVertexBuffer); // select shader/primitive topo - switch (drawList.m_primType) { + switch (drawList.m_primType) + { case Im3d::DrawPrimitive_Points: ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); ctx->VSSetShader(g_Im3dShaderPoints.m_vs, nullptr, 0); diff --git a/examples/MultiContext/im3d_multicontext.cpp b/examples/MultiContext/im3d_multicontext.cpp index 794ee0b..36ceb44 100644 --- a/examples/MultiContext/im3d_multicontext.cpp +++ b/examples/MultiContext/im3d_multicontext.cpp @@ -48,21 +48,25 @@ static void MainThreadDraw(); int main(int, char**) { Im3d::Example example; - if (!example.init(-1, -1, "Im3d Example")) { + if (!example.init(-1, -1, "Im3d Example")) + { return 1; } - for (int i = 0; i < kThreadCountMax; ++i) { + for (int i = 0; i < kThreadCountMax; ++i) + { float threadX = (float)i / (float)kThreadCountMax * 10.0f - 5.0f; g_ThreadGizmoTest[i] = Im3d::Mat4(Im3d::Vec3(threadX, 0.0f, 0.0f), Im3d::Mat3(1.0f), Im3d::Vec3(1.0f)); } - while (example.update()) { // calls Im3d_NewFrame() (see im3d_opengl33.cpp) + while (example.update()) // calls Im3d_NewFrame() (see im3d_opengl33.cpp) + { // At this point we have updated the default context and filled its AppData struct. // Each separate context could potentially use different AppData (e.g. different cameras/viewports). Here // we just copy the default for simplicity. - for (auto& ctx : g_ThreadContexts) { + for (auto& ctx : g_ThreadContexts) + { ctx.getAppData() = Im3d::GetAppData(); ctx.reset(); // equivalent to calling Im3d::NewFrame() on the thread @@ -72,17 +76,20 @@ int main(int, char**) // The frame can now proceed, threads can safely make Im3d:: calls (after setting the context ptr, see ThreadDraw()). std::thread threads[kThreadCountMax]; - for (int i = 0; i < g_ThreadCount; ++i) { + for (int i = 0; i < g_ThreadCount; ++i) + { threads[i] = std::thread(&ThreadDraw, i); } // Towards the end of the frame we need to synchronize so that we can safely merge vertex data from the per-thread contexts. - for (int i = 0; i < g_ThreadCount; ++i) { + for (int i = 0; i < g_ThreadCount; ++i) + { threads[i].join(); } // Prior to calling Im3d::EndFrame() we need to merge the per-thread contexts into the main thread context. - for (int i = 0; i < g_ThreadCount; ++i) { + for (int i = 0; i < g_ThreadCount; ++i) + { Im3d::MergeContexts(Im3d::GetContext(), g_ThreadContexts[i]); } @@ -127,14 +134,16 @@ void ThreadDraw(int _threadIndex) Im3d::SetColor(g_ThreadColors[_threadIndex]); Im3d::BeginPoints(); - for (int i = 0; i < 256; ++i) { + for (int i = 0; i < 256; ++i) + { Im3d::Vertex(Im3d::RandVec3(-10.0f, 10.0f), Im3d::RandFloat(2.0f, 16.0f)); } Im3d::End(); Im3d::SetAlpha(0.5f); Im3d::BeginTriangles(); - for (int i = 0; i < 32; ++i) { + for (int i = 0; i < 32; ++i) + { Im3d::Mat4 wm(1.0f); Im3d::PushMatrix(); Im3d::Rotate(Im3d::Normalize(Im3d::RandVec3(-1.0f, 1.0f)), Im3d::RandFloat(0.0f, 6.0f)); @@ -159,7 +168,8 @@ void MainThreadDraw() ImGui::Begin("Im3d Demo", nullptr, ImGuiWindowFlags_AlwaysAutoResize); ImGui::SetNextTreeNodeOpen(true, ImGuiSetCond_Once); - if (ImGui::TreeNode("About")) { + if (ImGui::TreeNode("About")) + { ImGui::Text("Welcome to the Im3d demo!"); ImGui::Spacing(); ImGui::Text("WASD = forward/left/backward/right"); @@ -173,25 +183,29 @@ void MainThreadDraw() ImGui::Spacing(); ImGui::SetNextTreeNodeOpen(true, ImGuiSetCond_Once); - if (ImGui::TreeNode("Threads")) { + if (ImGui::TreeNode("Threads")) + { ImGui::SliderInt("Thread Count", &g_ThreadCount, 0, kThreadCountMax); ImGui::Checkbox("Enable Sorting", &g_EnableSorting); ImGui::TreePop(); } ImGui::SetNextTreeNodeOpen(true, ImGuiSetCond_Once); - if (ImGui::TreeNode("Grid")) { + if (ImGui::TreeNode("Grid")) + { static int gridSize = 20; ImGui::SliderInt("Grid Size", &gridSize, 1, 50); const float gridHalf = (float)gridSize * 0.5f; Im3d::SetAlpha(1.0f); Im3d::SetSize(1.0f); Im3d::BeginLines(); - for (int x = 0; x <= gridSize; ++x) { + for (int x = 0; x <= gridSize; ++x) + { Im3d::Vertex(-gridHalf, 0.0f, (float)x - gridHalf, Im3d::Color(0.0f, 0.0f, 0.0f)); Im3d::Vertex( gridHalf, 0.0f, (float)x - gridHalf, Im3d::Color(1.0f, 0.0f, 0.0f)); } - for (int z = 0; z <= gridSize; ++z) { + for (int z = 0; z <= gridSize; ++z) + { Im3d::Vertex((float)z - gridHalf, 0.0f, -gridHalf, Im3d::Color(0.0f, 0.0f, 0.0f)); Im3d::Vertex((float)z - gridHalf, 0.0f, gridHalf, Im3d::Color(0.0f, 0.0f, 1.0f)); } diff --git a/examples/OpenGL31/im3d_opengl31.cpp b/examples/OpenGL31/im3d_opengl31.cpp index 3678c2f..5c86adb 100644 --- a/examples/OpenGL31/im3d_opengl31.cpp +++ b/examples/OpenGL31/im3d_opengl31.cpp @@ -21,60 +21,71 @@ bool Im3d_Init() // OpenGL uniform buffers require 16 byte alignment for structs - set IM3D_VERTEX_ALIGNMENT in im3d_config.h IM3D_ASSERT(sizeof(Im3d::VertexData) % 16 == 0); - { - GLuint vs = LoadCompileShader(GL_VERTEX_SHADER, "im3d.glsl", "VERTEX_SHADER\0POINTS\0"); + { GLuint vs = LoadCompileShader(GL_VERTEX_SHADER, "im3d.glsl", "VERTEX_SHADER\0POINTS\0"); GLuint fs = LoadCompileShader(GL_FRAGMENT_SHADER, "im3d.glsl", "FRAGMENT_SHADER\0POINTS\0"); - if (vs && fs) { + if (vs && fs) + { glAssert(g_Im3dShaderPoints = glCreateProgram()); glAssert(glAttachShader(g_Im3dShaderPoints, vs)); glAssert(glAttachShader(g_Im3dShaderPoints, fs)); bool ret = LinkShaderProgram(g_Im3dShaderPoints); glAssert(glDeleteShader(vs)); glAssert(glDeleteShader(fs)); - if (!ret) { + if (!ret) + { return false; } - } else { + } + else + { return false; } GLuint blockIndex; glAssert(blockIndex = glGetUniformBlockIndex(g_Im3dShaderPoints, "VertexDataBlock")); glAssert(glUniformBlockBinding(g_Im3dShaderPoints, blockIndex, 0)); } - { - GLuint vs = LoadCompileShader(GL_VERTEX_SHADER, "im3d.glsl", "VERTEX_SHADER\0LINES\0"); + + { GLuint vs = LoadCompileShader(GL_VERTEX_SHADER, "im3d.glsl", "VERTEX_SHADER\0LINES\0"); GLuint fs = LoadCompileShader(GL_FRAGMENT_SHADER, "im3d.glsl", "FRAGMENT_SHADER\0LINES\0"); - if (vs && fs) { + if (vs && fs) + { glAssert(g_Im3dShaderLines = glCreateProgram()); glAssert(glAttachShader(g_Im3dShaderLines, vs)); glAssert(glAttachShader(g_Im3dShaderLines, fs)); bool ret = LinkShaderProgram(g_Im3dShaderLines); glAssert(glDeleteShader(vs)); glAssert(glDeleteShader(fs)); - if (!ret) { + if (!ret) + { return false; } - } else { + } + else + { return false; } GLuint blockIndex; glAssert(blockIndex = glGetUniformBlockIndex(g_Im3dShaderLines, "VertexDataBlock")); glAssert(glUniformBlockBinding(g_Im3dShaderLines, blockIndex, 0)); } - { - GLuint vs = LoadCompileShader(GL_VERTEX_SHADER, "im3d.glsl", "VERTEX_SHADER\0TRIANGLES\0"); + + { GLuint vs = LoadCompileShader(GL_VERTEX_SHADER, "im3d.glsl", "VERTEX_SHADER\0TRIANGLES\0"); GLuint fs = LoadCompileShader(GL_FRAGMENT_SHADER, "im3d.glsl", "FRAGMENT_SHADER\0TRIANGLES\0"); - if (vs && fs) { + if (vs && fs) + { glAssert(g_Im3dShaderTriangles = glCreateProgram()); glAssert(glAttachShader(g_Im3dShaderTriangles, vs)); glAssert(glAttachShader(g_Im3dShaderTriangles, fs)); bool ret = LinkShaderProgram(g_Im3dShaderTriangles); glAssert(glDeleteShader(vs)); glAssert(glDeleteShader(fs)); - if (!ret) { + if (!ret) + { return false; } - } else { + } + else + { return false; } GLuint blockIndex; @@ -82,14 +93,14 @@ bool Im3d_Init() glAssert(glUniformBlockBinding(g_Im3dShaderTriangles, blockIndex, 0)); } - // in this example we're using a static buffer as the vertex source with a uniform buffer to provide - // the shader with the Im3d vertex data - Im3d::Vec4 vertexData[] = { - Im3d::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), - Im3d::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), - Im3d::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), - Im3d::Vec4( 1.0f, 1.0f, 0.0f, 1.0f) - }; + // In this example we're using a static buffer as the vertex source with a uniform buffer to provide the shader with the Im3d vertex data. + Im3d::Vec4 vertexData[] = + { + Im3d::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), + Im3d::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), + Im3d::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), + Im3d::Vec4( 1.0f, 1.0f, 0.0f, 1.0f) + }; glAssert(glCreateBuffers(1, &g_Im3dVertexBuffer));; glAssert(glCreateVertexArrays(1, &g_Im3dVertexArray)); glAssert(glBindVertexArray(g_Im3dVertexArray)); @@ -129,7 +140,7 @@ void Im3d_NewFrame() ad.m_projOrtho = g_Example->m_camOrtho; // m_projScaleY controls how gizmos are scaled in world space to maintain a constant screen height - ad.m_projScaleY = g_Example->m_camOrtho + ad.m_projScaleY = g_Example->m_camOrtho ? 2.0f / g_Example->m_camProj(1, 1) // use far plane height for an ortho projection : tanf(g_Example->m_camFovRad * 0.5f) * 2.0f // or vertical fov for a perspective projection ; @@ -139,14 +150,17 @@ void Im3d_NewFrame() cursorPos = (cursorPos / ad.m_viewportSize) * 2.0f - 1.0f; cursorPos.y = -cursorPos.y; // window origin is top-left, ndc is bottom-left Vec3 rayOrigin, rayDirection; - if (g_Example->m_camOrtho) { + if (g_Example->m_camOrtho) + { rayOrigin.x = cursorPos.x / g_Example->m_camProj(0, 0); rayOrigin.y = cursorPos.y / g_Example->m_camProj(1, 1); rayOrigin.z = 0.0f; rayOrigin = g_Example->m_camWorld * Vec4(rayOrigin, 1.0f); rayDirection = g_Example->m_camWorld * Vec4(0.0f, 0.0f, -1.0f, 0.0f); - } else { + } + else + { rayOrigin = ad.m_viewOrigin; rayDirection.x = cursorPos.x / g_Example->m_camProj(0, 0); rayDirection.y = cursorPos.y / g_Example->m_camProj(1, 1); @@ -193,17 +207,20 @@ void Im3d_EndFrame() glAssert(glBlendEquation(GL_FUNC_ADD)); glAssert(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); - for (U32 i = 0, n = Im3d::GetDrawListCount(); i < n; ++i) { + for (U32 i = 0, n = Im3d::GetDrawListCount(); i < n; ++i) + { auto& drawList = Im3d::GetDrawLists()[i]; - if (drawList.m_layerId == Im3d::MakeId("NamedLayer")) { + if (drawList.m_layerId == Im3d::MakeId("NamedLayer")) + { // The application may group primitives into layers, which can be used to change the draw state (e.g. enable depth testing, use a different shader) } GLenum prim; GLuint sh; int primVertexCount; - switch (drawList.m_primType) { + switch (drawList.m_primType) + { case Im3d::DrawPrimitive_Points: prim = GL_TRIANGLE_STRIP; primVertexCount = 1; @@ -241,7 +258,8 @@ void Im3d_EndFrame() int remainingPrimCount = drawList.m_vertexCount / primVertexCount; const Im3d::VertexData* vertexData = drawList.m_vertexData; - while (remainingPrimCount > 0) { + while (remainingPrimCount > 0) + { int passPrimCount = remainingPrimCount < kPrimsPerPass ? remainingPrimCount : kPrimsPerPass; int passVertexCount = passPrimCount * primVertexCount; diff --git a/examples/OpenGL31/im3d_opengl31_debug.exp b/examples/OpenGL31/im3d_opengl31_debug.exp deleted file mode 100644 index 241b9f72517f2f45672aad062d1aaf1a93d24d4e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 951 zcma)4+iu!G5FJBXdRI^$+Xq+Tf%IZwh$xCul?Jsoq93P1X8L{PO+qetl&-71h3QK06!mRm*{JUr zt70^Lt)g|`cs0~ia|vFeeqgM9)c1@MO+f)g=KlvcCUt`7I??x)^o_z7>yFkSl4Ibc&I<17_Xz`m$?^lCcyVyx2SVSMGu zIOLl3u~Q$r4VNu+z2?3KY89RxBq~TeX@3wHWLHRke>Y70VXe)Bi9{@bhU3?edE$W-KXKP#j E0{QmMwg3PC diff --git a/examples/OpenGL31/im3d_opengl31_debug.lib b/examples/OpenGL31/im3d_opengl31_debug.lib deleted file mode 100644 index f71c851ce89c8e111d41334e8b00d6222415975b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2176 zcmcIl-EI;=6#f>lwChiZnCOiLV-sy+`3E&I4QNS9x)efb(z}Ji0BgFtxGd_OFW}4g z2E8%qD|q3B58yN4nPsMcLc65tNp@z=nX@zJeDj@|r*B(MyT79*V)L?{n%AY46ob^8 zS7Ovu0o(!t77#iI)<|Cu0AW|x%avNS-q3eThwtm+Iu*4c$GX*RL_BYddDkYBQ{iKsqHMYO0hzEXw&j1gL9-#X8`IJy@V1K=6bR zq;Rf@he*{|K9|7a3syDp4<)W*L^>-u(o`3mTbzAiNJ#n!*Q?gdWv3WxN)Tg`XA1F) z@Fr2>9)UIwCn`{(!8fUhzJSQPxY233tIkdpmU$dJ={gKd%t3|9eZeZ-PnuzR!l1&?2Gxi?ha}E zN4@}+l{bn|%ZV1ok{wZK+vb3Bh;|iaJeFJYzq#p3;r5rj5yDpoN=uTYt5-;0a{R;*Yzi|Kn diff --git a/examples/OpenGL33/im3d_opengl33.cpp b/examples/OpenGL33/im3d_opengl33.cpp index f37932d..5763cca 100644 --- a/examples/OpenGL33/im3d_opengl33.cpp +++ b/examples/OpenGL33/im3d_opengl33.cpp @@ -16,8 +16,7 @@ using namespace Im3d; // draw primitive types (points, lines, triangles), plus some number of vertex buffers. bool Im3d_Init() { - { - GLuint vs = LoadCompileShader(GL_VERTEX_SHADER, "im3d.glsl", "VERTEX_SHADER\0POINTS\0"); + { GLuint vs = LoadCompileShader(GL_VERTEX_SHADER, "im3d.glsl", "VERTEX_SHADER\0POINTS\0"); GLuint fs = LoadCompileShader(GL_FRAGMENT_SHADER, "im3d.glsl", "FRAGMENT_SHADER\0POINTS\0"); if (vs && fs) { glAssert(g_Im3dShaderPoints = glCreateProgram()); @@ -26,18 +25,22 @@ bool Im3d_Init() bool ret = LinkShaderProgram(g_Im3dShaderPoints); glAssert(glDeleteShader(vs)); glAssert(glDeleteShader(fs)); - if (!ret) { + if (!ret) + { return false; } - } else { + } + else + { return false; } } - { - GLuint vs = LoadCompileShader(GL_VERTEX_SHADER, "im3d.glsl", "VERTEX_SHADER\0LINES\0"); + + { GLuint vs = LoadCompileShader(GL_VERTEX_SHADER, "im3d.glsl", "VERTEX_SHADER\0LINES\0"); GLuint gs = LoadCompileShader(GL_GEOMETRY_SHADER, "im3d.glsl", "GEOMETRY_SHADER\0LINES\0"); GLuint fs = LoadCompileShader(GL_FRAGMENT_SHADER, "im3d.glsl", "FRAGMENT_SHADER\0LINES\0"); - if (vs && gs && fs) { + if (vs && gs && fs) + { glAssert(g_Im3dShaderLines = glCreateProgram()); glAssert(glAttachShader(g_Im3dShaderLines, vs)); glAssert(glAttachShader(g_Im3dShaderLines, gs)); @@ -46,27 +49,34 @@ bool Im3d_Init() glAssert(glDeleteShader(vs)); glAssert(glDeleteShader(gs)); glAssert(glDeleteShader(fs)); - if (!ret) { + if (!ret) + { return false; } - } else { + } + else + { return false; } } - { - GLuint vs = LoadCompileShader(GL_VERTEX_SHADER, "im3d.glsl", "VERTEX_SHADER\0TRIANGLES\0"); + + { GLuint vs = LoadCompileShader(GL_VERTEX_SHADER, "im3d.glsl", "VERTEX_SHADER\0TRIANGLES\0"); GLuint fs = LoadCompileShader(GL_FRAGMENT_SHADER, "im3d.glsl", "FRAGMENT_SHADER\0TRIANGLES\0"); - if (vs && fs) { + if (vs && fs) + { glAssert(g_Im3dShaderTriangles = glCreateProgram()); glAssert(glAttachShader(g_Im3dShaderTriangles, vs)); glAssert(glAttachShader(g_Im3dShaderTriangles, fs)); bool ret = LinkShaderProgram(g_Im3dShaderTriangles); glAssert(glDeleteShader(vs)); glAssert(glDeleteShader(fs)); - if (!ret) { + if (!ret) + { return false; } - } else { + } + else + { return false; } } @@ -108,7 +118,7 @@ void Im3d_NewFrame() ad.m_projOrtho = g_Example->m_camOrtho; // m_projScaleY controls how gizmos are scaled in world space to maintain a constant screen height - ad.m_projScaleY = g_Example->m_camOrtho + ad.m_projScaleY = g_Example->m_camOrtho ? 2.0f / g_Example->m_camProj(1, 1) // use far plane height for an ortho projection : tanf(g_Example->m_camFovRad * 0.5f) * 2.0f // or vertical fov for a perspective projection ; @@ -118,14 +128,17 @@ void Im3d_NewFrame() cursorPos = (cursorPos / ad.m_viewportSize) * 2.0f - 1.0f; cursorPos.y = -cursorPos.y; // window origin is top-left, ndc is bottom-left Vec3 rayOrigin, rayDirection; - if (g_Example->m_camOrtho) { + if (g_Example->m_camOrtho) + { rayOrigin.x = cursorPos.x / g_Example->m_camProj(0, 0); rayOrigin.y = cursorPos.y / g_Example->m_camProj(1, 1); rayOrigin.z = 0.0f; rayOrigin = g_Example->m_camWorld * Vec4(rayOrigin, 1.0f); rayDirection = g_Example->m_camWorld * Vec4(0.0f, 0.0f, -1.0f, 0.0f); - } else { + } + else + { rayOrigin = ad.m_viewOrigin; rayDirection.x = cursorPos.x / g_Example->m_camProj(0, 0); rayDirection.y = cursorPos.y / g_Example->m_camProj(1, 1); @@ -175,16 +188,19 @@ void Im3d_EndFrame() glAssert(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); glAssert(glEnable(GL_PROGRAM_POINT_SIZE)); - for (U32 i = 0, n = Im3d::GetDrawListCount(); i < n; ++i) { + for (U32 i = 0, n = Im3d::GetDrawListCount(); i < n; ++i) + { const Im3d::DrawList& drawList = Im3d::GetDrawLists()[i]; - if (drawList.m_layerId == Im3d::MakeId("NamedLayer")) { + if (drawList.m_layerId == Im3d::MakeId("NamedLayer")) + { // The application may group primitives into layers, which can be used to change the draw state (e.g. enable depth testing, use a different shader) } GLenum prim; GLuint sh; - switch (drawList.m_primType) { + switch (drawList.m_primType) + { case Im3d::DrawPrimitive_Points: prim = GL_POINTS; sh = g_Im3dShaderPoints; diff --git a/examples/common/im3d_example.cpp b/examples/common/im3d_example.cpp index fb6465b..1ad7e39 100644 --- a/examples/common/im3d_example.cpp +++ b/examples/common/im3d_example.cpp @@ -63,112 +63,125 @@ static const char* StripPath(const char* _path) ImGuiIO& imgui = ImGui::GetIO(); Example* im3d = g_Example; - switch (_umsg) { - case WM_SIZE: { - int w = (int)LOWORD(_lparam), h = (int)HIWORD(_lparam); - if (im3d->m_width != w || im3d->m_height != h) { - im3d->m_width = w; - im3d->m_height = h; - } - #if defined(IM3D_DX11) - // DX requires that we reset the backbuffer when the window resizes - if (g_Example->m_d3dRenderTarget) { - g_Example->m_d3dRenderTarget->Release(); - g_Example->m_d3dDepthStencil->Release(); - dxAssert(g_Example->m_dxgiSwapChain->ResizeBuffers(0, (UINT)w, (UINT)h, DXGI_FORMAT_UNKNOWN, 0)); - ID3D11Texture2D* backBuffer; - dxAssert(g_Example->m_dxgiSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backBuffer)); - dxAssert(g_Example->m_d3dDevice->CreateRenderTargetView(backBuffer, nullptr, &g_Example->m_d3dRenderTarget)); - g_Example->m_d3dDepthStencil = CreateDepthStencil((UINT)w, (UINT)h, DXGI_FORMAT_D24_UNORM_S8_UINT); - g_Example->m_d3dDeviceCtx->OMSetRenderTargets(1, &g_Example->m_d3dRenderTarget, g_Example->m_d3dDepthStencil); - backBuffer->Release(); + switch (_umsg) + { + case WM_SIZE: + { + int w = (int)LOWORD(_lparam), h = (int)HIWORD(_lparam); + if (im3d->m_width != w || im3d->m_height != h) + { + im3d->m_width = w; + im3d->m_height = h; } + #if defined(IM3D_DX11) + // DX requires that we reset the backbuffer when the window resizes + if (g_Example->m_d3dRenderTarget) + { + g_Example->m_d3dRenderTarget->Release(); + g_Example->m_d3dDepthStencil->Release(); + dxAssert(g_Example->m_dxgiSwapChain->ResizeBuffers(0, (UINT)w, (UINT)h, DXGI_FORMAT_UNKNOWN, 0)); + ID3D11Texture2D* backBuffer; + dxAssert(g_Example->m_dxgiSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backBuffer)); + dxAssert(g_Example->m_d3dDevice->CreateRenderTargetView(backBuffer, nullptr, &g_Example->m_d3dRenderTarget)); + g_Example->m_d3dDepthStencil = CreateDepthStencil((UINT)w, (UINT)h, DXGI_FORMAT_D24_UNORM_S8_UINT); + g_Example->m_d3dDeviceCtx->OMSetRenderTargets(1, &g_Example->m_d3dRenderTarget, g_Example->m_d3dDepthStencil); + backBuffer->Release(); + } - #endif - break; - } - case WM_SIZING: { - RECT* r = (RECT*)_lparam; - int w = (int)(r->right - r->left); - int h = (int)(r->bottom - r->top); - if (im3d->m_width != w || im3d->m_height != h) { - im3d->m_width = w; - im3d->m_height = h; + #endif + break; } - break; - } - case WM_LBUTTONDOWN: - case WM_LBUTTONUP: - imgui.MouseDown[0] = _umsg == WM_LBUTTONDOWN; - break; - case WM_MBUTTONDOWN: - case WM_MBUTTONUP: - imgui.MouseDown[2] = _umsg == WM_MBUTTONDOWN; - break; - case WM_RBUTTONDOWN: - case WM_RBUTTONUP: - imgui.MouseDown[1] = _umsg == WM_RBUTTONDOWN; - break; - case WM_MOUSEWHEEL: - imgui.MouseWheel = (float)(GET_WHEEL_DELTA_WPARAM(_wparam)) / (float)(WHEEL_DELTA); - break; - case WM_MOUSEMOVE: - imgui.MousePos.x = LOWORD(_lparam); - imgui.MousePos.y = HIWORD(_lparam); - break; - case WM_SYSKEYDOWN: - case WM_SYSKEYUP: - case WM_KEYDOWN: - case WM_KEYUP: { - WPARAM vk = _wparam; - UINT sc = (_lparam & 0x00ff0000) >> 16; - bool e0 = (_lparam & 0x01000000) != 0; - if (vk == VK_SHIFT) { - vk = MapVirtualKey(sc, MAPVK_VSC_TO_VK_EX); + case WM_SIZING: + { + RECT* r = (RECT*)_lparam; + int w = (int)(r->right - r->left); + int h = (int)(r->bottom - r->top); + if (im3d->m_width != w || im3d->m_height != h) + { + im3d->m_width = w; + im3d->m_height = h; + } + break; } - switch (vk) { - case VK_CONTROL: - imgui.KeyCtrl = _umsg == WM_KEYDOWN; + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + imgui.MouseDown[0] = _umsg == WM_LBUTTONDOWN; break; - case VK_MENU: - imgui.KeyAlt = _umsg == WM_KEYDOWN; + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + imgui.MouseDown[2] = _umsg == WM_MBUTTONDOWN; break; - case VK_LSHIFT: - case VK_RSHIFT: - imgui.KeyShift = _umsg == WM_KEYDOWN; + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + imgui.MouseDown[1] = _umsg == WM_RBUTTONDOWN; break; - case VK_ESCAPE: - PostQuitMessage(0); + case WM_MOUSEWHEEL: + imgui.MouseWheel = (float)(GET_WHEEL_DELTA_WPARAM(_wparam)) / (float)(WHEEL_DELTA); break; - default: - if (vk < 512) { - imgui.KeysDown[vk] = _umsg == WM_KEYDOWN; - } + case WM_MOUSEMOVE: + imgui.MousePos.x = LOWORD(_lparam); + imgui.MousePos.y = HIWORD(_lparam); break; - }; - return 0; - } - case WM_CHAR: - if (_wparam > 0 && _wparam < 0x10000) { - imgui.AddInputCharacter((unsigned short)_wparam); + case WM_SYSKEYDOWN: + case WM_SYSKEYUP: + case WM_KEYDOWN: + case WM_KEYUP: + { + WPARAM vk = _wparam; + UINT sc = (_lparam & 0x00ff0000) >> 16; + bool e0 = (_lparam & 0x01000000) != 0; + if (vk == VK_SHIFT) + { + vk = MapVirtualKey(sc, MAPVK_VSC_TO_VK_EX); + } + switch (vk) + { + case VK_CONTROL: + imgui.KeyCtrl = _umsg == WM_KEYDOWN; + break; + case VK_MENU: + imgui.KeyAlt = _umsg == WM_KEYDOWN; + break; + case VK_LSHIFT: + case VK_RSHIFT: + imgui.KeyShift = _umsg == WM_KEYDOWN; + break; + case VK_ESCAPE: + PostQuitMessage(0); + break; + default: + if (vk < 512) + { + imgui.KeysDown[vk] = _umsg == WM_KEYDOWN; + } + break; + }; + return 0; } - return 0; - case WM_PAINT: - //IM3D_ASSERT(false); // should be suppressed by calling ValidateRect() - break; - case WM_CLOSE: - PostQuitMessage(0); - return 0; // prevent DefWindowProc from destroying the window - default: - break; + case WM_CHAR: + if (_wparam > 0 && _wparam < 0x10000) + { + imgui.AddInputCharacter((unsigned short)_wparam); + } + return 0; + case WM_PAINT: + //IM3D_ASSERT(false); // should be suppressed by calling ValidateRect() + break; + case WM_CLOSE: + PostQuitMessage(0); + return 0; // prevent DefWindowProc from destroying the window + default: + break; }; + return DefWindowProc(_hwnd, _umsg, _wparam, _lparam); } static bool InitWindow(int& _width_, int& _height_, const char* _title) { static ATOM wndclassex = 0; - if (wndclassex == 0) { + if (wndclassex == 0) + { WNDCLASSEX wc; memset(&wc, 0, sizeof(wc)); wc.cbSize = sizeof(wc); @@ -183,8 +196,9 @@ static const char* StripPath(const char* _path) DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; DWORD dwStyle = WS_OVERLAPPEDWINDOW | WS_MINIMIZEBOX | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; - if (_width_ == -1 || _height_ == -1) { - // auto size; get the dimensions of the primary screen area and subtract the non-client area + if (_width_ == -1 || _height_ == -1) + { + // auto size; get the dimensions of the primary screen area and subtract the non-client area RECT r; winAssert(SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0)); _width_ = r.right - r.left; @@ -212,12 +226,14 @@ static const char* StripPath(const char* _path) ); IM3D_ASSERT(g_Example->m_hwnd); ShowWindow(g_Example->m_hwnd, SW_SHOW); + return true; } static void ShutdownWindow() { - if (g_Example->m_hwnd) { + if (g_Example->m_hwnd) + { winAssert(DestroyWindow(g_Example->m_hwnd)); } } @@ -258,11 +274,12 @@ static const char* StripPath(const char* _path) glAssert(glGetIntegerv(GL_MINOR_VERSION, &platformVMin)); _vmaj = _vmaj < 0 ? platformVMaj : _vmaj; _vmin = _vmin < 0 ? platformVMin : _vmin; - if (platformVMaj < _vmaj || (platformVMaj >= _vmaj && platformVMin < _vmin)) { + if (platformVMaj < _vmaj || (platformVMaj >= _vmaj && platformVMin < _vmin)) + { fprintf(stderr, "OpenGL version %d.%d is not available (available version is %d.%d).", _vmaj, _vmin, platformVMaj, platformVMin); fprintf(stderr, "This error may occur if the platform has an integrated GPU."); + return false; - return 0; } // load wgl extensions for true context creation @@ -276,17 +293,19 @@ static const char* StripPath(const char* _path) // create true context int profileBit = WGL_CONTEXT_CORE_PROFILE_BIT_ARB; //profileBit = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; - int attr[] = { - WGL_CONTEXT_MAJOR_VERSION_ARB, _vmaj, - WGL_CONTEXT_MINOR_VERSION_ARB, _vmin, - WGL_CONTEXT_PROFILE_MASK_ARB, profileBit, - 0 - }; + int attr[] = + { + WGL_CONTEXT_MAJOR_VERSION_ARB, _vmaj, + WGL_CONTEXT_MINOR_VERSION_ARB, _vmin, + WGL_CONTEXT_PROFILE_MASK_ARB, profileBit, + 0 + }; winAssert(g_Example->m_hglrc = wglCreateContextAttribs(hdc, 0, attr)); hglrc = g_Example->m_hglrc; // load extensions - if (!wglMakeCurrent(hdc, hglrc)) { + if (!wglMakeCurrent(hdc, hglrc)) + { fprintf(stderr, "wglMakeCurrent failed"); return false; } @@ -304,11 +323,13 @@ static const char* StripPath(const char* _path) GlGetString(GL_RENDERER) ); - if (_vmaj == 3 && _vmin == 1) { + if (_vmaj == 3 && _vmin == 1) + { // check that the uniform blocks size is at least 64kb GLint maxUniformBlockSize; glAssert(glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUniformBlockSize)); - if (maxUniformBlockSize < (64 * 1024)) { + if (maxUniformBlockSize < (64*1024)) + { IM3D_ASSERT(false); fprintf(stderr, "GL_MAX_UNIFORM_BLOCK_SIZE is less than 64kb (%dkb)", maxUniformBlockSize / 1024); return false; @@ -366,7 +387,8 @@ static const char* StripPath(const char* _path) &featureLevel, &g_Example->m_d3dDeviceCtx )); - if (!g_Example->m_dxgiSwapChain || !g_Example->m_d3dDevice || !g_Example->m_d3dDeviceCtx) { + if (!g_Example->m_dxgiSwapChain || !g_Example->m_d3dDevice || !g_Example->m_d3dDeviceCtx) + { fprintf(stderr, "Error initializing DirectX"); return false; } @@ -399,7 +421,8 @@ static const char* StripPath(const char* _path) /******************************************************************************/ static void Append(const char* _str, Vector& _out_) { - while (*_str) { + while (*_str) + { _out_.push_back(*_str); ++_str; } @@ -412,9 +435,11 @@ static void AppendLine(const char* _str, Vector& _out_) static bool LoadShader(const char* _path, const char* _defines, Vector& _out_) { fprintf(stdout, "Loading shader: '%s'", StripPath(_path)); - if (_defines) { + if (_defines) + { fprintf(stdout, " "); - while (*_defines != '\0') { + while (*_defines != '\0') + { fprintf(stdout, " %s,", _defines); Append("#define ", _out_); AppendLine(_defines, _out_); @@ -426,7 +451,8 @@ static bool LoadShader(const char* _path, const char* _defines, Vector& _o fprintf(stdout, "\n"); FILE* fin = fopen(_path, "rb"); - if (!fin) { + if (!fin) + { fprintf(stderr, "Error opening '%s'\n", _path); return false; } @@ -436,7 +462,8 @@ static bool LoadShader(const char* _path, const char* _defines, Vector& _o int srcbeg = _out_.size(); _out_.resize(srcbeg + fsize, '\0'); - if (fread(_out_.data() + srcbeg, 1, fsize, fin) != fsize) { + if (fread(_out_.data() + srcbeg, 1, fsize, fin) != fsize) + { fclose(fin); fprintf(stderr, "Error reading '%s'\n", _path); return false; @@ -452,7 +479,8 @@ static bool LoadShader(const char* _path, const char* _defines, Vector& _o { Vector src; AppendLine("#version " IM3D_STRINGIFY(IM3D_OPENGL_VSHADER), src); - if (!LoadShader(_path, _defines, src)) { + if (!LoadShader(_path, _defines, src)) + { return 0; } @@ -465,7 +493,8 @@ static bool LoadShader(const char* _path, const char* _defines, Vector& _o glAssert(glCompileShader(ret)); GLint compileStatus = GL_FALSE; glAssert(glGetShaderiv(ret, GL_COMPILE_STATUS, &compileStatus)); - if (compileStatus == GL_FALSE) { + if (compileStatus == GL_FALSE) + { fprintf(stderr, "Error compiling '%s':\n\n", _path); GLint len; glAssert(glGetShaderiv(ret, GL_INFO_LOG_LENGTH, &len)); @@ -477,8 +506,10 @@ static bool LoadShader(const char* _path, const char* _defines, Vector& _o //fprintf(stderr, "\n\n%s", src.data()); fprintf(stderr, "\n"); glAssert(glDeleteShader(ret)); + return 0; } + return ret; } @@ -489,7 +520,8 @@ static bool LoadShader(const char* _path, const char* _defines, Vector& _o glAssert(glLinkProgram(_handle)); GLint linkStatus = GL_FALSE; glAssert(glGetProgramiv(_handle, GL_LINK_STATUS, &linkStatus)); - if (linkStatus == GL_FALSE) { + if (linkStatus == GL_FALSE) + { fprintf(stderr, "Error linking program:\n\n"); GLint len; glAssert(glGetProgramiv(_handle, GL_INFO_LOG_LENGTH, &len)); @@ -501,6 +533,7 @@ static bool LoadShader(const char* _path, const char* _defines, Vector& _o return false; } + return true; } @@ -508,12 +541,14 @@ static bool LoadShader(const char* _path, const char* _defines, Vector& _o { static GLuint vbQuad; static GLuint vaQuad; - if (vbQuad == 0) { - float quadv[8] = { - -1.0f, -1.0f, - 1.0f, -1.0f, - -1.0f, 1.0f, - 1.0f, 1.0f, + if (vbQuad == 0) + { + float quadv[8] = + { + -1.0f, -1.0f, + 1.0f, -1.0f, + -1.0f, 1.0f, + 1.0f, 1.0f, }; glAssert(glGenBuffers(1, &vbQuad)); glAssert(glGenVertexArrays(1, &vaQuad)); @@ -535,22 +570,28 @@ static bool LoadShader(const char* _path, const char* _defines, Vector& _o static GLuint vbTeapot; static GLuint ibTeapot; static GLuint vaTeapot; - if (shTeapot == 0) { + if (shTeapot == 0) + { GLuint vs = LoadCompileShader(GL_VERTEX_SHADER, "model.glsl", "VERTEX_SHADER\0"); GLuint fs = LoadCompileShader(GL_FRAGMENT_SHADER, "model.glsl", "FRAGMENT_SHADER\0"); - if (vs && fs) { + if (vs && fs) + { glAssert(shTeapot = glCreateProgram()); glAssert(glAttachShader(shTeapot, vs)); glAssert(glAttachShader(shTeapot, fs)); bool ret = LinkShaderProgram(shTeapot); glAssert(glDeleteShader(vs)); glAssert(glDeleteShader(fs)); - if (!ret) { + if (!ret) + { return; } - } else { + } + else + { return; } + glAssert(glGenBuffers(1, &vbTeapot)); glAssert(glGenBuffers(1, &ibTeapot)); glAssert(glGenVertexArrays(1, &vaTeapot)); @@ -568,6 +609,7 @@ static bool LoadShader(const char* _path, const char* _defines, Vector& _o glAssert(glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(s_teapotIndices), (GLvoid*)s_teapotIndices, GL_STATIC_DRAW)); glAssert(glBindVertexArray(0)); } + glAssert(glUseProgram(shTeapot)); glAssert(glUniformMatrix4fv(glGetUniformLocation(shTeapot, "uWorldMatrix"), 1, false, _world.m)); glAssert(glUniformMatrix4fv(glGetUniformLocation(shTeapot, "uViewProjMatrix"), 1, false, _viewProj.m)); @@ -584,7 +626,8 @@ static bool LoadShader(const char* _path, const char* _defines, Vector& _o const char* Im3d::GetGlEnumString(GLenum _enum) { #define CASE_ENUM(e) case e: return #e - switch (_enum) { + switch (_enum) + { // errors CASE_ENUM(GL_NONE); CASE_ENUM(GL_INVALID_ENUM); @@ -609,8 +652,9 @@ static bool LoadShader(const char* _path, const char* _defines, Vector& _o ID3DBlob* Im3d::LoadCompileShader(const char* _target, const char* _path, const char* _defines) { Vector src; - if (!LoadShader(_path, _defines, src)) { - return 0; + if (!LoadShader(_path, _defines, src)) + { + return nullptr; } ID3DBlob* ret = nullptr; ID3DBlob* err = nullptr; @@ -619,13 +663,16 @@ static bool LoadShader(const char* _path, const char* _defines, Vector& _o // D3DCompile is not portable - linking with d3dcompiler.lib introdices a dependency on d3dcompiler_XX.lib // \todo get a ptr to D3DCompile at runtime via LoadLibrary/GetProcAddress D3DCompile(src.data(), src.size(), nullptr, nullptr, nullptr, "main", _target, flags, 0, &ret, &err); - if (ret == nullptr) { + if (ret == nullptr) + { fprintf(stderr, "Error compiling '%s':\n\n", _path); - if (err) { + if (err) + { fprintf(stderr, (char*)err->GetBufferPointer()); err->Release(); } } + return ret; } @@ -663,6 +710,7 @@ static bool LoadShader(const char* _path, const char* _defines, Vector& _o dxAssert(g_Example->m_d3dDeviceCtx->Map(_buffer, 0, _mapType, 0, &subRes)); return subRes.pData; } + void Im3d::UnmapBuffer(ID3D11Buffer* _buffer) { g_Example->m_d3dDeviceCtx->Unmap(_buffer, 0); @@ -684,7 +732,8 @@ static bool LoadShader(const char* _path, const char* _defines, Vector& _o ID3D11Texture2D* ret = nullptr; D3D11_SUBRESOURCE_DATA subRes = {}; - if (_data) { + if (_data) + { subRes.pSysMem = _data; subRes.SysMemPitch = _width; switch (_format) { @@ -695,7 +744,8 @@ static bool LoadShader(const char* _path, const char* _defines, Vector& _o } dxAssert(d3d->CreateTexture2D(&txDesc, _data ? &subRes : nullptr, &ret)); - if (resView_) { + if (resView_) + { dxAssert(d3d->CreateShaderResourceView(ret, nullptr, resView_)); } @@ -742,7 +792,8 @@ static bool LoadShader(const char* _path, const char* _defines, Vector& _o ID3D11Device* d3d = g_Example->m_d3dDevice; ID3D11DeviceContext* ctx = g_Example->m_d3dDeviceCtx; - if (s_vsBlob == 0) { + if (s_vsBlob == 0) + { s_vsBlob = LoadCompileShader("vs_" IM3D_DX11_VSHADER, "model.hlsl", "VERTEX_SHADER\0"); dxAssert(d3d->CreateVertexShader((DWORD*)s_vsBlob->GetBufferPointer(), s_vsBlob->GetBufferSize(), nullptr, &s_vs)); s_psBlob = LoadCompileShader("ps_" IM3D_DX11_VSHADER, "model.hlsl", "PIXEL_SHADER\0"); @@ -751,10 +802,11 @@ static bool LoadShader(const char* _path, const char* _defines, Vector& _o s_vb = CreateVertexBuffer(sizeof(s_teapotVertices), D3D11_USAGE_IMMUTABLE, s_teapotVertices); s_ib = CreateIndexBuffer(sizeof(s_teapotIndices), D3D11_USAGE_IMMUTABLE, s_teapotIndices); - D3D11_INPUT_ELEMENT_DESC inputDesc[] = { - { "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 } - }; + D3D11_INPUT_ELEMENT_DESC inputDesc[] = + { + { "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 } + }; dxAssert(d3d->CreateInputLayout(inputDesc, 2, s_vsBlob->GetBufferPointer(), s_vsBlob->GetBufferSize(), &s_inputLayout)); s_cb = CreateConstantBuffer(sizeof(Mat4) * 2, D3D11_USAGE_DYNAMIC); @@ -796,12 +848,15 @@ void Im3d::Assert(const char* _e, const char* _file, int _line, const char* _msg const int kAssertMsgMax = 1024; char buf[kAssertMsgMax]; - if (_msg != nullptr) { + if (_msg != nullptr) + { va_list args; va_start(args, _msg); vsnprintf(buf, kAssertMsgMax, _msg, args); va_end(args); - } else { + } + else + { buf[0] = '\0'; } fprintf(stderr, "Assert (%s, line %d)\n\t'%s' %s", StripPath(_file), _line, _e ? _e : "", buf); @@ -852,7 +907,8 @@ Color Im3d::RandColor(float _min, float _max) int fbX, fbY; fbX = (int)(io.DisplaySize.x * io.DisplayFramebufferScale.x); fbY = (int)(io.DisplaySize.y * io.DisplayFramebufferScale.y); - if (fbX == 0 || fbY == 0) { + if (fbX == 0 || fbY == 0) + { return; } _drawData->ScaleClipRects(io.DisplayFramebufferScale); @@ -880,7 +936,8 @@ Color Im3d::RandColor(float _min, float _max) glAssert(glUniformMatrix4fv(glGetUniformLocation(g_ImGuiShader, "uProjMatrix"), 1, transpose, (const GLfloat*)ortho)); glAssert(glBindVertexArray(g_ImGuiVertexArray)); - for (int i = 0; i < _drawData->CmdListsCount; ++i) { + for (int i = 0; i < _drawData->CmdListsCount; ++i) + { const ImDrawList* drawList = _drawData->CmdLists[i]; const ImDrawIdx* indexOffset = 0; @@ -889,10 +946,14 @@ Color Im3d::RandColor(float _min, float _max) glAssert(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ImGuiIndexBuffer)); glAssert(glBufferData(GL_ELEMENT_ARRAY_BUFFER, drawList->IdxBuffer.Size * sizeof(ImDrawIdx), (GLvoid*)drawList->IdxBuffer.Data, GL_STREAM_DRAW)); - for (const ImDrawCmd* pcmd = drawList->CmdBuffer.begin(); pcmd != drawList->CmdBuffer.end(); ++pcmd) { - if (pcmd->UserCallback) { + for (const ImDrawCmd* pcmd = drawList->CmdBuffer.begin(); pcmd != drawList->CmdBuffer.end(); ++pcmd) + { + if (pcmd->UserCallback) + { pcmd->UserCallback(drawList, pcmd); - } else { + } + else + { glAssert(glBindTexture(GL_TEXTURE_2D, (GLuint)pcmd->TextureId)); glAssert(glScissor((int)pcmd->ClipRect.x, (int)(fbY - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y))); glAssert(glDrawElements(GL_TRIANGLES, pcmd->ElemCount, GL_UNSIGNED_SHORT, (GLvoid*)indexOffset)); @@ -910,19 +971,24 @@ Color Im3d::RandColor(float _min, float _max) { GLuint vs = LoadCompileShader(GL_VERTEX_SHADER, "imgui.glsl", "VERTEX_SHADER\0"); GLuint fs = LoadCompileShader(GL_FRAGMENT_SHADER, "imgui.glsl", "FRAGMENT_SHADER\0"); - if (vs && fs) { + if (vs && fs) + { glAssert(g_ImGuiShader = glCreateProgram()); glAssert(glAttachShader(g_ImGuiShader, vs)); glAssert(glAttachShader(g_ImGuiShader, fs)); bool ret = LinkShaderProgram(g_ImGuiShader); glAssert(glDeleteShader(vs)); glAssert(glDeleteShader(fs)); - if (!ret) { + if (!ret) + { return false; } - } else { + } + else + { return false; } + glAssert(glUseProgram(g_ImGuiShader)); glAssert(glUniform1i(glGetUniformLocation(g_ImGuiShader, "txTexture"), 0)); glAssert(glUseProgram(0)); @@ -991,8 +1057,10 @@ Color Im3d::RandColor(float _min, float _max) // (re)alloc vertex/index buffers static int s_vertexBufferSize = 0; - if (!g_ImGuiVertexBuffer || s_vertexBufferSize < _drawData->TotalVtxCount) { - if (g_ImGuiVertexBuffer) { + if (!g_ImGuiVertexBuffer || s_vertexBufferSize < _drawData->TotalVtxCount) + { + if (g_ImGuiVertexBuffer) + { g_ImGuiVertexBuffer->Release(); g_ImGuiVertexBuffer = nullptr; } @@ -1000,8 +1068,10 @@ Color Im3d::RandColor(float _min, float _max) g_ImGuiVertexBuffer = CreateVertexBuffer(s_vertexBufferSize * sizeof(ImDrawVert), D3D11_USAGE_DYNAMIC); } static int s_indexBufferSize = 0; - if (!g_ImGuiIndexBuffer || s_indexBufferSize < _drawData->TotalIdxCount) { - if (g_ImGuiIndexBuffer) { + if (!g_ImGuiIndexBuffer || s_indexBufferSize < _drawData->TotalIdxCount) + { + if (g_ImGuiIndexBuffer) + { g_ImGuiIndexBuffer->Release(); g_ImGuiIndexBuffer = nullptr; } @@ -1012,7 +1082,8 @@ Color Im3d::RandColor(float _min, float _max) // copy and convert all vertices into a single contiguous buffer ImDrawVert* vtxDst = (ImDrawVert*)MapBuffer(g_ImGuiVertexBuffer, D3D11_MAP_WRITE_DISCARD); ImDrawIdx* idxDst = (ImDrawIdx*)MapBuffer(g_ImGuiIndexBuffer, D3D11_MAP_WRITE_DISCARD); - for (int i = 0; i < _drawData->CmdListsCount; ++i) { + for (int i = 0; i < _drawData->CmdListsCount; ++i) + { const ImDrawList* cmdList = _drawData->CmdLists[i]; memcpy(vtxDst, cmdList->VtxBuffer.Data, cmdList->VtxBuffer.Size * sizeof(ImDrawVert)); memcpy(idxDst, cmdList->IdxBuffer.Data, cmdList->IdxBuffer.Size * sizeof(ImDrawIdx)); @@ -1057,12 +1128,17 @@ Color Im3d::RandColor(float _min, float _max) int vtxOffset = 0; int idxOffset = 0; - for (int i = 0; i < _drawData->CmdListsCount; ++i) { + for (int i = 0; i < _drawData->CmdListsCount; ++i) + { const ImDrawList* cmdList = _drawData->CmdLists[i]; - for (const ImDrawCmd* pcmd = cmdList->CmdBuffer.begin(); pcmd != cmdList->CmdBuffer.end(); ++pcmd) { - if (pcmd->UserCallback) { + for (const ImDrawCmd* pcmd = cmdList->CmdBuffer.begin(); pcmd != cmdList->CmdBuffer.end(); ++pcmd) + { + if (pcmd->UserCallback) + { pcmd->UserCallback(cmdList, pcmd); - } else { + } + else + { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); ctx->RSSetScissorRects(1, &r); @@ -1079,47 +1155,44 @@ Color Im3d::RandColor(float _min, float _max) ImGuiIO& io = ImGui::GetIO(); ID3D11Device* d3d = g_Example->m_d3dDevice; - { - g_ImGuiVertexShaderBlob = LoadCompileShader("vs_4_0", "imgui.hlsl", "VERTEX_SHADER\0"); - if (!g_ImGuiVertexShaderBlob) { + { g_ImGuiVertexShaderBlob = LoadCompileShader("vs_4_0", "imgui.hlsl", "VERTEX_SHADER\0"); + if (!g_ImGuiVertexShaderBlob) + { return false; } dxAssert(d3d->CreateVertexShader((DWORD*)g_ImGuiVertexShaderBlob->GetBufferPointer(), g_ImGuiVertexShaderBlob->GetBufferSize(), nullptr, &g_ImGuiVertexShader)); } - { - g_ImGuiPixelShaderBlob = LoadCompileShader("ps_4_0", "imgui.hlsl", "PIXEL_SHADER\0"); - if (!g_ImGuiPixelShaderBlob) { + { g_ImGuiPixelShaderBlob = LoadCompileShader("ps_4_0", "imgui.hlsl", "PIXEL_SHADER\0"); + if (!g_ImGuiPixelShaderBlob) + { return false; } dxAssert(d3d->CreatePixelShader((DWORD*)g_ImGuiPixelShaderBlob->GetBufferPointer(), g_ImGuiPixelShaderBlob->GetBufferSize(), nullptr, &g_ImGuiPixelShader)); } - { - D3D11_INPUT_ELEMENT_DESC desc[] = { - { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)offsetof(ImDrawVert, pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)offsetof(ImDrawVert, uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)offsetof(ImDrawVert, col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, - }; + { D3D11_INPUT_ELEMENT_DESC desc[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)offsetof(ImDrawVert, pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)offsetof(ImDrawVert, uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)offsetof(ImDrawVert, col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; dxAssert(d3d->CreateInputLayout(desc, 3, g_ImGuiVertexShaderBlob->GetBufferPointer(), g_ImGuiVertexShaderBlob->GetBufferSize(), &g_ImGuiInputLayout)); } g_ImGuiConstantBuffer = CreateConstantBuffer(sizeof(Mat4), D3D11_USAGE_DYNAMIC); - { - D3D11_RASTERIZER_DESC desc = {}; + { D3D11_RASTERIZER_DESC desc = {}; desc.FillMode = D3D11_FILL_SOLID; desc.CullMode = D3D11_CULL_NONE; desc.ScissorEnable = true; desc.DepthClipEnable = true; dxAssert(d3d->CreateRasterizerState(&desc, &g_ImGuiRasterizerState)); } - { - D3D11_DEPTH_STENCIL_DESC desc = {}; + { D3D11_DEPTH_STENCIL_DESC desc = {}; desc.DepthEnable = false; desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO; desc.StencilEnable = false; dxAssert(d3d->CreateDepthStencilState(&desc, &g_ImGuiDepthStencilState)); } - { - D3D11_BLEND_DESC desc = {}; + { D3D11_BLEND_DESC desc = {}; desc.RenderTarget[0].BlendEnable = true; desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; @@ -1131,8 +1204,7 @@ Color Im3d::RandColor(float _min, float _max) dxAssert(d3d->CreateBlendState(&desc, &g_ImGuiBlendState)); } - { - D3D11_SAMPLER_DESC desc = {}; + { D3D11_SAMPLER_DESC desc = {}; desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; desc.AddressU = desc.AddressV = desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; dxAssert(d3d->CreateSamplerState(&desc, &g_ImGuiFontSampler)); @@ -1228,23 +1300,28 @@ bool Example::init(int _width, int _height, const char* _title) m_width = _width; m_height = _height; m_title = _title; - if (!InitWindow(m_width, m_height, m_title)) { + if (!InitWindow(m_width, m_height, m_title)) + { goto Example_init_fail; } #if defined(IM3D_OPENGL) - if (!InitOpenGL(IM3D_OPENGL_VMAJ, IM3D_OPENGL_VMIN)) { + if (!InitOpenGL(IM3D_OPENGL_VMAJ, IM3D_OPENGL_VMIN)) + { goto Example_init_fail; } #elif defined(IM3D_DX11) - if (!InitDx11()) { + if (!InitDx11()) + { goto Example_init_fail; } #endif - if (!ImGui_Init()) { + if (!ImGui_Init()) + { goto Example_init_fail; } - if (!Im3d_Init()) { + if (!Im3d_Init()) + { goto Example_init_fail; } @@ -1287,7 +1364,8 @@ bool Example::update() m_deltaTime = (float)(microseconds / 1000000.0); MSG msg; - while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE) && msg.message != WM_QUIT) { + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE) && msg.message != WM_QUIT) + { TranslateMessage(&msg); DispatchMessage(&msg); } @@ -1296,8 +1374,6 @@ bool Example::update() ImGui_Update(); - - float kCamSpeed = 2.0f; float kCamSpeedMul = 10.0f; float kCamRotationMul = 10.0f; @@ -1305,34 +1381,46 @@ bool Example::update() m_camView = Inverse(m_camWorld); #if defined(IM3D_PLATFORM_WIN) Vec2 cursorPos = getWindowRelativeCursor(); - if (hasFocus()) { - if (!ImGui::GetIO().WantCaptureKeyboard) { - if (GetAsyncKeyState(VK_LSHIFT) & 0x8000) { + if (hasFocus()) + { + if (!ImGui::GetIO().WantCaptureKeyboard) + { + if (GetAsyncKeyState(VK_LSHIFT) & 0x8000) + { kCamSpeed *= 10.0f; } - if ((GetAsyncKeyState(VK_LCONTROL) & 0x8000) == 0 ) { // ctrl not pressed - if (GetAsyncKeyState(0x57) & 0x8000) { // W (forward) + if ((GetAsyncKeyState(VK_LCONTROL) & 0x8000) == 0 ) // ctrl not pressed + { + if (GetAsyncKeyState(0x57) & 0x8000) // W (forward) + { m_camPos = m_camPos - m_camWorld.getCol(2) * (m_deltaTime * kCamSpeed); } - if (GetAsyncKeyState(0x41) & 0x8000) { // A (left) + if (GetAsyncKeyState(0x41) & 0x8000) // A (left) + { m_camPos = m_camPos - m_camWorld.getCol(0) * (m_deltaTime * kCamSpeed); } - if (GetAsyncKeyState(0x53) & 0x8000) { // S (backward) + if (GetAsyncKeyState(0x53) & 0x8000) // S (backward) + { m_camPos = m_camPos + m_camWorld.getCol(2) * (m_deltaTime * kCamSpeed); } - if (GetAsyncKeyState(0x44) & 0x8000) { // D (right) + if (GetAsyncKeyState(0x44) & 0x8000) // D (right) + { m_camPos = m_camPos + m_camWorld.getCol(0) * (m_deltaTime * kCamSpeed); } - if (GetAsyncKeyState(0x51) & 0x8000) { // Q (down) + if (GetAsyncKeyState(0x51) & 0x8000) // Q (down) + { m_camPos = m_camPos - m_camWorld.getCol(1)* (m_deltaTime * kCamSpeed); } - if (GetAsyncKeyState(0x45) & 0x8000) { // D (up) + if (GetAsyncKeyState(0x45) & 0x8000) // D (up) + { m_camPos = m_camPos + m_camWorld.getCol(1) * (m_deltaTime * kCamSpeed); } } } - if (!ImGui::GetIO().WantCaptureMouse) { - if (GetAsyncKeyState(VK_RBUTTON) & 0x8000) { + if (!ImGui::GetIO().WantCaptureMouse) + { + if (GetAsyncKeyState(VK_RBUTTON) & 0x8000) + { Vec2 cursorDelta = ((cursorPos - m_prevCursorPos) / Vec2((float)m_width, (float)m_height)) * kCamRotationMul; m_camDir = Rotation(Vec3(0.0f, 1.0f, 0.0f), -cursorDelta.x) * m_camDir; m_camDir = Rotation(m_camWorld.getCol(0), -cursorDelta.y) * m_camDir; @@ -1349,7 +1437,8 @@ bool Example::update() float scale = tanf(m_camFovRad * 0.5f) * n; float viewZ = -1.0f; - if (m_camOrtho) { + if (m_camOrtho) + { // ortho proj scale = 5.0f; float r = scale * a; @@ -1369,7 +1458,9 @@ bool Example::update() 0.0f, 0.0f, 0.0f, 1.0f #endif ); - } else { + } + else + { // infinite perspective proj float r = a * scale; float l = -r; @@ -1474,14 +1565,14 @@ void Example::drawTextDrawListsImGui(const Im3d::TextDrawList _textDrawLists[], ImGui::PushStyleColor(ImGuiCol_WindowBg, IM_COL32_BLACK_TRANS); ImGui::SetNextWindowPos(ImVec2(0.0f, 0.0f)); ImGui::SetNextWindowSize(ImVec2((float)m_width, (float)m_height)); - ImGui::Begin("Invisible", nullptr, - ImGuiWindowFlags_NoTitleBar | - ImGuiWindowFlags_NoResize | - ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoInputs | - ImGuiWindowFlags_NoSavedSettings | - ImGuiWindowFlags_NoFocusOnAppearing | - ImGuiWindowFlags_NoBringToFrontOnFocus + ImGui::Begin("Invisible", nullptr, 0 + | ImGuiWindowFlags_NoTitleBar + | ImGuiWindowFlags_NoResize + | ImGuiWindowFlags_NoScrollbar + | ImGuiWindowFlags_NoInputs + | ImGuiWindowFlags_NoSavedSettings + | ImGuiWindowFlags_NoFocusOnAppearing + | ImGuiWindowFlags_NoBringToFrontOnFocus ); ImDrawList* imDrawList = ImGui::GetWindowDrawList(); diff --git a/examples/common/main.cpp b/examples/common/main.cpp index e104314..7cd8d9e 100644 --- a/examples/common/main.cpp +++ b/examples/common/main.cpp @@ -3,11 +3,13 @@ int main(int, char**) { Im3d::Example example; - if (!example.init(-1, -1, "Im3d Example")) { + if (!example.init(-1, -1, "Im3d Example")) + { return 1; } - while (example.update()) { + while (example.update()) + { Im3d::RandSeed(0); Im3d::Context& ctx = Im3d::GetContext(); @@ -16,7 +18,8 @@ int main(int, char**) ImGui::Begin("Im3d Demo", nullptr, ImGuiWindowFlags_AlwaysAutoResize); ImGui::SetNextTreeNodeOpen(true, ImGuiSetCond_Once); - if (ImGui::TreeNode("About")) { + if (ImGui::TreeNode("About")) + { ImGui::Text("Welcome to the Im3d demo!"); ImGui::Spacing(); ImGui::Text("WASD = forward/left/backward/right"); @@ -30,7 +33,8 @@ int main(int, char**) ImGui::Spacing(); ImGui::SetNextTreeNodeOpen(true, ImGuiSetCond_Once); - if (ImGui::TreeNode("Unified Gizmo")) { + if (ImGui::TreeNode("Unified Gizmo")) + { // Unified gizmo operates directly on a 4x4 matrix using the context-global gizmo modes. static Im3d::Mat4 transform(1.0f); @@ -46,20 +50,25 @@ int main(int, char**) Im3d::GetContext().m_gizmoMode = (Im3d::GizmoMode)gizmoMode; // The ID passed to Gizmo() should be unique during a frame - to create gizmos in a loop use PushId()/PopId(). - if (Im3d::Gizmo("GizmoUnified", transform)) { + if (Im3d::Gizmo("GizmoUnified", transform)) + { // if Gizmo() returns true, the transform was modified - switch (Im3d::GetContext().m_gizmoMode) { - case Im3d::GizmoMode_Translation: { + switch (Im3d::GetContext().m_gizmoMode) + { + case Im3d::GizmoMode_Translation: + { Im3d::Vec3 pos = transform.getTranslation(); ImGui::Text("Position: %.3f, %.3f, %.3f", pos.x, pos.y, pos.z); break; } - case Im3d::GizmoMode_Rotation: { + case Im3d::GizmoMode_Rotation: + { Im3d::Vec3 euler = Im3d::ToEulerXYZ(transform.getRotation()); ImGui::Text("Rotation: %.3f, %.3f, %.3f", Im3d::Degrees(euler.x), Im3d::Degrees(euler.y), Im3d::Degrees(euler.z)); break; } - case Im3d::GizmoMode_Scale: { + case Im3d::GizmoMode_Scale: + { Im3d::Vec3 scale = transform.getScale(); ImGui::Text("Scale: %.3f, %.3f, %.3f", scale.x, scale.y, scale.z); break; @@ -77,7 +86,8 @@ int main(int, char**) } - if (ImGui::TreeNode("Separate Gizmos")) { + if (ImGui::TreeNode("Separate Gizmos")) + { // Translation/rotation/scale can be modified separately - useful in cases where only certain transformations are valid. static Im3d::Vec3 translation(0.0f); static Im3d::Mat3 rotation(1.0f); @@ -96,21 +106,27 @@ int main(int, char**) ImGui::RadioButton("Scale (Ctrl+S)", &gizmoMode, Im3d::GizmoMode_Scale); Im3d::GetContext().m_gizmoMode = (Im3d::GizmoMode)gizmoMode; - switch (Im3d::GetContext().m_gizmoMode) { + switch (Im3d::GetContext().m_gizmoMode) + { case Im3d::GizmoMode_Translation: - if (Im3d::GizmoTranslation("GizmoTranslation", translation, Im3d::GetContext().m_gizmoLocal)) { + if (Im3d::GizmoTranslation("GizmoTranslation", translation, Im3d::GetContext().m_gizmoLocal)) + { ImGui::Text("Position: %.3f, %.3f, %.3f", translation.x, translation.y, translation.z); } break; - case Im3d::GizmoMode_Rotation: { - if (Im3d::GizmoRotation("GizmoRotation", rotation, Im3d::GetContext().m_gizmoLocal)) { + case Im3d::GizmoMode_Rotation: + { + if (Im3d::GizmoRotation("GizmoRotation", rotation, Im3d::GetContext().m_gizmoLocal)) + { Im3d::Vec3 euler = Im3d::ToEulerXYZ(rotation); ImGui::Text("Rotation: %.3f, %.3f, %.3f", Im3d::Degrees(euler.x), Im3d::Degrees(euler.y), Im3d::Degrees(euler.z)); } break; } - case Im3d::GizmoMode_Scale: { - if (Im3d::GizmoScale("GizmoScale", scale)) { + case Im3d::GizmoMode_Scale: + { + if (Im3d::GizmoScale("GizmoScale", scale)) + { ImGui::Text("Scale: %.3f, %.3f, %.3f", scale.x, scale.y, scale.z); } break; @@ -126,7 +142,8 @@ int main(int, char**) } - if (ImGui::TreeNode("Hierarchical Gizmos")) { + if (ImGui::TreeNode("Hierarchical Gizmos")) + { // It is often useful to modify a single node in a transformation hierarchy directly, which can be done as follows. // Note that scaling the parent is probably undesirable in these cases. static Im3d::Mat4 parent(1.0f); @@ -135,7 +152,8 @@ int main(int, char**) Im3d::Gizmo("GizmoParent", parent); // modify parent directly Im3d::Mat4 parentChild = parent * child; // modify the final world space transform - if (Im3d::Gizmo("GizmoChild", parentChild)) { + if (Im3d::Gizmo("GizmoChild", parentChild)) + { child = Im3d::Inverse(parent) * parentChild; // extract the child transform if modified } @@ -145,7 +163,8 @@ int main(int, char**) ImGui::TreePop(); } - if (ImGui::TreeNode("Gizmo Appearance")) { + if (ImGui::TreeNode("Gizmo Appearance")) + { // The size/radius of gizmos can be modified globally. static float alpha = 1.0f; static float size = Im3d::GetContext().m_gizmoSizePixels; @@ -172,21 +191,25 @@ int main(int, char**) ImGui::TreePop(); } - if (ImGui::TreeNode("Cursor Ray Intersection")) { + if (ImGui::TreeNode("Cursor Ray Intersection")) + { // Context exposes the 'hot depth' along the cursor ray which intersects with the current hot gizmo - this is useful // when drawing the cursor ray. float depth = FLT_MAX; depth = Im3d::Min(depth, Im3d::GetContext().m_hotDepth); float size = Im3d::Clamp(32.0f / depth, 4.0f, 32.0f); - if (depth != FLT_MAX) { + if (depth != FLT_MAX) + { ImGui::Text("Depth: %f", depth); Im3d::PushEnableSorting(true); Im3d::BeginPoints(); Im3d::Vertex(ad.m_cursorRayOrigin + ad.m_cursorRayDirection * depth * 0.99f, size, Im3d::Color_Magenta); Im3d::End(); Im3d::PopEnableSorting(); - } else { + } + else + { ImGui::Text("Depth: FLT_MAX"); } @@ -194,7 +217,8 @@ int main(int, char**) } //ImGui::SetNextTreeNodeOpen(true, ImGuiCond_Once); - if (ImGui::TreeNode("High Order Shapes")) { + if (ImGui::TreeNode("High Order Shapes")) + { // Im3d provides functions to easily draw high order shapes - these don't strictly require a matrix to be pushed on // the stack (although this is supported, as below). static Im3d::Mat4 transform(1.0f); @@ -241,54 +265,72 @@ int main(int, char**) Im3d::SetSize(thickness); Im3d::SetColor(Im3d::Color(color.x, color.y, color.z, color.w)); - switch ((Shape)currentShape) { + switch ((Shape)currentShape) + { case Shape_Quad: - case Shape_QuadFilled: { + case Shape_QuadFilled: + { static Im3d::Vec2 quadSize(1.0f); ImGui::SliderFloat2("Size", quadSize, 0.0f, 10.0f); - if (currentShape == Shape_Quad) { + if (currentShape == Shape_Quad) + { Im3d::DrawQuad(Im3d::Vec3(0.0f), Im3d::Vec3(0.0f, 0.0f, 1.0f), quadSize); - } else { + } + else + { Im3d::DrawQuadFilled(Im3d::Vec3(0.0f), Im3d::Vec3(0.0f, 0.0f, 1.0f), quadSize); } break; } case Shape_Circle: - case Shape_CircleFilled: { + case Shape_CircleFilled: + { static float circleRadius = 1.0f; ImGui::SliderFloat("Radius", &circleRadius, 0.0f, 10.0f); ImGui::SliderInt("Detail", &detail, -1, 128); - if (currentShape == Shape_Circle) { + if (currentShape == Shape_Circle) + { Im3d::DrawCircle(Im3d::Vec3(0.0f), Im3d::Vec3(0.0f, 0.0f, 1.0f), circleRadius, detail); - } else if (currentShape = Shape_CircleFilled) { + } + else if (currentShape = Shape_CircleFilled) + { Im3d::DrawCircleFilled(Im3d::Vec3(0.0f), Im3d::Vec3(0.0f, 0.0f, 1.0f), circleRadius, detail); } break; } case Shape_Sphere: - case Shape_SphereFilled: { + case Shape_SphereFilled: + { static float sphereRadius = 1.0f; ImGui::SliderFloat("Radius", &sphereRadius, 0.0f, 10.0f); ImGui::SliderInt("Detail", &detail, -1, 128); - if (currentShape == Shape_Sphere) { + if (currentShape == Shape_Sphere) + { Im3d::DrawSphere(Im3d::Vec3(0.0f), sphereRadius, detail); - } else { + } + else + { Im3d::DrawSphereFilled(Im3d::Vec3(0.0f), sphereRadius, detail); } break; } case Shape_AlignedBox: - case Shape_AlignedBoxFilled: { + case Shape_AlignedBoxFilled: + { static Im3d::Vec3 boxSize(1.0f); ImGui::SliderFloat3("Size", boxSize, 0.0f, 10.0f); - if (currentShape == Shape_AlignedBox) { + if (currentShape == Shape_AlignedBox) + { Im3d::DrawAlignedBox(-boxSize, boxSize); - } else { + } + else + { Im3d::DrawAlignedBoxFilled(-boxSize, boxSize); } break; } - case Shape_Cylinder: { + case Shape_Cylinder: + { static float cylinderRadius = 1.0f; static float cylinderLength = 1.0f; ImGui::SliderFloat("Radius", &cylinderRadius, 0.0f, 10.0f); @@ -297,7 +339,8 @@ int main(int, char**) Im3d::DrawCylinder(Im3d::Vec3(0.0f, -cylinderLength, 0.0f), Im3d::Vec3(0.0f, cylinderLength, 0.0f), cylinderRadius, detail); break; } - case Shape_Capsule: { + case Shape_Capsule: + { static float capsuleRadius = 0.5f; static float capsuleLength = 1.0f; ImGui::SliderFloat("Radius", &capsuleRadius, 0.0f, 10.0f); @@ -306,7 +349,8 @@ int main(int, char**) Im3d::DrawCapsule(Im3d::Vec3(0.0f, -capsuleLength, 0.0f), Im3d::Vec3(0.0f, capsuleLength, 0.0f), capsuleRadius, detail); break; } - case Shape_Prism: { + case Shape_Prism: + { static float prismRadius = 1.0f; static float prismLength = 1.0f; static int prismSides = 3; @@ -316,7 +360,8 @@ int main(int, char**) Im3d::DrawPrism(Im3d::Vec3(0.0f, -prismLength, 0.0f), Im3d::Vec3(0.0f, prismLength, 0.0f), prismRadius, prismSides); break; } - case Shape_Arrow: { + case Shape_Arrow: + { static float arrowLength = 1.0f; static float headLength = -1.0f; static float headThickness = -1.0f; @@ -337,7 +382,8 @@ int main(int, char**) } - if (ImGui::TreeNode("Basic Perf")) { + if (ImGui::TreeNode("Basic Perf")) + { // Simple perf test: draw a large number of points, enable/disable sorting and the use of the matrix stack. static bool enableSorting = false; static bool useMatrix = false; // if the matrix stack size == 1 Im3d assumes it's the identity matrix and skips the matrix mul as an optimisation @@ -348,17 +394,22 @@ int main(int, char**) Im3d::PushEnableSorting(enableSorting); Im3d::BeginPoints(); - if (useMatrix) { + if (useMatrix) + { Im3d::PushMatrix(); - for (int i = 0; i < primCount; ++i) { + for (int i = 0; i < primCount; ++i) + { Im3d::Mat4 wm(1.0f); wm.setTranslation(Im3d::RandVec3(-10.0f, 10.0f)); Im3d::SetMatrix(wm); Im3d::Vertex(Im3d::Vec3(0.0f), Im3d::RandFloat(2.0f, 16.0f), Im3d::RandColor(0.0f, 1.0f)); } Im3d::PopMatrix(); - } else { - for (int i = 0; i < primCount; ++i) { + } + else + { + for (int i = 0; i < primCount; ++i) + { Im3d::Vec3 t = Im3d::RandVec3(-10.0f, 10.0f); Im3d::Vertex(t, Im3d::RandFloat(2.0f, 16.0f), Im3d::RandColor(0.0f, 1.0f)); } @@ -370,7 +421,8 @@ int main(int, char**) } - if (ImGui::TreeNode("Sorting")) { + if (ImGui::TreeNode("Sorting")) + { // If sorting is enabled, primitives are sorted back-to-front for rendering. Lines/triangles use the primitive midpoint, so very long // lines or large triangles may not sort correctly. static bool enableSorting = true; @@ -381,7 +433,8 @@ int main(int, char**) Im3d::PushDrawState(); Im3d::EnableSorting(enableSorting); Im3d::SetAlpha(0.9f); - for (int i = 0; i < primCount / 3; ++i) { + for (int i = 0; i < primCount / 3; ++i) + { Im3d::PushMatrix(); Im3d::Mat4 wm(1.0f); wm.setRotation(Im3d::Rotation(Im3d::Normalize(Im3d::RandVec3(-1.0f, 1.0f)), Im3d::RandFloat(0.0f, 6.0f))); @@ -397,7 +450,8 @@ int main(int, char**) Im3d::SetAlpha(0.9f); Im3d::SetSize(2.5f); - for (int i = 0; i < primCount / 3 / 3; ++i) { + for (int i = 0; i < primCount / 3 / 3; ++i) + { Im3d::PushMatrix(); Im3d::Mat4 wm(1.0f); wm.setRotation(Im3d::Rotation(Im3d::Normalize(Im3d::RandVec3(-1.0f, 1.0f)), Im3d::RandFloat(0.0f, 6.0f))); @@ -413,7 +467,8 @@ int main(int, char**) Im3d::SetAlpha(0.9f); Im3d::SetSize(16.0f); - for (int i = 0; i < primCount / 3; ++i) { + for (int i = 0; i < primCount / 3; ++i) + { Im3d::PushMatrix(); Im3d::Mat4 wm(1.0f); wm.setTranslation(Im3d::RandVec3(-10.0f, 10.0f)); @@ -428,7 +483,8 @@ int main(int, char**) ImGui::TreePop(); } - if (ImGui::TreeNode("Layers")) { + if (ImGui::TreeNode("Layers")) + { // Layers allow primitives to be grouped by the application. Each layer results in a separate call to the draw callback, which gives the // application opportunity to modify the rendering on a per-layer basis (e.g. to enable depth testing). Layers can also be used to // achieve some coarse-grained sorting, as below: @@ -457,18 +513,21 @@ int main(int, char**) ImGui::SetNextTreeNodeOpen(true, ImGuiSetCond_Once); - if (ImGui::TreeNode("Grid")) { + if (ImGui::TreeNode("Grid")) + { static int gridSize = 20; ImGui::SliderInt("Grid Size", &gridSize, 1, 50); const float gridHalf = (float)gridSize * 0.5f; Im3d::SetAlpha(1.0f); Im3d::SetSize(1.0f); Im3d::BeginLines(); - for (int x = 0; x <= gridSize; ++x) { + for (int x = 0; x <= gridSize; ++x) + { Im3d::Vertex(-gridHalf, 0.0f, (float)x - gridHalf, Im3d::Color(0.0f, 0.0f, 0.0f)); Im3d::Vertex( gridHalf, 0.0f, (float)x - gridHalf, Im3d::Color(1.0f, 0.0f, 0.0f)); } - for (int z = 0; z <= gridSize; ++z) { + for (int z = 0; z <= gridSize; ++z) + { Im3d::Vertex((float)z - gridHalf, 0.0f, -gridHalf, Im3d::Color(0.0f, 0.0f, 0.0f)); Im3d::Vertex((float)z - gridHalf, 0.0f, gridHalf, Im3d::Color(0.0f, 0.0f, 1.0f)); } @@ -477,7 +536,8 @@ int main(int, char**) ImGui::TreePop(); } - if (ImGui::TreeNode("Camera")) { + if (ImGui::TreeNode("Camera")) + { ImGui::Checkbox("Ortho", &example.m_camOrtho); ImGui::TreePop(); diff --git a/im3d.cpp b/im3d.cpp index 4a7d23e..ea280a4 100644 --- a/im3d.cpp +++ b/im3d.cpp @@ -219,20 +219,23 @@ void Im3d::DrawCircle(const Vec3& _origin, const Vec3& _normal, float _radius, i { Context& ctx = GetContext(); #if IM3D_CULL_PRIMITIVES - if (!ctx.isVisible(_origin, _radius)) { + if (!ctx.isVisible(_origin, _radius)) + { return; } #endif - if (_detail < 0) { + if (_detail < 0) + { _detail = ctx.estimateLevelOfDetail(_origin, _radius, 8, 48); } _detail = Max(_detail, 3); ctx.pushMatrix(ctx.getMatrix() * LookAt(_origin, _origin + _normal, ctx.getAppData().m_worldUp)); ctx.begin(PrimitiveMode_LineLoop); - for (int i = 0; i < _detail; ++i) { + for (int i = 0; i < _detail; ++i) + { float rad = TwoPi * ((float)i / (float)_detail); ctx.vertex(Vec3(cosf(rad) * _radius, sinf(rad) * _radius, 0.0f)); } @@ -243,12 +246,14 @@ void Im3d::DrawCircleFilled(const Vec3& _origin, const Vec3& _normal, float _rad { Context& ctx = GetContext(); #if IM3D_CULL_PRIMITIVES - if (!ctx.isVisible(_origin, _radius)) { + if (!ctx.isVisible(_origin, _radius)) + { return; } #endif - if (_detail < 0) { + if (_detail < 0) + { _detail = ctx.estimateLevelOfDetail(_origin, _radius, 8, 64); } _detail = Max(_detail, 3); @@ -257,7 +262,8 @@ void Im3d::DrawCircleFilled(const Vec3& _origin, const Vec3& _normal, float _rad ctx.begin(PrimitiveMode_Triangles); float cp = _radius; float sp = 0.0f; - for (int i = 1; i <= _detail; ++i) { + for (int i = 1; i <= _detail; ++i) + { ctx.vertex(Vec3(0.0f, 0.0f, 0.0f)); ctx.vertex(Vec3(cp, sp, 0.0f)); float rad = TwoPi * ((float)i / (float)_detail); @@ -274,33 +280,38 @@ void Im3d::DrawSphere(const Vec3& _origin, float _radius, int _detail) { Context& ctx = GetContext(); #if IM3D_CULL_PRIMITIVES - if (!ctx.isVisible(_origin, _radius)) { + if (!ctx.isVisible(_origin, _radius)) + { return; } #endif - if (_detail < 0) { + if (_detail < 0) + { _detail = ctx.estimateLevelOfDetail(_origin, _radius, 8, 48); } _detail = Max(_detail, 3); // xy circle ctx.begin(PrimitiveMode_LineLoop); - for (int i = 0; i < _detail; ++i) { + for (int i = 0; i < _detail; ++i) + { float rad = TwoPi * ((float)i / (float)_detail); ctx.vertex(Vec3(cosf(rad) * _radius + _origin.x, sinf(rad) * _radius + _origin.y, 0.0f + _origin.z)); } ctx.end(); // xz circle ctx.begin(PrimitiveMode_LineLoop); - for (int i = 0; i < _detail; ++i) { + for (int i = 0; i < _detail; ++i) + { float rad = TwoPi * ((float)i / (float)_detail); ctx.vertex(Vec3(cosf(rad) * _radius + _origin.x, 0.0f + _origin.y, sinf(rad) * _radius + _origin.z)); } ctx.end(); // yz circle ctx.begin(PrimitiveMode_LineLoop); - for (int i = 0; i < _detail; ++i) { + for (int i = 0; i < _detail; ++i) + { float rad = TwoPi * ((float)i / (float)_detail); ctx.vertex(Vec3(0.0f + _origin.x, cosf(rad) * _radius + _origin.y, sinf(rad) * _radius + _origin.z)); } @@ -310,12 +321,14 @@ void Im3d::DrawSphereFilled(const Vec3& _origin, float _radius, int _detail) { Context& ctx = GetContext(); #if IM3D_CULL_PRIMITIVES - if (!ctx.isVisible(_origin, _radius)) { + if (!ctx.isVisible(_origin, _radius)) + { return; } #endif - if (_detail < 0) { + if (_detail < 0) + { _detail = ctx.estimateLevelOfDetail(_origin, _radius, 12, 32); } _detail = Max(_detail, 6); @@ -323,14 +336,16 @@ void Im3d::DrawSphereFilled(const Vec3& _origin, float _radius, int _detail) ctx.begin(PrimitiveMode_Triangles); float yp = -_radius; float rp = 0.0f; - for (int i = 1; i <= _detail / 2; ++i) { + for (int i = 1; i <= _detail / 2; ++i) + { float y = ((float)i / (float)(_detail / 2)) * 2.0f - 1.0f; float r = cosf(y * HalfPi) * _radius; y = sinf(y * HalfPi) * _radius; float xp = 1.0f; float zp = 0.0f; - for (int j = 1; j <= _detail; ++j) { + for (int j = 1; j <= _detail; ++j) + { float x = ((float)j / (float)(_detail)) * TwoPi; float z = sinf(x); x = cosf(x); @@ -356,7 +371,8 @@ void Im3d::DrawAlignedBox(const Vec3& _min, const Vec3& _max) { Context& ctx = GetContext(); #if IM3D_CULL_PRIMITIVES - if (!ctx.isVisible(_min, _max)) { + if (!ctx.isVisible(_min, _max)) + { return; } #endif @@ -387,7 +403,8 @@ void Im3d::DrawAlignedBoxFilled(const Vec3& _min, const Vec3& _max) { Context& ctx = GetContext(); #if IM3D_CULL_PRIMITIVES - if (!ctx.isVisible(_min, _max)) { + if (!ctx.isVisible(_min, _max)) + { return; } #endif @@ -441,13 +458,15 @@ void Im3d::DrawCylinder(const Vec3& _start, const Vec3& _end, float _radius, int { Context& ctx = GetContext(); #if IM3D_CULL_PRIMITIVES - if (!ctx.isVisible((_start + _end) * 0.5f, Max(Length2(_start - _end), _radius))) { + if (!ctx.isVisible((_start + _end) * 0.5f, Max(Length2(_start - _end), _radius))) + { return; } #endif Vec3 org = _start + (_end - _start) * 0.5f; - if (_detail < 0) { + if (_detail < 0) + { _detail = ctx.estimateLevelOfDetail(org, _radius, 16, 24); } _detail = Max(_detail, 3); @@ -455,19 +474,22 @@ void Im3d::DrawCylinder(const Vec3& _start, const Vec3& _end, float _radius, int float ln = Length(_end - _start) * 0.5f; ctx.pushMatrix(ctx.getMatrix() * LookAt(org, _end, ctx.getAppData().m_worldUp)); ctx.begin(PrimitiveMode_LineLoop); - for (int i = 0; i <= _detail; ++i) { + for (int i = 0; i <= _detail; ++i) + { float rad = TwoPi * ((float)i / (float)_detail) - HalfPi; ctx.vertex(Vec3(0.0f, 0.0f, -ln) + Vec3(cosf(rad), sinf(rad), 0.0f) * _radius); } ctx.end(); ctx.begin(PrimitiveMode_LineLoop); - for (int i = 0; i <= _detail; ++i) { + for (int i = 0; i <= _detail; ++i) + { float rad = TwoPi * ((float)i / (float)_detail) - HalfPi; ctx.vertex(Vec3(0.0f, 0.0f, ln) + Vec3(cosf(rad), sinf(rad), 0.0f) * _radius); } ctx.end(); ctx.begin(PrimitiveMode_Lines); - for (int i = 0; i <= 6; ++i) { + for (int i = 0; i <= 6; ++i) + { float rad = TwoPi * ((float)i / 6.0f) - HalfPi; ctx.vertex(Vec3(0.0f, 0.0f, -ln) + Vec3(cosf(rad), sinf(rad), 0.0f) * _radius); ctx.vertex(Vec3(0.0f, 0.0f, ln) + Vec3(cosf(rad), sinf(rad), 0.0f) * _radius); @@ -479,13 +501,15 @@ void Im3d::DrawCapsule(const Vec3& _start, const Vec3& _end, float _radius, int { Context& ctx = GetContext(); #if IM3D_CULL_PRIMITIVES - if (!ctx.isVisible((_start + _end) * 0.5f, Max(Length2(_start - _end), _radius))) { + if (!ctx.isVisible((_start + _end) * 0.5f, Max(Length2(_start - _end), _radius))) + { return; } #endif Vec3 org = _start + (_end - _start) * 0.5f; - if (_detail < 0) { + if (_detail < 0) + { _detail = ctx.estimateLevelOfDetail(org, _radius, 6, 24); } _detail = Max(_detail, 3); @@ -495,30 +519,36 @@ void Im3d::DrawCapsule(const Vec3& _start, const Vec3& _end, float _radius, int ctx.pushMatrix(ctx.getMatrix() * LookAt(org, _end, ctx.getAppData().m_worldUp)); ctx.begin(PrimitiveMode_LineLoop); // yz silhoette + cap bases - for (int i = 0; i <= detail2; ++i) { + for (int i = 0; i <= detail2; ++i) + { float rad = TwoPi * ((float)i / (float)detail2) - HalfPi; ctx.vertex(Vec3(0.0f, 0.0f, -ln) + Vec3(cosf(rad), sinf(rad), 0.0f) * _radius); } - for (int i = 0; i < _detail; ++i) { + for (int i = 0; i < _detail; ++i) + { float rad = Pi * ((float)i / (float)_detail) + Pi; ctx.vertex(Vec3(0.0f, 0.0f, -ln) + Vec3(0.0f, cosf(rad), sinf(rad)) * _radius); } - for (int i = 0; i < _detail; ++i) { + for (int i = 0; i < _detail; ++i) + { float rad = Pi * ((float)i / (float)_detail); ctx.vertex(Vec3(0.0f, 0.0f, ln) + Vec3(0.0f, cosf(rad), sinf(rad)) * _radius); } - for (int i = 0; i <= detail2; ++i) { + for (int i = 0; i <= detail2; ++i) + { float rad = TwoPi * ((float)i / (float)detail2) - HalfPi; ctx.vertex(Vec3(0.0f, 0.0f, ln) + Vec3(cosf(rad), sinf(rad), 0.0f) * _radius); } ctx.end(); ctx.begin(PrimitiveMode_LineLoop); // xz silhoette - for (int i = 0; i < _detail; ++i) { + for (int i = 0; i < _detail; ++i) + { float rad = Pi * ((float)i / (float)_detail) + Pi; ctx.vertex(Vec3(0.0f, 0.0f, -ln) + Vec3(cosf(rad), 0.0f, sinf(rad)) * _radius); } - for (int i = 0; i < _detail; ++i) { + for (int i = 0; i < _detail; ++i) + { float rad = Pi * ((float)i / (float)_detail); ctx.vertex(Vec3(0.0f, 0.0f, ln) + Vec3(cosf(rad), 0.0f, sinf(rad)) * _radius); } @@ -530,7 +560,8 @@ void Im3d::DrawPrism(const Vec3& _start, const Vec3& _end, float _radius, int _s _sides = Max(_sides, 2); Context& ctx = GetContext(); #if IM3D_CULL_PRIMITIVES - if (!ctx.isVisible((_start + _end) * 0.5f, Max(Length2(_start - _end), _radius))) { + if (!ctx.isVisible((_start + _end) * 0.5f, Max(Length2(_start - _end), _radius))) + { return; } #endif @@ -539,17 +570,20 @@ void Im3d::DrawPrism(const Vec3& _start, const Vec3& _end, float _radius, int _s float ln = Length(_end - _start) * 0.5f; ctx.pushMatrix(ctx.getMatrix() * LookAt(org, _end, ctx.getAppData().m_worldUp)); ctx.begin(PrimitiveMode_LineLoop); - for (int i = 0; i <= _sides; ++i) { + for (int i = 0; i <= _sides; ++i) + { float rad = TwoPi * ((float)i / (float)_sides) - HalfPi; ctx.vertex(Vec3(0.0f, 0.0f, -ln) + Vec3(cosf(rad), sinf(rad), 0.0f) * _radius); } - for (int i = 0; i <= _sides; ++i) { + for (int i = 0; i <= _sides; ++i) + { float rad = TwoPi * ((float)i / (float)_sides) - HalfPi; ctx.vertex(Vec3(0.0f, 0.0f, ln) + Vec3(cosf(rad), sinf(rad), 0.0f) * _radius); } ctx.end(); ctx.begin(PrimitiveMode_Lines); - for (int i = 0; i <= _sides; ++i) { + for (int i = 0; i <= _sides; ++i) + { float rad = TwoPi * ((float)i / (float)_sides) - HalfPi; ctx.vertex(Vec3(0.0f, 0.0f, -ln) + Vec3(cosf(rad), sinf(rad), 0.0f) * _radius); ctx.vertex(Vec3(0.0f, 0.0f, ln) + Vec3(cosf(rad), sinf(rad), 0.0f) * _radius); @@ -561,13 +595,15 @@ void Im3d::DrawArrow(const Vec3& _start, const Vec3& _end, float _headLength, fl { Context& ctx = GetContext(); - if (_headThickness < 0.0f) { + if (_headThickness < 0.0f) + { _headThickness = ctx.getSize() * 2.0f; } Vec3 dir = _end - _start; float dirlen = Length(dir); - if (_headLength < 0.0f) { + if (_headLength < 0.0f) + { _headLength = Min(dirlen / 2.0f, ctx.pixelsToWorldSize(_end, _headThickness * 2.0f)); } dir = dir / dirlen; @@ -604,7 +640,8 @@ static U32 Hash(const char* _buf, int _buflen, U32 _base) { U32 ret = _base; const char* lim = _buf + _buflen; - while (_buf < lim) { + while (_buf < lim) + { ret ^= (U32)*_buf++; ret *= kFnv1aPrime32; } @@ -613,7 +650,8 @@ static U32 Hash(const char* _buf, int _buflen, U32 _base) static U32 HashStr(const char* _str, U32 _base) { U32 ret = _base; - while (*_str) { + while (*_str) + { ret ^= (U32)*_str++; ret *= kFnv1aPrime32; } @@ -632,10 +670,10 @@ Im3d::Id Im3d::MakeId(int _i) return Hash((const char*)&_i, sizeof(int), GetContext().getId()); } - inline static float Snap(float _val, float _snap) { - if (_snap > 0.0f) { + if (_snap > 0.0f) + { return floorf(_val / _snap) * _snap; } return _val; @@ -643,7 +681,8 @@ inline static float Snap(float _val, float _snap) inline static Vec3 Snap(const Vec3& _val, float _snap) { - if (_snap > 0.0f) { + if (_snap > 0.0f) + { return Vec3(floorf(_val.x / _snap) * _snap, floorf(_val.y / _snap) * _snap, floorf(_val.z / _snap) * _snap); } return _val; @@ -651,7 +690,8 @@ inline static Vec3 Snap(const Vec3& _val, float _snap) inline static Vec3 Snap(const Vec3& _pos, const Plane& _plane, float _snap) { - if (_snap > 0.0f) { + if (_snap > 0.0f) + { // get basis vectors on the plane Mat3 basis = AlignZ(_plane.m_normal); Vec3 i = basis.getCol(0); @@ -665,7 +705,8 @@ inline static Vec3 Snap(const Vec3& _pos, const Plane& _plane, float _snap) float ilen = Length(i); float jlen = Length(j); - if (ilen < 1e-7f || jlen < 1e-7f) { // \hack prevent DBZ when _pos is 0 + if (ilen < 1e-7f || jlen < 1e-7f) // \hack prevent DBZ when _pos is 0 + { return _pos; } @@ -691,7 +732,8 @@ bool Im3d::GizmoTranslation(Id _id, float _translation_[3], bool _local) float worldHeight = ctx.pixelsToWorldSize(drawAt, ctx.m_gizmoHeightPixels); #if IM3D_CULL_GIZMOS - if (!ctx.isVisible(drawAt, worldHeight)) { + if (!ctx.isVisible(drawAt, worldHeight)) + { return false; } #endif @@ -699,7 +741,8 @@ bool Im3d::GizmoTranslation(Id _id, float _translation_[3], bool _local) ctx.pushId(_id); ctx.m_appId = _id; - if (_local) { + if (_local) + { Mat4 localMatrix = ctx.getMatrix(); localMatrix.setScale(Vec3(1.0f)); ctx.pushMatrix(localMatrix); @@ -710,26 +753,32 @@ bool Im3d::GizmoTranslation(Id _id, float _translation_[3], bool _local) float worldSize = ctx.pixelsToWorldSize(drawAt, ctx.m_gizmoSizePixels); struct AxisG { Id m_id; Vec3 m_axis; Color m_color; }; - AxisG axes[] = { - { MakeId("axisX"), Vec3(1.0f, 0.0f, 0.0f), Color_Red }, - { MakeId("axisY"), Vec3(0.0f, 1.0f, 0.0f), Color_Green }, - { MakeId("axisZ"), Vec3(0.0f, 0.0f, 1.0f), Color_Blue } - }; + AxisG axes[] = + { + { MakeId("axisX"), Vec3(1.0f, 0.0f, 0.0f), Color_Red }, + { MakeId("axisY"), Vec3(0.0f, 1.0f, 0.0f), Color_Green }, + { MakeId("axisZ"), Vec3(0.0f, 0.0f, 1.0f), Color_Blue } + }; struct PlaneG { Id m_id; Vec3 m_origin; }; - PlaneG planes[] = { - { MakeId("planeYZ"), Vec3(0.0f, planeOffset, planeOffset) }, - { MakeId("planeXZ"), Vec3(planeOffset, 0.0f, planeOffset) }, - { MakeId("planeXY"), Vec3(planeOffset, planeOffset, 0.0f) }, - { MakeId("planeV"), Vec3(0.0f, 0.0f, 0.0f) } - }; + + PlaneG planes[] = + { + { MakeId("planeYZ"), Vec3(0.0f, planeOffset, planeOffset) }, + { MakeId("planeXZ"), Vec3(planeOffset, 0.0f, planeOffset) }, + { MakeId("planeXY"), Vec3(planeOffset, planeOffset, 0.0f) }, + { MakeId("planeV"), Vec3(0.0f, 0.0f, 0.0f) } + }; // invert axes if viewing from behind const AppData& appData = ctx.getAppData(); /*Vec3 viewDir = appData.m_viewOrigin - *outVec3; - for (int i = 0; i < 3; ++i) { - if (Dot(axes[i].m_axis, viewDir) < 0.0f) { + for (int i = 0; i < 3; ++i) + { + if (Dot(axes[i].m_axis, viewDir) < 0.0f) + { axes[i].m_axis = -axes[i].m_axis; - for (int j = 0; j < 3; ++j) { + for (int j = 0; j < 3; ++j) + { planes[j].m_origin[i] = -planes[j].m_origin[i]; } } @@ -741,23 +790,30 @@ bool Im3d::GizmoTranslation(Id _id, float _translation_[3], bool _local) // planes ctx.pushEnableSorting(true); - if (_local) { + if (_local) + { // local planes need to be drawn with the pushed matrix for correct orientation - for (int i = 0; i < 3; ++i) { + for (int i = 0; i < 3; ++i) + { const PlaneG& plane = planes[i]; ctx.gizmoPlaneTranslation_Draw(plane.m_id, plane.m_origin, axes[i].m_axis, planeSize, Color_GizmoHighlight); axes[i].m_axis = Normalize(Vec3(ctx.getMatrix().getCol(i))); // if local, extract axes from the pushed matrix - if (intersects) { + if (intersects) + { ret |= ctx.gizmoPlaneTranslation_Behavior(plane.m_id, ctx.getMatrix() * plane.m_origin, axes[i].m_axis, appData.m_snapTranslation, planeSize, outVec3); } } - } else { + } + else + { ctx.pushMatrix(Mat4(1.0f)); - for (int i = 0; i < 3; ++i) { + for (int i = 0; i < 3; ++i) + { const PlaneG& plane = planes[i]; ctx.gizmoPlaneTranslation_Draw(plane.m_id, drawAt + plane.m_origin, axes[i].m_axis, planeSize, Color_GizmoHighlight); - if (intersects) { + if (intersects) + { ret |= ctx.gizmoPlaneTranslation_Behavior(plane.m_id, drawAt + plane.m_origin, axes[i].m_axis, appData.m_snapTranslation, planeSize, outVec3); } } @@ -766,30 +822,42 @@ bool Im3d::GizmoTranslation(Id _id, float _translation_[3], bool _local) ctx.pushMatrix(Mat4(1.0f)); - if (intersects) { + if (intersects) + { // view plane (store the normal when the gizmo becomes active) Id currentId = ctx.m_activeId; Vec3& storedViewNormal= *((Vec3*)ctx.m_gizmoStateMat3.m); Vec3 viewNormal; - if (planes[3].m_id == ctx.m_activeId) { + if (planes[3].m_id == ctx.m_activeId) + { viewNormal = storedViewNormal; - } else { + } + else + { viewNormal = ctx.getAppData().m_viewDirection; } ret |= ctx.gizmoPlaneTranslation_Behavior(planes[3].m_id, drawAt, viewNormal, appData.m_snapTranslation, worldSize, outVec3); - if (currentId != ctx.m_activeId) { + if (currentId != ctx.m_activeId) + { // gizmo became active, store the view normal storedViewNormal = viewNormal; } // highlight axes if the corresponding plane is hot - if (planes[0].m_id == ctx.m_hotId) { // YZ + if (planes[0].m_id == ctx.m_hotId) // YZ + { axes[1].m_color = axes[2].m_color = Color_GizmoHighlight; - } else if (planes[1].m_id == ctx.m_hotId) { // XZ + } + else if (planes[1].m_id == ctx.m_hotId) // XZ + { axes[0].m_color = axes[2].m_color = Color_GizmoHighlight; - } else if (planes[2].m_id == ctx.m_hotId) { // XY + } + else if (planes[2].m_id == ctx.m_hotId) // XY + { axes[0].m_color = axes[1].m_color = Color_GizmoHighlight; - } else if (planes[3].m_id == ctx.m_hotId) { + } + else if (planes[3].m_id == ctx.m_hotId) // view plane + { axes[0].m_color = axes[1].m_color = axes[2].m_color = Color_GizmoHighlight; } } @@ -799,17 +867,20 @@ bool Im3d::GizmoTranslation(Id _id, float _translation_[3], bool _local) ctx.end(); // axes - for (int i = 0; i < 3; ++i) { + for (int i = 0; i < 3; ++i) + { AxisG& axis = axes[i]; ctx.gizmoAxisTranslation_Draw(axis.m_id, drawAt, axis.m_axis, worldHeight, worldSize, axis.m_color); - if (intersects) { + if (intersects) + { ret |= ctx.gizmoAxisTranslation_Behavior(axis.m_id, drawAt, axis.m_axis, appData.m_snapTranslation, worldHeight, worldSize, outVec3); } } ctx.popMatrix(); ctx.popEnableSorting(); - if (_local) { + if (_local) + { ctx.popMatrix(); } @@ -824,7 +895,8 @@ bool Im3d::GizmoRotation(Id _id, float _rotation_[3*3], bool _local) Vec3 origin = ctx.getMatrix().getTranslation(); float worldRadius = ctx.pixelsToWorldSize(origin, ctx.m_gizmoHeightPixels); #if IM3D_CULL_GIZMOS - if (!ctx.isVisible(origin, worldRadius)) { + if (!ctx.isVisible(origin, worldRadius)) + { return false; } #endif @@ -840,11 +912,12 @@ bool Im3d::GizmoRotation(Id _id, float _rotation_[3*3], bool _local) float worldSize = ctx.pixelsToWorldSize(origin, ctx.m_gizmoSizePixels); struct AxisG { Id m_id; Vec3 m_axis; Color m_color; }; - AxisG axes[] = { - { MakeId("axisX"), Vec3(1.0f, 0.0f, 0.0f), Color_Red }, - { MakeId("axisY"), Vec3(0.0f, 1.0f, 0.0f), Color_Green }, - { MakeId("axisZ"), Vec3(0.0f, 0.0f, 1.0f), Color_Blue } - }; + AxisG axes[] = + { + { MakeId("axisX"), Vec3(1.0f, 0.0f, 0.0f), Color_Red }, + { MakeId("axisY"), Vec3(0.0f, 1.0f, 0.0f), Color_Green }, + { MakeId("axisZ"), Vec3(0.0f, 0.0f, 1.0f), Color_Blue } + }; Id viewId = MakeId("axisV"); Sphere boundingSphere(origin, worldRadius); @@ -853,27 +926,36 @@ bool Im3d::GizmoRotation(Id _id, float _rotation_[3*3], bool _local) const AppData& appData = ctx.getAppData(); - if (_local) { + if (_local) + { // extract axes from the pushed matrix - for (int i = 0; i < 3; ++i) { - if (ctx.m_activeId == axes[i].m_id) { + for (int i = 0; i < 3; ++i) + { + if (ctx.m_activeId == axes[i].m_id) + { // use the stored matrix where the id is active, avoid rotating the axis frame during interaction (cause numerical instability) axes[i].m_axis = Normalize(Vec3(storedRotation.getCol(i))); - } else { + } + else + { axes[i].m_axis = Normalize(Vec3(ctx.getMatrix().getCol(i))); } } } ctx.pushMatrix(Mat4(1.0f)); - for (int i = 0; i < 3; ++i) { - if (i == 0 && (ctx.m_activeId == axes[1].m_id || ctx.m_activeId == axes[2].m_id || ctx.m_activeId == viewId)) { + for (int i = 0; i < 3; ++i) + { + if (i == 0 && (ctx.m_activeId == axes[1].m_id || ctx.m_activeId == axes[2].m_id || ctx.m_activeId == viewId)) + { continue; } - if (i == 1 && (ctx.m_activeId == axes[2].m_id || ctx.m_activeId == axes[0].m_id || ctx.m_activeId == viewId)) { + if (i == 1 && (ctx.m_activeId == axes[2].m_id || ctx.m_activeId == axes[0].m_id || ctx.m_activeId == viewId)) + { continue; } - if (i == 2 && (ctx.m_activeId == axes[0].m_id || ctx.m_activeId == axes[1].m_id || ctx.m_activeId == viewId)) { + if (i == 2 && (ctx.m_activeId == axes[0].m_id || ctx.m_activeId == axes[1].m_id || ctx.m_activeId == viewId)) + { continue; } @@ -884,10 +966,12 @@ bool Im3d::GizmoRotation(Id _id, float _rotation_[3*3], bool _local) ret = true; } } - if (!(ctx.m_activeId == axes[0].m_id || ctx.m_activeId == axes[1].m_id || ctx.m_activeId == axes[2].m_id)) { + if (!(ctx.m_activeId == axes[0].m_id || ctx.m_activeId == axes[1].m_id || ctx.m_activeId == axes[2].m_id)) + { Vec3 viewNormal = ctx.getAppData().m_viewDirection; float angle = 0.0f; - if (intersects && ctx.gizmoAxislAngle_Behavior(viewId, origin, viewNormal, appData.m_snapRotation, worldRadius, worldSize, &angle)) { + if (intersects && ctx.gizmoAxislAngle_Behavior(viewId, origin, viewNormal, appData.m_snapRotation, worldRadius, worldSize, &angle)) + { *outMat3 = Rotation(viewNormal, angle) * storedRotation; ret = true; } @@ -895,7 +979,8 @@ bool Im3d::GizmoRotation(Id _id, float _rotation_[3*3], bool _local) } ctx.popMatrix(); - if (currentId != ctx.m_activeId) { + if (currentId != ctx.m_activeId) + { // gizmo became active, store rotation matrix storedRotation = *outMat3; } @@ -909,7 +994,8 @@ bool Im3d::GizmoScale(Id _id, float _scale_[3]) Vec3 origin = ctx.getMatrix().getTranslation(); float worldHeight = ctx.pixelsToWorldSize(origin, ctx.m_gizmoHeightPixels); #if IM3D_CULL_GIZMOS - if (!ctx.isVisible(origin, worldHeight)) { + if (!ctx.isVisible(origin, worldHeight)) + { return false; } #endif @@ -925,17 +1011,20 @@ bool Im3d::GizmoScale(Id _id, float _scale_[3]) float worldSize = ctx.pixelsToWorldSize(origin, ctx.m_gizmoSizePixels); struct AxisG { Id m_id; Vec3 m_axis; Color m_color; }; - AxisG axes[] = { - { MakeId("axisX"), Normalize(ctx.getMatrix().getCol(0)), Color_Red }, - { MakeId("axisY"), Normalize(ctx.getMatrix().getCol(1)), Color_Green }, - { MakeId("axisZ"), Normalize(ctx.getMatrix().getCol(2)), Color_Blue } - }; + AxisG axes[] = + { + { MakeId("axisX"), Normalize(ctx.getMatrix().getCol(0)), Color_Red }, + { MakeId("axisY"), Normalize(ctx.getMatrix().getCol(1)), Color_Green }, + { MakeId("axisZ"), Normalize(ctx.getMatrix().getCol(2)), Color_Blue } + }; // invert axes if viewing from behind const AppData& appData = ctx.getAppData(); /*Vec3 viewDir = appData.m_viewOrigin - *outVec3; - for (int i = 0; i < 3; ++i) { - if (Dot(axes[i].m_axis, viewDir) < 0.0f) { + for (int i = 0; i < 3; ++i) + { + if (Dot(axes[i].m_axis, viewDir) < 0.0f) + { axes[i].m_axis = -axes[i].m_axis; } }*/ @@ -949,14 +1038,17 @@ bool Im3d::GizmoScale(Id _id, float _scale_[3]) { // uniform scale Id uniformId = MakeId("uniform"); - if (intersects) { + if (intersects) + { Sphere handle(origin, ctx.pixelsToWorldSize(origin, ctx.m_gizmoSizePixels * 4.0f)); float t0, t1; bool intersects = Intersect(ray, handle, t0, t1); Vec3& storedScale = ctx.m_gizmoStateVec3; Vec3& storedPosition = *((Vec3*)ctx.m_gizmoStateMat3.m); - if (uniformId == ctx.m_activeId) { - if (ctx.isKeyDown(Action_Select)) { + if (uniformId == ctx.m_activeId) + { + if (ctx.isKeyDown(Action_Select)) + { Plane plane(Normalize(origin - appData.m_viewOrigin), origin); Intersect(ray, plane, t0); Vec3 intersection = ray.m_origin + ray.m_direction * t0; @@ -965,30 +1057,42 @@ bool Im3d::GizmoScale(Id _id, float _scale_[3]) scale = Snap(scale, appData.m_snapScale); *outVec3 = storedScale * Vec3(Max(1.0f + copysignf(scale, sign), 1e-4f)); ret = true; - } else { + } + else + { ctx.makeActive(Id_Invalid); } - } else if (uniformId == ctx.m_hotId) { - if (intersects) { - if (ctx.isKeyDown(Action_Select)) { + } + else if (uniformId == ctx.m_hotId) + { + if (intersects) + { + if (ctx.isKeyDown(Action_Select)) + { ctx.makeActive(uniformId); storedScale = *outVec3; storedPosition = ray.m_origin + ray.m_direction * t0; } - } else { + } + else + { ctx.resetId(); } - } else { + } + else + { float depth = Length2(origin - appData.m_viewOrigin); ctx.makeHot(uniformId, depth, intersects); } } bool activeOrHot = ctx.m_activeId == uniformId || ctx.m_hotId == uniformId; - if (activeOrHot) { - for (int i = 0; i < 3; ++i) { + if (activeOrHot) + { + for (int i = 0; i < 3; ++i) + { axes[i].m_color = Color_GizmoHighlight; } ctx.pushColor(Color_GizmoHighlight); @@ -1006,10 +1110,12 @@ bool Im3d::GizmoScale(Id _id, float _scale_[3]) ctx.popAlpha(); } - for (int i = 0; i < 3; ++i) { + for (int i = 0; i < 3; ++i) + { AxisG& axis = axes[i]; ctx.gizmoAxisScale_Draw(axis.m_id, origin, axis.m_axis, worldHeight, worldSize, axis.m_color); - if (intersects) { + if (intersects) + { ret |= ctx.gizmoAxisScale_Behavior(axis.m_id, origin, axis.m_axis, appData.m_snapScale, worldHeight, worldSize, &(*outVec3)[i]); } } @@ -1029,26 +1135,33 @@ bool Im3d::Gizmo(Id _id, float _transform_[4*4]) ctx.pushMatrix(*outMat4); bool ret = false; - switch (ctx.m_gizmoMode) { - case GizmoMode_Translation: { + switch (ctx.m_gizmoMode) + { + case GizmoMode_Translation: + { Vec3 translation = outMat4->getTranslation(); - if (GizmoTranslation(_id, translation, ctx.m_gizmoLocal)) { + if (GizmoTranslation(_id, translation, ctx.m_gizmoLocal)) + { outMat4->setTranslation(translation); ret = true; } break; } - case GizmoMode_Rotation: { + case GizmoMode_Rotation: + { Mat3 rotation = outMat4->getRotation(); - if (GizmoRotation(_id, rotation, ctx.m_gizmoLocal)) { + if (GizmoRotation(_id, rotation, ctx.m_gizmoLocal)) + { outMat4->setRotation(rotation); ret = true; } break; } - case GizmoMode_Scale: { + case GizmoMode_Scale: + { Vec3 scale = outMat4->getScale(); - if (GizmoScale(_id, scale)) { + if (GizmoScale(_id, scale)) + { outMat4->setScale(scale); ret = true; } @@ -1075,24 +1188,31 @@ bool Im3d::Gizmo(Id _id, float _translation_[3], float _rotation_[3*3], float _s ctx.pushMatrix(transform); bool ret = false; - switch (ctx.m_gizmoMode) { + switch (ctx.m_gizmoMode) + { case GizmoMode_Translation: - if (_translation_) { - if (GizmoTranslation(_id, _translation_, ctx.m_gizmoLocal)) { + if (_translation_) + { + if (GizmoTranslation(_id, _translation_, ctx.m_gizmoLocal)) + { ret = true; } } break; case GizmoMode_Rotation: - if (_rotation_) { - if (GizmoRotation(_id, _rotation_, ctx.m_gizmoLocal)) { + if (_rotation_) + { + if (GizmoRotation(_id, _rotation_, ctx.m_gizmoLocal)) + { ret = true; } } break; case GizmoMode_Scale: - if (_scale_) { - if (GizmoScale(_id, _scale_)) { + if (_scale_) + { + if (GizmoScale(_id, _scale_)) + { ret = true; } } @@ -1133,12 +1253,15 @@ void AppData::setCullFrustum(const Mat4& _viewProj, bool _ndcZNegativeOneToOne) m_cullFrustum[FrustumPlane_Far].z = _viewProj(3, 2) - _viewProj(2, 2); m_cullFrustum[FrustumPlane_Far].w = -(_viewProj(3, 3) - _viewProj(2, 3)); - if (_ndcZNegativeOneToOne) { + if (_ndcZNegativeOneToOne) + { m_cullFrustum[FrustumPlane_Near].x = _viewProj(3, 0) + _viewProj(2, 0); m_cullFrustum[FrustumPlane_Near].y = _viewProj(3, 1) + _viewProj(2, 1); m_cullFrustum[FrustumPlane_Near].z = _viewProj(3, 2) + _viewProj(2, 2); m_cullFrustum[FrustumPlane_Near].w = -(_viewProj(3, 3) + _viewProj(2, 3)); - } else { + } + else + { m_cullFrustum[FrustumPlane_Near].x = _viewProj(2, 0); m_cullFrustum[FrustumPlane_Near].y = _viewProj(2, 1); m_cullFrustum[FrustumPlane_Near].z = _viewProj(2, 2); @@ -1146,7 +1269,8 @@ void AppData::setCullFrustum(const Mat4& _viewProj, bool _ndcZNegativeOneToOne) } // normalize - for (int i = 0; i < FrustumPlane_Count; ++i) { + for (int i = 0; i < FrustumPlane_Count; ++i) + { float d = 1.0f / Length(Vec3(m_cullFrustum[i])); m_cullFrustum[i] = m_cullFrustum[i] * d; } @@ -1164,13 +1288,16 @@ static void* AlignedMalloc(size_t _size, size_t _align) IM3D_ASSERT(_align > 0); size_t grow = (_align - 1) + sizeof(void*); size_t mem = (size_t)IM3D_MALLOC(_size + grow); - if (mem) { + if (mem) + { size_t ret = (mem + grow) & (~(_align - 1)); IM3D_ASSERT(ret % _align == 0); // aligned correctly IM3D_ASSERT(ret >= mem + sizeof(void*)); // header large enough to store a ptr *((void**)(ret - sizeof(void*))) = (void*)mem; return (void*)ret; - } else { + } + else + { return nullptr; } } @@ -1183,7 +1310,8 @@ static void AlignedFree(void* _ptr_) template Vector::~Vector() { - if (m_data) { + if (m_data) + { AlignedFree(m_data); m_data = 0; } @@ -1192,7 +1320,8 @@ Vector::~Vector() template void Vector::append(const T* _v, U32 _count) { - if (_count == 0) { + if (_count == 0) + { return; } U32 sz = m_size + _count; @@ -1205,11 +1334,13 @@ template void Vector::reserve(U32 _capacity) { _capacity = _capacity < 8 ? 8 : _capacity; - if (_capacity <= m_capacity) { + if (_capacity <= m_capacity) + { return; } T* data = (T*)AlignedMalloc(sizeof(T) * _capacity, alignof(T)); - if (m_data) { + if (m_data) + { memcpy(data, m_data, sizeof(T) * m_size); AlignedFree(m_data);; } @@ -1222,7 +1353,8 @@ void Vector::resize(U32 _size, const T& _val) { IM3D_ASSERT(_size >= m_size); // only support growing the vector reserve(_size); - while (m_size < _size) { + while (m_size < _size) + { push_back(_val); } m_size = _size; @@ -1273,7 +1405,8 @@ void Context::begin(PrimitiveMode _mode) IM3D_ASSERT(m_primMode == PrimitiveMode_None); // forgot to call End() m_primMode = _mode; m_vertCountThisPrim = 0; - switch (m_primMode) { + switch (m_primMode) + { case PrimitiveMode_Points: m_primType = DrawPrimitive_Points; break; @@ -1295,9 +1428,11 @@ void Context::begin(PrimitiveMode _mode) void Context::end() { IM3D_ASSERT(m_primMode != PrimitiveMode_None); // End() called without Begin*() - if (m_vertCountThisPrim > 0) { + if (m_vertCountThisPrim > 0) + { VertexList* vertexList = getCurrentVertexList(); - switch (m_primMode) { + switch (m_primMode) + { case PrimitiveMode_Points: break; case PrimitiveMode_Lines: @@ -1324,7 +1459,8 @@ void Context::end() // \hack force the bounds to be slightly conservative to account for point/line size m_minVertThisPrim = m_minVertThisPrim - Vec3(1.0f); m_maxVertThisPrim = m_maxVertThisPrim + Vec3(1.0f); - if (!isVisible(m_minVertThisPrim, m_maxVertThisPrim)) { + if (!isVisible(m_minVertThisPrim, m_maxVertThisPrim)) + { vertexList->resize(m_firstVertThisPrim, VertexData()); } #endif @@ -1333,7 +1469,8 @@ void Context::end() m_primType = DrawPrimitive_Count; #if IM3D_CULL_PRIMITIVES // \debug draw primitive BBs - //if (m_enableCulling) { + //if (m_enableCulling) + //{ // m_enableCulling = false; // pushColor(Im3d::Color_Magenta); // pushSize(1.0f); @@ -1352,23 +1489,28 @@ void Context::vertex(const Vec3& _position, float _size, Color _color) IM3D_ASSERT(m_primMode != PrimitiveMode_None); // Vertex() called without Begin*() VertexData vd(_position, _size, _color); - if (m_matrixStack.size() > 1) { // optim, skip the matrix multiplication when the stack size is 1 + if (m_matrixStack.size() > 1) // optim, skip the matrix multiplication when the stack size is 1 + { vd.m_positionSize = Vec4(m_matrixStack.back() * _position, _size); } vd.m_color.setA(vd.m_color.getA() * m_alphaStack.back()); #if IM3D_CULL_PRIMITIVES Vec3 p = Vec3(vd.m_positionSize); - if (m_vertCountThisPrim == 0) { // p is the first vertex + if (m_vertCountThisPrim == 0) // p is the first vertex + { m_minVertThisPrim = m_maxVertThisPrim = p; - } else { + } + else + { m_minVertThisPrim = Min(m_minVertThisPrim, p); m_maxVertThisPrim = Max(m_maxVertThisPrim, p); } #endif VertexList* vertexList = getCurrentVertexList(); - switch (m_primMode) { + switch (m_primMode) + { case PrimitiveMode_Points: case PrimitiveMode_Lines: case PrimitiveMode_Triangles: @@ -1376,14 +1518,16 @@ void Context::vertex(const Vec3& _position, float _size, Color _color) break; case PrimitiveMode_LineStrip: case PrimitiveMode_LineLoop: - if (m_vertCountThisPrim >= 2) { + if (m_vertCountThisPrim >= 2) + { vertexList->push_back(vertexList->back()); ++m_vertCountThisPrim; } vertexList->push_back(vd); break; case PrimitiveMode_TriangleStrip: - if (m_vertCountThisPrim >= 3) { + if (m_vertCountThisPrim >= 3) + { vertexList->push_back(*(vertexList->end() - 2)); vertexList->push_back(*(vertexList->end() - 2)); m_vertCountThisPrim += 2; @@ -1399,9 +1543,11 @@ void Context::vertex(const Vec3& _position, float _size, Color _color) // per-vertex primitive culling; this method is generally too expensive to be practical (and can't cull line loops). // check if the primitive was visible and rewind vertex data if not - switch (m_primMode) { + switch (m_primMode) + { case PrimitiveMode_Points: - if (!isVisible(&vertexList->back(), DrawPrimitive_Points)) { + if (!isVisible(&vertexList->back(), DrawPrimitive_Points)) + { vertexList->pop_back(); --m_vertCountThisPrim; } @@ -1410,9 +1556,12 @@ void Context::vertex(const Vec3& _position, float _size, Color _color) break; // can't cull line loops; end() may add an invalid line if any vertices are culled case PrimitiveMode_Lines: case PrimitiveMode_LineStrip: - if (m_vertCountThisPrim % 2 == 0) { - if (!isVisible(&vertexList->back() - 1, DrawPrimitive_Lines)) { - for (int i = 0; i < 2; ++i) { + if (m_vertCountThisPrim % 2 == 0) + { + if (!isVisible(&vertexList->back() - 1, DrawPrimitive_Lines)) + { + for (int i = 0; i < 2; ++i) + { vertexList->pop_back(); --m_vertCountThisPrim; } @@ -1421,9 +1570,12 @@ void Context::vertex(const Vec3& _position, float _size, Color _color) break; case PrimitiveMode_Triangles: case PrimitiveMode_TriangleStrip: - if (m_vertCountThisPrim % 3 == 0) { - if (!isVisible(&vertexList->back() - 2, DrawPrimitive_Triangles)) { - for (int i = 0; i < 3; ++i) { + if (m_vertCountThisPrim % 3 == 0) + { + if (!isVisible(&vertexList->back() - 2, DrawPrimitive_Triangles)) + { + for (int i = 0; i < 3; ++i) + { vertexList->pop_back(); --m_vertCountThisPrim; } @@ -1440,7 +1592,8 @@ void Context::text(const Vec3& _position, float _size, Color _color, TextFlags _ { TextData& td = getCurrentTextList()->push_back(); td.m_positionSize = Vec4(_position, _size); - if (m_matrixStack.size() > 1) { // optim, skip the matrix multiplication when the stack size is 1 + if (m_matrixStack.size() > 1) // optim, skip the matrix multiplication when the stack size is 1 + { td.m_positionSize = Vec4(m_matrixStack.back() * _position, _size); } td.m_color = _color; @@ -1460,7 +1613,8 @@ void Context::text(const Vec3& _position, float _size, Color _color, TextFlags _ { TextData& td = getCurrentTextList()->push_back(); td.m_positionSize = Vec4(_position, _size); - if (m_matrixStack.size() > 1) { // optim, skip the matrix multiplication when the stack size is 1 + if (m_matrixStack.size() > 1) // optim, skip the matrix multiplication when the stack size is 1 + { td.m_positionSize = Vec4(m_matrixStack.back() * _position, _size); } td.m_color = _color; @@ -1495,12 +1649,14 @@ void Context::reset() m_primType = DrawPrimitive_Count; IM3D_ASSERT(m_vertexData[0].size() == m_vertexData[1].size()); - for (U32 i = 0; i < m_vertexData[0].size(); ++i) { + for (U32 i = 0; i < m_vertexData[0].size(); ++i) + { m_vertexData[0][i]->clear(); m_vertexData[1][i]->clear(); } m_drawLists.clear(); - for (U32 i = 0; i < m_textData.size(); ++i) { + for (U32 i = 0; i < m_textData.size(); ++i) + { m_textData[i]->clear(); } m_textDrawLists.clear(); @@ -1517,29 +1673,38 @@ void Context::reset() // process cull frustum m_cullFrustumCount = 0; - for (int i = 0; i < FrustumPlane_Count; ++i) { + for (int i = 0; i < FrustumPlane_Count; ++i) + { const Vec4& plane = m_appData.m_cullFrustum[i]; - if (m_appData.m_projOrtho && i == FrustumPlane_Near) { // skip near plane if perspective + if (m_appData.m_projOrtho && i == FrustumPlane_Near) // skip near plane if perspective + { continue; } - if (std::isinf(plane.w)) { // may be the case e.g. for the far plane if projection is infinite + if (std::isinf(plane.w)) // may be the case e.g. for the far plane if projection is infinite + { continue; } m_cullFrustum[m_cullFrustumCount++] = plane; } // update gizmo modes - if (wasKeyPressed(Action_GizmoTranslation)) { + if (wasKeyPressed(Action_GizmoTranslation)) + { m_gizmoMode = GizmoMode_Translation; resetId(); - } else if (wasKeyPressed(Action_GizmoRotation)) { + } + else if (wasKeyPressed(Action_GizmoRotation)) + { m_gizmoMode = GizmoMode_Rotation; resetId(); - } else if (wasKeyPressed(Action_GizmoScale)) { + } + else if (wasKeyPressed(Action_GizmoScale)) + { m_gizmoMode = GizmoMode_Scale; resetId(); } - if (wasKeyPressed(Action_GizmoLocal)) { + if (wasKeyPressed(Action_GizmoLocal)) + { m_gizmoLocal = !m_gizmoLocal; resetId(); } @@ -1550,15 +1715,18 @@ void Context::merge(const Context& _src) IM3D_ASSERT(!m_endFrameCalled && !_src.m_endFrameCalled); // call MergeContexts() before calling EndFrame() // layer IDs - for (Id id : _src.m_layerIdMap) { + for (Id id : _src.m_layerIdMap) + { pushLayerId(id); // add a new layer if id doesn't alrady exist popLayerId(); } // vertex data - for (U32 i = 0; i < 2; ++i) { + for (U32 i = 0; i < 2; ++i) + { const auto& vertexData = _src.m_vertexData[i]; - for (U32 j = 0; j < vertexData.size(); ++j) { + for (U32 j = 0; j < vertexData.size(); ++j) + { // for each layer in _src, find the matching layer in this const Id layerId = _src.m_layerIdMap[j / DrawPrimitive_Count]; const int layerIndex = findLayerIndex(layerId); @@ -1569,7 +1737,8 @@ void Context::merge(const Context& _src) } // text data - for (U32 i = 0; i < _src.m_textData.size(); ++i) { + for (U32 i = 0; i < _src.m_textData.size(); ++i) + { const Id layerId = _src.m_layerIdMap[i]; const int layerIndex = findLayerIndex(layerId); IM3D_ASSERT(layerIndex >= 0); @@ -1577,7 +1746,8 @@ void Context::merge(const Context& _src) const U32 textBufferOffset = m_textBuffer.size(); m_textBuffer.append(_src.m_textBuffer); const auto& textList = _src.m_textData[i]; - for (U32 j = 0; j < textList->size(); ++j) { + for (U32 j = 0; j < textList->size(); ++j) + { m_textData[i]->push_back((*_src.m_textData[i])[j]); m_textData[i]->back().m_textBufferOffset += textBufferOffset; } @@ -1590,8 +1760,10 @@ void Context::endFrame() m_endFrameCalled = true; // draw unsorted primitives first - for (U32 i = 0; i < m_vertexData[0].size(); ++i) { - if (m_vertexData[0][i]->size() > 0) { + for (U32 i = 0; i < m_vertexData[0].size(); ++i) + { + if (m_vertexData[0][i]->size() > 0) + { DrawList& dl = m_drawLists.push_back(); dl.m_layerId = m_layerIdMap[i / DrawPrimitive_Count]; dl.m_primType = (DrawPrimitiveType)(i % DrawPrimitive_Count); @@ -1601,12 +1773,14 @@ void Context::endFrame() } // draw sorted primitives second - if (!m_sortCalled) { + if (!m_sortCalled) + { sort(); } for (U32 i = 0; i < m_textData.size(); ++i) { - if (m_textData[i]->size() > 0) { + if (m_textData[i]->size() > 0) + { TextDrawList& dl = m_textDrawLists.push_back(); dl.m_layerId = m_layerIdMap[i]; dl.m_textData = m_textData[i]->data(); @@ -1618,12 +1792,14 @@ void Context::endFrame() void Context::draw() { - if (m_drawLists.empty()) { + if (m_drawLists.empty()) + { endFrame(); } IM3D_ASSERT(m_appData.drawCallback); - for (auto& drawList : m_drawLists) { + for (auto& drawList : m_drawLists) + { m_appData.drawCallback(drawList); } } @@ -1651,10 +1827,12 @@ void Context::pushLayerId(Id _layer) { IM3D_ASSERT(m_primMode == PrimitiveMode_None); // can't change layer mid-primitive int idx = findLayerIndex(_layer); - if (idx == -1) { // not found, push new layer + if (idx == -1) // not found, push new layer + { idx = m_layerIdMap.size(); m_layerIdMap.push_back(_layer); - for (int i = 0; i < DrawPrimitive_Count; ++i) { + for (int i = 0; i < DrawPrimitive_Count; ++i) + { m_vertexData[0].push_back((VertexList*)IM3D_MALLOC(sizeof(VertexList))); *m_vertexData[0].back() = VertexList(); m_vertexData[1].push_back((VertexList*)IM3D_MALLOC(sizeof(VertexList))); @@ -1699,7 +1877,8 @@ Context::Context() memset(&m_keyDownPrev, 0, sizeof(m_keyDownPrev)); // init cull frustum to INF effectively disables culling - for (int i = 0; i < FrustumPlane_Count; ++i) { + for (int i = 0; i < FrustumPlane_Count; ++i) + { m_appData.m_cullFrustum[i] = Vec4(INFINITY); } @@ -1714,13 +1893,22 @@ Context::Context() Context::~Context() { - for (int i = 0; i < 2; ++i) { - while (!m_vertexData[i].empty()) { + for (int i = 0; i < 2; ++i) + { + while (!m_vertexData[i].empty()) + { m_vertexData[i].back()->~Vector(); // manually call dtor (vector is allocated via IM3D_MALLOC during pushLayerId) IM3D_FREE(m_vertexData[i].back()); m_vertexData[i].pop_back(); } } + + while (!m_textData.empty()) + { + m_textData.back()->~Vector(); // see above + IM3D_FREE(m_textData.back()); + m_textData.pop_back(); + } } namespace { @@ -1736,11 +1924,16 @@ namespace { { float ka = ((SortData*)_a)->m_key; float kb = ((SortData*)_b)->m_key; - if (ka < kb) { + if (ka < kb) + { return 1; - } else if (ka > kb) { + } + else if (ka > kb) + { return -1; - } else { + } + else + { return 0; } } @@ -1749,8 +1942,10 @@ namespace { { Vector ret; ret.reserve(_data_.size()); - for (U32 i = 0; i < _sortCount; ++i) { - for (U32 j = 0; j < _primSize; ++j) { + for (U32 i = 0; i < _sortCount; ++i) + { + for (U32 j = 0; j < _primSize; ++j) + { ret.push_back(*(_sort[i].m_start + j)); } } @@ -1762,19 +1957,24 @@ void Context::sort() { static IM3D_THREAD_LOCAL Vector sortData[DrawPrimitive_Count]; // reduces # allocs - for (U32 layer = 0; layer < m_layerIdMap.size(); ++layer) { + for (U32 layer = 0; layer < m_layerIdMap.size(); ++layer) + { Vec3 viewOrigin = m_appData.m_viewOrigin; // sort each primitive list internally - for (int i = 0 ; i < DrawPrimitive_Count; ++i) { + for (int i = 0 ; i < DrawPrimitive_Count; ++i) + { Vector& vertexData = *(m_vertexData[1][layer * DrawPrimitive_Count + i]); sortData[i].clear(); - if (!vertexData.empty()) { + if (!vertexData.empty()) + { sortData[i].reserve(vertexData.size() / VertsPerDrawPrimitive[i]); - for (VertexData* v = vertexData.begin(); v != vertexData.end(); ) { + for (VertexData* v = vertexData.begin(); v != vertexData.end(); ) + { sortData[i].push_back(SortData(0.0f, v)); IM3D_ASSERT(v < vertexData.end()); - for (int j = 0; j < VertsPerDrawPrimitive[i]; ++j, ++v) { + for (int j = 0; j < VertsPerDrawPrimitive[i]; ++j, ++v) + { // sort key is the primitive midpoint distance to view origin sortData[i].back().m_key += Length2(Vec3(v->m_positionSize) - viewOrigin); } @@ -1790,36 +1990,46 @@ void Context::sort() int cprim = 0; SortData* search[DrawPrimitive_Count]; int emptyCount = 0; - for (int i = 0; i < DrawPrimitive_Count; ++i) { - if (sortData[i].empty()) { + for (int i = 0; i < DrawPrimitive_Count; ++i) + { + if (sortData[i].empty()) + { search[i] = 0; ++emptyCount; - } else { + } + else + { search[i] = sortData[i].begin(); } } bool first = true; #define modinc(v) ((v + 1) % DrawPrimitive_Count) - while (emptyCount != DrawPrimitive_Count) { - while (search[cprim] == 0) { + while (emptyCount != DrawPrimitive_Count) + { + while (search[cprim] == 0) + { cprim = modinc(cprim); } + // find the max key at the current position across all sort data float mxkey = search[cprim]->m_key; int mxprim = cprim; - for (int p = modinc(cprim); p != cprim; p = modinc(p)) { - if (search[p] != 0 && search[p]->m_key > mxkey) { + for (int p = modinc(cprim); p != cprim; p = modinc(p)) + { + if (search[p] != 0 && search[p]->m_key > mxkey) + { mxkey = search[p]->m_key; mxprim = p; } } // if draw list is empty or the layer or primitive changed, start a new draw list - if ( - first || - m_drawLists.back().m_layerId != layer || - m_drawLists.back().m_primType != mxprim - ) { + if (false + || first + || (m_drawLists.back().m_layerId != layer) + || (m_drawLists.back().m_primType != mxprim) + ) + { cprim = mxprim; DrawList dl; dl.m_layerId = layer; @@ -1833,7 +2043,8 @@ void Context::sort() // increment the vertex count for the current draw list m_drawLists.back().m_vertexCount += VertsPerDrawPrimitive[cprim]; ++search[cprim]; - if (search[cprim] == sortData[cprim].end()) { + if (search[cprim] == sortData[cprim].end()) + { search[cprim] = 0; ++emptyCount; } @@ -1847,8 +2058,10 @@ void Context::sort() int Context::findLayerIndex(Id _id) const { - for (int i = 0; i < (int)m_layerIdMap.size(); ++i) { - if (m_layerIdMap[i] == _id) { + for (int i = 0; i < (int)m_layerIdMap.size(); ++i) + { + if (m_layerIdMap[i] == _id) + { return i; } } @@ -1859,17 +2072,22 @@ bool Context::isVisible(const VertexData* _vdata, DrawPrimitiveType _prim) { Vec3 pos[3]; float size[3]; - for (int i = 0; i < VertsPerDrawPrimitive[_prim]; ++i) { + for (int i = 0; i < VertsPerDrawPrimitive[_prim]; ++i) + { pos[i] = Vec3(_vdata[i].m_positionSize); size[i] = _prim == DrawPrimitive_Triangles ? 0.0f : pixelsToWorldSize(pos[i], _vdata[i].m_positionSize.w); } - for (int i = 0; i < m_cullFrustumCount; ++i) { + for (int i = 0; i < m_cullFrustumCount; ++i) + { const Vec4& plane = m_cullFrustum[i]; bool isVisible= false; - for (int j = 0; j < VertsPerDrawPrimitive[_prim]; ++j) { + for (int j = 0; j < VertsPerDrawPrimitive[_prim]; ++j) + { isVisible |= Distance(plane, pos[j]) > -size[j]; } - if (!isVisible) { + + if (!isVisible) + { return false; } } @@ -1878,9 +2096,11 @@ bool Context::isVisible(const VertexData* _vdata, DrawPrimitiveType _prim) bool Context::isVisible(const Vec3& _origin, float _radius) { - for (int i = 0; i < m_cullFrustumCount; ++i) { + for (int i = 0; i < m_cullFrustumCount; ++i) + { const Vec4& plane = m_cullFrustum[i]; - if (Distance(plane, _origin) < -_radius) { + if (Distance(plane, _origin) < -_radius) + { return false; } } @@ -1890,34 +2110,42 @@ bool Context::isVisible(const Vec3& _origin, float _radius) bool Context::isVisible(const Vec3& _min, const Vec3& _max) { #if 0 - const Vec3 points[] = { - Vec3(_min.x, _min.y, _min.z), - Vec3(_max.x, _min.y, _min.z), - Vec3(_max.x, _max.y, _min.z), - Vec3(_min.x, _max.y, _min.z), - - Vec3(_min.x, _min.y, _max.z), - Vec3(_max.x, _min.y, _max.z), - Vec3(_max.x, _max.y, _max.z), - Vec3(_min.x, _max.y, _max.z) - }; + const Vec3 points[] = + { + Vec3(_min.x, _min.y, _min.z), + Vec3(_max.x, _min.y, _min.z), + Vec3(_max.x, _max.y, _min.z), + Vec3(_min.x, _max.y, _min.z), + + Vec3(_min.x, _min.y, _max.z), + Vec3(_max.x, _min.y, _max.z), + Vec3(_max.x, _max.y, _max.z), + Vec3(_min.x, _max.y, _max.z) + }; - for (int i = 0; i < m_cullFrustumCount; ++i) { + for (int i = 0; i < m_cullFrustumCount; ++i) + { const Vec4& plane = m_cullFrustum[i]; bool inside = false; - for (int j = 0; j < 8; ++j) { - if (Distance(plane, points[j]) > 0.0f) { + for (int j = 0; j < 8; ++j) + { + if (Distance(plane, points[j]) > 0.0f) + { inside = true; break; } } - if (!inside) { + + if (!inside) + { return false; } } + return true; #else - for (int i = 0; i < m_cullFrustumCount; ++i) { + for (int i = 0; i < m_cullFrustumCount; ++i) + { const Vec4& plane = m_cullFrustum[i]; float d = Max(_min.x * plane.x, _max.x * plane.x) + @@ -1925,11 +2153,13 @@ bool Context::isVisible(const Vec3& _min, const Vec3& _max) Max(_min.z * plane.z, _max.z * plane.z) - plane.w ; - if (d < 0.0f) { + + if (d < 0.0f) + { return false; } - } + return true; #endif } @@ -1958,26 +2188,31 @@ float Context::worldSizeToPixels(const Vec3& _position, float _size) int Context::estimateLevelOfDetail(const Vec3& _position, float _worldSize, int _min, int _max) { - if (m_appData.m_projOrtho) { + if (m_appData.m_projOrtho) + { return _max; } + float d = Length(_position - m_appData.m_viewOrigin); float x = Clamp(2.0f * atanf(_worldSize / (2.0f * d)), 0.0f, 1.0f); float fmin = (float)_min; float fmax = (float)_max; + return (int)(fmin + (fmax - fmin) * x); } bool Context::gizmoAxisTranslation_Behavior(Id _id, const Vec3& _origin, const Vec3& _axis, float _snap, float _worldHeight, float _worldSize, Vec3* _out_) { - if (_id != m_hotId) { + if (_id != m_hotId) + { // disable behavior when aligned Vec3 viewDir = m_appData.m_projOrtho ? m_appData.m_viewDirection : Normalize(m_appData.m_viewOrigin - _origin) ; float aligned = 1.0f - fabs(Dot(_axis, viewDir)); - if (aligned < 0.01f) { + if (aligned < 0.01f) + { return false; } } @@ -1987,7 +2222,8 @@ bool Context::gizmoAxisTranslation_Behavior(Id _id, const Vec3& _origin, const V Capsule axisCapsule(_origin + _axis * (0.2f * _worldHeight), _origin + _axis * _worldHeight, _worldSize); #if IM3D_GIZMO_DEBUG - if (_id == m_hotId) { + if (_id == m_hotId) + { PushDrawState(); EnableSorting(false); SetColor(Color_Magenta); @@ -1999,8 +2235,10 @@ bool Context::gizmoAxisTranslation_Behavior(Id _id, const Vec3& _origin, const V Vec3& storedPosition = m_gizmoStateVec3; - if (_id == m_activeId) { - if (isKeyDown(Action_Select)) { + if (_id == m_activeId) + { + if (isKeyDown(Action_Select)) + { float tr, tl; Nearest(ray, axisLine, tr, tl); #if IM3D_RELATIVE_SNAP @@ -2010,21 +2248,31 @@ bool Context::gizmoAxisTranslation_Behavior(Id _id, const Vec3& _origin, const V #endif return true; - } else { + } + else + { makeActive(Id_Invalid); } - } else if (_id == m_hotId) { - if (Intersects(ray, axisCapsule)) { - if (isKeyDown(Action_Select)) { + } + else if (_id == m_hotId) + { + if (Intersects(ray, axisCapsule)) + { + if (isKeyDown(Action_Select)) + { makeActive(_id); float tr, tl; Nearest(ray, axisLine, tr, tl); storedPosition = _axis * tl; } - } else { + } + else + { resetId(); } - } else { + } + else + { float t0, t1; bool intersects = Intersect(ray, axisCapsule, t0, t1); makeHot(_id, t0, intersects); @@ -2042,7 +2290,8 @@ void Context::gizmoAxisTranslation_Draw(Id _id, const Vec3& _origin, const Vec3& float aligned = 1.0f - fabs(Dot(_axis, viewDir)); aligned = Remap(aligned, 0.05f, 0.1f); Color color = _color; - if (_id == m_activeId) { + if (_id == m_activeId) + { color = Color_GizmoHighlight; pushEnableSorting(false); begin(PrimitiveMode_Lines); @@ -2050,7 +2299,9 @@ void Context::gizmoAxisTranslation_Draw(Id _id, const Vec3& _origin, const Vec3& vertex(_origin + _axis * 999.0f, m_gizmoSizePixels * 0.5f, _color); end(); popEnableSorting(); - } else if (_id == m_hotId) { + } + else if (_id == m_hotId) + { color = Color_GizmoHighlight; aligned = 1.0f; } @@ -2071,7 +2322,8 @@ bool Context::gizmoPlaneTranslation_Behavior(Id _id, const Vec3& _origin, const Plane plane(_normal, _origin); #if IM3D_GIZMO_DEBUG - if (_id == m_hotId) { + if (_id == m_hotId) + { PushDrawState(); EnableSorting(false); SetColor(Color_Magenta); @@ -2088,7 +2340,8 @@ bool Context::gizmoPlaneTranslation_Behavior(Id _id, const Vec3& _origin, const float tr; bool intersects = Intersect(ray, plane, tr); - if (!intersects) { + if (!intersects) + { return false; } Vec3 intersection = ray.m_origin + ray.m_direction * tr; @@ -2096,8 +2349,10 @@ bool Context::gizmoPlaneTranslation_Behavior(Id _id, const Vec3& _origin, const Vec3& storedPosition = m_gizmoStateVec3; - if (_id == m_activeId) { - if (isKeyDown(Action_Select)) { + if (_id == m_activeId) + { + if (isKeyDown(Action_Select)) + { #if IM3D_RELATIVE_SNAP intersection = Snap(intersection, plane, _snap); *_out_ = intersection + storedPosition; @@ -2105,19 +2360,29 @@ bool Context::gizmoPlaneTranslation_Behavior(Id _id, const Vec3& _origin, const *_out_ = Snap(intersection + storedPosition, plane, _snap); #endif return true; - } else { + } + else + { makeActive(Id_Invalid); } - } else if (_id == m_hotId) { - if (intersects) { - if (isKeyDown(Action_Select)) { + } + else if (_id == m_hotId) + { + if (intersects) + { + if (isKeyDown(Action_Select)) + { makeActive(_id); storedPosition = *_out_ - intersection; } - } else { + } + else + { resetId(); } - } else { + } + else + { makeHot(_id, tr, intersects); } @@ -2153,7 +2418,8 @@ bool Context::gizmoAxislAngle_Behavior(Id _id, const Vec3& _origin, const Vec3& Ray ray(m_appData.m_cursorRayOrigin, m_appData.m_cursorRayDirection); bool intersects = false; Vec3 intersection; - if (aligned < 0.05f) { + if (aligned < 0.05f) + { // ray-plane intersection fails at grazing angles, use capsule interesection float t1; Vec3 capsuleAxis = Cross(viewDir, _axis); @@ -2161,7 +2427,8 @@ bool Context::gizmoAxislAngle_Behavior(Id _id, const Vec3& _origin, const Vec3& intersects = Intersect(ray, capsule, tr, t1); intersection = ray.m_origin + ray.m_direction * tr; #if IM3D_GIZMO_DEBUG - if (_id == m_hotId) { + if (_id == m_hotId) + { PushDrawState(); SetColor(Im3d::Color_Magenta); SetSize(3.0f); @@ -2169,7 +2436,9 @@ bool Context::gizmoAxislAngle_Behavior(Id _id, const Vec3& _origin, const Vec3& PopDrawState(); } #endif - } else { + } + else + { Plane plane(_axis, _origin); intersects = Intersect(ray, plane, tr); intersection = ray.m_origin + ray.m_direction * tr; @@ -2186,8 +2455,10 @@ bool Context::gizmoAxislAngle_Behavior(Id _id, const Vec3& _origin, const Vec3& Intersect(ray, viewPlane, tr); intersection = ray.m_origin + ray.m_direction * tr; - if (_id == m_activeId) { - if (isKeyDown(Action_Select)) { + if (_id == m_activeId) + { + if (isKeyDown(Action_Select)) + { Vec3 delta = Normalize(intersection - _origin); float sign = Dot(Cross(storedVec, delta), _axis); float angle = acosf(Clamp(Dot(delta, storedVec), -1.0f, 1.0f)); @@ -2197,22 +2468,32 @@ bool Context::gizmoAxislAngle_Behavior(Id _id, const Vec3& _origin, const Vec3& *_out_ = Snap(storedAngle + copysignf(angle, sign), _snap); #endif return true; - } else { + } + else + { makeActive(Id_Invalid); } - } else if (_id == m_hotId) { - if (intersects) { - if (isKeyDown(Action_Select)) { + } + else if (_id == m_hotId) + { + if (intersects) + { + if (isKeyDown(Action_Select)) + { makeActive(_id); storedVec = Normalize(intersection - _origin); storedAngle = Snap(*_out_, m_appData.m_snapRotation); } - } else { + } + else + { resetId(); } - } else { + } + else + { makeHot(_id, tr, intersects); } return false; @@ -2228,12 +2509,14 @@ void Context::gizmoAxislAngle_Draw(Id _id, const Vec3& _origin, const Vec3& _axi Vec3& storedVec = m_gizmoStateVec3; Color color = _color; - if (_id == m_activeId) { + if (_id == m_activeId) + { color = Color_GizmoHighlight; Ray ray(m_appData.m_cursorRayOrigin, m_appData.m_cursorRayDirection); Plane plane(_axis, _origin); float tr; - if (Intersect(ray, plane, tr)) { + if (Intersect(ray, plane, tr)) + { Vec3 intersection = ray.m_origin + ray.m_direction * tr; Vec3 delta = Normalize(intersection - _origin); @@ -2258,11 +2541,14 @@ void Context::gizmoAxislAngle_Draw(Id _id, const Vec3& _origin, const Vec3& _axi end(); } - } else if (_id == m_hotId) { + } + else if (_id == m_hotId) + { color = Color_GizmoHighlight; } aligned = Max(Remap(aligned, 0.9f, 1.0f), 0.1f); - if (m_activeId == _id) { + if (m_activeId == _id) + { aligned = 1.0f; } pushColor(color); @@ -2270,7 +2556,8 @@ void Context::gizmoAxislAngle_Draw(Id _id, const Vec3& _origin, const Vec3& _axi pushMatrix(getMatrix() * LookAt(_origin, _origin + _axis, m_appData.m_worldUp)); begin(PrimitiveMode_LineLoop); const int detail = estimateLevelOfDetail(_origin, _worldRadius, 16, 128); - for (int i = 0; i < detail; ++i) { + for (int i = 0; i < detail; ++i) + { float rad = TwoPi * ((float)i / (float)detail); vertex(Vec3(cosf(rad) * _worldRadius, sinf(rad) * _worldRadius, 0.0f)); @@ -2294,7 +2581,8 @@ bool Context::gizmoAxisScale_Behavior(Id _id, const Vec3& _origin, const Vec3& _ Capsule axisCapsule(_origin + _axis * (0.2f * _worldHeight), _origin + _axis * _worldHeight, _worldSize); #if IM3D_GIZMO_DEBUG - if (_id == m_hotId) { + if (_id == m_hotId) + { PushDrawState(); EnableSorting(false); SetColor(Color_Magenta); @@ -2307,8 +2595,10 @@ bool Context::gizmoAxisScale_Behavior(Id _id, const Vec3& _origin, const Vec3& _ Vec3& storedPosition = m_gizmoStateVec3; float& storedScale = m_gizmoStateFloat; - if (_id == m_activeId) { - if (isKeyDown(Action_Select)) { + if (_id == m_activeId) + { + if (isKeyDown(Action_Select)) + { float tr, tl; Nearest(ray, axisLine, tr, tl); Vec3 intersection = _axis * tl; @@ -2323,24 +2613,35 @@ bool Context::gizmoAxisScale_Behavior(Id _id, const Vec3& _origin, const Vec3& _ float scale = Length(delta) / _worldHeight; *_out_ = Max(Snap(storedScale * (1.0f + copysignf(scale, sign)), _snap), 1e-3f); #endif + return true; - } else { + } + else + { makeActive(Id_Invalid); } - } else if (_id == m_hotId) { - if (Intersects(ray, axisCapsule)) { - if (isKeyDown(Action_Select)) { + } + else if (_id == m_hotId) + { + if (Intersects(ray, axisCapsule)) + { + if (isKeyDown(Action_Select)) + { makeActive(_id); float tr, tl; Nearest(ray, axisLine, tr, tl); storedPosition = _axis * tl; storedScale = *_out_; } - } else { + } + else + { resetId(); } - } else { + } + else + { float t0, t1; bool intersects = Intersect(ray, axisCapsule, t0, t1); makeHot(_id, t0, intersects); @@ -2357,7 +2658,8 @@ void Context::gizmoAxisScale_Draw(Id _id, const Vec3& _origin, const Vec3& _axis float aligned = 1.0f - fabs(Dot(_axis, viewDir)); aligned = Remap(aligned, 0.05f, 0.1f); Color color = _color; - if (_id == m_activeId) { + if (_id == m_activeId) + { color = Color_GizmoHighlight; pushEnableSorting(false); begin(PrimitiveMode_Lines); @@ -2365,7 +2667,9 @@ void Context::gizmoAxisScale_Draw(Id _id, const Vec3& _origin, const Vec3& _axis vertex(_origin + _axis * 999.0f, m_gizmoSizePixels * 0.5f, _color); end(); popEnableSorting(); - } else if (_id == m_hotId) { + } + else if (_id == m_hotId) + { color = Color_GizmoHighlight; aligned = 1.0f; } @@ -2381,12 +2685,15 @@ void Context::gizmoAxisScale_Draw(Id _id, const Vec3& _origin, const Vec3& _axis bool Context::makeHot(Id _id, float _depth, bool _intersects) { - if (m_activeId == Id_Invalid && _depth < m_hotDepth && _intersects && !isKeyDown(Action_Select)) { + if (m_activeId == Id_Invalid && _depth < m_hotDepth && _intersects && !isKeyDown(Action_Select)) + { m_hotId = _id; m_appHotId = m_appId; m_hotDepth = _depth; + return true; } + return false; } @@ -2405,20 +2712,24 @@ void Context::resetId() U32 Context::getPrimitiveCount(DrawPrimitiveType _type) const { U32 ret = 0; - for (U32 i = 0; i < m_layerIdMap.size(); ++i) { + for (U32 i = 0; i < m_layerIdMap.size(); ++i) + { U32 j = i * DrawPrimitive_Count + _type; ret += m_vertexData[0][j]->size() + m_vertexData[1][j]->size(); } ret /= VertsPerDrawPrimitive[_type]; + return ret; } U32 Context::getTextCount() const { U32 ret = 0; - for (U32 i = 0; i < m_layerIdMap.size(); ++i) { + for (U32 i = 0; i < m_layerIdMap.size(); ++i) + { ret += m_textData[i]->size(); } + return ret; } @@ -2509,17 +2820,23 @@ Vec3 Im3d::ToEulerXYZ(const Mat3& _m) { // http://www.staff.city.ac.uk/~sbbh653/publications/euler.pdf Vec3 ret; - if_likely (fabs(_m(2, 0)) < 1.0f) { + if_likely (fabs(_m(2, 0)) < 1.0f) + { ret.y = -asinf(_m(2, 0)); float c = 1.0f / cosf(ret.y); ret.x = atan2f(_m(2, 1) * c, _m(2, 2) * c); ret.z = atan2f(_m(1, 0) * c, _m(0, 0) * c); - } else { + } + else + { ret.z = 0.0f; - if (!(_m(2, 0) > -1.0f)) { + if (!(_m(2, 0) > -1.0f)) + { ret.x = ret.z + atan2f(_m(0, 1), _m(0, 2)); ret.y = HalfPi; - } else { + } + else + { ret.x = -ret.z + atan2f(-_m(0, 1), -_m(0, 2)); ret.y = -HalfPi; } @@ -2693,9 +3010,11 @@ Mat4 Im3d::Inverse(const Mat4& _m) ret(3, 3) = _m(0, 1) * _m(1, 2) * _m(2, 0) - _m(0, 2) * _m(1, 1) * _m(2, 0) + _m(0, 2) * _m(1, 0) * _m(2, 1) - _m(0, 0) * _m(1, 2) * _m(2, 1) - _m(0, 1) * _m(1, 0) * _m(2, 2) + _m(0, 0) * _m(1, 1) * _m(2, 2); float det = 1.0f / Determinant(_m); - for (int i = 0; i < 16; ++i) { + for (int i = 0; i < 16; ++i) + { ret[i] *= det; } + return ret; } Mat4 Im3d::Transpose(const Mat4& _m) @@ -2721,11 +3040,13 @@ Mat4 Im3d::AlignZ(const Vec3& _axis, const Vec3& _up) Vec3 x, y; y = _up - _axis * Dot(_up, _axis); float ylen = Length(y); - if_unlikely (ylen < FLT_EPSILON) { + if_unlikely (ylen < FLT_EPSILON) + { Vec3 k = Vec3(1.0f, 0.0f, 0.0f); y = k - _axis * Dot(k, _axis); ylen = Length(y); - if_unlikely (ylen < FLT_EPSILON) { + if_unlikely (ylen < FLT_EPSILON) + { k = Vec3(0.0f, 0.0f, 1.0f); y = k - _axis * Dot(k, _axis); ylen = Length(y); @@ -2801,23 +3122,29 @@ bool Im3d::Intersects(const Ray& _r, const Sphere& _s) float p2 = Length2(p); float q = Dot(p, _r.m_direction); float r2 = _s.m_radius * _s.m_radius; - if (q < 0.0f && p2 > r2) { + if (q < 0.0f && p2 > r2) + { return false; } + return p2 - (q * q) <= r2; } bool Im3d::Intersect(const Ray& _r, const Sphere& _s, float& t0_, float& t1_) { Vec3 p = _s.m_origin - _r.m_origin; float q = Dot(p, _r.m_direction); - if (q < 0.0f) { + if (q < 0.0f) + { return false; } + float p2 = Length2(p) - q * q; float r2 = _s.m_radius * _s.m_radius; - if (p2 > r2) { + if (p2 > r2) + { return false; } + float s = sqrtf(r2 - p2); t0_ = Max(q - s, 0.0f); t1_ = q + s; @@ -2842,10 +3169,13 @@ void Im3d::Nearest(const Line& _line0, const Line& _line1, float& t0_, float& t1 float s = Dot(_line1.m_direction, p); float d = 1.0f - q * q; - if (d < FLT_EPSILON) { // lines are parallel + if (d < FLT_EPSILON) // lines are parallel + { t0_ = 0.0f; t1_ = s; - } else { + } + else + { float r = Dot(_line0.m_direction, p); t0_ = (q * s - r) / d; t1_ = (s - q * r) / d; @@ -2867,19 +3197,25 @@ Vec3 Im3d::Nearest(const Ray& _ray, const LineSegment& _segment, float& tr_) float sn, sd, tn, td; float denom = q - r * r; - if (denom < FLT_EPSILON) { + if (denom < FLT_EPSILON) + { sd = td = 1.0f; sn = 0.0f; tn = t; - } else { + } + else + { sd = td = denom; sn = r * t - s; tn = q * t - r * s; - if (sn < 0.0f) { + if (sn < 0.0f) + { sn = 0.0f; tn = t; td = 1.0f; - } else if (sn > sd) { + } + else if (sn > sd) + { sn = sd; tn = t + r; td = 1.0f; @@ -2887,19 +3223,28 @@ Vec3 Im3d::Nearest(const Ray& _ray, const LineSegment& _segment, float& tr_) } float ts; - if (tn < 0.0f) { + if (tn < 0.0f) + { tr_ = 0.0f; - if (r >= 0.0f) { + if (r >= 0.0f) + { ts = 0.0f; - } else if (s <= q) { + } + else if (s <= q) + { ts = 1.0f; - } else { + } + else + { ts = -s / q; } - } else { + } + else + { tr_ = tn / td; ts = sn / sd; } + return _segment.m_start + ldir * ts; } float Im3d::Distance2(const Ray& _ray, const LineSegment& _segment) diff --git a/im3d.h b/im3d.h index dfa04ec..8f2f47c 100644 --- a/im3d.h +++ b/im3d.h @@ -145,8 +145,8 @@ IM3D_API void DrawArrow(const Vec3& _start, const Vec3& _end, float _headLength IM3D_API void Text(const Vec3& _position, U32 _textFlags, const char* _text, ...); // use the current draw state for size/color IM3D_API void Text(const Vec3& _position, float _size, Color _color, U32 _textFlags, const char* _text, ...); -// Ids are used to uniquely identify gizmos and layers. Gizmo should have a unique id during a frame. -// Note that ids are a hash of the whole id stack, see PushId(), PopId(). +// IDs are used to uniquely identify gizmos and layers. Gizmo should have a unique ID during a frame. +// Note that ids are a hash of the whole ID stack, see PushId(), PopId(). IM3D_API Id MakeId(const char* _str); IM3D_API Id MakeId(const void* _ptr); IM3D_API Id MakeId(int _i); @@ -159,8 +159,6 @@ IM3D_API void PushId(const void* _ptr); IM3D_API void PushId(int _i); IM3D_API void PopId(); IM3D_API Id GetId(); -IM3D_API Id GetActiveId(); // GetActiveId() != Id_Invalid means that a gizmo is in use -IM3D_API Id GetHotId(); // Layer id state, subsequent primitives are added to a separate draw list associated with the id (per primitive). IM3D_API void PushLayerId(Id _layer); @@ -168,7 +166,6 @@ IM3D_API void PushLayerId(const char* _str); // calls PushLayerId(MakeId(_str)) IM3D_API void PopLayerId(); IM3D_API Id GetLayerId(); - // Manipulate translation/rotation/scale via a gizmo. Return true if the gizmo is 'active' (if it modified the output parameter). // If _local is true, the Gizmo* functions expect that the local matrix is on the matrix stack; in general the application should // push the local matrix before calling any of the following. @@ -179,13 +176,18 @@ IM3D_API bool GizmoScale(const char* _id, float _scale_[3]); // local scale only IM3D_API bool Gizmo(const char* _id, float _translation_[3], float _rotation_[3*3], float _scale_[3]); // any of _translation_/_rotation_/_scale_ may be null. IM3D_API bool Gizmo(const char* _id, float _transform_[4*4]); -// Gizmo* overloads which take an Id directly. In some cases the app may want to call MakeId() separately, usually to change the gizmo appearance if hot/active. +// Gizmo* overloads which take an ID directly. In some cases the app may want to call MakeId() separately, usually to change the gizmo appearance if hot/active. IM3D_API bool GizmoTranslation(Id _id, float _translation_[3], bool _local = false); IM3D_API bool GizmoRotation(Id _id, float _rotation_[3*3], bool _local = false); IM3D_API bool GizmoScale(Id _id, float _scale_[3]); IM3D_API bool Gizmo(Id _id, float _transform_[4*4]); IM3D_API bool Gizmo(Id _id, float _translation_[3], float _rotation_[3*3], float _scale_[3]); +// Active gizmo ID. This will match the _id parameter passed to a Gizmo* function. Return Id_Invalid if no gizmo is in use. +IM3D_API Id GetActiveId(); +// ID of the current current 'hot' gizmo (nearest intersecting gizmo along the cursor ray). +IM3D_API Id GetHotId(); + // Visibility tests. The application must set a culling frustum via AppData. IM3D_API bool IsVisible(const Vec3& _origin, float _radius); // sphere IM3D_API bool IsVisible(const Vec3& _min, const Vec3& _max); // axis-aligned bounding box @@ -197,49 +199,63 @@ IM3D_API void SetContext(Context& _ctx); // Merge vertex data from _src into _dst_. Layers are preserved. Call before EndFrame(). IM3D_API void MergeContexts(Context& _dst_, const Context& _src); + struct IM3D_API Vec2 { float x, y; + Vec2() {} Vec2(float _xy): x(_xy), y(_xy) {} Vec2(float _x, float _y): x(_x), y(_y) {} + operator float*() { return &x; } operator const float*() const { return &x; } + #ifdef IM3D_VEC2_APP IM3D_VEC2_APP #endif }; + struct IM3D_API Vec3 { float x, y, z; + Vec3() {} Vec3(float _xyz): x(_xyz), y(_xyz), z(_xyz) {} Vec3(float _x, float _y, float _z): x(_x), y(_y), z(_z) {} Vec3(const Vec2& _xy, float _z): x(_xy.x), y(_xy.y), z(_z) {} Vec3(const Vec4& _v); // discards w + operator float*() { return &x; } operator const float*() const { return &x; } + #ifdef IM3D_VEC3_APP IM3D_VEC3_APP #endif }; + struct IM3D_API Vec4 { float x, y, z, w; + Vec4() {} Vec4(float _xyzw): x(_xyzw), y(_xyzw), z(_xyzw), w(_xyzw) {} Vec4(float _x, float _y, float _z, float _w): x(_x), y(_y), z(_z), w(_w) {} Vec4(const Vec3& _xyz, float _w): x(_xyz.x), y(_xyz.y), z(_xyz.z), w(_w) {} Vec4(Color _rgba); + operator float*() { return &x; } operator const float*() const { return &x; } + #ifdef IM3D_VEC4_APP IM3D_VEC4_APP #endif }; + struct IM3D_API Mat3 { float m[3*3]; // column-major unless IM3D_MATRIX_ROW_MAJOR defined + Mat3() {} Mat3(float _diagonal); Mat3( @@ -249,6 +265,7 @@ struct IM3D_API Mat3 ); Mat3(const Vec3& _colX, const Vec3& _colY, const Vec3& _colZ); Mat3(const Mat4& _mat4); // extract upper 3x3 + operator float*() { return m; } operator const float*() const { return m; } @@ -283,9 +300,11 @@ struct IM3D_API Mat3 IM3D_MAT3_APP #endif }; + struct IM3D_API Mat4 { float m[4*4]; // column-major unless IM3D_MATRIX_ROW_MAJOR defined + Mat4() {} Mat4(float _diagonal); Mat4( @@ -296,6 +315,7 @@ struct IM3D_API Mat4 ); Mat4(const Mat3& _mat3); Mat4(const Vec3& _translation, const Mat3& _rotation, const Vec3& _scale); + operator float*() { return m; } operator const float*() const { return m; } @@ -334,9 +354,11 @@ struct IM3D_API Mat4 IM3D_MAT4_APP #endif }; + struct IM3D_API Color { U32 v; // rgba8 (MSB = r) + constexpr Color(): v(0) {} constexpr Color(U32 _rgba): v(_rgba) {} Color(const Vec4& _rgba); @@ -373,13 +395,14 @@ struct IM3D_API Color | ((v & (0xff << 24)) >> 24) // r | ((v & (0xff << 16)) >> 8) // g | ((v & (0xff << 8)) << 8) // b - | ((v & (0xff )) << 24) // b + | ((v & (0xff )) << 24) // a ; } }; constexpr Color Color_Black = Color(0x000000ff); constexpr Color Color_White = Color(0xffffffff); +constexpr Color Color_Gray = Color(0x808080ff); constexpr Color Color_Red = Color(0xff0000ff); constexpr Color Color_Green = Color(0x00ff00ff); constexpr Color Color_Blue = Color(0x0000ffff); @@ -387,6 +410,14 @@ constexpr Color Color_Magenta = Color(0xff00ffff); constexpr Color Color_Yellow = Color(0xffff00ff); constexpr Color Color_Cyan = Color(0x00ffffff); +constexpr Color Color_Pink = Color(0xffc0cbff); +constexpr Color Color_Orange = Color(0xffa500ff); +constexpr Color Color_Gold = Color(0xffd700ff); +constexpr Color Color_Brown = Color(0x8b4513ff); +constexpr Color Color_Purple = Color(0x800080ff); +constexpr Color Color_Teal = Color(0x008080ff); +constexpr Color Color_Navy = Color(0x000080ff); + struct alignas(IM3D_VERTEX_ALIGNMENT) VertexData { Vec4 m_positionSize; // xyz = position, w = size @@ -503,37 +534,37 @@ struct AppData template struct Vector { - Vector() {} - ~Vector(); - - T& operator[](U32 _i) { IM3D_ASSERT(_i < m_size); return m_data[_i]; } - const T& operator[](U32 _i) const { IM3D_ASSERT(_i < m_size); return m_data[_i]; } - T* data() { return m_data; } - const T* data() const { return m_data; } - - T& push_back() { if (m_size == m_capacity) { reserve(m_capacity + m_capacity / 2); } return m_data[m_size++]; } - void push_back(const T& _v) { T tmp = _v; if (m_size == m_capacity) { reserve(m_capacity + m_capacity / 2); } m_data[m_size++] = tmp; } - void pop_back() { IM3D_ASSERT(m_size > 0); --m_size; } - void append(const T* _v, U32 _count); - void append(const Vector& _other) { append(_other.data(), _other.size()); } - - T* begin() { return m_data; } - const T* begin() const { return m_data; } - T* end() { return m_data + m_size; } - const T* end() const { return m_data + m_size; } - T& front() { IM3D_ASSERT(m_size > 0); return m_data[0]; } - const T& front() const { IM3D_ASSERT(m_size > 0); return m_data[0]; } - T& back() { IM3D_ASSERT(m_size > 0); return m_data[m_size - 1]; } - const T& back() const { IM3D_ASSERT(m_size > 0); return m_data[m_size - 1]; } - - U32 size() const { return m_size; } - U32 capacity() const { return m_capacity; } - bool empty() const { return m_size == 0; } - - void clear() { m_size = 0; } - void reserve(U32 _capacity); - void resize(U32 _size, const T& _val); - void resize(U32 _size); + Vector() {} + ~Vector(); + + T& operator[](U32 _i) { IM3D_ASSERT(_i < m_size); return m_data[_i]; } + const T& operator[](U32 _i) const { IM3D_ASSERT(_i < m_size); return m_data[_i]; } + T* data() { return m_data; } + const T* data() const { return m_data; } + + T& push_back() { if (m_size == m_capacity) { reserve(m_capacity + m_capacity / 2); } return m_data[m_size++]; } + void push_back(const T& _v) { T tmp = _v; if (m_size == m_capacity) { reserve(m_capacity + m_capacity / 2); } m_data[m_size++] = tmp; } + void pop_back() { IM3D_ASSERT(m_size > 0); --m_size; } + void append(const T* _v, U32 _count); + void append(const Vector& _other) { append(_other.data(), _other.size()); } + + T* begin() { return m_data; } + const T* begin() const { return m_data; } + T* end() { return m_data + m_size; } + const T* end() const { return m_data + m_size; } + T& front() { IM3D_ASSERT(m_size > 0); return m_data[0]; } + const T& front() const { IM3D_ASSERT(m_size > 0); return m_data[0]; } + T& back() { IM3D_ASSERT(m_size > 0); return m_data[m_size - 1]; } + const T& back() const { IM3D_ASSERT(m_size > 0); return m_data[m_size - 1]; } + + U32 size() const { return m_size; } + U32 capacity() const { return m_capacity; } + bool empty() const { return m_size == 0; } + + void clear() { m_size = 0; } + void reserve(U32 _capacity); + void resize(U32 _size, const T& _val); + void resize(U32 _size); static void swap(Vector& _a_, Vector& _b_); @@ -565,131 +596,134 @@ enum GizmoMode // Context stores all relevant state - main interface affects the context currently bound via SetCurrentContext(). struct IM3D_API Context { - void begin(PrimitiveMode _mode); - void end(); - void vertex(const Vec3& _position, float _size, Color _color); - void vertex(const Vec3& _position ) { vertex(_position, getSize(), getColor()); } + Context(); + ~Context(); - void text(const Vec3& _position, float _size, Color _color, TextFlags _flags, const char* _textStart, const char* _textEnd); - void text(const Vec3& _position, float _size, Color _color, TextFlags _flags, const char* _text, va_list _args); + void begin(PrimitiveMode _mode); + void end(); - void reset(); - void merge(const Context& _src); - void endFrame(); - void draw(); // DEPRECATED (see Im3d::Draw) + void vertex(const Vec3& _position, float _size, Color _color); + void vertex(const Vec3& _position ) { vertex(_position, getSize(), getColor()); } - const DrawList* getDrawLists() const { return m_drawLists.data(); } - U32 getDrawListCount() const { return m_drawLists.size(); } + void text(const Vec3& _position, float _size, Color _color, TextFlags _flags, const char* _textStart, const char* _textEnd); + void text(const Vec3& _position, float _size, Color _color, TextFlags _flags, const char* _text, va_list _args); - const TextDrawList* getTextDrawLists() const { return m_textDrawLists.data(); } - U32 getTextDrawListCount() const { return m_textDrawLists.size(); } + void reset(); + void merge(const Context& _src); + void endFrame(); + void draw(); // DEPRECATED (see Im3d::Draw) + const DrawList* getDrawLists() const { return m_drawLists.data(); } + U32 getDrawListCount() const { return m_drawLists.size(); } - void setColor(Color _color) { m_colorStack.back() = _color; } - Color getColor() const { return m_colorStack.back(); } - void pushColor(Color _color) { m_colorStack.push_back(_color); } - void popColor() { IM3D_ASSERT(m_colorStack.size() > 1); m_colorStack.pop_back(); } + const TextDrawList* getTextDrawLists() const { return m_textDrawLists.data(); } + U32 getTextDrawListCount() const { return m_textDrawLists.size(); } - void setAlpha(float _alpha) { m_alphaStack.back() = _alpha; } - float getAlpha() const { return m_alphaStack.back(); } - void pushAlpha(float _alpha) { m_alphaStack.push_back(_alpha); } - void popAlpha() { IM3D_ASSERT(m_alphaStack.size() > 1); m_alphaStack.pop_back(); } - void setSize(float _size) { m_sizeStack.back() = _size; } - float getSize() const { return m_sizeStack.back(); } - void pushSize(float _size) { m_sizeStack.push_back(_size); } - void popSize() { IM3D_ASSERT(m_sizeStack.size() > 1); m_sizeStack.pop_back(); } + void setColor(Color _color) { m_colorStack.back() = _color; } + Color getColor() const { return m_colorStack.back(); } + void pushColor(Color _color) { m_colorStack.push_back(_color); } + void popColor() { IM3D_ASSERT(m_colorStack.size() > 1); m_colorStack.pop_back(); } - void setEnableSorting(bool _enable); - bool getEnableSorting() const { return m_enableSortingStack.back(); } - void pushEnableSorting(bool _enable); - void popEnableSorting(); + void setAlpha(float _alpha) { m_alphaStack.back() = _alpha; } + float getAlpha() const { return m_alphaStack.back(); } + void pushAlpha(float _alpha) { m_alphaStack.push_back(_alpha); } + void popAlpha() { IM3D_ASSERT(m_alphaStack.size() > 1); m_alphaStack.pop_back(); } - Id getLayerId() const { return m_layerIdStack.back(); } - void pushLayerId(Id _layer); - void popLayerId(); + void setSize(float _size) { m_sizeStack.back() = _size; } + float getSize() const { return m_sizeStack.back(); } + void pushSize(float _size) { m_sizeStack.push_back(_size); } + void popSize() { IM3D_ASSERT(m_sizeStack.size() > 1); m_sizeStack.pop_back(); } - void setMatrix(const Mat4& _mat4) { m_matrixStack.back() = _mat4; } - const Mat4& getMatrix() const { return m_matrixStack.back(); } - void pushMatrix(const Mat4& _mat4) { m_matrixStack.push_back(_mat4); } - void popMatrix() { IM3D_ASSERT(m_matrixStack.size() > 1); m_matrixStack.pop_back(); } + void setEnableSorting(bool _enable); + bool getEnableSorting() const { return m_enableSortingStack.back(); } + void pushEnableSorting(bool _enable); + void popEnableSorting(); - void setId(Id _id) { m_idStack.back() = _id; } - Id getId() const { return m_idStack.back(); } - void pushId(Id _id) { m_idStack.push_back(_id); } - void popId() { IM3D_ASSERT(m_idStack.size() > 1); m_idStack.pop_back(); } + Id getLayerId() const { return m_layerIdStack.back(); } + void pushLayerId(Id _layer); + void popLayerId(); - AppData& getAppData() { return m_appData; } + void setMatrix(const Mat4& _mat4) { m_matrixStack.back() = _mat4; } + const Mat4& getMatrix() const { return m_matrixStack.back(); } + void pushMatrix(const Mat4& _mat4) { m_matrixStack.push_back(_mat4); } + void popMatrix() { IM3D_ASSERT(m_matrixStack.size() > 1); m_matrixStack.pop_back(); } - Context(); - ~Context(); + void setId(Id _id) { m_idStack.back() = _id; } + Id getId() const { return m_idStack.back(); } + void pushId(Id _id) { m_idStack.push_back(_id); } + void popId() { IM3D_ASSERT(m_idStack.size() > 1); m_idStack.pop_back(); } - // low-level interface for internal and app-defined gizmos, may be subject to breaking changes + AppData& getAppData() { return m_appData; } - bool gizmoAxisTranslation_Behavior(Id _id, const Vec3& _origin, const Vec3& _axis, float _snap, float _worldHeight, float _worldSize, Vec3* _out_); - void gizmoAxisTranslation_Draw (Id _id, const Vec3& _origin, const Vec3& _axis, float _worldHeight, float _worldSize, Color _color); + // Low-level interface for internal and app-defined gizmos. May be subject to breaking changes. - bool gizmoPlaneTranslation_Behavior(Id _id, const Vec3& _origin, const Vec3& _normal, float _snap, float _worldSize, Vec3* _out_); - void gizmoPlaneTranslation_Draw (Id _id, const Vec3& _origin, const Vec3& _normal, float _worldSize, Color _color); + bool gizmoAxisTranslation_Behavior(Id _id, const Vec3& _origin, const Vec3& _axis, float _snap, float _worldHeight, float _worldSize, Vec3* _out_); + void gizmoAxisTranslation_Draw(Id _id, const Vec3& _origin, const Vec3& _axis, float _worldHeight, float _worldSize, Color _color); - bool gizmoAxislAngle_Behavior(Id _id, const Vec3& _origin, const Vec3& _axis, float _snap, float _worldRadius, float _worldSize, float* _out_); - void gizmoAxislAngle_Draw (Id _id, const Vec3& _origin, const Vec3& _axis, float _worldRadius, float _angle, Color _color); + bool gizmoPlaneTranslation_Behavior(Id _id, const Vec3& _origin, const Vec3& _normal, float _snap, float _worldSize, Vec3* _out_); + void gizmoPlaneTranslation_Draw(Id _id, const Vec3& _origin, const Vec3& _normal, float _worldSize, Color _color); - bool gizmoAxisScale_Behavior(Id _id, const Vec3& _origin, const Vec3& _axis, float _snap, float _worldHeight, float _worldSize, float *_out_); - void gizmoAxisScale_Draw (Id _id, const Vec3& _origin, const Vec3& _axis, float _worldHeight, float _worldSize, Color _color); + bool gizmoAxislAngle_Behavior(Id _id, const Vec3& _origin, const Vec3& _axis, float _snap, float _worldRadius, float _worldSize, float* _out_); + void gizmoAxislAngle_Draw(Id _id, const Vec3& _origin, const Vec3& _axis, float _worldRadius, float _angle, Color _color); + + bool gizmoAxisScale_Behavior(Id _id, const Vec3& _origin, const Vec3& _axis, float _snap, float _worldHeight, float _worldSize, float *_out_); + void gizmoAxisScale_Draw(Id _id, const Vec3& _origin, const Vec3& _axis, float _worldHeight, float _worldSize, Color _color); // Convert pixels -> world space size based on distance between _position and view origin. - float pixelsToWorldSize(const Vec3& _position, float _pixels); + float pixelsToWorldSize(const Vec3& _position, float _pixels); // Convert world space size -> pixels based on distance between _position and view origin. - float worldSizeToPixels(const Vec3& _position, float _pixels); + float worldSizeToPixels(const Vec3& _position, float _pixels); // Blend between _min and _max based on distance betwen _position and view origin. - int estimateLevelOfDetail(const Vec3& _position, float _worldSize, int _min = 4, int _max = 256); + int estimateLevelOfDetail(const Vec3& _position, float _worldSize, int _min = 4, int _max = 256); // Make _id hot if _depth < m_hotDepth && _intersects. - bool makeHot(Id _id, float _depth, bool _intersects); + bool makeHot(Id _id, float _depth, bool _intersects); // Make _id active. - void makeActive(Id _id); + void makeActive(Id _id); // Reset the acive/hot ids and the hot depth. - void resetId(); + void resetId(); // Interpret key state. - bool isKeyDown(Key _key) const { return m_keyDownCurr[_key]; } - bool wasKeyPressed(Key _key) const { return m_keyDownCurr[_key] && !m_keyDownPrev[_key]; } + bool isKeyDown(Key _key) const { return m_keyDownCurr[_key]; } + bool wasKeyPressed(Key _key) const { return m_keyDownCurr[_key] && !m_keyDownPrev[_key]; } // Visibiity tests for culling. - bool isVisible(const VertexData* _vdata, DrawPrimitiveType _prim); // per-vertex - bool isVisible(const Vec3& _origin, float _radius); // sphere - bool isVisible(const Vec3& _min, const Vec3& _max); // axis-aligned box - - // gizmo state - bool m_gizmoLocal; // Global mode selection for gizmos. - GizmoMode m_gizmoMode; // " - Id m_activeId; // Currently active gizmo. If set, this is the same as m_hotId. - Id m_hotId; - Id m_appId; - Id m_appActiveId; - Id m_appHotId; - float m_hotDepth; // Depth of the current hot gizmo along the cursor ray, for handling occlusion. - Vec3 m_gizmoStateVec3; // Stored state for the active gizmo. - Mat3 m_gizmoStateMat3; // " - float m_gizmoStateFloat; // " - float m_gizmoHeightPixels; // Height/radius of gizmos. - float m_gizmoSizePixels; // Thickness of gizmo lines. - - - // stats/debugging + bool isVisible(const VertexData* _vdata, DrawPrimitiveType _prim); // per-vertex + bool isVisible(const Vec3& _origin, float _radius); // sphere + bool isVisible(const Vec3& _min, const Vec3& _max); // axis-aligned box + + // Gizmo state. + + bool m_gizmoLocal; // Global mode selection for gizmos. + GizmoMode m_gizmoMode; // " + Id m_activeId; // Currently active gizmo. If set, this is the same as m_hotId. + Id m_hotId; // ID of the current 'hot' gizmo (nearest intersecting gizmo along the cursor ray). NB this is the id of the *sub* gizmo, not the app-specified ID. + float m_hotDepth; // Depth of the current hot gizmo along the cursor ray, for handling occlusion. + Id m_appId; // Current ID *without* the hashing the ID stack (= _id arg to Gizmo* functions). + Id m_appActiveId; // Copied from m_appId for the current active gizmo. + Id m_appHotId; // Copied from m_appId for the current 'hot' gizmo. + Vec3 m_gizmoStateVec3; // Stored state for the active gizmo. + Mat3 m_gizmoStateMat3; // " + float m_gizmoStateFloat; // " + float m_gizmoHeightPixels; // Height/radius of gizmos. + float m_gizmoSizePixels; // Thickness of gizmo lines. + + + // Stats, debugging. // Return the total number of primitives (sorted + unsorted) of the given _type in all layers. - U32 getPrimitiveCount(DrawPrimitiveType _type) const; + U32 getPrimitiveCount(DrawPrimitiveType _type) const; // Return the total number of text primitives in all layers. - U32 getTextCount() const; + U32 getTextCount() const; // Return the number of layers. - U32 getLayerCount() const { return m_layerIdMap.size(); } + U32 getLayerCount() const { return m_layerIdMap.size(); } private: - // state stacks + + // State stacks. Vector m_colorStack; Vector m_alphaStack; Vector m_sizeStack; @@ -698,147 +732,148 @@ struct IM3D_API Context Vector m_idStack; Vector m_layerIdStack; - // vertex data: one list per layer, per primitive type, *2 for sorted/unsorted + // Vertex data: one list per layer, per primitive type, *2 for sorted/unsorted. typedef Vector VertexList; - Vector m_vertexData[2]; // Each layer is DrawPrimitive_Count consecutive lists. - int m_vertexDataIndex; // 0, or 1 if sorting enabled. - Vector m_layerIdMap; // Map Id -> vertex data index. - int m_layerIndex; // Index of the currently active layer in m_layerIdMap. - Vector m_drawLists; // All draw lists for the current frame, available after calling endFrame() before calling reset(). - bool m_sortCalled; // Avoid calling sort() during every call to draw(). - bool m_endFrameCalled; // For assert, if vertices are pushed after endFrame() was called. - - // text data: one list per layer + Vector m_vertexData[2]; // Each layer is DrawPrimitive_Count consecutive lists. + int m_vertexDataIndex; // 0, or 1 if sorting enabled. + Vector m_layerIdMap; // Map Id -> vertex data index. + int m_layerIndex; // Index of the currently active layer in m_layerIdMap. + Vector m_drawLists; // All draw lists for the current frame, available after calling endFrame() before calling reset(). + bool m_sortCalled; // Avoid calling sort() during every call to draw(). + bool m_endFrameCalled; // For assert, if vertices are pushed after endFrame() was called. + + // Text data: one list per layer. typedef Vector TextList; Vector m_textData; Vector m_textBuffer; Vector m_textDrawLists; - // primitive state + // Primitive state. PrimitiveMode m_primMode; DrawPrimitiveType m_primType; - U32 m_firstVertThisPrim; // Index of the first vertex pushed during this primitive. - U32 m_vertCountThisPrim; // # calls to vertex() since the last call to begin(). + U32 m_firstVertThisPrim; // Index of the first vertex pushed during this primitive. + U32 m_vertCountThisPrim; // # calls to vertex() since the last call to begin(). Vec3 m_minVertThisPrim; Vec3 m_maxVertThisPrim; - // app data + // App data. AppData m_appData; - bool m_keyDownCurr[Key_Count]; // Key state captured during reset(). - bool m_keyDownPrev[Key_Count]; // Key state from previous frame. + bool m_keyDownCurr[Key_Count]; // Key state captured during reset(). + bool m_keyDownPrev[Key_Count]; // Key state from previous frame. Vec4 m_cullFrustum[FrustumPlane_Count]; // Optimized frustum planes from m_appData.m_cullFrustum. - int m_cullFrustumCount; // # valid frustum planes in m_cullFrustum. - + int m_cullFrustumCount; // # valid frustum planes in m_cullFrustum. // Sort primitive data. - void sort(); + void sort(); // Return -1 if _id not found. - int findLayerIndex(Id _id) const; + int findLayerIndex(Id _id) const; - VertexList* getCurrentVertexList(); - TextList* getCurrentTextList(); + // Access the current vertex/text data based on m_layerIndex. + VertexList* getCurrentVertexList(); + TextList* getCurrentTextList(); }; namespace internal { - #if IM3D_THREAD_LOCAL_CONTEXT_PTR - #define IM3D_THREAD_LOCAL thread_local - #else - #define IM3D_THREAD_LOCAL - #endif - extern IM3D_THREAD_LOCAL Context* g_CurrentContext; + +#if IM3D_THREAD_LOCAL_CONTEXT_PTR + #define IM3D_THREAD_LOCAL thread_local +#else + #define IM3D_THREAD_LOCAL +#endif + +extern IM3D_THREAD_LOCAL Context* g_CurrentContext; + } -inline AppData& GetAppData() { return GetContext().getAppData(); } -inline void NewFrame() { GetContext().reset(); } -inline void EndFrame() { GetContext().endFrame(); } -inline void Draw() { GetContext().draw(); } - -inline const DrawList* GetDrawLists() { return GetContext().getDrawLists(); } -inline U32 GetDrawListCount() { return GetContext().getDrawListCount(); } - -inline const TextDrawList* GetTextDrawLists() { return GetContext().getTextDrawLists(); } -inline U32 GetTextDrawListCount() { return GetContext().getTextDrawListCount(); } - -inline void BeginPoints() { GetContext().begin(PrimitiveMode_Points); } -inline void BeginLines() { GetContext().begin(PrimitiveMode_Lines); } -inline void BeginLineLoop() { GetContext().begin(PrimitiveMode_LineLoop); } -inline void BeginLineStrip() { GetContext().begin(PrimitiveMode_LineStrip); } -inline void BeginTriangles() { GetContext().begin(PrimitiveMode_Triangles); } -inline void BeginTriangleStrip() { GetContext().begin(PrimitiveMode_TriangleStrip); } -inline void End() { GetContext().end(); } - -inline void Vertex(const Vec3& _position) { GetContext().vertex(_position, GetContext().getSize(), GetContext().getColor()); } -inline void Vertex(const Vec3& _position, Color _color) { GetContext().vertex(_position, GetContext().getSize(), _color); } -inline void Vertex(const Vec3& _position, float _size) { GetContext().vertex(_position, _size, GetContext().getColor()); } -inline void Vertex(const Vec3& _position, float _size, Color _color) { GetContext().vertex(_position, _size, _color); } -inline void Vertex(float _x, float _y, float _z) { Vertex(Vec3(_x, _y, _z)); } -inline void Vertex(float _x, float _y, float _z, Color _color) { Vertex(Vec3(_x, _y, _z), _color); } -inline void Vertex(float _x, float _y, float _z, float _size) { Vertex(Vec3(_x, _y, _z), _size); } -inline void Vertex(float _x, float _y, float _z, float _size, Color _color) { Vertex(Vec3(_x, _y, _z), _size, _color); } - -inline void PushDrawState() { Context& ctx = GetContext(); ctx.pushColor(ctx.getColor()); ctx.pushAlpha(ctx.getAlpha()); ctx.pushSize(ctx.getSize()); ctx.pushEnableSorting(ctx.getEnableSorting()); } -inline void PopDrawState() { Context& ctx = GetContext(); ctx.popColor(); ctx.popAlpha(); ctx.popSize(); ctx.popEnableSorting(); } - -inline void PushColor() { GetContext().pushColor(GetContext().getColor()); } -inline void PushColor(Color _color) { GetContext().pushColor(_color); } -inline void PopColor() { GetContext().popColor(); } -inline void SetColor(Color _color) { GetContext().setColor(_color); } -inline void SetColor(float _r, float _g, float _b, float _a) { GetContext().setColor(Color(_r, _g, _b, _a)); } -inline Color GetColor() { return GetContext().getColor(); } - -inline void PushAlpha() { GetContext().pushAlpha(GetContext().getAlpha()); } -inline void PushAlpha(float _alpha) { GetContext().pushAlpha(_alpha); } -inline void PopAlpha() { GetContext().popAlpha(); } -inline void SetAlpha(float _alpha) { GetContext().setAlpha(_alpha); } -inline float GetAlpha() { return GetContext().getAlpha(); } - -inline void PushSize() { GetContext().pushSize(GetContext().getAlpha()); } -inline void PushSize(float _size) { GetContext().pushSize(_size); } -inline void PopSize() { GetContext().popSize(); } -inline void SetSize(float _size) { GetContext().setSize(_size); } -inline float GetSize() { return GetContext().getSize(); } - -inline void PushEnableSorting() { GetContext().pushEnableSorting(GetContext().getEnableSorting()); } -inline void PushEnableSorting(bool _enable) { GetContext().pushEnableSorting(_enable); } -inline void PopEnableSorting() { GetContext().popEnableSorting(); } -inline void EnableSorting(bool _enable) { GetContext().setEnableSorting(_enable); } - -inline void PushMatrix() { GetContext().pushMatrix(GetContext().getMatrix()); } -inline void PushMatrix(const Mat4& _mat4) { GetContext().pushMatrix(_mat4); } -inline void PopMatrix() { GetContext().popMatrix(); } -inline void SetMatrix(const Mat4& _mat4) { GetContext().setMatrix(_mat4); } -inline void SetIdentity() { GetContext().setMatrix(Mat4(1.0f)); } - -inline void PushId() { GetContext().pushId(GetContext().getId()); } -inline void PushId(Id _id) { GetContext().pushId(_id); } -inline void PushId(const char* _str) { GetContext().pushId(MakeId(_str)); } -inline void PushId(const void* _ptr) { GetContext().pushId(MakeId(_ptr)); } -inline void PushId(int _i) { GetContext().pushId(MakeId(_i)); } -inline void PopId() { GetContext().popId(); } -inline Id GetId() { return GetContext().getId(); } -inline Id GetActiveId() { return GetContext().m_appActiveId; } -inline Id GetHotId() { return GetContext().m_appHotId; } - -inline void PushLayerId() { GetContext().pushLayerId(GetContext().getLayerId()); } -inline void PushLayerId(Id _layer) { GetContext().pushLayerId(_layer); } -inline void PushLayerId(const char* _str) { PushLayerId(MakeId(_str)); } -inline void PopLayerId() { GetContext().popLayerId(); } -inline Id GetLayerId() { return GetContext().getLayerId(); } - -inline bool GizmoTranslation(const char* _id, float _translation_[3], bool _local) { return GizmoTranslation(MakeId(_id), _translation_, _local); } -inline bool GizmoRotation(const char* _id, float _rotation_[3*3], bool _local) { return GizmoRotation(MakeId(_id), _rotation_, _local); } -inline bool GizmoScale(const char* _id, float _scale_[3]) { return GizmoScale(MakeId(_id), _scale_); } -inline bool Gizmo(const char* _id, float _translation_[3], float _rotation_[3*3], float _scale_[3]) { return Gizmo(MakeId(_id), _translation_, _rotation_, _scale_); } -inline bool Gizmo(const char* _id, float _transform_[4*4]) { return Gizmo(MakeId(_id), _transform_); } - -inline bool IsVisible(const Vec3& _origin, float _radius) { return GetContext().isVisible(_origin, _radius); } -inline bool IsVisible(const Vec3& _min, const Vec3& _max) { return GetContext().isVisible(_min, _max); } - -inline Context& GetContext() { return *internal::g_CurrentContext; } -inline void SetContext(Context& _ctx) { internal::g_CurrentContext = &_ctx; } - -inline void MergeContexts(Context& _dst_, const Context& _src) { _dst_.merge(_src); } +inline AppData& GetAppData() { return GetContext().getAppData(); } +inline void NewFrame() { GetContext().reset(); } +inline void EndFrame() { GetContext().endFrame(); } +inline void Draw() { GetContext().draw(); } + +inline const DrawList* GetDrawLists() { return GetContext().getDrawLists(); } +inline U32 GetDrawListCount() { return GetContext().getDrawListCount(); } + +inline const TextDrawList* GetTextDrawLists() { return GetContext().getTextDrawLists(); } +inline U32 GetTextDrawListCount() { return GetContext().getTextDrawListCount(); } + +inline void BeginPoints() { GetContext().begin(PrimitiveMode_Points); } +inline void BeginLines() { GetContext().begin(PrimitiveMode_Lines); } +inline void BeginLineLoop() { GetContext().begin(PrimitiveMode_LineLoop); } +inline void BeginLineStrip() { GetContext().begin(PrimitiveMode_LineStrip); } +inline void BeginTriangles() { GetContext().begin(PrimitiveMode_Triangles); } +inline void BeginTriangleStrip() { GetContext().begin(PrimitiveMode_TriangleStrip); } +inline void End() { GetContext().end(); } + +inline void Vertex(const Vec3& _position) { GetContext().vertex(_position, GetContext().getSize(), GetContext().getColor()); } +inline void Vertex(const Vec3& _position, Color _color) { GetContext().vertex(_position, GetContext().getSize(), _color); } +inline void Vertex(const Vec3& _position, float _size) { GetContext().vertex(_position, _size, GetContext().getColor()); } +inline void Vertex(const Vec3& _position, float _size, Color _color) { GetContext().vertex(_position, _size, _color); } +inline void Vertex(float _x, float _y, float _z) { Vertex(Vec3(_x, _y, _z)); } +inline void Vertex(float _x, float _y, float _z, Color _color) { Vertex(Vec3(_x, _y, _z), _color); } +inline void Vertex(float _x, float _y, float _z, float _size) { Vertex(Vec3(_x, _y, _z), _size); } +inline void Vertex(float _x, float _y, float _z, float _size, Color _color) { Vertex(Vec3(_x, _y, _z), _size, _color); } + +inline void PushDrawState() { Context& ctx = GetContext(); ctx.pushColor(ctx.getColor()); ctx.pushAlpha(ctx.getAlpha()); ctx.pushSize(ctx.getSize()); ctx.pushEnableSorting(ctx.getEnableSorting()); } +inline void PopDrawState() { Context& ctx = GetContext(); ctx.popColor(); ctx.popAlpha(); ctx.popSize(); ctx.popEnableSorting(); } + +inline void PushColor() { GetContext().pushColor(GetContext().getColor()); } +inline void PushColor(Color _color) { GetContext().pushColor(_color); } +inline void PopColor() { GetContext().popColor(); } +inline void SetColor(Color _color) { GetContext().setColor(_color); } +inline void SetColor(float _r, float _g, float _b, float _a) { GetContext().setColor(Color(_r, _g, _b, _a)); } +inline Color GetColor() { return GetContext().getColor(); } + +inline void PushAlpha() { GetContext().pushAlpha(GetContext().getAlpha()); } +inline void PushAlpha(float _alpha) { GetContext().pushAlpha(_alpha); } +inline void PopAlpha() { GetContext().popAlpha(); } +inline void SetAlpha(float _alpha) { GetContext().setAlpha(_alpha); } +inline float GetAlpha() { return GetContext().getAlpha(); } + +inline void PushSize() { GetContext().pushSize(GetContext().getAlpha()); } +inline void PushSize(float _size) { GetContext().pushSize(_size); } +inline void PopSize() { GetContext().popSize(); } +inline void SetSize(float _size) { GetContext().setSize(_size); } +inline float GetSize() { return GetContext().getSize(); } + +inline void PushEnableSorting() { GetContext().pushEnableSorting(GetContext().getEnableSorting()); } +inline void PushEnableSorting(bool _enable) { GetContext().pushEnableSorting(_enable); } +inline void PopEnableSorting() { GetContext().popEnableSorting(); } +inline void EnableSorting(bool _enable) { GetContext().setEnableSorting(_enable); } + +inline void PushMatrix() { GetContext().pushMatrix(GetContext().getMatrix()); } +inline void PushMatrix(const Mat4& _mat4) { GetContext().pushMatrix(_mat4); } +inline void PopMatrix() { GetContext().popMatrix(); } +inline void SetMatrix(const Mat4& _mat4) { GetContext().setMatrix(_mat4); } +inline void SetIdentity() { GetContext().setMatrix(Mat4(1.0f)); } + +inline void PushId() { GetContext().pushId(GetContext().getId()); } +inline void PushId(Id _id) { GetContext().pushId(_id); } +inline void PushId(const char* _str) { GetContext().pushId(MakeId(_str)); } +inline void PushId(const void* _ptr) { GetContext().pushId(MakeId(_ptr)); } +inline void PushId(int _i) { GetContext().pushId(MakeId(_i)); } +inline void PopId() { GetContext().popId(); } +inline Id GetId() { return GetContext().getId(); } + +inline void PushLayerId() { GetContext().pushLayerId(GetContext().getLayerId()); } +inline void PushLayerId(Id _layer) { GetContext().pushLayerId(_layer); } +inline void PushLayerId(const char* _str) { PushLayerId(MakeId(_str)); } +inline void PopLayerId() { GetContext().popLayerId(); } +inline Id GetLayerId() { return GetContext().getLayerId(); } + +inline bool GizmoTranslation(const char* _id, float _translation_[3], bool _local) { return GizmoTranslation(MakeId(_id), _translation_, _local); } +inline bool GizmoRotation(const char* _id, float _rotation_[3*3], bool _local) { return GizmoRotation(MakeId(_id), _rotation_, _local);} +inline bool GizmoScale(const char* _id, float _scale_[3]) { return GizmoScale(MakeId(_id), _scale_); } +inline bool Gizmo(const char* _id, float _translation_[3], float _rotation_[3*3], float _scale_[3]) { return Gizmo(MakeId(_id), _translation_, _rotation_, _scale_); } +inline bool Gizmo(const char* _id, float _transform_[4*4]) { return Gizmo(MakeId(_id), _transform_); } +inline Id GetActiveId() { return GetContext().m_appActiveId;} +inline Id GetHotId() { return GetContext().m_appHotId; } + +inline bool IsVisible(const Vec3& _origin, float _radius) { return GetContext().isVisible(_origin, _radius); } +inline bool IsVisible(const Vec3& _min, const Vec3& _max) { return GetContext().isVisible(_min, _max);} + +inline Context& GetContext() { return *internal::g_CurrentContext; } +inline void SetContext(Context& _ctx) { internal::g_CurrentContext = &_ctx; } +inline void MergeContexts(Context& _dst_, const Context& _src) { _dst_.merge(_src); } } // namespac Im3d - diff --git a/im3d_math.h b/im3d_math.h index 8cc5d1f..fc1276c 100644 --- a/im3d_math.h +++ b/im3d_math.h @@ -71,6 +71,7 @@ inline Mat3 operator*(const Mat3& _lhs, const Mat3& _rhs) ret(2, 0) = _lhs(2, 0) * _rhs(0, 0) + _lhs(2, 1) * _rhs(1, 0) + _lhs(2, 2) * _rhs(2, 0); ret(2, 1) = _lhs(2, 0) * _rhs(0, 1) + _lhs(2, 1) * _rhs(1, 1) + _lhs(2, 2) * _rhs(2, 1); ret(2, 2) = _lhs(2, 0) * _rhs(0, 2) + _lhs(2, 1) * _rhs(1, 2) + _lhs(2, 2) * _rhs(2, 2); + return ret; } inline Vec3 operator*(const Mat3& _m, const Vec3& _v) @@ -116,6 +117,7 @@ inline Mat4 operator*(const Mat4& _lhs, const Mat4& _rhs) ret(3, 1) = _lhs(3, 0) * _rhs(0, 1) + _lhs(3, 1) * _rhs(1, 1) + _lhs(3, 2) * _rhs(2, 1) + _lhs(3, 3) * _rhs(3, 1); ret(3, 2) = _lhs(3, 0) * _rhs(0, 2) + _lhs(3, 1) * _rhs(1, 2) + _lhs(3, 2) * _rhs(2, 2) + _lhs(3, 3) * _rhs(3, 2); ret(3, 3) = _lhs(3, 0) * _rhs(0, 3) + _lhs(3, 1) * _rhs(1, 3) + _lhs(3, 2) * _rhs(2, 3) + _lhs(3, 3) * _rhs(3, 3); + return ret; } inline Vec3 operator*(const Mat4& _m, const Vec3& _pos) @@ -194,11 +196,11 @@ struct Capsule // Ray-primitive intersections. Use Intersects() when you don't need t. -bool Intersects(const Ray& _ray, const Plane& _plane); -bool Intersect (const Ray& _ray, const Plane& _plane, float& t0_); -bool Intersects(const Ray& _ray, const Sphere& _sphere); -bool Intersect (const Ray& _ray, const Sphere& _sphere, float& t0_, float& t1_); -bool Intersects(const Ray& _ray, const Capsule& _capsule); +bool Intersects(const Ray& _ray, const Plane& _plane ); +bool Intersect (const Ray& _ray, const Plane& _plane, float& t0_ ); +bool Intersects(const Ray& _ray, const Sphere& _sphere ); +bool Intersect (const Ray& _ray, const Sphere& _sphere, float& t0_, float& t1_); +bool Intersects(const Ray& _ray, const Capsule& _capsule ); bool Intersect (const Ray& _ray, const Capsule& _capsule, float& t0_, float& t1_); // Find point t0_ along _line0 nearest to _line1 and t1_ along _line1 nearest to _line0. @@ -210,7 +212,7 @@ Vec3 Nearest(const Ray& _ray, const LineSegment& _segment, float& tr_); float Distance2(const Ray& _ray, const LineSegment& _segment); -inline float Distance(const Vec4& _plane, const Vec3& _point) { return _plane.x * _point.x + _plane.y * _point.y + _plane.z * _point.z - _plane.w; } +inline float Distance(const Vec4& _plane, const Vec3& _point){ return _plane.x * _point.x + _plane.y * _point.y + _plane.z * _point.z - _plane.w; } constexpr float Pi = 3.14159265359f; constexpr float TwoPi = 2.0f * Pi; @@ -244,8 +246,10 @@ inline bool _AllLess(const T& _a, const T& _b, ScalarT) template inline bool _AllLess(const T& _a, const T& _b, CompositeT) { - for (int i = 0, n = TypeTraits::kSize; i < n; ++i) { - if (_a[i] > _b[i]) { + for (int i = 0, n = TypeTraits::kSize; i < n; ++i) + { + if (_a[i] > _b[i]) + { return false; } } @@ -276,7 +280,8 @@ template inline T _Min(const T& _a, const T& _b, CompositeT) { T ret; - for (int i = 0, n = TypeTraits::kSize; i < n; ++i) { + for (int i = 0, n = TypeTraits::kSize; i < n; ++i) + { ret[i] = _Min(_a[i], _b[i], ScalarT()); } return ret;