This commit is contained in:
2019-05-06 21:03:22 +02:00
parent ea2cf73bdb
commit 898afe9052
8 changed files with 216 additions and 36 deletions

View File

@@ -277,7 +277,7 @@ void Canvas::stroke_draw_mix(const glm::vec2& bb_min, const glm::vec2& bb_sz)
gl.restore();
}
std::array<std::vector<vertex_t>, 6> Canvas::stroke_draw_project(std::array<vertex_t, 4>& B) const
std::array<std::vector<vertex_t>, 6> Canvas::stroke_draw_project(std::array<vertex_t, 4>& B, bool project_3d /*= false*/, glm::mat4 mv /*= glm::mat4(1)*/) const
{
// intersect P with the current face to clip diverging points from the plane
const auto unp_vp = zw(m_box);
@@ -285,59 +285,69 @@ std::array<std::vector<vertex_t>, 6> Canvas::stroke_draw_project(std::array<vert
std::array<std::vector<vertex_t>, 6> ret;
for (int i = 0; i < 6; i++)
{
auto P = poly_intersect(B.data(), B.data() + 4, m_plane_shape[i]);
glm::mat4 plane_camera = glm::lookAt(m_plane_origin[i], m_plane_normal[i], m_plane_tangent[i]);
int intersections = 0;
for (int j = 0; j < P.size(); j++)
struct ray_t {
glm::vec3 o;
glm::vec3 d;
vertex_t v;
ray_t(glm::vec3 o, glm::vec3 d, vertex_t v) : o(o), d(d), v(v) { }
};
std::vector<ray_t> rays;
if (project_3d)
{
glm::vec3 ray_origin, ray_dir;
//if (s.pos.z == 0)
rays.reserve(B.size());
for (auto const& b : B)
rays.emplace_back(glm::vec3(0), b.pos, b);
}
else
{
auto P = poly_intersect(B.data(), B.data() + 4, m_plane_shape[i]);
rays.reserve(P.size());
for (auto const& p : P)
{
//point_unproject(P[j].pos, { 0, 0, zw(m_box) }, m_mv, m_proj, ray_origin, ray_dir);
auto clip_space = glm::vec2(P[j].pos.x, unp_vp.y - P[j].pos.y - 1.f) / unp_vp * 2.f - 1.f;
glm::vec3 ray_origin, ray_dir;
auto clip_space = glm::vec2(p.pos.x, unp_vp.y - p.pos.y - 1.f) / unp_vp * 2.f - 1.f;
auto wp0 = unp_inv * glm::vec4(clip_space, 0, 1);
auto wp1 = unp_inv * glm::vec4(clip_space, .5, 1);
ray_origin = xyz(wp0 / wp0.w);
ray_dir = glm::normalize(xyz(wp1 / wp1.w) - ray_origin);
rays.emplace_back(ray_origin, ray_dir, p);
}
//else
//{
// auto m = glm::inverse(glm::lookAt({ 0, 0, 0 }, s.pos, { 0, 1, 0 }));
// glm::vec3 off_3d = m * glm::vec4(off[j], 0, 1);
// ray_origin = glm::vec3(0);
// ray_dir = s.pos + off_3d;
//}
}
glm::mat4 plane_camera = glm::lookAt(m_plane_origin[i], m_plane_normal[i], m_plane_tangent[i]);
std::vector<vertex_t> face_ret;
face_ret.reserve(rays.size());
for (auto const& r : rays)
{
glm::vec3 hit;
float hit_t;
if (ray_intersect(ray_origin, ray_dir, m_plane_origin[i], m_plane_normal[i], m_plane_tangent[i], hit, hit_t))
if (ray_intersect(r.o, r.d, m_plane_origin[i], m_plane_normal[i], m_plane_tangent[i], hit, hit_t))
{
glm::vec4 plane_local = plane_camera * glm::vec4(hit, 1);
//P[j].uvs2 = xy(P[j].pos) / glm::vec2(App::I.width, App::I.height);
P[j].pos.x = -(plane_local.x * 0.5f - 0.5f) * m_width;
P[j].pos.y = (plane_local.y * 0.5f + 0.5f) * m_height;
vertex_t v;
v.pos.x = -(plane_local.x * 0.5f - 0.5f) * m_width;
v.pos.y = (plane_local.y * 0.5f + 0.5f) * m_height;
// Black magic - BEWARE!
// interpolation perspective correction, use the current camera projection to correct the interpolation
// because the new shape will have z fixed with an ortho projection when drawn to the face
// we need to imitate the same perspective as the once in the camera
// see: https://www.scratchapixel.com/lessons/3d-basic-rendering/rasterization-practical-implementation/perspective-correct-interpolation-vertex-attributes
auto hit_cam = m_mv * glm::vec4(hit, 1);
P[j].pos.z = 0;
P[j].pos.w = hit_cam.z;
P[j].uvs *= hit_cam.z;
P[j].uvs2 *= hit_cam.z;
intersections++;
auto hit_cam = mv * glm::vec4(hit, 1);
v.pos.z = 0;
v.pos.w = hit_cam.z;
v.uvs = r.v.uvs * hit_cam.z;
v.uvs2 = r.v.uvs2 * hit_cam.z;
face_ret.emplace_back(v);
}
else
{
break;
}
}
if (intersections >= 3)
ret[i] = P;
if (face_ret.size() >= 3)
ret[i] = std::move(face_ret);
}
return ret;
}
@@ -443,7 +453,16 @@ std::vector<Canvas::StrokeFrame> Canvas::stroke_draw_compute(Stroke& stroke) con
mixer_bb_min = glm::max({ 0, 0 }, glm::min(mixer_bb_min, p));
mixer_bb_max = glm::min(mixer_sz, glm::max(mixer_bb_max, p));
B[j].pos = glm::vec4(xy(s.pos) + App::I.zoom * s.scale * off[j] * glm::orientate2(-s.angle) - glm::vec2(0, 1), 1, 1);
if (s.pos.z == 0.f)
{
B[j].pos = glm::vec4(xy(s.pos) + App::I.zoom * s.scale * off[j] * glm::orientate2(-s.angle) - glm::vec2(0, 1), 1, 1);
}
else
{
auto m = glm::inverse(glm::lookAt({ 0, 0, 0 }, s.pos, { 0, 1, 0 }));
glm::vec3 off_3d = m * glm::vec4(off[j], 0, 1);
B[j].pos = glm::vec4(s.pos + off_3d, 1.f);
}
B[j].uvs2 = p / mixer_sz;
}
@@ -451,7 +470,15 @@ std::vector<Canvas::StrokeFrame> Canvas::stroke_draw_compute(Stroke& stroke) con
f.col = glm::vec4(s.col, 1);
f.flow = s.flow;
f.opacity = s.opacity;
f.shapes = stroke_draw_project(B);
if (s.pos.z == 0.f)
{
f.shapes = stroke_draw_project(B, false, m_mv);
}
else
{
auto m = glm::lookAt({ 0, 0, 0 }, s.pos, { 0, 1, 0 });
f.shapes = stroke_draw_project(B, true, m);
}
prev = s;
}