cylinder rendering

Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
2026-07-03 03:55:33 +03:00
parent 918568e7e6
commit 99db152499
3 changed files with 111 additions and 21 deletions
+17 -19
View File
@@ -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<float>(
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<float>(buffer->width) };
auto const height { static_cast<float>(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.draw_sphere(m_camera.target, 0.01f);
if (m_openxr && m_openxr->hand_tracking_supported) {
render_hands(gl, view_projection);
}
} };
+90
View File
@@ -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
+2
View File
@@ -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<AllocatedImage const *> texture
= std::nullopt) -> void;
auto set_culling(bool enabled) -> void;