#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& 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 legacy_canvas_face_to_shape_2d(const Canvas& canvas, int plane_index) { static std::array 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 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 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