Add polygon triangulation example
This commit is contained in:
parent
b2a714f88a
commit
ecb723af1a
2 changed files with 3240 additions and 0 deletions
184
examples/triangulation.cpp
Normal file
184
examples/triangulation.cpp
Normal file
|
|
@ -0,0 +1,184 @@
|
||||||
|
#include <psemek/app/app.hpp>
|
||||||
|
#include <psemek/app/main.hpp>
|
||||||
|
#include <psemek/gfx/painter.hpp>
|
||||||
|
#include <psemek/gfx/gl.hpp>
|
||||||
|
#include <psemek/geom/scale.hpp>
|
||||||
|
#include <psemek/geom/camera.hpp>
|
||||||
|
#include <psemek/geom/constants.hpp>
|
||||||
|
#include <psemek/cg/bbox.hpp>
|
||||||
|
#include <psemek/cg/triangulation/ear_clipping.hpp>
|
||||||
|
#include <psemek/cg/triangulation/monotone.hpp>
|
||||||
|
#include <psemek/log/log.hpp>
|
||||||
|
#include <psemek/prof/profiler.hpp>
|
||||||
|
#include <psemek/util/clock.hpp>
|
||||||
|
#include <psemek/util/to_string.hpp>
|
||||||
|
#include <psemek/geom/homogeneous.hpp>
|
||||||
|
#include <psemek/geom/swizzle.hpp>
|
||||||
|
#include <psemek/random/generator.hpp>
|
||||||
|
#include <psemek/random/uniform.hpp>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
using namespace psemek;
|
||||||
|
|
||||||
|
struct triangulation_app
|
||||||
|
: app::app
|
||||||
|
{
|
||||||
|
triangulation_app()
|
||||||
|
: app("Triangulation example", 16)
|
||||||
|
{
|
||||||
|
std::ifstream in(PSEMEK_EXAMPLES_DIR "/turkey");
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
geom::point<float, 2> p;
|
||||||
|
in >> p[0] >> p[1];
|
||||||
|
if (!in)
|
||||||
|
break;
|
||||||
|
points_.push_back(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::reverse(points_.begin(), points_.end());
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < points_.size();)
|
||||||
|
{
|
||||||
|
std::size_t j = (i + 1) % points_.size();
|
||||||
|
if (points_[i] == points_[j])
|
||||||
|
{
|
||||||
|
points_.erase(points_.begin() + i);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log::info() << points_.size() << " input points";
|
||||||
|
|
||||||
|
bbox_ = cg::bbox(points_.begin(), points_.end());
|
||||||
|
camera_center_ = bbox_.center();
|
||||||
|
camera_size_ = std::max(bbox_[0].length(), bbox_[1].length()) * 1.125f;
|
||||||
|
camera_size_tgt_ = camera_size_;
|
||||||
|
|
||||||
|
{
|
||||||
|
prof::profiler prof("triangulate");
|
||||||
|
indices_ = cg::ear_clipping<std::uint16_t>(points_.begin(), points_.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
prof::dump();
|
||||||
|
|
||||||
|
log::info() << (indices_.size() / 3) << " triangles";
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_left_button_down() override
|
||||||
|
{
|
||||||
|
app::on_left_button_down();
|
||||||
|
|
||||||
|
if (mouse())
|
||||||
|
drag_start_ = mouse();
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_left_button_up() override
|
||||||
|
{
|
||||||
|
app::on_left_button_up();
|
||||||
|
|
||||||
|
drag_start_ = std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_mouse_wheel(int delta) override
|
||||||
|
{
|
||||||
|
camera_size_tgt_ *= std::pow(0.8f, delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
void update() override
|
||||||
|
{
|
||||||
|
float const dt = clock_.restart().count();
|
||||||
|
|
||||||
|
if (drag_start_ && mouse())
|
||||||
|
{
|
||||||
|
auto delta = *mouse() - *drag_start_;
|
||||||
|
delta[1] *= -1;
|
||||||
|
camera_center_ -= geom::cast<float>(delta) * camera_size_ / (1.f * height());
|
||||||
|
drag_start_ = mouse();
|
||||||
|
}
|
||||||
|
|
||||||
|
camera_size_ += (camera_size_tgt_ - camera_size_) * (1.f - std::exp(- 20.f * dt));
|
||||||
|
}
|
||||||
|
|
||||||
|
void present() override
|
||||||
|
{
|
||||||
|
gl::ClearColor(1.f, 1.f, 1.f, 1.f);
|
||||||
|
gl::Clear(gl::COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
float aspect_ratio = (width() * 1.f) / height();
|
||||||
|
geom::box<float, 2> view_bbox = geom::expand(geom::box<float, 2>::singleton(camera_center_), geom::vector{camera_size_ * 0.5f * aspect_ratio, camera_size_ * 0.5f});
|
||||||
|
|
||||||
|
float line_width = 4.f * camera_size_ / height();
|
||||||
|
|
||||||
|
auto edge = [this, line_width](auto i0, auto i1, gfx::color_rgba const & color)
|
||||||
|
{
|
||||||
|
painter_.line(points_[i0], points_[i1], line_width, color, false);
|
||||||
|
};
|
||||||
|
|
||||||
|
random::generator rng;
|
||||||
|
for (std::size_t i = 0; i < indices_.size(); i += 3)
|
||||||
|
{
|
||||||
|
// edge(indices_[i + 0], indices_[i + 1], gfx::blue);
|
||||||
|
// edge(indices_[i + 1], indices_[i + 2], gfx::blue);
|
||||||
|
// edge(indices_[i + 2], indices_[i + 0], gfx::blue);
|
||||||
|
|
||||||
|
gfx::color_rgba c;
|
||||||
|
c[0] = random::uniform<std::uint8_t>(rng, {0, 255});
|
||||||
|
c[1] = random::uniform<std::uint8_t>(rng, {0, 255});
|
||||||
|
c[2] = random::uniform<std::uint8_t>(rng, {0, 255});
|
||||||
|
c[3] = 255;
|
||||||
|
|
||||||
|
painter_.triangle(points_[indices_[i + 0]], points_[indices_[i + 1]], points_[indices_[i + 2]], c);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < points_.size(); ++i)
|
||||||
|
{
|
||||||
|
edge(i, (i + 1) % points_.size(), gfx::black);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto camera_transform = geom::orthographic_camera{view_bbox}.transform();
|
||||||
|
|
||||||
|
painter_.render(camera_transform);
|
||||||
|
|
||||||
|
if(false)
|
||||||
|
for (std::size_t i = 0; i < points_.size(); ++i)
|
||||||
|
// for (std::size_t i : {2993, 2087, 2089, 2088})
|
||||||
|
{
|
||||||
|
gfx::painter::text_options opts;
|
||||||
|
opts.c = {0, 0, 0, 255};
|
||||||
|
opts.x = gfx::painter::x_align::left;
|
||||||
|
opts.y = gfx::painter::y_align::bottom;
|
||||||
|
opts.scale = 2.f;
|
||||||
|
auto p = geom::swizzle<0, 1>(geom::as_point(camera_transform * geom::homogeneous(geom::swizzle<0, 1, -1>(points_[i]))));
|
||||||
|
p[0] = std::round((p[0] * 0.5f + 0.5f) * width());
|
||||||
|
p[1] = std::round((0.5f - p[1] * 0.5f) * height());
|
||||||
|
painter_.text(p, util::to_string(i), opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
painter_.render(geom::window_camera{width(), height()}.transform());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<geom::point<float, 2>> points_;
|
||||||
|
std::vector<std::uint16_t> indices_;
|
||||||
|
geom::box<float, 2> bbox_;
|
||||||
|
geom::point<float, 2> camera_center_;
|
||||||
|
float camera_size_;
|
||||||
|
float camera_size_tgt_;
|
||||||
|
|
||||||
|
std::optional<geom::point<int, 2>> drag_start_;
|
||||||
|
|
||||||
|
gfx::painter painter_;
|
||||||
|
|
||||||
|
util::clock<std::chrono::duration<float>, std::chrono::high_resolution_clock> clock_;
|
||||||
|
};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
return app::main<triangulation_app>();
|
||||||
|
}
|
||||||
3056
examples/turkey
Normal file
3056
examples/turkey
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue