Extract canvas projection helpers and thin preview and node loading

This commit is contained in:
2026-06-16 18:16:04 +02:00
parent 1442c13dd7
commit 8906756d12
11 changed files with 565 additions and 341 deletions

View File

@@ -0,0 +1,179 @@
#include "pch.h"
#include "legacy_canvas_projection_services.h"
#include "canvas.h"
namespace pp::panopainter {
bool legacy_canvas_point_trace(Canvas& canvas, glm::vec2 loc, glm::vec3& ray_origin, glm::vec3& ray_dir,
glm::vec3& hit_pos, glm::vec2& fb_pos, glm::vec3& hit_normal, int& out_plane_id)
{
legacy_canvas_point_unproject(loc, { 0, 0, zw(canvas.m_box) }, canvas.m_mv, canvas.m_proj, ray_origin, ray_dir);
glm::vec3 hit;
float hit_t;
for (int i = 0; i < 6; i++)
{
if (ray_intersect(ray_origin, ray_dir, canvas.m_plane_origin[i], canvas.m_plane_normal[i], canvas.m_plane_tangent[i], hit, hit_t))
{
glm::mat4 plane_camera = glm::lookAt(canvas.m_plane_origin[i], canvas.m_plane_normal[i], canvas.m_plane_tangent[i]);
glm::vec4 plane_local = plane_camera * glm::vec4(hit, 1);
if (glm::abs(plane_local.x) < 1.f && glm::abs(plane_local.y) < 1.f)
{
fb_pos.x = -(plane_local.x * 0.5f - 0.5f) * canvas.m_width;
fb_pos.y = (plane_local.y * 0.5f + 0.5f) * canvas.m_height;
hit_pos = hit;
hit_normal = canvas.m_plane_normal[i];
out_plane_id = i;
return true;
}
}
}
return false;
}
bool legacy_canvas_point_trace_plane(Canvas& canvas, glm::vec2 loc, glm::vec3& ray_origin, glm::vec3& ray_dir,
glm::vec3& hit_pos, glm::vec3& hit_normal, glm::vec2& hit_fb_pos, int plane_id)
{
legacy_canvas_point_unproject(loc, { 0, 0, zw(canvas.m_box) }, canvas.m_mv, canvas.m_proj, ray_origin, ray_dir);
glm::vec3 hit;
float hit_t;
if (ray_intersect(ray_origin, ray_dir, canvas.m_plane_origin[plane_id],
canvas.m_plane_normal[plane_id], canvas.m_plane_tangent[plane_id], hit, hit_t))
{
glm::mat4 plane_camera = glm::lookAt(canvas.m_plane_origin[plane_id], canvas.m_plane_normal[plane_id], canvas.m_plane_tangent[plane_id]);
glm::vec4 plane_local = plane_camera * glm::vec4(hit, 1);
hit_pos = hit;
hit_normal = canvas.m_plane_normal[plane_id];
hit_fb_pos.x = -(plane_local.x * 0.5f - 0.5f);
hit_fb_pos.y = (plane_local.y * 0.5f + 0.5f);
return true;
}
return false;
}
void legacy_canvas_point_unproject(glm::vec2 loc, glm::vec4 vp, glm::mat4 camera, glm::mat4 proj,
glm::vec3& out_origin, glm::vec3& out_dir)
{
auto clip_space = glm::vec2(loc.x, vp.w - loc.y - 1.f) / zw(vp) * 2.f - 1.f;
auto inv = glm::inverse(proj * camera);
auto wp0 = inv * glm::vec4(clip_space, 0, 1);
auto wp1 = inv * glm::vec4(clip_space, .5, 1);
out_origin = xyz(wp0 / wp0.w);
out_dir = glm::normalize(xyz(wp1 / wp1.w) - out_origin);
}
void legacy_canvas_point_unproject(Canvas& canvas, glm::vec2 loc, glm::vec3& out_origin, glm::vec3& out_dir)
{
auto clip_space = glm::vec2(loc.x, canvas.m_vp.w - loc.y - 1.f) / zw(canvas.m_vp) * 2.f - 1.f;
auto inv = glm::inverse(canvas.m_proj * canvas.m_mv);
auto wp0 = inv * glm::vec4(clip_space, 0, 1);
auto wp1 = inv * glm::vec4(clip_space, .5, 1);
out_origin = xyz(wp0 / wp0.w);
out_dir = glm::normalize(xyz(wp1 / wp1.w) - out_origin);
}
glm::vec3 legacy_canvas_point_trace(Canvas& canvas, glm::vec2 loc)
{
glm::vec3 ray_origin;
glm::vec3 ray_dir;
glm::vec3 hit_pos;
glm::vec3 hit_normal;
glm::vec2 fb_pos;
int plane_id;
if (legacy_canvas_point_trace(canvas, loc, ray_origin, ray_dir, hit_pos, fb_pos, hit_normal, plane_id))
return hit_pos;
return glm::vec3(0);
}
void legacy_canvas_project_2d_points(Canvas& canvas, std::vector<vertex_t>& vertices)
{
for (auto& p : vertices)
{
glm::vec3 ro, rd, hit_o, hit_d;
glm::vec2 hit_fb;
int plane_id;
if (legacy_canvas_point_trace(canvas, p.pos, ro, rd, hit_o, hit_fb, hit_d, plane_id))
p.pos = glm::vec4(hit_o, 1);
}
}
glm::vec3 legacy_canvas_project_2d_point(Canvas& canvas, glm::vec2 pt)
{
glm::vec3 ro, rd, hit_o, hit_d;
glm::vec2 hit_fb;
int plane_id;
if (legacy_canvas_point_trace(canvas, pt, ro, rd, hit_o, hit_fb, hit_d, plane_id))
return glm::vec4(hit_o, 1);
return glm::vec3(0);
}
std::vector<glm::vec2> legacy_canvas_face_to_shape_2d(const Canvas& canvas, int plane_index)
{
static std::array<glm::vec4, 4> corners{
glm::vec4(-1.f, +1.f, -1.f, 1.f),
glm::vec4(+1.f, +1.f, -1.f, 1.f),
glm::vec4(+1.f, -1.f, -1.f, 1.f),
glm::vec4(-1.f, -1.f, -1.f, 1.f),
};
std::vector<glm::vec3> pt_cam;
for (auto c : corners)
{
auto pt_world = canvas.m_plane_transform[plane_index] * c;
pt_cam.push_back(canvas.m_mv * pt_world);
}
pt_cam = poly_clip_near(pt_cam, 0.01f);
std::vector<glm::vec2> points;
for (auto p : pt_cam)
{
auto pt_clip = canvas.m_proj * glm::vec4(p, 1);
pt_clip = pt_clip / pt_clip.w;
glm::vec2 pt_screen = (glm::vec2(pt_clip) * 0.5f + 0.5f) * zw(canvas.m_vp);
pt_screen.y = canvas.m_vp.w - pt_screen.y - 1;
points.push_back(pt_screen);
}
return points;
}
void legacy_canvas_push_camera(Canvas& canvas)
{
canvas.m_camera_stack.push(legacy_canvas_get_camera(canvas));
}
void legacy_canvas_pop_camera(Canvas& canvas)
{
if (!canvas.m_camera_stack.empty())
{
legacy_canvas_set_camera(canvas, canvas.m_camera_stack.top());
canvas.m_camera_stack.pop();
}
}
CameraData legacy_canvas_get_camera(const Canvas& canvas)
{
CameraData camera;
camera.m_box = canvas.m_box;
camera.m_mv = canvas.m_mv;
camera.m_pan = canvas.m_pan;
std::copy_n(canvas.m_plane_dir, 6, camera.m_plane_dir);
std::copy_n(canvas.m_plane_unproject, 6, camera.m_plane_unproject);
camera.m_proj = canvas.m_proj;
camera.m_vp = canvas.m_vp;
return camera;
}
void legacy_canvas_set_camera(Canvas& canvas, const CameraData& camera)
{
canvas.m_box = camera.m_box;
canvas.m_mv = camera.m_mv;
canvas.m_pan = camera.m_pan;
std::copy_n(camera.m_plane_dir, 6, canvas.m_plane_dir);
std::copy_n(camera.m_plane_unproject, 6, canvas.m_plane_unproject);
canvas.m_proj = camera.m_proj;
canvas.m_vp = camera.m_vp;
}
} // namespace pp::panopainter