180 lines
6.1 KiB
C++
180 lines
6.1 KiB
C++
#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
|