diff --git a/Content/Documentation/ScriptingAPI-Documentation.md b/Content/Documentation/ScriptingAPI-Documentation.md index 518c4ea68..b49d26eb8 100644 --- a/Content/Documentation/ScriptingAPI-Documentation.md +++ b/Content/Documentation/ScriptingAPI-Documentation.md @@ -147,11 +147,11 @@ You can use the Renderer with the following functions, all of which are in the g - SetDebugCamerasEnabled(bool value) - SetVSyncEnabled(opt bool enabled) - SetOcclusionCullingEnabled(bool enabled) -- DrawLine(Vector origin,end, opt Vector color) -- DrawPoint(Vector origin, opt float size, opt Vector color) -- DrawBox(Matrix boxMatrix, opt Vector color) -- DrawSphere(Sphere sphere, opt Vector color) -- DrawCapsule(Capsule capsule, opt Vector color) +- DrawLine(Vector origin,end, opt Vector color, opt bool depth = false) +- DrawPoint(Vector origin, opt float size, opt Vector color, opt bool depth = false) +- DrawBox(Matrix boxMatrix, opt Vector color, opt bool depth = true) +- DrawSphere(Sphere sphere, opt Vector color, opt bool depth = true) +- DrawCapsule(Capsule capsule, opt Vector color, opt bool depth = true) - DrawDebugText(string text, opt Vector position, opt Vector color, opt float scaling, opt int flags) DrawDebugText flags, these can be combined with binary OR operator: [outer]DEBUG_TEXT_DEPTH_TEST -- text can be occluded by geometry diff --git a/Editor/Editor.cpp b/Editor/Editor.cpp index 308bea35a..b8ba6691b 100644 --- a/Editor/Editor.cpp +++ b/Editor/Editor.cpp @@ -2047,12 +2047,17 @@ void EditorComponent::Update(float dt) } bool force_collider_visualizer = false; + bool force_spring_visualizer = false; for (auto& x : translator.selected) { if (scene.colliders.Contains(x.entity)) { force_collider_visualizer = true; } + if (scene.springs.Contains(x.entity)) + { + force_spring_visualizer = true; + } } if (force_collider_visualizer) { @@ -2062,6 +2067,14 @@ void EditorComponent::Update(float dt) { wi::renderer::SetToDrawDebugColliders(optionsWnd.generalWnd.colliderVisCheckBox.GetCheck()); } + if (force_spring_visualizer) + { + wi::renderer::SetToDrawDebugSprings(true); + } + else + { + wi::renderer::SetToDrawDebugSprings(optionsWnd.generalWnd.springVisCheckBox.GetCheck()); + } } void EditorComponent::PostUpdate() { @@ -2147,19 +2160,6 @@ void EditorComponent::Render() const wi::renderer::DrawBox(hoverBox, XMFLOAT4(0, 0.5f, 0, 0.5f)); } } - - // Spring visualizer: - if (componentsWnd.springWnd.debugCheckBox.GetCheck()) - { - for (size_t i = 0; i < scene.springs.GetCount(); ++i) - { - const SpringComponent& spring = scene.springs[i]; - wi::primitive::Sphere sphere; - sphere.center = spring.currentTail; - sphere.radius = spring.hitRadius; - wi::renderer::DrawSphere(sphere, XMFLOAT4(1, 1, 0, 1)); - } - } } // Selected items box: @@ -2990,54 +2990,63 @@ void EditorComponent::Render() const const TransformComponent& transform = *scene.transforms.GetComponent(entity); XMVECTOR a = transform.GetPositionV(); XMVECTOR b = a + XMVectorSet(0, 0.1f, 0, 0); - // Search for child to connect bone tip: - bool child_found = false; - for (size_t h = 0; (h < scene.humanoids.GetCount()) && !child_found; ++h) + const SpringComponent* spring = scene.springs.GetComponent(entity); + if (spring != nullptr) { - const HumanoidComponent& humanoid = scene.humanoids[h]; - int bodypart = 0; - for (Entity child : humanoid.bones) + // Spring has information about bone tip already: + b = XMLoadFloat3(&spring->currentTail); + } + else + { + // Search for child to connect bone tip: + bool child_found = false; + for (size_t h = 0; (h < scene.humanoids.GetCount()) && !child_found; ++h) { - const HierarchyComponent* hierarchy = scene.hierarchy.GetComponent(child); - if (hierarchy != nullptr && hierarchy->parentID == entity && scene.transforms.Contains(child)) + const HumanoidComponent& humanoid = scene.humanoids[h]; + int bodypart = 0; + for (Entity child : humanoid.bones) { - if (bodypart == int(HumanoidComponent::HumanoidBone::Hips)) + const HierarchyComponent* hierarchy = scene.hierarchy.GetComponent(child); + if (hierarchy != nullptr && hierarchy->parentID == entity && scene.transforms.Contains(child)) { - // skip root-hip connection + if (bodypart == int(HumanoidComponent::HumanoidBone::Hips)) + { + // skip root-hip connection + child_found = true; + break; + } + const TransformComponent& child_transform = *scene.transforms.GetComponent(child); + b = child_transform.GetPositionV(); child_found = true; break; } - const TransformComponent& child_transform = *scene.transforms.GetComponent(child); - b = child_transform.GetPositionV(); - child_found = true; - break; + bodypart++; } - bodypart++; } - } - if (!child_found) - { - for (Entity child : armature.boneCollection) + if (!child_found) { - const HierarchyComponent* hierarchy = scene.hierarchy.GetComponent(child); - if (hierarchy != nullptr && hierarchy->parentID == entity && scene.transforms.Contains(child)) + for (Entity child : armature.boneCollection) { - const TransformComponent& child_transform = *scene.transforms.GetComponent(child); - b = child_transform.GetPositionV(); - child_found = true; - break; + const HierarchyComponent* hierarchy = scene.hierarchy.GetComponent(child); + if (hierarchy != nullptr && hierarchy->parentID == entity && scene.transforms.Contains(child)) + { + const TransformComponent& child_transform = *scene.transforms.GetComponent(child); + b = child_transform.GetPositionV(); + child_found = true; + break; + } } } - } - if (!child_found) - { - // No child, try to guess bone tip compared to parent (if it has parent): - const HierarchyComponent* hierarchy = scene.hierarchy.GetComponent(entity); - if (hierarchy != nullptr && scene.transforms.Contains(hierarchy->parentID)) + if (!child_found) { - const TransformComponent& parent_transform = *scene.transforms.GetComponent(hierarchy->parentID); - XMVECTOR ab = a - parent_transform.GetPositionV(); - b = a + ab; + // No child, try to guess bone tip compared to parent (if it has parent): + const HierarchyComponent* hierarchy = scene.hierarchy.GetComponent(entity); + if (hierarchy != nullptr && scene.transforms.Contains(hierarchy->parentID)) + { + const TransformComponent& parent_transform = *scene.transforms.GetComponent(hierarchy->parentID); + XMVECTOR ab = a - parent_transform.GetPositionV(); + b = a + ab; + } } } XMVECTOR ab = XMVector3Normalize(b - a); @@ -3050,13 +3059,13 @@ void EditorComponent::Render() const XMStoreFloat3(&capsule.tip, b); XMFLOAT4 color = inactiveEntityColor; - if (scene.springs.Contains(entity)) + if (spring != nullptr) { - color = wi::Color(255, 70, 165, uint8_t(color.w * 255)); + color = springDebugColor; } - if (scene.inverse_kinematics.Contains(entity)) + else if (scene.inverse_kinematics.Contains(entity)) { - color = wi::Color(49, 190, 103, uint8_t(color.w * 255)); + color = ikDebugColor; } if (hovered.entity == entity) diff --git a/Editor/Editor.h b/Editor/Editor.h index 72a5a6bb8..ad81bdaf1 100644 --- a/Editor/Editor.h +++ b/Editor/Editor.h @@ -99,6 +99,9 @@ public: wi::Color backgroundEntityColor = wi::Color::Black(); wi::Color dummyColor = wi::Color::White(); + const wi::Color springDebugColor = wi::Color(255, 70, 165, 255); + const wi::Color ikDebugColor = wi::Color(49, 190, 103, 255); + wi::graphics::Texture editor_depthbuffer; Translator translator; diff --git a/Editor/GeneralWindow.cpp b/Editor/GeneralWindow.cpp index fdca17d6b..427cda80d 100644 --- a/Editor/GeneralWindow.cpp +++ b/Editor/GeneralWindow.cpp @@ -13,7 +13,7 @@ void GeneralWindow::Create(EditorComponent* _editor) wi::gui::Window::Create("General", wi::gui::Window::WindowControls::COLLAPSE); - SetSize(XMFLOAT2(580, 680)); + SetSize(XMFLOAT2(580, 700)); physicsDebugCheckBox.Create("Physics visualizer: "); physicsDebugCheckBox.SetTooltip("Visualize the physics world"); @@ -44,7 +44,7 @@ void GeneralWindow::Create(EditorComponent* _editor) aabbDebugCheckBox.SetCheck(wi::renderer::GetToDrawDebugPartitionTree()); AddWidget(&aabbDebugCheckBox); - boneLinesCheckBox.Create("Bone line visualizer: "); + boneLinesCheckBox.Create(ICON_ARMATURE " Bone line visualizer: "); boneLinesCheckBox.SetTooltip("Visualize bones of armatures"); boneLinesCheckBox.SetScriptTip("SetDebugBonesEnabled(bool enabled)"); boneLinesCheckBox.OnClick([](wi::gui::EventArgs args) { @@ -53,7 +53,7 @@ void GeneralWindow::Create(EditorComponent* _editor) boneLinesCheckBox.SetCheck(wi::renderer::GetToDrawDebugBoneLines()); AddWidget(&boneLinesCheckBox); - debugEmittersCheckBox.Create("Emitter visualizer: "); + debugEmittersCheckBox.Create(ICON_EMITTER " Emitter visualizer: "); debugEmittersCheckBox.SetTooltip("Visualize emitters"); debugEmittersCheckBox.SetScriptTip("SetDebugEmittersEnabled(bool enabled)"); debugEmittersCheckBox.OnClick([](wi::gui::EventArgs args) { @@ -62,7 +62,7 @@ void GeneralWindow::Create(EditorComponent* _editor) debugEmittersCheckBox.SetCheck(wi::renderer::GetToDrawDebugEmitters()); AddWidget(&debugEmittersCheckBox); - debugForceFieldsCheckBox.Create("Force Field visualizer: "); + debugForceFieldsCheckBox.Create(ICON_FORCE " Force Field visualizer: "); debugForceFieldsCheckBox.SetTooltip("Visualize force fields"); debugForceFieldsCheckBox.SetScriptTip("SetDebugForceFieldsEnabled(bool enabled)"); debugForceFieldsCheckBox.OnClick([](wi::gui::EventArgs args) { @@ -79,7 +79,7 @@ void GeneralWindow::Create(EditorComponent* _editor) debugRaytraceBVHCheckBox.SetCheck(wi::renderer::GetRaytraceDebugBVHVisualizerEnabled()); AddWidget(&debugRaytraceBVHCheckBox); - envProbesCheckBox.Create("Env probe visualizer: "); + envProbesCheckBox.Create(ICON_ENVIRONMENTPROBE " Env probe visualizer: "); envProbesCheckBox.SetTooltip("Toggle visualization of environment probes as reflective spheres"); envProbesCheckBox.OnClick([](wi::gui::EventArgs args) { wi::renderer::SetToDrawDebugEnvProbes(args.bValue); @@ -87,7 +87,7 @@ void GeneralWindow::Create(EditorComponent* _editor) envProbesCheckBox.SetCheck(wi::renderer::GetToDrawDebugEnvProbes()); AddWidget(&envProbesCheckBox); - cameraVisCheckBox.Create("Camera visualizer: "); + cameraVisCheckBox.Create(ICON_CAMERA " Camera visualizer: "); cameraVisCheckBox.SetTooltip("Toggle visualization of camera proxies in the scene"); cameraVisCheckBox.OnClick([](wi::gui::EventArgs args) { wi::renderer::SetToDrawDebugCameras(args.bValue); @@ -95,7 +95,7 @@ void GeneralWindow::Create(EditorComponent* _editor) cameraVisCheckBox.SetCheck(wi::renderer::GetToDrawDebugCameras()); AddWidget(&cameraVisCheckBox); - colliderVisCheckBox.Create("Collider visualizer: "); + colliderVisCheckBox.Create(ICON_COLLIDER " Collider visualizer: "); colliderVisCheckBox.SetTooltip("Toggle visualization of colliders in the scene"); colliderVisCheckBox.OnClick([](wi::gui::EventArgs args) { wi::renderer::SetToDrawDebugColliders(args.bValue); @@ -103,6 +103,14 @@ void GeneralWindow::Create(EditorComponent* _editor) colliderVisCheckBox.SetCheck(wi::renderer::GetToDrawDebugColliders()); AddWidget(&colliderVisCheckBox); + springVisCheckBox.Create(ICON_SPRING " Spring visualizer: "); + springVisCheckBox.SetTooltip("Toggle visualization of springs in the scene"); + springVisCheckBox.OnClick([](wi::gui::EventArgs args) { + wi::renderer::SetToDrawDebugSprings(args.bValue); + }); + springVisCheckBox.SetCheck(wi::renderer::GetToDrawDebugSprings()); + AddWidget(&springVisCheckBox); + gridHelperCheckBox.Create("Grid helper: "); gridHelperCheckBox.SetTooltip("Toggle showing of unit visualizer grid in the world origin"); if (editor->main->config.GetSection("options").Has("grid_helper")) @@ -237,7 +245,7 @@ void GeneralWindow::Create(EditorComponent* _editor) }); AddWidget(&bonePickerOpacitySlider); - skeletonsVisibleCheckBox.Create("Skeletons always visible: "); + skeletonsVisibleCheckBox.Create(ICON_BONE " Skeletons always visible: "); skeletonsVisibleCheckBox.SetTooltip("Armature skeletons will be always visible, even when not selected."); AddWidget(&skeletonsVisibleCheckBox); @@ -765,6 +773,7 @@ void GeneralWindow::ResizeLayout() add_right(envProbesCheckBox); add_right(cameraVisCheckBox); add_right(colliderVisCheckBox); + add_right(springVisCheckBox); y += jump; diff --git a/Editor/GeneralWindow.h b/Editor/GeneralWindow.h index 03fa5438c..3ebec4f6e 100644 --- a/Editor/GeneralWindow.h +++ b/Editor/GeneralWindow.h @@ -26,6 +26,7 @@ public: wi::gui::CheckBox envProbesCheckBox; wi::gui::CheckBox cameraVisCheckBox; wi::gui::CheckBox colliderVisCheckBox; + wi::gui::CheckBox springVisCheckBox; wi::gui::CheckBox freezeCullingCameraCheckBox; wi::gui::CheckBox disableAlbedoMapsCheckBox; wi::gui::CheckBox forceDiffuseLightingCheckBox; diff --git a/Editor/SpringWindow.cpp b/Editor/SpringWindow.cpp index 329df8097..c8a1478ae 100644 --- a/Editor/SpringWindow.cpp +++ b/Editor/SpringWindow.cpp @@ -43,17 +43,13 @@ void SpringWindow::Create(EditorComponent* _editor) }); AddWidget(&resetAllButton); - debugCheckBox.Create("DEBUG: "); - debugCheckBox.SetTooltip("Enabling this will visualize springs as small yellow X-es in the scene"); - debugCheckBox.SetPos(XMFLOAT2(x, y += step)); - debugCheckBox.SetSize(XMFLOAT2(hei, hei)); - AddWidget(&debugCheckBox); - disabledCheckBox.Create("Disabled: "); disabledCheckBox.SetTooltip("Disable simulation."); disabledCheckBox.SetPos(XMFLOAT2(x, y += step)); disabledCheckBox.SetSize(XMFLOAT2(hei, hei)); disabledCheckBox.OnClick([=](wi::gui::EventArgs args) { + if (!editor->GetCurrentScene().springs.Contains(entity)) + return; editor->GetCurrentScene().springs.GetComponent(entity)->SetDisabled(args.bValue); }); AddWidget(&disabledCheckBox); @@ -63,6 +59,8 @@ void SpringWindow::Create(EditorComponent* _editor) gravityCheckBox.SetPos(XMFLOAT2(x, y += step)); gravityCheckBox.SetSize(XMFLOAT2(hei, hei)); gravityCheckBox.OnClick([=](wi::gui::EventArgs args) { + if (!editor->GetCurrentScene().springs.Contains(entity)) + return; editor->GetCurrentScene().springs.GetComponent(entity)->SetGravityEnabled(args.bValue); }); AddWidget(&gravityCheckBox); @@ -72,6 +70,8 @@ void SpringWindow::Create(EditorComponent* _editor) stiffnessSlider.SetPos(XMFLOAT2(x, y += step)); stiffnessSlider.SetSize(XMFLOAT2(siz, hei)); stiffnessSlider.OnSlide([&](wi::gui::EventArgs args) { + if (!editor->GetCurrentScene().springs.Contains(entity)) + return; editor->GetCurrentScene().springs.GetComponent(entity)->stiffnessForce = args.fValue; }); AddWidget(&stiffnessSlider); @@ -81,6 +81,8 @@ void SpringWindow::Create(EditorComponent* _editor) dragSlider.SetPos(XMFLOAT2(x, y += step)); dragSlider.SetSize(XMFLOAT2(siz, hei)); dragSlider.OnSlide([&](wi::gui::EventArgs args) { + if (!editor->GetCurrentScene().springs.Contains(entity)) + return; editor->GetCurrentScene().springs.GetComponent(entity)->dragForce = args.fValue; }); AddWidget(&dragSlider); @@ -90,6 +92,8 @@ void SpringWindow::Create(EditorComponent* _editor) windSlider.SetPos(XMFLOAT2(x, y += step)); windSlider.SetSize(XMFLOAT2(siz, hei)); windSlider.OnSlide([&](wi::gui::EventArgs args) { + if (!editor->GetCurrentScene().springs.Contains(entity)) + return; editor->GetCurrentScene().springs.GetComponent(entity)->windForce = args.fValue; }); AddWidget(&windSlider); @@ -99,10 +103,23 @@ void SpringWindow::Create(EditorComponent* _editor) gravitySlider.SetPos(XMFLOAT2(x, y += step)); gravitySlider.SetSize(XMFLOAT2(siz, hei)); gravitySlider.OnSlide([&](wi::gui::EventArgs args) { + if (!editor->GetCurrentScene().springs.Contains(entity)) + return; editor->GetCurrentScene().springs.GetComponent(entity)->gravityPower = args.fValue; }); AddWidget(&gravitySlider); + hitradiusSlider.Create(0, 1, 0, 100000, "Collision hit radius: "); + hitradiusSlider.SetTooltip("The radius of the spring's collision sphere, that will be checked against colliders."); + hitradiusSlider.SetPos(XMFLOAT2(x, y += step)); + hitradiusSlider.SetSize(XMFLOAT2(siz, hei)); + hitradiusSlider.OnSlide([&](wi::gui::EventArgs args) { + if (!editor->GetCurrentScene().springs.Contains(entity)) + return; + editor->GetCurrentScene().springs.GetComponent(entity)->hitRadius = args.fValue; + }); + AddWidget(&hitradiusSlider); + SetMinimized(true); SetVisible(false); @@ -126,13 +143,12 @@ void SpringWindow::SetEntity(Entity entity) dragSlider.SetValue(spring->dragForce); windSlider.SetValue(spring->windForce); gravitySlider.SetValue(spring->gravityPower); + hitradiusSlider.SetValue(spring->hitRadius); } else { SetEnabled(false); } - - debugCheckBox.SetEnabled(true); } void SpringWindow::ResizeLayout() @@ -173,12 +189,12 @@ void SpringWindow::ResizeLayout() }; add_fullwidth(resetAllButton); - add_right(debugCheckBox); add_right(disabledCheckBox); add_right(gravityCheckBox); add(stiffnessSlider); add(dragSlider); add(windSlider); add(gravitySlider); + add(hitradiusSlider); } diff --git a/Editor/SpringWindow.h b/Editor/SpringWindow.h index 25c93985b..b20e26fb0 100644 --- a/Editor/SpringWindow.h +++ b/Editor/SpringWindow.h @@ -11,13 +11,13 @@ public: void SetEntity(wi::ecs::Entity entity); wi::gui::Button resetAllButton; - wi::gui::CheckBox debugCheckBox; wi::gui::CheckBox disabledCheckBox; wi::gui::CheckBox gravityCheckBox; wi::gui::Slider stiffnessSlider; wi::gui::Slider dragSlider; wi::gui::Slider windSlider; wi::gui::Slider gravitySlider; + wi::gui::Slider hitradiusSlider; void ResizeLayout() override; }; diff --git a/WickedEngine/wiPrimitive.cpp b/WickedEngine/wiPrimitive.cpp index a709113ee..0bc70d7fd 100644 --- a/WickedEngine/wiPrimitive.cpp +++ b/WickedEngine/wiPrimitive.cpp @@ -306,8 +306,10 @@ namespace wi::primitive A -= N * b.radius; B += N * b.radius; XMVECTOR C = XMLoadFloat3(¢er); - dist = wi::math::GetPointSegmentDistance(C, A, B); - XMStoreFloat3(&direction, (C - wi::math::ClosestPointOnLineSegment(A, B, C)) / dist); + XMVECTOR D = C - wi::math::ClosestPointOnLineSegment(A, B, C); + dist = XMVectorGetX(XMVector3Length(D)); + D /= dist; + XMStoreFloat3(&direction, D); dist = dist - radius - b.radius; return dist < 0; } diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 21c10d5bc..b064675c6 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -106,6 +106,7 @@ bool debugEnvProbes = false; bool debugForceFields = false; bool debugCameras = false; bool debugColliders = false; +bool debugSprings = false; bool gridHelper = false; bool advancedLightCulling = true; bool variableRateShadingClassification = false; @@ -142,13 +143,20 @@ int max_shadow_resolution_2D = 1024; int max_shadow_resolution_cube = 256; wi::vector> renderableBoxes; +wi::vector> renderableBoxes_depth; wi::vector> renderableSpheres; +wi::vector> renderableSpheres_depth; wi::vector> renderableCapsules; +wi::vector> renderableCapsules_depth; wi::vector renderableLines; +wi::vector renderableLines_depth; wi::vector renderableLines2D; wi::vector renderablePoints; +wi::vector renderablePoints_depth; wi::vector renderableTriangles_solid; wi::vector renderableTriangles_wireframe; +wi::vector renderableTriangles_solid_depth; +wi::vector renderableTriangles_wireframe_depth; wi::vector debugTextStorage; // A stream of DebugText struct + text characters wi::vector paintrads; wi::vector painttextures; @@ -637,9 +645,13 @@ enum DEBUGRENDERING DEBUGRENDERING_DDGI, DEBUGRENDERING_GRID, DEBUGRENDERING_CUBE, + DEBUGRENDERING_CUBE_DEPTH, DEBUGRENDERING_LINES, + DEBUGRENDERING_LINES_DEPTH, DEBUGRENDERING_TRIANGLE_SOLID, DEBUGRENDERING_TRIANGLE_WIREFRAME, + DEBUGRENDERING_TRIANGLE_SOLID_DEPTH, + DEBUGRENDERING_TRIANGLE_WIREFRAME_DEPTH, DEBUGRENDERING_EMITTER, DEBUGRENDERING_PAINTRADIUS, DEBUGRENDERING_VOXEL, @@ -1529,6 +1541,15 @@ void LoadShaders() desc.pt = PrimitiveTopology::LINELIST; break; case DEBUGRENDERING_CUBE: + desc.vs = &shaders[VSTYPE_VERTEXCOLOR]; + desc.ps = &shaders[PSTYPE_VERTEXCOLOR]; + desc.il = &inputLayouts[ILTYPE_VERTEXCOLOR]; + desc.dss = &depthStencils[DSSTYPE_DEPTHDISABLED]; + desc.rs = &rasterizers[RSTYPE_WIRE_DOUBLESIDED_SMOOTH]; + desc.bs = &blendStates[BSTYPE_TRANSPARENT]; + desc.pt = PrimitiveTopology::LINELIST; + break; + case DEBUGRENDERING_CUBE_DEPTH: desc.vs = &shaders[VSTYPE_VERTEXCOLOR]; desc.ps = &shaders[PSTYPE_VERTEXCOLOR]; desc.il = &inputLayouts[ILTYPE_VERTEXCOLOR]; @@ -1546,7 +1567,34 @@ void LoadShaders() desc.bs = &blendStates[BSTYPE_TRANSPARENT]; desc.pt = PrimitiveTopology::LINELIST; break; + case DEBUGRENDERING_LINES_DEPTH: + desc.vs = &shaders[VSTYPE_VERTEXCOLOR]; + desc.ps = &shaders[PSTYPE_VERTEXCOLOR]; + desc.il = &inputLayouts[ILTYPE_VERTEXCOLOR]; + desc.dss = &depthStencils[DSSTYPE_DEPTHREAD]; + desc.rs = &rasterizers[RSTYPE_WIRE_DOUBLESIDED_SMOOTH]; + desc.bs = &blendStates[BSTYPE_TRANSPARENT]; + desc.pt = PrimitiveTopology::LINELIST; + break; case DEBUGRENDERING_TRIANGLE_SOLID: + desc.vs = &shaders[VSTYPE_VERTEXCOLOR]; + desc.ps = &shaders[PSTYPE_VERTEXCOLOR]; + desc.il = &inputLayouts[ILTYPE_VERTEXCOLOR]; + desc.dss = &depthStencils[DSSTYPE_DEPTHDISABLED]; + desc.rs = &rasterizers[RSTYPE_DOUBLESIDED]; + desc.bs = &blendStates[BSTYPE_TRANSPARENT]; + desc.pt = PrimitiveTopology::TRIANGLELIST; + break; + case DEBUGRENDERING_TRIANGLE_WIREFRAME: + desc.vs = &shaders[VSTYPE_VERTEXCOLOR]; + desc.ps = &shaders[PSTYPE_VERTEXCOLOR]; + desc.il = &inputLayouts[ILTYPE_VERTEXCOLOR]; + desc.dss = &depthStencils[DSSTYPE_DEPTHDISABLED]; + desc.rs = &rasterizers[RSTYPE_WIRE_DOUBLESIDED_SMOOTH]; + desc.bs = &blendStates[BSTYPE_TRANSPARENT]; + desc.pt = PrimitiveTopology::TRIANGLELIST; + break; + case DEBUGRENDERING_TRIANGLE_SOLID_DEPTH: desc.vs = &shaders[VSTYPE_VERTEXCOLOR]; desc.ps = &shaders[PSTYPE_VERTEXCOLOR]; desc.il = &inputLayouts[ILTYPE_VERTEXCOLOR]; @@ -1555,7 +1603,7 @@ void LoadShaders() desc.bs = &blendStates[BSTYPE_TRANSPARENT]; desc.pt = PrimitiveTopology::TRIANGLELIST; break; - case DEBUGRENDERING_TRIANGLE_WIREFRAME: + case DEBUGRENDERING_TRIANGLE_WIREFRAME_DEPTH: desc.vs = &shaders[VSTYPE_VERTEXCOLOR]; desc.ps = &shaders[PSTYPE_VERTEXCOLOR]; desc.il = &inputLayouts[ILTYPE_VERTEXCOLOR]; @@ -6306,7 +6354,7 @@ void DrawDebugWorld( if (debugCameras) { - device->EventBegin("DebugCameras", cmd); + device->EventBegin("Debug Cameras", cmd); static GPUBuffer wirecamVB; static GPUBuffer wirecamIB; @@ -6407,6 +6455,7 @@ void DrawDebugWorld( if (GetToDrawDebugColliders()) { + const XMFLOAT4 colliderColor = wi::Color(88, 218, 83, 255); for (size_t i = 0; i < scene.colliders.GetCount(); ++i) { ColliderComponent& collider = scene.colliders[i]; @@ -6414,16 +6463,16 @@ void DrawDebugWorld( { default: case ColliderComponent::Shape::Sphere: - DrawSphere(collider.sphere, XMFLOAT4(1, 0, 1, 1)); + DrawSphere(collider.sphere, colliderColor, false); break; case ColliderComponent::Shape::Capsule: - DrawCapsule(collider.capsule, XMFLOAT4(1, 0, 1, 1)); + DrawCapsule(collider.capsule, colliderColor, false); break; case ColliderComponent::Shape::Plane: { RenderableLine line; - line.color_start = XMFLOAT4(1, 0, 1, 1); - line.color_end = XMFLOAT4(1, 0, 1, 1); + line.color_start = colliderColor; + line.color_end = colliderColor; XMMATRIX planeMatrix = XMMatrixInverse(nullptr, XMLoadFloat4x4(&collider.plane.projection)); XMVECTOR P0 = XMVector3Transform(XMVectorSet(-1, 0, -1, 1), planeMatrix); XMVECTOR P1 = XMVector3Transform(XMVectorSet(1, 0, -1, 1), planeMatrix); @@ -6431,27 +6480,50 @@ void DrawDebugWorld( XMVECTOR P3 = XMVector3Transform(XMVectorSet(-1, 0, 1, 1), planeMatrix); XMStoreFloat3(&line.start, P0); XMStoreFloat3(&line.end, P1); - DrawLine(line); + DrawLine(line, false); XMStoreFloat3(&line.start, P1); XMStoreFloat3(&line.end, P2); - DrawLine(line); + DrawLine(line, false); XMStoreFloat3(&line.start, P2); XMStoreFloat3(&line.end, P3); - DrawLine(line); + DrawLine(line, false); XMStoreFloat3(&line.start, P3); XMStoreFloat3(&line.end, P0); - DrawLine(line); + DrawLine(line, false); XMVECTOR O = XMLoadFloat3(&collider.plane.origin); XMVECTOR N = XMLoadFloat3(&collider.plane.normal); XMStoreFloat3(&line.start, O); XMStoreFloat3(&line.end, O + N); - DrawLine(line); + DrawLine(line, false); } break; } } } + if (GetToDrawDebugSprings()) + { + const XMFLOAT4 springDebugColor = wi::Color(255, 70, 165, 255); + for (size_t i = 0; i < scene.springs.GetCount(); ++i) + { + Entity entity = scene.springs.GetEntity(i); + const SpringComponent& spring = scene.springs[i]; + const TransformComponent* transform = scene.transforms.GetComponent(entity); + if (transform != nullptr) + { + wi::renderer::RenderableLine line; + line.start = transform->GetPosition(); + line.end = spring.currentTail; + line.color_end = line.color_start = springDebugColor; + wi::renderer::DrawLine(line, false); + } + wi::primitive::Sphere sphere; + sphere.center = spring.currentTail; + sphere.radius = spring.hitRadius; + wi::renderer::DrawSphere(sphere, springDebugColor, false); + } + } + if (debugPartitionTree) { device->EventBegin("DebugPartitionTree", cmd); @@ -6625,159 +6697,135 @@ void DrawDebugWorld( device->EventEnd(cmd); } - if (!renderableTriangles_solid.empty()) + if( + !renderableTriangles_solid.empty() || + !renderableTriangles_wireframe.empty() || + !renderableTriangles_solid_depth.empty() || + !renderableTriangles_wireframe_depth.empty() + ) { - device->EventBegin("DebugTriangles (Solid)", cmd); + device->EventBegin("Debug Triangles", cmd); + + auto draw_triangle = [&](wi::vector& dbg) { + if (dbg.empty()) + return; + MiscCB sb; + XMStoreFloat4x4(&sb.g_xTransform, camera.GetViewProjection()); + sb.g_xColor = XMFLOAT4(1, 1, 1, 1); + device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); + + struct Vertex + { + XMFLOAT4 position; + XMFLOAT4 color; + }; + GraphicsDevice::GPUAllocation mem = device->AllocateGPU(sizeof(Vertex) * dbg.size() * 3, cmd); + + int i = 0; + for (auto& triangle : dbg) + { + Vertex vertices[3]; + vertices[0].position = XMFLOAT4(triangle.positionA.x, triangle.positionA.y, triangle.positionA.z, 1); + vertices[0].color = triangle.colorA; + vertices[1].position = XMFLOAT4(triangle.positionB.x, triangle.positionB.y, triangle.positionB.z, 1); + vertices[1].color = triangle.colorB; + vertices[2].position = XMFLOAT4(triangle.positionC.x, triangle.positionC.y, triangle.positionC.z, 1); + vertices[2].color = triangle.colorC; + + memcpy((void*)((size_t)mem.data + i * sizeof(vertices)), vertices, sizeof(vertices)); + i++; + } + + const GPUBuffer* vbs[] = { + &mem.buffer, + }; + const uint32_t strides[] = { + sizeof(Vertex), + }; + const uint64_t offsets[] = { + mem.offset, + }; + device->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, offsets, cmd); + + device->Draw(3 * i, 0, cmd); + + dbg.clear(); + }; device->BindPipelineState(&PSO_debug[DEBUGRENDERING_TRIANGLE_SOLID], cmd); - - MiscCB sb; - XMStoreFloat4x4(&sb.g_xTransform, camera.GetViewProjection()); - sb.g_xColor = XMFLOAT4(1, 1, 1, 1); - device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); - - struct Vertex - { - XMFLOAT4 position; - XMFLOAT4 color; - }; - GraphicsDevice::GPUAllocation mem = device->AllocateGPU(sizeof(Vertex) * renderableTriangles_solid.size() * 3, cmd); - - int i = 0; - for (auto& triangle : renderableTriangles_solid) - { - Vertex vertices[3]; - vertices[0].position = XMFLOAT4(triangle.positionA.x, triangle.positionA.y, triangle.positionA.z, 1); - vertices[0].color = triangle.colorA; - vertices[1].position = XMFLOAT4(triangle.positionB.x, triangle.positionB.y, triangle.positionB.z, 1); - vertices[1].color = triangle.colorB; - vertices[2].position = XMFLOAT4(triangle.positionC.x, triangle.positionC.y, triangle.positionC.z, 1); - vertices[2].color = triangle.colorC; - - memcpy((void*)((size_t)mem.data + i * sizeof(vertices)), vertices, sizeof(vertices)); - i++; - } - - const GPUBuffer* vbs[] = { - &mem.buffer, - }; - const uint32_t strides[] = { - sizeof(Vertex), - }; - const uint64_t offsets[] = { - mem.offset, - }; - device->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, offsets, cmd); - - device->Draw(3 * i, 0, cmd); - - renderableTriangles_solid.clear(); - - device->EventEnd(cmd); - } - - if (!renderableTriangles_wireframe.empty()) - { - device->EventBegin("DebugTriangles (Wireframe)", cmd); + draw_triangle(renderableTriangles_solid); device->BindPipelineState(&PSO_debug[DEBUGRENDERING_TRIANGLE_WIREFRAME], cmd); + draw_triangle(renderableTriangles_wireframe); - MiscCB sb; - XMStoreFloat4x4(&sb.g_xTransform, camera.GetViewProjection()); - sb.g_xColor = XMFLOAT4(1, 1, 1, 1); - device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); + device->BindPipelineState(&PSO_debug[DEBUGRENDERING_TRIANGLE_SOLID_DEPTH], cmd); + draw_triangle(renderableTriangles_solid_depth); - struct Vertex - { - XMFLOAT4 position; - XMFLOAT4 color; - }; - GraphicsDevice::GPUAllocation mem = device->AllocateGPU(sizeof(Vertex) * renderableTriangles_wireframe.size() * 3, cmd); - - int i = 0; - for (auto& triangle : renderableTriangles_wireframe) - { - Vertex vertices[3]; - vertices[0].position = XMFLOAT4(triangle.positionA.x, triangle.positionA.y, triangle.positionA.z, 1); - vertices[0].color = triangle.colorA; - vertices[1].position = XMFLOAT4(triangle.positionB.x, triangle.positionB.y, triangle.positionB.z, 1); - vertices[1].color = triangle.colorB; - vertices[2].position = XMFLOAT4(triangle.positionC.x, triangle.positionC.y, triangle.positionC.z, 1); - vertices[2].color = triangle.colorC; - - memcpy((void*)((size_t)mem.data + i * sizeof(vertices)), vertices, sizeof(vertices)); - i++; - } - - const GPUBuffer* vbs[] = { - &mem.buffer, - }; - const uint32_t strides[] = { - sizeof(Vertex), - }; - const uint64_t offsets[] = { - mem.offset, - }; - device->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, offsets, cmd); - - device->Draw(3 * i, 0, cmd); - - renderableTriangles_wireframe.clear(); + device->BindPipelineState(&PSO_debug[DEBUGRENDERING_TRIANGLE_WIREFRAME_DEPTH], cmd); + draw_triangle(renderableTriangles_wireframe_depth); device->EventEnd(cmd); } - if (!renderableLines.empty()) + if(!renderableLines.empty() || !renderableLines_depth.empty()) { - device->EventBegin("DebugLines", cmd); + device->EventBegin("Debug Lines - 3D", cmd); + + auto draw_line = [&](wi::vector& dbg) { + if (dbg.empty()) + return; + MiscCB sb; + XMStoreFloat4x4(&sb.g_xTransform, camera.GetViewProjection()); + sb.g_xColor = XMFLOAT4(1, 1, 1, 1); + device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); + + struct LineSegment + { + XMFLOAT4 a, colorA, b, colorB; + }; + GraphicsDevice::GPUAllocation mem = device->AllocateGPU(sizeof(LineSegment) * dbg.size(), cmd); + + int i = 0; + for (auto& line : dbg) + { + LineSegment segment; + segment.a = XMFLOAT4(line.start.x, line.start.y, line.start.z, 1); + segment.b = XMFLOAT4(line.end.x, line.end.y, line.end.z, 1); + segment.colorA = line.color_start; + segment.colorB = line.color_end; + + memcpy((void*)((size_t)mem.data + i * sizeof(LineSegment)), &segment, sizeof(LineSegment)); + i++; + } + + const GPUBuffer* vbs[] = { + &mem.buffer, + }; + const uint32_t strides[] = { + sizeof(XMFLOAT4) + sizeof(XMFLOAT4), + }; + const uint64_t offsets[] = { + mem.offset, + }; + device->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, offsets, cmd); + + device->Draw(2 * i, 0, cmd); + + dbg.clear(); + }; device->BindPipelineState(&PSO_debug[DEBUGRENDERING_LINES], cmd); + draw_line(renderableLines); - MiscCB sb; - XMStoreFloat4x4(&sb.g_xTransform, camera.GetViewProjection()); - sb.g_xColor = XMFLOAT4(1, 1, 1, 1); - device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); - - struct LineSegment - { - XMFLOAT4 a, colorA, b, colorB; - }; - GraphicsDevice::GPUAllocation mem = device->AllocateGPU(sizeof(LineSegment) * renderableLines.size(), cmd); - - int i = 0; - for (auto& line : renderableLines) - { - LineSegment segment; - segment.a = XMFLOAT4(line.start.x, line.start.y, line.start.z, 1); - segment.b = XMFLOAT4(line.end.x, line.end.y, line.end.z, 1); - segment.colorA = line.color_start; - segment.colorB = line.color_end; - - memcpy((void*)((size_t)mem.data + i * sizeof(LineSegment)), &segment, sizeof(LineSegment)); - i++; - } - - const GPUBuffer* vbs[] = { - &mem.buffer, - }; - const uint32_t strides[] = { - sizeof(XMFLOAT4) + sizeof(XMFLOAT4), - }; - const uint64_t offsets[] = { - mem.offset, - }; - device->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, offsets, cmd); - - device->Draw(2 * i, 0, cmd); - - renderableLines.clear(); + device->BindPipelineState(&PSO_debug[DEBUGRENDERING_LINES_DEPTH], cmd); + draw_line(renderableLines_depth); device->EventEnd(cmd); } if (!renderableLines2D.empty()) { - device->EventBegin("DebugLines - 2D", cmd); + device->EventBegin("Debug Lines - 2D", cmd); device->BindPipelineState(&PSO_debug[DEBUGRENDERING_LINES], cmd); @@ -6823,74 +6871,80 @@ void DrawDebugWorld( device->EventEnd(cmd); } - if (!renderablePoints.empty()) + if(!renderablePoints.empty() || !renderablePoints_depth.empty()) { - device->EventBegin("DebugPoints", cmd); + device->EventBegin("Debug Points", cmd); + + auto draw_point = [&](wi::vector& dbg) { + if (dbg.empty()) + return; + MiscCB sb; + XMStoreFloat4x4(&sb.g_xTransform, camera.GetProjection()); // only projection, we will expand in view space on CPU below to be camera facing! + sb.g_xColor = XMFLOAT4(1, 1, 1, 1); + device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); + + // Will generate 2 line segments for each point forming a cross section: + struct LineSegment + { + XMFLOAT4 a, colorA, b, colorB; + }; + GraphicsDevice::GPUAllocation mem = device->AllocateGPU(sizeof(LineSegment) * dbg.size() * 2, cmd); + + XMMATRIX V = camera.GetView(); + + int i = 0; + for (auto& point : dbg) + { + LineSegment segment; + segment.colorA = segment.colorB = point.color; + + // the cross section will be transformed to view space and expanded here: + XMVECTOR _c = XMLoadFloat3(&point.position); + _c = XMVector3Transform(_c, V); + + XMVECTOR _a = _c + XMVectorSet(-1, -1, 0, 0) * point.size; + XMVECTOR _b = _c + XMVectorSet(1, 1, 0, 0) * point.size; + XMStoreFloat4(&segment.a, _a); + XMStoreFloat4(&segment.b, _b); + memcpy((void*)((size_t)mem.data + i * sizeof(LineSegment)), &segment, sizeof(LineSegment)); + i++; + + _a = _c + XMVectorSet(-1, 1, 0, 0) * point.size; + _b = _c + XMVectorSet(1, -1, 0, 0) * point.size; + XMStoreFloat4(&segment.a, _a); + XMStoreFloat4(&segment.b, _b); + memcpy((void*)((size_t)mem.data + i * sizeof(LineSegment)), &segment, sizeof(LineSegment)); + i++; + } + + const GPUBuffer* vbs[] = { + &mem.buffer, + }; + const uint32_t strides[] = { + sizeof(XMFLOAT4) + sizeof(XMFLOAT4), + }; + const uint64_t offsets[] = { + mem.offset, + }; + device->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, offsets, cmd); + + device->Draw(2 * i, 0, cmd); + + dbg.clear(); + }; device->BindPipelineState(&PSO_debug[DEBUGRENDERING_LINES], cmd); + draw_point(renderablePoints); - MiscCB sb; - XMStoreFloat4x4(&sb.g_xTransform, camera.GetProjection()); // only projection, we will expand in view space on CPU below to be camera facing! - sb.g_xColor = XMFLOAT4(1, 1, 1, 1); - device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); - - // Will generate 2 line segments for each point forming a cross section: - struct LineSegment - { - XMFLOAT4 a, colorA, b, colorB; - }; - GraphicsDevice::GPUAllocation mem = device->AllocateGPU(sizeof(LineSegment) * renderablePoints.size() * 2, cmd); - - XMMATRIX V = camera.GetView(); - - int i = 0; - for (auto& point : renderablePoints) - { - LineSegment segment; - segment.colorA = segment.colorB = point.color; - - // the cross section will be transformed to view space and expanded here: - XMVECTOR _c = XMLoadFloat3(&point.position); - _c = XMVector3Transform(_c, V); - - XMVECTOR _a = _c + XMVectorSet(-1, -1, 0, 0) * point.size; - XMVECTOR _b = _c + XMVectorSet(1, 1, 0, 0) * point.size; - XMStoreFloat4(&segment.a, _a); - XMStoreFloat4(&segment.b, _b); - memcpy((void*)((size_t)mem.data + i * sizeof(LineSegment)), &segment, sizeof(LineSegment)); - i++; - - _a = _c + XMVectorSet(-1, 1, 0, 0) * point.size; - _b = _c + XMVectorSet(1, -1, 0, 0) * point.size; - XMStoreFloat4(&segment.a, _a); - XMStoreFloat4(&segment.b, _b); - memcpy((void*)((size_t)mem.data + i * sizeof(LineSegment)), &segment, sizeof(LineSegment)); - i++; - } - - const GPUBuffer* vbs[] = { - &mem.buffer, - }; - const uint32_t strides[] = { - sizeof(XMFLOAT4) + sizeof(XMFLOAT4), - }; - const uint64_t offsets[] = { - mem.offset, - }; - device->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, offsets, cmd); - - device->Draw(2 * i, 0, cmd); - - renderablePoints.clear(); + device->BindPipelineState(&PSO_debug[DEBUGRENDERING_LINES_DEPTH], cmd); + draw_point(renderablePoints_depth); device->EventEnd(cmd); } - if (!renderableBoxes.empty()) + if(!renderableBoxes.empty() || !renderableBoxes_depth.empty()) { - device->EventBegin("DebugBoxes", cmd); - - device->BindPipelineState(&PSO_debug[DEBUGRENDERING_CUBE], cmd); + device->EventBegin("Debug Boxes", cmd); const GPUBuffer* vbs[] = { &wirecubeVB, @@ -6901,25 +6955,36 @@ void DrawDebugWorld( device->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, nullptr, cmd); device->BindIndexBuffer(&wirecubeIB, IndexBufferFormat::UINT16, 0, cmd); - MiscCB sb; + auto draw_box = [&](wi::vector>& dbg) { + if (dbg.empty()) + return; - for (auto& x : renderableBoxes) - { - XMStoreFloat4x4(&sb.g_xTransform, XMLoadFloat4x4(&x.first)*camera.GetViewProjection()); - sb.g_xColor = x.second; + MiscCB sb; - device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); + for (auto& x : dbg) + { + XMStoreFloat4x4(&sb.g_xTransform, XMLoadFloat4x4(&x.first) * camera.GetViewProjection()); + sb.g_xColor = x.second; - device->DrawIndexed(24, 0, 0, cmd); - } - renderableBoxes.clear(); + device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); + + device->DrawIndexed(24, 0, 0, cmd); + } + dbg.clear(); + }; + + device->BindPipelineState(&PSO_debug[DEBUGRENDERING_CUBE], cmd); + draw_box(renderableBoxes); + + device->BindPipelineState(&PSO_debug[DEBUGRENDERING_CUBE_DEPTH], cmd); + draw_box(renderableBoxes_depth); device->EventEnd(cmd); } - if (!renderableSpheres.empty()) + if (!renderableSpheres.empty() || !renderableSpheres_depth.empty()) { - device->EventBegin("DebugSpheres", cmd); + device->EventBegin("Debug Spheres", cmd); static GPUBuffer wiresphereVB; static GPUBuffer wiresphereIB; @@ -6987,8 +7052,6 @@ void DrawDebugWorld( device->CreateBuffer(&bd, indices.data(), &wiresphereIB); } - device->BindPipelineState(&PSO_debug[DEBUGRENDERING_CUBE], cmd); - const GPUBuffer* vbs[] = { &wiresphereVB, }; @@ -6998,125 +7061,142 @@ void DrawDebugWorld( device->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, nullptr, cmd); device->BindIndexBuffer(&wiresphereIB, IndexBufferFormat::UINT16, 0, cmd); - MiscCB sb; + auto draw_sphere = [&](wi::vector>& dbg) { + if (dbg.empty()) + return; - for (auto& x : renderableSpheres) - { - const Sphere& sphere = x.first; - XMStoreFloat4x4(&sb.g_xTransform, - XMMatrixScaling(sphere.radius, sphere.radius, sphere.radius) * - XMMatrixTranslation(sphere.center.x, sphere.center.y, sphere.center.z) * - camera.GetViewProjection() - ); - sb.g_xColor = x.second; + MiscCB sb; + for (auto& x : dbg) + { + const Sphere& sphere = x.first; + XMStoreFloat4x4(&sb.g_xTransform, + XMMatrixScaling(sphere.radius, sphere.radius, sphere.radius) * + XMMatrixTranslation(sphere.center.x, sphere.center.y, sphere.center.z) * + camera.GetViewProjection() + ); + sb.g_xColor = x.second; - device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); + device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); - device->DrawIndexed((uint32_t)(wiresphereIB.GetDesc().size / sizeof(uint16_t)), 0, 0, cmd); - } - renderableSpheres.clear(); - - device->EventEnd(cmd); - } - - if (!renderableCapsules.empty()) - { - device->EventBegin("DebugCapsules", cmd); + device->DrawIndexed((uint32_t)(wiresphereIB.GetDesc().size / sizeof(uint16_t)), 0, 0, cmd); + } + dbg.clear(); + }; device->BindPipelineState(&PSO_debug[DEBUGRENDERING_CUBE], cmd); + draw_sphere(renderableSpheres); - MiscCB sb; - XMStoreFloat4x4(&sb.g_xTransform, camera.GetViewProjection()); - sb.g_xColor = XMFLOAT4(1, 1, 1, 1); - device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); - - const int segmentcount = 18 + 1 + 18 + 1; - const int linecount = (int)renderableCapsules.size() * segmentcount; - - struct LineSegment - { - XMFLOAT4 a, colorA, b, colorB; - }; - GraphicsDevice::GPUAllocation mem = device->AllocateGPU(sizeof(LineSegment) * (size_t)linecount, cmd); - - XMVECTOR Eye = camera.GetEye(); - XMVECTOR Unit = XMVectorSet(0, 1, 0, 0); - - LineSegment* linearray = (LineSegment*)mem.data; - int j = 0; - for (auto& it : renderableCapsules) - { - const Capsule& capsule = it.first; - const float radius = capsule.radius; - - XMVECTOR Base = XMLoadFloat3(&capsule.base); - XMVECTOR Tip = XMLoadFloat3(&capsule.tip); - XMVECTOR Radius = XMVectorReplicate(capsule.radius); - XMVECTOR Normal = XMVector3Normalize(Tip - Base); - XMVECTOR Tangent = XMVector3Normalize(XMVector3Cross(Normal, Base - Eye)); - XMVECTOR Binormal = XMVector3Normalize(XMVector3Cross(Tangent, Normal)); - XMVECTOR LineEndOffset = Normal * Radius; - XMVECTOR A = Base + LineEndOffset; - XMVECTOR B = Tip - LineEndOffset; - XMVECTOR AB = Unit * XMVector3Length(B - A); - XMMATRIX M = { Tangent,Normal,Binormal,XMVectorSetW(A, 1) }; - - for (int i = 0; i < segmentcount; i += 1) - { - const float angle0 = XM_PIDIV2 + (float)i / (float)segmentcount * XM_2PI; - const float angle1 = XM_PIDIV2 + (float)(i + 1) / (float)segmentcount * XM_2PI; - XMVECTOR a, b; - if (i < 18) - { - - a = XMVectorSet(sinf(angle0) * radius, cosf(angle0) * radius, 0, 1); - b = XMVectorSet(sinf(angle1) * radius, cosf(angle1) * radius, 0, 1); - } - else if (i == 18) - { - a = XMVectorSet(sinf(angle0) * radius, cosf(angle0) * radius, 0, 1); - b = AB + XMVectorSet(sinf(angle1) * radius, cosf(angle1) * radius, 0, 1); - } - else if (i > 18 && i < 18 + 1 + 18) - { - a = AB + XMVectorSet(sinf(angle0) * radius, cosf(angle0) * radius, 0, 1); - b = AB + XMVectorSet(sinf(angle1) * radius, cosf(angle1) * radius, 0, 1); - } - else - { - a = AB + XMVectorSet(sinf(angle0) * radius, cosf(angle0) * radius, 0, 1); - b = XMVectorSet(sinf(angle1) * radius, cosf(angle1) * radius, 0, 1); - } - a = XMVector3Transform(a, M); - b = XMVector3Transform(b, M); - LineSegment line; - XMStoreFloat4(&line.a, a); - XMStoreFloat4(&line.b, b); - line.colorA = line.colorB = it.second; - std::memcpy(linearray + j, &line, sizeof(line)); - j++; - } - - } - - const GPUBuffer* vbs[] = { - &mem.buffer, - }; - const uint32_t strides[] = { - sizeof(XMFLOAT4) + sizeof(XMFLOAT4), - }; - const uint64_t offsets[] = { - mem.offset, - }; - device->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, offsets, cmd); - - device->Draw(linecount * 2, 0, cmd); - - renderableCapsules.clear(); + device->BindPipelineState(&PSO_debug[DEBUGRENDERING_CUBE_DEPTH], cmd); + draw_sphere(renderableSpheres_depth); device->EventEnd(cmd); } + if (!renderableCapsules.empty() || !renderableCapsules_depth.empty()) + { + device->EventBegin("Debug Capsules", cmd); + + auto draw_capsule = [&](wi::vector>& dbg) { + if (dbg.empty()) + return; + MiscCB sb; + XMStoreFloat4x4(&sb.g_xTransform, camera.GetViewProjection()); + sb.g_xColor = XMFLOAT4(1, 1, 1, 1); + device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); + + const int segmentcount = 18 + 1 + 18 + 1; + const int linecount = (int)dbg.size() * segmentcount; + + struct LineSegment + { + XMFLOAT4 a, colorA, b, colorB; + }; + GraphicsDevice::GPUAllocation mem = device->AllocateGPU(sizeof(LineSegment) * (size_t)linecount, cmd); + + XMVECTOR Eye = camera.GetEye(); + XMVECTOR Unit = XMVectorSet(0, 1, 0, 0); + + LineSegment* linearray = (LineSegment*)mem.data; + int j = 0; + for (auto& it : dbg) + { + const Capsule& capsule = it.first; + const float radius = capsule.radius; + + XMVECTOR Base = XMLoadFloat3(&capsule.base); + XMVECTOR Tip = XMLoadFloat3(&capsule.tip); + XMVECTOR Radius = XMVectorReplicate(capsule.radius); + XMVECTOR Normal = XMVector3Normalize(Tip - Base); + XMVECTOR Tangent = XMVector3Normalize(XMVector3Cross(Normal, Base - Eye)); + XMVECTOR Binormal = XMVector3Normalize(XMVector3Cross(Tangent, Normal)); + XMVECTOR LineEndOffset = Normal * Radius; + XMVECTOR A = Base + LineEndOffset; + XMVECTOR B = Tip - LineEndOffset; + XMVECTOR AB = Unit * XMVector3Length(B - A); + XMMATRIX M = { Tangent,Normal,Binormal,XMVectorSetW(A, 1) }; + + for (int i = 0; i < segmentcount; i += 1) + { + const float angle0 = XM_PIDIV2 + (float)i / (float)segmentcount * XM_2PI; + const float angle1 = XM_PIDIV2 + (float)(i + 1) / (float)segmentcount * XM_2PI; + XMVECTOR a, b; + if (i < 18) + { + + a = XMVectorSet(sinf(angle0) * radius, cosf(angle0) * radius, 0, 1); + b = XMVectorSet(sinf(angle1) * radius, cosf(angle1) * radius, 0, 1); + } + else if (i == 18) + { + a = XMVectorSet(sinf(angle0) * radius, cosf(angle0) * radius, 0, 1); + b = AB + XMVectorSet(sinf(angle1) * radius, cosf(angle1) * radius, 0, 1); + } + else if (i > 18 && i < 18 + 1 + 18) + { + a = AB + XMVectorSet(sinf(angle0) * radius, cosf(angle0) * radius, 0, 1); + b = AB + XMVectorSet(sinf(angle1) * radius, cosf(angle1) * radius, 0, 1); + } + else + { + a = AB + XMVectorSet(sinf(angle0) * radius, cosf(angle0) * radius, 0, 1); + b = XMVectorSet(sinf(angle1) * radius, cosf(angle1) * radius, 0, 1); + } + a = XMVector3Transform(a, M); + b = XMVector3Transform(b, M); + LineSegment line; + XMStoreFloat4(&line.a, a); + XMStoreFloat4(&line.b, b); + line.colorA = line.colorB = it.second; + std::memcpy(linearray + j, &line, sizeof(line)); + j++; + } + + } + + const GPUBuffer* vbs[] = { + &mem.buffer, + }; + const uint32_t strides[] = { + sizeof(XMFLOAT4) + sizeof(XMFLOAT4), + }; + const uint64_t offsets[] = { + mem.offset, + }; + device->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, offsets, cmd); + + device->Draw(linecount * 2, 0, cmd); + + dbg.clear(); + }; + + device->BindPipelineState(&PSO_debug[DEBUGRENDERING_CUBE], cmd); + draw_capsule(renderableCapsules); + + device->BindPipelineState(&PSO_debug[DEBUGRENDERING_CUBE_DEPTH], cmd); + draw_capsule(renderableCapsules_depth); + + device->EventEnd(cmd); + } if (debugEnvProbes) { @@ -17163,39 +17243,68 @@ Ray GetPickRay(long cursorX, long cursorY, const wi::Canvas& canvas, const Camer return Ray(lineStart, rayDirection); } -void DrawBox(const XMFLOAT4X4& boxMatrix, const XMFLOAT4& color) +void DrawBox(const XMFLOAT4X4& boxMatrix, const XMFLOAT4& color, bool depth) { - renderableBoxes.push_back(std::make_pair(boxMatrix,color)); + if(depth) + renderableBoxes_depth.push_back(std::make_pair(boxMatrix, color)); + else + renderableBoxes.push_back(std::make_pair(boxMatrix,color)); } -void DrawSphere(const Sphere& sphere, const XMFLOAT4& color) +void DrawSphere(const Sphere& sphere, const XMFLOAT4& color, bool depth) { - renderableSpheres.push_back(std::make_pair(sphere, color)); + if(depth) + renderableSpheres_depth.push_back(std::make_pair(sphere, color)); + else + renderableSpheres.push_back(std::make_pair(sphere, color)); } -void DrawCapsule(const Capsule& capsule, const XMFLOAT4& color) +void DrawCapsule(const Capsule& capsule, const XMFLOAT4& color, bool depth) { - renderableCapsules.push_back(std::make_pair(capsule, color)); + if(depth) + renderableCapsules_depth.push_back(std::make_pair(capsule, color)); + else + renderableCapsules.push_back(std::make_pair(capsule, color)); } -void DrawLine(const RenderableLine& line) +void DrawLine(const RenderableLine& line, bool depth) { - renderableLines.push_back(line); + if(depth) + renderableLines_depth.push_back(line); + else + renderableLines.push_back(line); } void DrawLine(const RenderableLine2D& line) { renderableLines2D.push_back(line); } -void DrawPoint(const RenderablePoint& point) +void DrawPoint(const RenderablePoint& point, bool depth) { - renderablePoints.push_back(point); + if(depth) + renderablePoints_depth.push_back(point); + else + renderablePoints.push_back(point); } -void DrawTriangle(const RenderableTriangle& triangle, bool wireframe) +void DrawTriangle(const RenderableTriangle& triangle, bool wireframe, bool depth) { - if (wireframe) + if(depth) { - renderableTriangles_wireframe.push_back(triangle); + if (wireframe) + { + renderableTriangles_wireframe_depth.push_back(triangle); + } + else + { + renderableTriangles_solid_depth.push_back(triangle); + } } else { - renderableTriangles_solid.push_back(triangle); + if (wireframe) + { + renderableTriangles_wireframe.push_back(triangle); + } + else + { + renderableTriangles_solid.push_back(triangle); + } } } void DrawDebugText(const char* text, const DebugTextParams& params) @@ -17264,6 +17373,8 @@ void SetToDrawDebugCameras(bool param) { debugCameras = param; } bool GetToDrawDebugCameras() { return debugCameras; } void SetToDrawDebugColliders(bool param) { debugColliders = param; } bool GetToDrawDebugColliders() { return debugColliders; } +void SetToDrawDebugSprings(bool param) { debugSprings = param; } +bool GetToDrawDebugSprings() { return debugSprings; } bool GetToDrawGridHelper() { return gridHelper; } void SetToDrawGridHelper(bool value) { gridHelper = value; } bool GetToDrawVoxelHelper() { return VXGI_DEBUG; } diff --git a/WickedEngine/wiRenderer.h b/WickedEngine/wiRenderer.h index 8c32e1970..80fb7c36c 100644 --- a/WickedEngine/wiRenderer.h +++ b/WickedEngine/wiRenderer.h @@ -1025,6 +1025,8 @@ namespace wi::renderer bool GetToDrawDebugCameras(); void SetToDrawDebugColliders(bool param); bool GetToDrawDebugColliders(); + void SetToDrawDebugSprings(bool param); + bool GetToDrawDebugSprings(); bool GetToDrawGridHelper(); void SetToDrawGridHelper(bool value); bool GetToDrawVoxelHelper(); @@ -1086,11 +1088,11 @@ namespace wi::renderer // Add box to render in next frame. It will be rendered in DrawDebugWorld() - void DrawBox(const XMFLOAT4X4& boxMatrix, const XMFLOAT4& color = XMFLOAT4(1,1,1,1)); + void DrawBox(const XMFLOAT4X4& boxMatrix, const XMFLOAT4& color = XMFLOAT4(1,1,1,1), bool depth = true); // Add sphere to render in next frame. It will be rendered in DrawDebugWorld() - void DrawSphere(const wi::primitive::Sphere& sphere, const XMFLOAT4& color = XMFLOAT4(1, 1, 1, 1)); + void DrawSphere(const wi::primitive::Sphere& sphere, const XMFLOAT4& color = XMFLOAT4(1, 1, 1, 1), bool depth = true); // Add capsule to render in next frame. It will be rendered in DrawDebugWorld() - void DrawCapsule(const wi::primitive::Capsule& capsule, const XMFLOAT4& color = XMFLOAT4(1, 1, 1, 1)); + void DrawCapsule(const wi::primitive::Capsule& capsule, const XMFLOAT4& color = XMFLOAT4(1, 1, 1, 1), bool depth = true); struct RenderableLine { @@ -1100,7 +1102,7 @@ namespace wi::renderer XMFLOAT4 color_end = XMFLOAT4(1, 1, 1, 1); }; // Add line to render in the next frame. It will be rendered in DrawDebugWorld() - void DrawLine(const RenderableLine& line); + void DrawLine(const RenderableLine& line, bool depth = false); struct RenderableLine2D { @@ -1119,7 +1121,7 @@ namespace wi::renderer XMFLOAT4 color = XMFLOAT4(1, 1, 1, 1); }; // Add point to render in the next frame. It will be rendered in DrawDebugWorld() as an X - void DrawPoint(const RenderablePoint& point); + void DrawPoint(const RenderablePoint& point, bool depth = false); struct RenderableTriangle { @@ -1131,7 +1133,7 @@ namespace wi::renderer XMFLOAT4 colorC = XMFLOAT4(1, 1, 1, 1); }; // Add triangle to render in the next frame. It will be rendered in DrawDebugWorld() - void DrawTriangle(const RenderableTriangle& triangle, bool wireframe = false); + void DrawTriangle(const RenderableTriangle& triangle, bool wireframe = false, bool depth = true); struct DebugTextParams { diff --git a/WickedEngine/wiRenderer_BindLua.cpp b/WickedEngine/wiRenderer_BindLua.cpp index e3495e16f..9487eeaef 100644 --- a/WickedEngine/wiRenderer_BindLua.cpp +++ b/WickedEngine/wiRenderer_BindLua.cpp @@ -238,6 +238,7 @@ namespace wi::lua::renderer wi::renderer::RenderableLine line; XMStoreFloat3(&line.start, XMLoadFloat4(&a->data)); XMStoreFloat3(&line.end, XMLoadFloat4(&b->data)); + bool depth = false; if (argc > 2) { Vector_BindLua* c = Luna::lightcheck(L, 3); @@ -247,15 +248,20 @@ namespace wi::lua::renderer XMStoreFloat4(&line.color_end, XMLoadFloat4(&c->data)); } else - wi::lua::SError(L, "DrawLine(Vector origin,end, opt Vector color) one or more arguments are not vectors!"); + wi::lua::SError(L, "DrawLine(Vector origin,end, opt Vector color, opt bool depth = false) one or more arguments are not vectors!"); + + if (argc > 3) + { + depth = wi::lua::SGetBool(L, 4); + } } - wi::renderer::DrawLine(line); + wi::renderer::DrawLine(line, depth); } else - wi::lua::SError(L, "DrawLine(Vector origin,end, opt Vector color) one or more arguments are not vectors!"); + wi::lua::SError(L, "DrawLine(Vector origin,end, opt Vector color, opt bool depth = false) one or more arguments are not vectors!"); } else - wi::lua::SError(L, "DrawLine(Vector origin,end, opt Vector color) not enough arguments!"); + wi::lua::SError(L, "DrawLine(Vector origin,end, opt Vector color, opt bool depth = false) not enough arguments!"); return 0; } @@ -269,6 +275,7 @@ namespace wi::lua::renderer { wi::renderer::RenderablePoint point; XMStoreFloat3(&point.position, XMLoadFloat4(&a->data)); + bool depth = false; if (argc > 1) { point.size = wi::lua::SGetFloat(L, 2); @@ -280,15 +287,20 @@ namespace wi::lua::renderer { point.color = color->data; } + + if (argc > 3) + { + depth = wi::lua::SGetBool(L, 4); + } } } - wi::renderer::DrawPoint(point); + wi::renderer::DrawPoint(point, depth); } else - wi::lua::SError(L, "DrawPoint(Vector origin, opt float size, opt Vector color) first argument must be a Vector type!"); + wi::lua::SError(L, "DrawPoint(Vector origin, opt float size, opt Vector color, opt bool depth = false) first argument must be a Vector type!"); } else - wi::lua::SError(L, "DrawPoint(Vector origin, opt float size, opt Vector color) not enough arguments!"); + wi::lua::SError(L, "DrawPoint(Vector origin, opt float size, opt Vector color, opt bool depth = false) not enough arguments!"); return 0; } @@ -305,7 +317,12 @@ namespace wi::lua::renderer Vector_BindLua* color = Luna::lightcheck(L, 2); if (color) { - wi::renderer::DrawBox(m->data, color->data); + bool depth = true; + if (argc > 2) + { + depth = wi::lua::SGetBool(L, 3); + } + wi::renderer::DrawBox(m->data, color->data, depth); return 0; } } @@ -313,10 +330,10 @@ namespace wi::lua::renderer wi::renderer::DrawBox(m->data); } else - wi::lua::SError(L, "DrawBox(Matrix boxMatrix, opt Vector color) first argument must be a Matrix type!"); + wi::lua::SError(L, "DrawBox(Matrix boxMatrix, opt Vector color, opt bool depth = true) first argument must be a Matrix type!"); } else - wi::lua::SError(L, "DrawBox(Matrix boxMatrix, opt Vector color) not enough arguments!"); + wi::lua::SError(L, "DrawBox(Matrix boxMatrix, opt Vector color, opt bool depth = true) not enough arguments!"); return 0; } @@ -333,7 +350,12 @@ namespace wi::lua::renderer Vector_BindLua* color = Luna::lightcheck(L, 2); if (color) { - wi::renderer::DrawSphere(sphere->sphere, color->data); + bool depth = true; + if (argc > 2) + { + depth = wi::lua::SGetBool(L, 3); + } + wi::renderer::DrawSphere(sphere->sphere, color->data, depth); return 0; } } @@ -341,10 +363,10 @@ namespace wi::lua::renderer wi::renderer::DrawSphere(sphere->sphere); } else - wi::lua::SError(L, "DrawSphere(Sphere sphere, opt Vector color) first argument must be a Matrix type!"); + wi::lua::SError(L, "DrawSphere(Sphere sphere, opt Vector color, opt bool depth = true) first argument must be a Matrix type!"); } else - wi::lua::SError(L, "DrawSphere(Sphere sphere, opt Vector color) not enough arguments!"); + wi::lua::SError(L, "DrawSphere(Sphere sphere, opt Vector color, opt bool depth = true) not enough arguments!"); return 0; } @@ -361,7 +383,12 @@ namespace wi::lua::renderer Vector_BindLua* color = Luna::lightcheck(L, 2); if (color) { - wi::renderer::DrawCapsule(capsule->capsule, color->data); + bool depth = true; + if (argc > 2) + { + depth = wi::lua::SGetBool(L, 3); + } + wi::renderer::DrawCapsule(capsule->capsule, color->data, depth); return 0; } } @@ -369,10 +396,10 @@ namespace wi::lua::renderer wi::renderer::DrawCapsule(capsule->capsule); } else - wi::lua::SError(L, "DrawCapsule(Capsule capsule, opt Vector color) first argument must be a Matrix type!"); + wi::lua::SError(L, "DrawCapsule(Capsule capsule, opt Vector color, opt bool depth = true) first argument must be a Matrix type!"); } else - wi::lua::SError(L, "DrawCapsule(Capsule capsule, opt Vector color) not enough arguments!"); + wi::lua::SError(L, "DrawCapsule(Capsule capsule, opt Vector color, opt bool depth = true) not enough arguments!"); return 0; } diff --git a/WickedEngine/wiScene.cpp b/WickedEngine/wiScene.cpp index 406c95bc7..90d4d930c 100644 --- a/WickedEngine/wiScene.cpp +++ b/WickedEngine/wiScene.cpp @@ -6725,7 +6725,7 @@ namespace wi::scene break; } } - if (!child_found) + if (!child_found && parent_spring != nullptr) { // No child, try to guess tail position compared to parent (if it has parent): const XMVECTOR parent_pos = parentWorldMatrix.r[3]; diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index b20b2ecfa..438b6d285 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wi::version // minor features, major updates, breaking compatibility changes const int minor = 71; // minor bug fixes, alterations, refactors, updates - const int revision = 452; + const int revision = 453; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);