add transform mode and tollbar button, implement polygon clipping with uvs interpolation and cube faces projection with near plane clipping, add duplicate points removal template function, implement Spere mesh surface section creation.
This commit is contained in:
145
src/canvas.cpp
145
src/canvas.cpp
@@ -18,6 +18,7 @@ std::vector<CanvasMode*> ui::Canvas::modes[] = {
|
||||
{ new CanvasModeLine, new CanvasModeBasicCamera },
|
||||
{ new CanvasModeCamera, new CanvasModeBasicCamera },
|
||||
{ new CanvasModeGrid, new CanvasModeBasicCamera },
|
||||
{ new CanvasModeTransform, new CanvasModeBasicCamera },
|
||||
{ new CanvasModeFill, new CanvasModeBasicCamera },
|
||||
{ new CanvasModeMaskFree, new CanvasModeBasicCamera },
|
||||
{ new CanvasModeMaskLine, new CanvasModeBasicCamera },
|
||||
@@ -46,6 +47,7 @@ glm::vec3 ui::Canvas::m_plane_tangent[6] = {
|
||||
{0, 0,-1}, // top
|
||||
{0, 0, 1}, // bottom
|
||||
};
|
||||
// only rotation
|
||||
glm::mat4 ui::Canvas::m_plane_transform[6] = {
|
||||
glm::lookAt(glm::vec3(), { 0, 0,-1}, {0, 1, 0}), // front
|
||||
glm::lookAt(glm::vec3(), {-1, 0, 0}, {0, 1, 0}), // right
|
||||
@@ -440,7 +442,8 @@ void ui::Canvas::stroke_draw()
|
||||
}
|
||||
|
||||
glm::vec3 hit;
|
||||
if (ray_intersect(ray_origin, ray_dir, m_plane_origin[i], m_plane_normal[i], m_plane_tangent[i], 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))
|
||||
{
|
||||
glm::mat4 plane_camera = glm::lookAt(m_plane_origin[i], m_plane_normal[i], m_plane_tangent[i]);
|
||||
glm::vec4 plane_local = plane_camera * glm::vec4(hit, 1);
|
||||
@@ -535,13 +538,14 @@ void ui::Canvas::stroke_draw()
|
||||
}
|
||||
}
|
||||
bool ui::Canvas::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)
|
||||
glm::vec3& hit_pos, glm::vec2& fb_pos, glm::vec3& hit_normal, int& out_plane_id)
|
||||
{
|
||||
point_unproject(loc, { 0, 0, zw(m_box) }, m_mv, 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, m_plane_origin[i], m_plane_normal[i], m_plane_tangent[i], hit))
|
||||
if (ray_intersect(ray_origin, ray_dir, m_plane_origin[i], m_plane_normal[i], m_plane_tangent[i], hit, hit_t))
|
||||
{
|
||||
glm::mat4 plane_camera = glm::lookAt(m_plane_origin[i], m_plane_normal[i], m_plane_tangent[i]);
|
||||
glm::vec4 plane_local = plane_camera * glm::vec4(hit, 1);
|
||||
@@ -561,13 +565,14 @@ 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& ray_origin, glm::vec3& ray_dir,
|
||||
glm::vec3& hit_pos, glm::vec3& hit_normal, glm::vec2& hit_fb_pos, int plane_id)
|
||||
glm::vec3& hit_pos, glm::vec3& hit_normal, glm::vec2& hit_fb_pos, int plane_id)
|
||||
{
|
||||
point_unproject(loc, { 0, 0, zw(m_box) }, m_mv, m_proj, ray_origin, ray_dir);
|
||||
glm::vec3 hit;
|
||||
glm::vec2 fb_pos;
|
||||
float hit_t;
|
||||
if (ray_intersect(ray_origin, ray_dir, m_plane_origin[plane_id],
|
||||
m_plane_normal[plane_id], m_plane_tangent[plane_id], hit))
|
||||
m_plane_normal[plane_id], m_plane_tangent[plane_id], hit, hit_t))
|
||||
{
|
||||
glm::mat4 plane_camera = glm::lookAt(m_plane_origin[plane_id], m_plane_normal[plane_id], m_plane_tangent[plane_id]);
|
||||
glm::vec4 plane_local = plane_camera * glm::vec4(hit, 1);
|
||||
@@ -579,23 +584,8 @@ bool ui::Canvas::point_trace_plane(glm::vec2 loc, glm::vec3& ray_origin, glm::ve
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool ui::Canvas::ray_intersect(glm::vec3 ray_origin, glm::vec3 ray_dir, glm::vec3 plane_origin,
|
||||
glm::vec3 plane_normal, glm::vec3 plane_tangent, glm::vec3& out_hit)
|
||||
{
|
||||
float den = glm::dot(ray_dir, plane_normal);
|
||||
if (den == 0)
|
||||
return false; // no intersection
|
||||
float num = glm::dot(plane_origin - ray_origin, plane_normal);
|
||||
float t = num / den;
|
||||
if (t > 0)
|
||||
out_hit = ray_origin + ray_dir * t;
|
||||
else
|
||||
// negative intersection
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
void ui::Canvas::point_unproject(glm::vec2 loc, glm::vec4 vp, glm::mat4 camera, glm::mat4 proj,
|
||||
glm::vec3& out_origin, glm::vec3& out_dir)
|
||||
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);
|
||||
@@ -604,6 +594,15 @@ void ui::Canvas::point_unproject(glm::vec2 loc, glm::vec4 vp, glm::mat4 camera,
|
||||
out_origin = xyz(wp0 / wp0.w);
|
||||
out_dir = glm::normalize(xyz(wp1 / wp1.w) - out_origin);
|
||||
};
|
||||
void ui::Canvas::point_unproject(glm::vec2 loc, glm::vec3& out_origin, glm::vec3& out_dir)
|
||||
{
|
||||
auto clip_space = glm::vec2(loc.x, m_vp.w - loc.y - 1.f) / zw(m_vp) * 2.f - 1.f;
|
||||
auto inv = glm::inverse(m_proj * 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);
|
||||
};
|
||||
void ui::Canvas::stroke_commit()
|
||||
{
|
||||
if (!m_dirty || m_layers.empty())
|
||||
@@ -1014,7 +1013,7 @@ void ui::Canvas::import_equirectangular_thread(std::string file_path)
|
||||
if (img.width == img.height / 6)
|
||||
{
|
||||
Texture2D tex;
|
||||
static GLint indices[] = { 5, 1, 4, 0, 2, 3 };
|
||||
static GLint indices[] = { 5, 0, 4, 1, 2, 3 };
|
||||
static GLint formats[] = { GL_RED, GL_RG, GL_RGB, GL_RGBA };
|
||||
static GLint iformats[] = { GL_R8, GL_RG8, GL_RGB8, GL_RGBA8 };
|
||||
tex.create(img.width, img.width, iformats[img.comp - 1], formats[img.comp - 1]);
|
||||
@@ -1028,7 +1027,7 @@ void ui::Canvas::import_equirectangular_thread(std::string file_path)
|
||||
tex.bind();
|
||||
ShaderManager::use(ui::kShader::Texture);
|
||||
ShaderManager::u_int(kShaderUniform::Tex, 0);
|
||||
ShaderManager::u_mat4(kShaderUniform::MVP, glm::scale(glm::vec3(1, -1, 1)));
|
||||
ShaderManager::u_mat4(kShaderUniform::MVP, glm::scale(glm::vec3(-1, -1, 1)));
|
||||
plane.draw_fill();
|
||||
tex.unbind();
|
||||
m_sampler.unbind();
|
||||
@@ -1048,7 +1047,7 @@ void ui::Canvas::import_equirectangular_thread(std::string file_path)
|
||||
ShaderManager::use(ui::kShader::Texture);
|
||||
ShaderManager::u_int(kShaderUniform::Tex, 0);
|
||||
ShaderManager::u_mat4(kShaderUniform::MVP, proj * camera *
|
||||
glm::eulerAngleY(glm::radians(-90.f)) * glm::scale(glm::vec3(1, -1, 1)));
|
||||
glm::eulerAngleY(glm::radians(180.f)) * glm::scale(glm::vec3(1, -1, 1)));
|
||||
sphere.draw_fill();
|
||||
tex.unbind();
|
||||
m_sampler.unbind();
|
||||
@@ -1988,7 +1987,7 @@ void ui::Canvas::draw_objects(std::function<void(const glm::mat4& camera, const
|
||||
draw_objects(observer, m_layers[m_current_layer_idx]);
|
||||
}
|
||||
|
||||
void ui::Canvas::project2Dpoints(std::vector<ui::Shape::vertex_t>& vertices)
|
||||
void ui::Canvas::project2Dpoints(std::vector<vertex_t>& vertices)
|
||||
{
|
||||
for (auto& p : vertices)
|
||||
{
|
||||
@@ -2000,7 +1999,92 @@ void ui::Canvas::project2Dpoints(std::vector<ui::Shape::vertex_t>& vertices)
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<ui::Shape::vertex_t> ui::Canvas::triangulate(const std::vector<std::shared_ptr<p2t::Point>>& points)
|
||||
glm::vec3 ui::Canvas::project2Dpoint(glm::vec2 pt)
|
||||
{
|
||||
glm::vec3 ro, rd, hit_o, hit_d;
|
||||
glm::vec2 hit_fb;
|
||||
int plane_id;
|
||||
if (point_trace(pt, ro, rd, hit_o, hit_fb, hit_d, plane_id))
|
||||
return glm::vec4(hit_o, 1);
|
||||
return glm::vec3(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// return the 2d shape of the faces based on the current camera
|
||||
// this can be used for screen space shapes clipping
|
||||
std::vector<glm::vec2> ui::Canvas::face_to_shape2D(int plane_index)
|
||||
{
|
||||
static std::array<glm::vec4, 4> corners{
|
||||
glm::vec4(-1.f, +1.f, -1.f, 1.f), // A top-left
|
||||
glm::vec4(+1.f, +1.f, -1.f, 1.f), // B top-right
|
||||
glm::vec4(+1.f, -1.f, -1.f, 1.f), // C bottom-right
|
||||
glm::vec4(-1.f, -1.f, -1.f, 1.f), // D bottom-left
|
||||
};
|
||||
|
||||
// compute points in camera space
|
||||
std::vector<glm::vec3> pt_cam;
|
||||
for (auto c : corners)
|
||||
{
|
||||
auto pt_world = m_plane_transform[plane_index] * c;
|
||||
pt_cam.push_back(m_mv * pt_world);
|
||||
}
|
||||
|
||||
// clip at near plane
|
||||
pt_cam = poly_clip_near(pt_cam, 0.01);
|
||||
|
||||
// compute windows space
|
||||
std::vector<glm::vec2> points;
|
||||
for (auto p : pt_cam)
|
||||
{
|
||||
auto pt_clip = m_proj * glm::vec4(p, 1);
|
||||
pt_clip = pt_clip / pt_clip.w;
|
||||
glm::vec2 pt_screen = (glm::vec2(pt_clip) * glm::vec2(1,-1) * 0.5f + 0.5f) * zw(m_vp);
|
||||
//pt_screen.y = m_vp.w - pt_screen.y - 1;
|
||||
points.push_back(pt_screen);
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
std::vector<vertex_t> ui::Canvas::triangulate_simple(const std::vector<vertex_t>& vertices)
|
||||
{
|
||||
std::vector<vertex_t> ret;
|
||||
std::vector<p2t::Point> points(vertices.size());
|
||||
std::vector<p2t::Point*> points_ptr(vertices.size());
|
||||
for (size_t i = 0; i < vertices.size(); i++)
|
||||
{
|
||||
points[i] = { vertices[i].pos.x, vertices[i].pos.y };
|
||||
points_ptr[i] = &points[i];
|
||||
}
|
||||
|
||||
auto cdt = std::make_unique<p2t::CDT>(points_ptr);
|
||||
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);
|
||||
auto index = std::distance(points.data(), p);
|
||||
vertex.pos = glm::vec4(p->x, p->y, 0, 1);
|
||||
vertex.uvs = vertices[index].uvs;
|
||||
ret.push_back(vertex);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<vertex_t> ui::Canvas::triangulate(const std::vector<glm::vec2>& points)
|
||||
{
|
||||
std::vector<std::shared_ptr<p2t::Point>> tmp;
|
||||
for (auto pt : points)
|
||||
tmp.push_back(std::make_shared<p2t::Point>(pt.x, pt.y));
|
||||
return triangulate(tmp);
|
||||
}
|
||||
|
||||
std::vector<vertex_t> ui::Canvas::triangulate(const std::vector<std::shared_ptr<p2t::Point>>& points)
|
||||
{
|
||||
struct Segment
|
||||
{
|
||||
@@ -2056,8 +2140,9 @@ std::vector<ui::Shape::vertex_t> ui::Canvas::triangulate(const std::vector<std::
|
||||
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 hit_uv;
|
||||
glm::vec2 is;
|
||||
if (segments_intersect(s0a, s0b, s1a, s1b, is))
|
||||
if (segments_intersect(s0a, s0b, s1a, s1b, is, hit_uv))
|
||||
{
|
||||
auto p = std::make_shared<p2t::Point>(is.x, is.y);
|
||||
auto poly_root = std::make_shared<Segment>();
|
||||
@@ -2083,7 +2168,7 @@ std::vector<ui::Shape::vertex_t> ui::Canvas::triangulate(const std::vector<std::
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<ui::Shape::vertex_t> vertices;
|
||||
std::vector<vertex_t> vertices;
|
||||
for (auto poly : polys)
|
||||
{
|
||||
std::vector<p2t::Point*> outline;
|
||||
@@ -2095,7 +2180,7 @@ std::vector<ui::Shape::vertex_t> ui::Canvas::triangulate(const std::vector<std::
|
||||
node = node->end ? nullptr : node->next;
|
||||
current->next = nullptr;
|
||||
}
|
||||
LOG("poly %zu", outline.size());
|
||||
//LOG("poly %zu", outline.size());
|
||||
|
||||
if (outline.size() > 2)
|
||||
{
|
||||
@@ -2104,7 +2189,7 @@ std::vector<ui::Shape::vertex_t> ui::Canvas::triangulate(const std::vector<std::
|
||||
auto tr = cdt->GetTriangles();
|
||||
for (auto t : tr)
|
||||
{
|
||||
ui::Shape::vertex_t vertex;
|
||||
vertex_t vertex;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
auto p = t->GetPoint(i);
|
||||
|
||||
Reference in New Issue
Block a user