improve brush preview

This commit is contained in:
2019-02-19 11:33:41 +01:00
parent e4ee87e4c6
commit 08cca154b7
11 changed files with 612 additions and 246 deletions

View File

@@ -1,6 +1,7 @@
#include "pch.h"
#include "log.h"
#include "util.h"
#include <poly2tri.h>
template<>
std::vector<vertex_t> poly_remove_duplicate<vertex_t>(const std::vector<vertex_t>& v, const float tollerance)
@@ -236,6 +237,176 @@ std::vector<glm::vec3> poly_clip_near(const std::vector<glm::vec3>& poly, float
return poly_remove_duplicate(ret);
}
std::vector<vertex_t> 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 index = std::distance(points.data(), t->GetPoint(i));
ret.push_back(vertices[index]);
}
}
return ret;
}
std::vector<vertex_t> triangulate(const std::vector<glm::vec2>& points)
{
std::vector<vertex_t> tmp;
for (auto pt : points)
tmp.push_back(pt);
return triangulate(tmp);
}
std::vector<vertex_t> triangulate(const std::vector<vertex_t>& points)
{
struct Segment
{
const vertex_t* a = nullptr;
const vertex_t* b = nullptr;
Segment* prev = nullptr;
std::shared_ptr<Segment> next = nullptr;
bool end = false;
};
std::vector<std::shared_ptr<vertex_t>> new_points;
std::shared_ptr<Segment> root = std::make_shared<Segment>();
std::shared_ptr<Segment> node = root;
for (int i = 0; i < points.size(); i++)
{
node->a = &points[i];
if (i == points.size() - 1)
{
node->b = &points[0];
node->next = root;
node->end = true;
root->prev = node.get();
}
else
{
node->b = &points[i + 1];
node->next = std::make_shared<Segment>();
node->next->prev = node.get();
}
node = node->next;
}
node = root;
std::stack<std::shared_ptr<Segment>> todo;
std::vector<std::shared_ptr<Segment>> polys;
todo.push(root);
while (!todo.empty())
{
node = todo.top();
todo.pop();
polys.push_back(node);
while (node)
{
std::shared_ptr<Segment> other = node->next;
while (other)
{
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->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))
{
new_points.push_back(std::make_unique<vertex_t>());
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<Segment>();
poly_root->a = p;
poly_root->b = node->b;
poly_root->next = node->next;
todo.push(poly_root);
other->a = p;
node->b = p;
auto poly_end = std::make_shared<Segment>();
poly_end->a = other->prev->b;
poly_end->b = p;
poly_end->end = true;
poly_end->prev = other->prev;
other->prev->next = poly_end;
other->prev = node.get();
node->next = other;
break;
}
other = other->end ? nullptr : other->next;
}
node = node->end ? nullptr : node->next;
}
}
std::vector<vertex_t> ret;
for (auto poly : polys)
{
std::vector<const vertex_t*> outline;
node = poly;
while (node)
{
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;
}
if (outline.size() > 2)
{
std::vector<p2t::Point> points(outline.size());
std::vector<p2t::Point*> 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)
{
for (int i = 0; i < 3; i++)
{
auto index = std::distance(points.data(), t->GetPoint(i));
ret.push_back(*outline[index]);
}
}
}
}
return ret;
}
glm::vec4 rand_color()
{
float r = (rand() % 256) / 256.f;