From 6f9b1b1c239ecdc35d0f7a5d712c2a2cb8887ff2 Mon Sep 17 00:00:00 2001 From: omigamedev Date: Thu, 22 Nov 2018 10:30:31 +0100 Subject: [PATCH] transform tool wip --- src/app_shaders.cpp | 2 +- src/canvas.cpp | 150 +++++++++++++++++--------- src/canvas.h | 4 +- src/canvas_modes.cpp | 252 ++++++++++++++++++++++++++----------------- src/canvas_modes.h | 10 +- src/node_canvas.cpp | 3 +- 6 files changed, 267 insertions(+), 154 deletions(-) diff --git a/src/app_shaders.cpp b/src/app_shaders.cpp index e9c4016..24dd656 100644 --- a/src/app_shaders.cpp +++ b/src/app_shaders.cpp @@ -314,7 +314,7 @@ void App::initShaders() "void main(){\n" " uv = uvs;\n" " uv_2 = uvs2;\n" - " q = pos.z;\n" + " q = pos.w;\n" " gl_Position = mvp * vec4(pos.xy, 0.0, 1.0);\n" "}\n"; static const char* shader_stroke_f = diff --git a/src/canvas.cpp b/src/canvas.cpp index a6937db..2eb0b17 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -374,6 +374,23 @@ void ui::Canvas::stroke_draw() stroke_draw_mix(bb_min, bb_sz); } + // P is the initial square centered at the cursor location + glm::vec2 dx(s.size * 0.5f, 0), dy(0, s.size * 0.5f); + glm::vec2 off[4] = { + -dx - dy, // A - bottom-left + -dx + dy, // B - top-left + +dx + dy, // C - top-right + +dx - dy, // D - bottom-right + }; + std::vector B{ + vertex_t{ {0, 0, 1, 1}, {0, 0}, {0, 0} }, + vertex_t{ {0, 0, 1, 1}, {0, 1}, {0, 1} }, + vertex_t{ {0, 0, 1, 1}, {1, 1}, {1, 1} }, + vertex_t{ {0, 0, 1, 1}, {1, 0}, {1, 0} }, + }; + for (int j = 0; j < 4; j++) + B[j].pos = glm::vec4(xy(s.pos) + off[j] * glm::orientate2(-s.angle), 1, 1); + glViewport(0, 0, m_width, m_height); glActiveTexture(GL_TEXTURE0); @@ -414,31 +431,13 @@ void ui::Canvas::stroke_draw() // some trigonometric shit, tangent and stuff // if (dot < -0.3f) // continue; - - - glm::vec2 dx(s.size * 0.5f, 0), dy(0, s.size * 0.5f); - glm::vec2 off[4] = { - - dx - dy, // A - bottom-left - - dx + dy, // B - top-left - + dx + dy, // C - top-right - + dx - dy, // D - bottom-right - }; int intersected = 0; int inside = 0; // face is the 2d shape of the cube plane i projected onto the window space auto face = face_to_shape2D(i); - // P is the initial square centered at the cursor location - std::vector P{ - vertex_t{ {0, 0, 1, 1}, {0, 0}, {0, 0} }, - vertex_t{ {0, 0, 1, 1}, {0, 1}, {0, 1} }, - vertex_t{ {0, 0, 1, 1}, {1, 1}, {1, 1} }, - vertex_t{ {0, 0, 1, 1}, {1, 0}, {1, 0} }, - }; - for (int j = 0; j < 4; j++) - P[j].pos = glm::vec4(xy(s.pos) + off[j] * glm::orientate2(-s.angle), 1, 1); // intersect P with the current face to clip diverging points from the plane - P = poly_intersect(P, face); + auto P = poly_intersect(B, face); for (int j = 0; j < P.size(); j++) { @@ -475,7 +474,8 @@ void ui::Canvas::stroke_draw() // 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 = hit_cam.z; + P[j].pos.z = 0; + P[j].pos.w = hit_cam.z; P[j].uvs *= hit_cam.z; P[j].uvs2 *= hit_cam.z; @@ -617,9 +617,31 @@ bool ui::Canvas::point_trace(glm::vec2 loc, glm::vec3& ray_origin, glm::vec3& ra } return false; } +/* +bool ui::Canvas::point_trace_plane(glm::vec2 loc, glm::vec3& hit_pos, glm::vec2& hit_fb_pos, int plane_id) +{ + auto ln = (loc / zw(m_box)) * 2.f - 1.f; + auto p = m_plane_unproject[plane_id] * glm::vec4(ln, 1, 1); + if (p.w <= 0) + { + + return true; + } + return false; +} +*/ bool ui::Canvas::point_trace_plane(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) { +/* + auto ln = (loc / zw(m_box)) * 2.f - 1.f; + auto p = m_plane_unproject[plane_id] * glm::vec4(ln, 1, 1); + if (p.w <= 0) + { + + return true; + } +*/ point_unproject(loc, { 0, 0, zw(m_box) }, m_mv, m_proj, ray_origin, ray_dir); glm::vec3 hit; glm::vec2 fb_pos; @@ -655,7 +677,19 @@ void ui::Canvas::point_unproject(glm::vec2 loc, glm::vec3& out_origin, glm::vec3 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 ui::Canvas::point_trace(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 (point_trace(loc, ray_origin, ray_dir, hit_pos, fb_pos, hit_normal, plane_id)) + return hit_pos; + return glm::vec3(0); +} void ui::Canvas::stroke_commit() { if (!m_dirty || m_layers.empty()) @@ -962,6 +996,7 @@ void ui::Canvas::resize(int width, int height) { m_width = width; m_height = height; + m_size = { width, height }; for (int i = 0; i < 6; i++) { #if defined(__IOS__) || defined(__ANDROID__) @@ -982,6 +1017,7 @@ bool ui::Canvas::create(int width, int height) { m_width = width; m_height = height; + m_size = { width, height }; for (int i = 0; i < 6; i++) { #if defined(__IOS__) || defined(__ANDROID__) @@ -2018,7 +2054,7 @@ void ui::Canvas::draw_objects(std::function ui::Canvas::triangulate_simple(const std::vector std::vector ui::Canvas::triangulate(const std::vector& points) { - std::vector> tmp; + std::vector tmp; for (auto pt : points) - tmp.push_back(std::make_shared(pt.x, pt.y)); + tmp.push_back(pt); return triangulate(tmp); } -std::vector ui::Canvas::triangulate(const std::vector>& points) +std::vector ui::Canvas::triangulate(const std::vector& points) { struct Segment { - std::shared_ptr a = nullptr; - std::shared_ptr b = nullptr; + const vertex_t* a = nullptr; + const vertex_t* b = nullptr; Segment* prev = nullptr; std::shared_ptr next = nullptr; bool end = false; }; - + std::vector> new_points; std::shared_ptr root = std::make_shared(); std::shared_ptr node = root; for (int i = 0; i < points.size(); i++) { - node->a = points[i]; + node->a = &points[i]; if (i == points.size() - 1) { - node->b = points[0]; + node->b = &points[0]; node->next = root; node->end = true; root->prev = node.get(); } else { - node->b = points[i + 1]; + node->b = &points[i + 1]; node->next = std::make_shared(); node->next->prev = node.get(); } @@ -2181,21 +2217,25 @@ std::vector ui::Canvas::triangulate(const std::vector other = node->next; while (other) { - if (*node->a == *other->a || *node->a == *other->b || - *node->b == *other->a || *node->b == *other->b) + if (node->a->pos == other->a->pos || node->a->pos == other->b->pos || + node->b->pos == other->a->pos || node->b->pos == other->b->pos) { other = other->end ? nullptr : other->next; continue; } - glm::vec2 s0a(node->a->x, node->a->y); - glm::vec2 s0b(node->b->x, node->b->y); - glm::vec2 s1a(other->a->x, other->a->y); - glm::vec2 s1b(other->b->x, other->b->y); + glm::vec2 s0a(node->a->pos); + glm::vec2 s0b(node->b->pos); + glm::vec2 s1a(other->a->pos); + glm::vec2 s1b(other->b->pos); glm::vec2 hit_uv; glm::vec2 is; if (segments_intersect(s0a, s0b, s1a, s1b, is, hit_uv)) { - auto p = std::make_shared(is.x, is.y); + new_points.push_back(std::make_unique()); + auto p = new_points.back().get(); + p->pos = glm::lerp(node->a->pos, node->b->pos, hit_uv.x); + p->uvs = glm::lerp(node->a->uvs, node->b->uvs, hit_uv.x); + p->uvs2 = glm::lerp(node->a->uvs2, node->b->uvs2, hit_uv.x); auto poly_root = std::make_shared(); poly_root->a = p; poly_root->b = node->b; @@ -2219,43 +2259,49 @@ std::vector ui::Canvas::triangulate(const std::vector vertices; + std::vector ret; for (auto poly : polys) { - std::vector outline; + std::vector outline; node = poly; while (node) { - outline.push_back(new p2t::Point(*node->a)); + if (outline.empty() || // if empty insert right away + outline.back() != node->a && // insert only if different than the last post + (outline.front() != node->a || !node->end)) // if is the end check against the first one + { + outline.push_back(node->a); + } auto current = node; node = node->end ? nullptr : node->next; current->next = nullptr; } - //LOG("poly %zu", outline.size()); if (outline.size() > 2) { - p2t::CDT* cdt = new p2t::CDT(outline); + std::vector points(outline.size()); + std::vector points_ptr(outline.size()); + for (size_t i = 0; i < outline.size(); i++) + { + points[i] = { outline[i]->pos.x, outline[i]->pos.y }; + points_ptr[i] = &points[i]; + } + + p2t::CDT* cdt = new p2t::CDT(points_ptr); // TODO: remove duplicates cdt->Triangulate(); auto tr = cdt->GetTriangles(); for (auto t : tr) { - vertex_t vertex; for (int i = 0; i < 3; i++) { - auto p = t->GetPoint(i); - vertex.pos = glm::vec4(p->x, p->y, 0, 1); - vertices.push_back(vertex); + auto index = std::distance(points.data(), t->GetPoint(i)); + ret.push_back(*outline[index]); } } - - delete cdt; } - for (auto p : outline) - delete p; } - return vertices; + return ret; } /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/canvas.h b/src/canvas.h index f0c546a..b98bce2 100644 --- a/src/canvas.h +++ b/src/canvas.h @@ -122,6 +122,7 @@ public: glm::vec4 m_box{ 0 }; glm::vec4 m_vp{ 0 }; glm::vec2 m_pan{ 0 }; + glm::vec2 m_size{ 0 }; int m_width = 0; int m_height = 0; bool m_use_instanced = false; @@ -229,12 +230,13 @@ public: void point_unproject(glm::vec2 loc, glm::vec4 vp, glm::mat4 camera, glm::mat4 proj, glm::vec3 &out_origin, glm::vec3 &out_dir); void point_unproject(glm::vec2 loc, glm::vec3 &out_origin, glm::vec3 &out_dir); + glm::vec3 point_trace(glm::vec2 loc); bool point_trace(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); bool point_trace_plane(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); std::vector triangulate_simple(const std::vector& vertices); - std::vector triangulate(const std::vector>& points); + std::vector triangulate(const std::vector& points); std::vector triangulate(const std::vector& points); void project2Dpoints(std::vector& vertices); glm::vec3 project2Dpoint(glm::vec2 pt); diff --git a/src/canvas_modes.cpp b/src/canvas_modes.cpp index 3316445..722f09c 100644 --- a/src/canvas_modes.cpp +++ b/src/canvas_modes.cpp @@ -603,9 +603,9 @@ void CanvasModeMaskLine::leave() { if (m_points2d.size() > 3) { - std::vector> points; + std::vector points; for (int i = 0; i < (int)m_points2d.size(); i++) - points.emplace_back(std::make_shared(m_points2d[i].x, m_points2d[i].y)); + points.emplace_back(m_points2d[i]); auto v = canvas->triangulate(points); canvas->project2Dpoints(v); LOG("%d points", (int)v.size()); @@ -844,6 +844,106 @@ void CanvasModeTransform::init() m_sphere.create(1.f, glm::radians(-10.f), glm::radians(10.f), glm::radians(-10.f), glm::radians(10.f), 1.f); m_circle.create<16>(1.f); m_shape.create(); + m_xform = glm::mat4(1); +} + +void CanvasModeTransform::enter() +{ + auto m = static_cast(canvas->modes[(int)ui::Canvas::kCanvasMode::MaskFree][0]); + int plane = 0; + auto face = canvas->face_to_shape2D(plane); + auto shape2d = poly_intersect(m->m_points2d, face); + std::vector shape3d; + shape3d.reserve(shape2d.size()); + glm::vec2 bb_min(canvas->m_size); + glm::vec2 bb_max(0, 0); + glm::vec2 midpoint(0); + for (auto p2d : shape2d) + { + //p2d.y = canvas->m_box.w - p2d.y - 1; + auto p2d_clip = ((p2d / zw(canvas->m_box)) * 2.f - 1.f) * glm::vec2(1, -1); + auto p3d_plane = canvas->m_plane_unproject[plane] * glm::vec4(p2d_clip, 0, 1); + auto p2d_plane = (-xy(p3d_plane) / p3d_plane.z)/* * glm::vec2(-1, 1)*/; + auto p2d_plane_raster = (p2d_plane * 0.5f + 0.5f) * canvas->m_size; + auto p3d_world = canvas->m_plane_transform[plane] * glm::vec4(p2d_plane, -1, 1); + bb_min = glm::min(bb_min, p2d_plane_raster); + bb_max = glm::max(bb_max, p2d_plane_raster); + + //p2d.y = canvas->m_box.w - p2d.y - 1; + midpoint += p2d; + + glm::vec3 pt_o, pt_d; + canvas->point_unproject(p2d, pt_o, pt_d); + + vertex_t v; + v.pos = glm::vec4(xyz(p3d_world), 1); + v.uvs = p2d_plane_raster; + shape3d.push_back(v); + } + auto bb_sz = bb_max - bb_min; + auto bb_center = (bb_min + bb_max) * 0.5f; + midpoint = midpoint / (float)shape2d.size(); + auto center3d = canvas->point_trace(midpoint); + auto cam_up = glm::inverse(canvas->m_mv) * glm::vec4(0, 1, 0, 1); + m_xform = glm::lookAt({ 0, 0, 0 }, canvas->point_trace(midpoint), xyz(cam_up)); + for (auto& v : shape3d) + { + v.uvs = (v.uvs - bb_min) / bb_sz; + v.pos = m_xform * v.pos; + } + m_xform = glm::inverse(glm::lookAt({ 0, 0, 0 }, canvas->point_trace(midpoint), xyz(cam_up))); + + shape3d = canvas->triangulate(shape3d); + m_shape.update_vertices(shape3d.data(), shape3d.size()); + + canvas->m_layers[canvas->m_current_layer_idx].m_rtt[plane].bindFramebuffer(); + m_tex.create(bb_sz.x, bb_sz.y); + m_tex.bind(); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bb_min.x, bb_min.y, bb_sz.x, bb_sz.y); + m_tex.unbind(); + canvas->m_layers[canvas->m_current_layer_idx].m_rtt[plane].unbindFramebuffer(); +} + +void CanvasModeTransform::leave() +{ + auto& layer = canvas->m_layers[canvas->m_current_layer_idx]; + + GLint vp[4]; + glGetIntegerv(GL_VIEWPORT, vp); + glViewport(0, 0, layer.w, layer.h); + + bool depth = glIsEnabled(GL_DEPTH_TEST); + bool blend = glIsEnabled(GL_BLEND); + + glDisable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + glActiveTexture(GL_TEXTURE0); + + //glm::perspective(glm::radians(m_canvas->m_cam_fov), box.z / box.w, 0.01f, 1000.f); + glm::mat4 proj = glm::perspective(glm::radians(90.f), 1.f, .01f, 1000.f); + for (int i = 0; i < 6; i++) + { + glm::mat4 plane_camera = glm::lookAt(glm::vec3(0), canvas->m_plane_origin[i], canvas->m_plane_tangent[i]); + layer.m_rtt[i].bindFramebuffer(); + + ui::ShaderManager::use(ui::kShader::Color); + ui::ShaderManager::u_mat4(ui::kShaderUniform::MVP, proj * plane_camera * m_xform); + ui::ShaderManager::u_vec4(ui::kShaderUniform::Col, { 0, 1, 1, .1 }); + m_shape.draw_fill(); + + ui::ShaderManager::use(ui::kShader::Texture); + ui::ShaderManager::u_int(ui::kShaderUniform::Tex, 0); + ui::ShaderManager::u_mat4(ui::kShaderUniform::MVP, proj * plane_camera * m_xform); + m_tex.bind(); + canvas->m_sampler.bind(0); + m_shape.draw_fill(); + m_tex.unbind(); + + layer.m_rtt[i].unbindFramebuffer(); + } + depth ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST); + blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND); + glViewport(vp[0], vp[1], vp[2], vp[3]); } void CanvasModeTransform::on_Draw(const glm::mat4& ortho, const glm::mat4& proj, const glm::mat4& camera) @@ -860,33 +960,39 @@ void CanvasModeTransform::on_Draw(const glm::mat4& ortho, const glm::mat4& proj, auto p = glm::vec3(x, y, z); //auto m = glm::inverse(glm::lookAt({ 0, 0, 0 }, m_center_pos, { 0, 1, 0 })); - //auto m = static_cast(canvas->modes[(int)ui::Canvas::kCanvasMode::MaskFree][0]); + auto m = static_cast(canvas->modes[(int)ui::Canvas::kCanvasMode::MaskFree][0]); + auto rot = glm::inverse(glm::lookAt(glm::vec3(0), m_origin, { 0, 1, 0 })); ui::ShaderManager::use(ui::kShader::Color); ui::ShaderManager::u_mat4(ui::kShaderUniform::MVP, proj * camera * rot); ui::ShaderManager::u_vec4(ui::kShaderUniform::Col, { 0, 0, 0, 1 }); - m_sphere.draw_fill(); + //m_sphere.draw_fill(); - for (auto pt : m_points2d) - { - ui::ShaderManager::u_mat4(ui::kShaderUniform::MVP, ortho * glm::translate(glm::vec3(pt, 0)) * glm::scale(glm::vec3(5.f))); - ui::ShaderManager::u_vec4(ui::kShaderUniform::Col, { 0, 1, 1, 1 }); - m_circle.draw_fill(); - } + auto face = canvas->face_to_shape2D(0); + auto shape = poly_intersect(m->m_points2d, face); - ui::ShaderManager::use(ui::kShader::StrokePreview); - ui::ShaderManager::u_int(ui::kShaderUniform::Tex, 0); - ui::ShaderManager::u_float(ui::kShaderUniform::Alpha, canvas->m_current_brush.m_tip_flow); - auto tip_color = glm::vec4(glm::vec3(canvas->m_current_brush.m_tip_color), 1); - ui::ShaderManager::u_vec4(ui::kShaderUniform::Col, tip_color); - ui::ShaderManager::u_mat4(ui::kShaderUniform::MVP, ortho); +// for (auto pt : shape) +// { +// pt.y = canvas->m_box.w - pt.y - 1; +// ui::ShaderManager::u_mat4(ui::kShaderUniform::MVP, ortho * glm::translate(glm::vec3(pt, 0)) * glm::scale(glm::vec3(5.f))); +// ui::ShaderManager::u_vec4(ui::kShaderUniform::Col, { 0, 1, 1, 1 }); +// m_circle.draw_fill(); +// } + + //ui::ShaderManager::use(ui::kShader::UVs); + ui::ShaderManager::u_mat4(ui::kShaderUniform::MVP, proj * camera * m_xform); + ui::ShaderManager::u_vec4(ui::kShaderUniform::Col, { 0, 1, 1, .1 }); + m_shape.draw_fill(); + glEnable(GL_BLEND); + ui::ShaderManager::use(ui::kShader::Texture); + ui::ShaderManager::u_int(ui::kShaderUniform::Tex, 0); + ui::ShaderManager::u_mat4(ui::kShaderUniform::MVP, proj * camera * m_xform); glActiveTexture(GL_TEXTURE0); - auto& tex = TextureManager::get(canvas->m_current_brush.m_tex_id); - tex.bind(); + m_tex.bind(); canvas->m_sampler.bind(0); m_shape.draw_fill(); - tex.unbind(); + m_tex.unbind(); if (depth) glEnable(GL_DEPTH_TEST); } @@ -896,86 +1002,39 @@ void CanvasModeTransform::on_MouseEvent(MouseEvent* me, glm::vec2& loc) switch (me->m_type) { case kEventType::MouseDownR: - //m_origin = canvas->project2Dpoint(loc); { - auto p = loc; - // flip the y coordinate to match opengl Y up - p.y = canvas->m_box.w - loc.y - 1; - //LOG("loc %f %f", p.x, p.y); - auto ln = (p / zw(canvas->m_box)) * 2.f - 1.f; - - glm::vec3 ro, rd, hit_o, hit_d; - glm::vec2 hit_fb; - canvas->point_trace_plane(loc, ro , rd, hit_o, hit_d, hit_fb, 0); - - //LOG("hit plane %f %f %f", hit_o.x, hit_o.y, hit_o.z); - auto plane2cam = canvas->m_proj * canvas->m_mv * canvas->m_plane_transform[0] * glm::vec4(hit_o, 1); - plane2cam = plane2cam / plane2cam.w; - - auto p3d_back = glm::inverse(canvas->m_proj * canvas->m_mv * canvas->m_plane_transform[0]) * plane2cam; - p3d_back = p3d_back / p3d_back.w; - //LOG("\nloc nor %f %f", ln.x, ln.y); - //LOG("plane2cam %f %f %f %f", plane2cam.x, plane2cam.y, plane2cam.z, plane2cam.w); - //LOG("\ncam2plane inv %f %f %f %f", p3d_back.x, p3d_back.y, p3d_back.z, p3d_back.w); - - auto loc_back = glm::inverse(canvas->m_proj * canvas->m_mv * canvas->m_plane_transform[0]) * glm::vec4(ln, 1, 1); - loc_back = loc_back / loc_back.z; - //LOG("loc inv %f %f %f %f", loc_back.x, loc_back.y, loc_back.z, loc_back.w); - - auto p2d = (xy(plane2cam) * 0.5f + 0.5f) * zw(canvas->m_box); - p2d.y = canvas->m_box.w - p2d.y - 1; - //LOG("vp %f %f", p2d.x, p2d.y); - - auto loc_vp = (xy(loc_back) * glm::vec2(-1, -1) * 0.5f + 0.5f) * glm::vec2(canvas->m_width, canvas->m_height); - - LOG("trc fb %f %f", hit_fb.x, hit_fb.y); - LOG("prj vp %f %f", loc_vp.x, loc_vp.y); - - LOG("trc dir %f %f %f", hit_d.x, hit_d.y, hit_d.z); - LOG("prj dir %f %f %f", canvas->m_plane_dir[0].x, canvas->m_plane_dir[0].y, canvas->m_plane_dir[0].z); - - LOG("------------------------------------------"); - // convert to normalized cube space - //auto p3d = glm::vec4((p / zw(canvas->m_box)) * 2.f - 1.f, 1, 1); - //auto m = glm::inverse(canvas->m_proj * canvas->m_mv * canvas->m_plane_transform[0]); - //p3d = p3d * m; - //p3d = p3d / p3d.w; - //auto p3d = glm::unProject(glm::vec3(loc, 1), canvas->m_mv * canvas->m_plane_transform[0], canvas->m_proj, canvas->m_vp); - //p3d = p3d / p3d.z; - -/* - { - double sum = 0; - auto start = std::chrono::steady_clock::now(); - for (int i = 0; i < 10000000; i++) - { - glm::vec3 ro, rd, hit_o, hit_d; - glm::vec2 hit_fb; - canvas->point_trace_plane(loc, ro, rd, hit_o, hit_d, hit_fb, 0); - sum += hit_fb.x; - } - auto t1 = std::chrono::steady_clock::now(); - auto m = glm::inverse(canvas->m_proj * canvas->m_mv * canvas->m_plane_transform[0]); - for (int i = 0; i < 10000000; i++) - { - auto loc_back = m * glm::vec4(ln, 1, 1); - loc_back = loc_back / loc_back.z; - //auto loc_vp = (xy(loc_back) * glm::vec2(-1, -1) * 0.5f + 0.5f) * glm::vec2(canvas->m_width, canvas->m_height); - sum += loc_back.x; - } - auto t2 = std::chrono::steady_clock::now(); - LOG("t1 %d", (int)std::chrono::duration_cast(t1 - start).count()); - LOG("t2 %d", (int)std::chrono::duration_cast(t2 - t1).count()); - LOG("sum %f", sum); - } -*/ - } + break; + case kEventType::MouseUpL: + m_dragging = false; + break; + case kEventType::MouseDownL: + m_dragging = true; + m_drag_start = loc; + m_drag_xform = m_xform; + //m_xform = glm::inverse(glm::lookAt({ 0, 0, 0 }, canvas->point_trace(loc), { 0, 1, 0 })); break; case kEventType::MouseMove: - case kEventType::MouseUpL: - case kEventType::MouseDownL: { + if (m_dragging) + { + //auto diff = glm::radians(loc - m_drag_start) * 0.1f; + //auto m = glm::eulerAngleXY(-diff.y, -diff.x); + //m_xform = m * m_drag_xform; + auto cam_up = glm::inverse(canvas->m_mv) * glm::vec4(0, 1, 0, 1); + m_xform = glm::inverse(glm::lookAt({ 0, 0, 0 }, canvas->point_trace(loc), xyz(cam_up))); + } + { + auto p2d = loc; + //p2d.y = canvas->m_box.w - p2d.y - 1; + auto p2d_clip = ((p2d / zw(canvas->m_box)) * 2.f - 1.f) * glm::vec2(1, -1); + auto p3d_plane = canvas->m_plane_unproject[0] * glm::vec4(p2d_clip, 0, 1); + auto p2d_plane = -p3d_plane / p3d_plane.z; +// auto p3d_world = canvas->m_plane_transform[0] * glm::vec4(p2d_plane, -1, 1); + int x = 0; + LOG("pt %f %f %f %f", p2d_plane.x, p2d_plane.y, p2d_plane.z, p2d_plane.w); + } + auto m = glm::lookAt(glm::vec3(0), m_origin, { 0, 1, 0 }); m_center_point = m * glm::vec4(canvas->project2Dpoint(loc), 1); @@ -997,7 +1056,6 @@ void CanvasModeTransform::on_MouseEvent(MouseEvent* me, glm::vec2& loc) m_points2d.clear(); if (!poly.empty()) { - //LOG("size %d", (int)is.size()); std::vector> points; for (auto& v : poly) { @@ -1005,8 +1063,8 @@ void CanvasModeTransform::on_MouseEvent(MouseEvent* me, glm::vec2& loc) m_points2d.push_back(v.pos); points.push_back(std::make_shared(v.pos.x, v.pos.y)); } - auto vert = canvas->triangulate_simple(poly); - m_shape.update_vertices(vert.data(), vert.size()); + auto vert = canvas->triangulate(poly); + //m_shape.update_vertices(vert.data(), vert.size()); } } diff --git a/src/canvas_modes.h b/src/canvas_modes.h index 46e0972..9729494 100644 --- a/src/canvas_modes.h +++ b/src/canvas_modes.h @@ -2,6 +2,7 @@ #include "event.h" #include "shape.h" #include "brush.h" +#include "texture.h" #include NS_START @@ -114,6 +115,7 @@ public: class CanvasModeMaskFree : public CanvasMode { + friend class CanvasModeTransform; ui::DynamicShape m_shape; bool m_dragging = false; std::vector m_points; @@ -147,11 +149,15 @@ class CanvasModeTransform : public CanvasMode ui::DynamicShape m_shape; ui::Sphere m_sphere; ui::Circle m_circle; + Texture2D m_tex; glm::vec3 m_origin{0, 0, 1 }; glm::vec3 m_center_point; glm::vec2 m_center_point_uv; + glm::mat4 m_xform; int m_counter = 0; bool m_dragging = false; + glm::vec2 m_drag_start; + glm::mat4 m_drag_xform; std::vector m_points; std::vector m_points2d; std::map m_dirty_planes; @@ -161,6 +167,6 @@ public: virtual void on_Draw(const glm::mat4& ortho, const glm::mat4& proj, const glm::mat4& camera) override;; virtual void on_MouseEvent(MouseEvent* me, glm::vec2& loc) override;; virtual void init() override;; - //virtual void enter() override; - //virtual void leave() override; + virtual void enter() override; + virtual void leave() override; }; diff --git a/src/node_canvas.cpp b/src/node_canvas.cpp index 6a6a36b..2276b23 100644 --- a/src/node_canvas.cpp +++ b/src/node_canvas.cpp @@ -101,7 +101,8 @@ void NodeCanvas::draw() for (int plane_index = 0; plane_index < 6; plane_index++) { - m_canvas->m_plane_unproject[plane_index] = glm::inverse(m_canvas->m_proj * m_canvas->m_mv * m_canvas->m_plane_transform[0]); + glm::mat4 plane_camera = glm::lookAt(m_canvas->m_plane_origin[plane_index], m_canvas->m_plane_normal[plane_index], m_canvas->m_plane_tangent[plane_index]); + m_canvas->m_plane_unproject[plane_index] = glm::inverse(m_canvas->m_proj * m_canvas->m_mv * m_canvas->m_plane_transform[plane_index]); m_canvas->m_plane_dir[plane_index] = -(m_canvas->m_plane_transform[plane_index] * glm::vec4(m_canvas->m_plane_origin[plane_index], 1)); auto plane_mvp = proj * camera * glm::scale(glm::vec3(m_canvas->m_order.size() + 500)) *