mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-16 21:42:43 +00:00
57 lines
2.4 KiB
C++
57 lines
2.4 KiB
C++
#pragma once
|
|
|
|
// Quadric error metric decimation (Garland & Heckbert), with two additions that matter on a
|
|
// displaced mesh.
|
|
//
|
|
// Crease quadrics: an interior edge sharper than the threshold gets penalty planes at both endpoints,
|
|
// perpendicular to each adjacent face and through the edge, weighted so such edges collapse last or
|
|
// not at all. A texture's hard step keeps its geometry while the flat ground around it reduces.
|
|
//
|
|
// Flat-face harvesting: the loop keeps going past the triangle target while each collapse's error
|
|
// stays under an absolute bound, so flat faces that cost nothing to remove are not left behind.
|
|
|
|
#include <cstdint>
|
|
#include <functional>
|
|
#include <vector>
|
|
|
|
#include "TextureBakeIndex.hpp"
|
|
|
|
namespace Slic3r {
|
|
namespace TextureBake {
|
|
|
|
// Reject a collapse deviating more than about 78 degrees from the old face normal.
|
|
static constexpr double DECIMATE_FLIP_DOT = 0.2;
|
|
// Edges sharper than 60 degrees are treated as creases.
|
|
static constexpr double DECIMATE_CREASE_COS = 0.5;
|
|
// Quadric penalty weight for a crease plane.
|
|
static constexpr double DECIMATE_CREASE_WEIGHT = 1e4;
|
|
|
|
// Upper bound in mm on the deviation a harvested collapse may introduce; the real one is smaller,
|
|
// since the cost sums squared distances over all incident faces.
|
|
//
|
|
// Absolute, not relative to the cost at which the target was crossed. A relative band fails in the
|
|
// case with the most to shed: when the target is reached with a large flat surplus left, the crossing
|
|
// cost is essentially zero, so the band is too and nothing is harvested.
|
|
static constexpr double DECIMATE_DEFAULT_HARVEST_TOL = 0.005;
|
|
|
|
// Returns false to cancel.
|
|
using DecimateProgressFn = std::function<bool(double fraction)>;
|
|
|
|
struct DecimateResult
|
|
{
|
|
TriSoup geometry;
|
|
// The locked faces alone met the target, so it was unreachable without touching preserved
|
|
// geometry.
|
|
bool locked_over_budget = false;
|
|
};
|
|
|
|
// `locked_faces`: one entry per input triangle; a vertex touching one may neither move nor be
|
|
// removed, which also pins the ring between the two regions.
|
|
DecimateResult decimate(const TriSoup &geometry, size_t target_triangles, bool harvest_flat = true,
|
|
double harvest_tol = DECIMATE_DEFAULT_HARVEST_TOL,
|
|
const std::vector<uint8_t> &locked_faces = {},
|
|
const DecimateProgressFn &on_progress = {});
|
|
|
|
} // namespace TextureBake
|
|
} // namespace Slic3r
|