From 99db152499b1ec2811b62326f9580cb60b93b3de Mon Sep 17 00:00:00 2001 From: Slendi Date: Fri, 3 Jul 2026 03:55:33 +0300 Subject: [PATCH] cylinder rendering Signed-off-by: Slendi --- src/Application.cpp | 40 +++++++++---------- src/VulkanRenderer.cpp | 90 ++++++++++++++++++++++++++++++++++++++++++ src/VulkanRenderer.h | 2 + 3 files changed, 111 insertions(+), 21 deletions(-) diff --git a/src/Application.cpp b/src/Application.cpp index 5ffd829..0a6767e 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -901,7 +901,7 @@ auto Application::run() -> void ImGui::NewFrame(); - ImGui::SetNextWindowSize({ 300, 100 }); + ImGui::SetNextWindowSize({ 300, 120 }); ImGui::SetNextWindowPos({ 0, 0 }); ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4 { 0, 0, 0, 0.5f }); bool debug_open { ImGui::Begin("Debug Info", nullptr, @@ -917,6 +917,9 @@ auto Application::run() -> void m_camera.up.y(), m_camera.up.z()); ImGui::Text("Cursor r/theta/phi: %.2f, %.2f, %.2f", m_cursor.r, m_cursor.theta, m_cursor.phi); + ImGui::Text("%s", + std::format("Wayland display: {}", m_wayland->socket_name()) + .c_str()); } ImGui::End(); ImGui::PopStyleColor(); @@ -1076,11 +1079,6 @@ auto Application::run() -> void { 0, 0.5f }, { 0.5f, 0.5f }, { Colors::TEAL, 1.0f }); gl.set_transform(view_projection); - gl.draw_sphere(m_camera.target, 0.01f); - - if (m_openxr && m_openxr->hand_tracking_supported) { - render_hands(gl, view_projection); - } assert(m_wayland); @@ -1090,9 +1088,9 @@ auto Application::run() -> void auto const draw_height { static_cast( wayland_draw_extent.height) }; if (draw_width > 0.0f && draw_height > 0.0f) { - gl.set_transform(smath::Mat4::identity()); - gl.set_culling(true); gl.use_pipeline(m_renderer->wayland_pipeline()); + gl.set_culling(true); + for (auto *surface : m_wayland->surfaces()) { auto buffer { surface->current_buffer() }; if (!buffer) { @@ -1102,23 +1100,23 @@ auto Application::run() -> void if (!texture) { continue; } - auto const width { static_cast(buffer->width) }; - auto const height { static_cast(buffer->height) }; - auto const size { smath::Vec2 { - (width / draw_width) * 2.0f, - (height / draw_height) * 2.0f, - } }; - auto const pos { smath::Vec2 { -1.0f, 1.0f - size.y() } }; auto image { m_renderer->create_image( *texture, vk::ImageUsageFlagBits::eSampled) }; - gl.set_texture(&image); - gl.draw_rectangle(pos, size); - gl.flush(); - gl.set_texture(std::nullopt); + + gl.draw_texture_cyl( + &image, smath::Vec3 {}, {}, 7, 0.01, true); + + gl.set_culling(false); m_renderer->destroy_image_later(image); } - gl.use_pipeline(m_renderer->mesh_pipeline()); - gl.set_culling(true); + } + gl.use_pipeline(m_renderer->mesh_pipeline()); + gl.set_culling(true); + + gl.draw_sphere(m_camera.target, 0.01f); + + if (m_openxr && m_openxr->hand_tracking_supported) { + render_hands(gl, view_projection); } } }; diff --git a/src/VulkanRenderer.cpp b/src/VulkanRenderer.cpp index 7f27eb2..40df9a8 100644 --- a/src/VulkanRenderer.cpp +++ b/src/VulkanRenderer.cpp @@ -517,6 +517,96 @@ auto VulkanRenderer::GL::draw_sphere(smath::Vec3 center, float radius, end(); } +auto VulkanRenderer::GL::draw_texture_cyl(AllocatedImage const *texture, + smath::Vec3 sphere_center, PolarCoordinate coord, float rad, float scale, + bool y_flip) -> void +{ + // midpoint on the sphere where the panel should sit (its center) + auto fwd { coord.to_vec3() }; + if (fwd.magnitude() < 1e-6f) + fwd = smath::Vec3 { 0, 0, 1 }; + fwd = fwd.normalized(); + + // build a local tangent frame at that point (right, up, forward) + smath::Vec3 worldUp { 0, 1, 0 }; + if (fabsf(worldUp.dot(fwd)) > 0.99f) + worldUp = smath::Vec3 { 1, 0, 0 }; + auto const right = worldUp.cross(fwd).normalized(); + auto const up = fwd.cross(right).normalized(); + + float const r = fabsf(rad); + float const arc_len + = (float)texture->extent.width * scale; // world units across + float const theta = arc_len / r; // total horizontal FOV in radians + float const half_t = 0.5f * theta; + float const half_h = 0.5f * (float)texture->extent.height * scale; + + // shift so cylinder's surface midpoint lands exactly at coord.r from + // sphere_center + auto const delta + = sphere_center + fwd * (coord.r - r) + smath::Vec3 { 0, 0, 0 }; + + // tessellation: about 3deg per slice (min 8, max 1024) + int slices = (int)ceilf(fmaxf(theta * (180.0f / M_PI) / 3.0f, 8.0f)); + if (slices > 1024) + slices = 1024; + + float vt = y_flip ? 1.0f : 0.0f; + float vb = y_flip ? 0.0f : 1.0f; + + this->set_texture(texture); + color(smath::Vec3 { 1.0f, 1.0f, 1.0f }); + this->begin(GeometryKind::Quads); + + for (int i = 0; i < slices; ++i) { + auto const u0 { (float)i / (float)slices }; + auto const u1 { (float)(i + 1) / (float)slices }; + + auto const aL { -half_t + theta * u0 }; + auto const aR { -half_t + theta * u1 }; + + // local outward directions on the cylindrical surface + auto nL { right * sinf(aL) + fwd * cosf(aL) }; + auto nR { right * sinf(aR) + fwd * cosf(aR) }; + + if (rad < 0.0f) { + nL = nL * -1.0; + nR = nR * -1.0; + } + + // surface points (center band), then top/bottom by +/- up*half_h + auto const cL { delta + nL * r }; + auto const cR { delta + nR * r }; + + auto const pLT { cL + up * half_h }; + auto const pLB { cL + up * (-half_h) }; + auto const pRT { cR + up * half_h }; + auto const pRB { cR + up * (-half_h) }; + + auto const U0 = 1.0f - u0; + auto const U1 = 1.0f - u1; + + normal(nL); + uv(smath::Vec2 { U0, vt }); + vert(pLT); + + normal(nR); + uv(smath::Vec2 { U1, vt }); + vert(pRT); + + normal(nL); + uv(smath::Vec2 { U0, vb }); + vert(pLB); + + normal(nR); + uv(smath::Vec2 { U1, vb }); + vert(pRB); + } + + this->end(); + this->set_texture(); +} + auto VulkanRenderer::GL::draw_mesh(GPUMeshBuffers const &mesh, smath::Mat4 const &transform, uint32_t index_count, uint32_t first_index, int32_t vertex_offset) -> void diff --git a/src/VulkanRenderer.h b/src/VulkanRenderer.h index 99eb0da..cabd36a 100644 --- a/src/VulkanRenderer.h +++ b/src/VulkanRenderer.h @@ -72,10 +72,12 @@ struct VulkanRenderer { push_vertex(pos); } + auto color(smath::Vec3 const &rgb) -> void; auto color(smath::Vec4 const &rgba) -> void; auto uv(smath::Vec2 const &uv) -> void; auto normal(smath::Vec3 const &normal) -> void; + auto set_texture(std::optional texture = std::nullopt) -> void; auto set_culling(bool enabled) -> void;