80 void TriangulatePoly(std::span<const Vec3> inPositions, std::span<int> poly, ContainerType<Vec3i, Args...>& outTris)
82 using IndexType = std::remove_cvref_t<decltype(std::declval<Vec3i>()[0])>;
83 using AllocatorType =
typename ContainerType<Vec3i, Args...>::allocator_type;
89 for (
size_t i = 0, j = poly.size() - 1; i < poly.size(); j = i++)
91 const Vec3& p = inPositions[poly[i]];
92 const Vec3& q = inPositions[poly[j]];
101 enum Axis { X = 0, Y, Z } drop =
105 auto project = [&](
const Vec3& v) ->
Vec2
109 case X:
return {
GetY(v),
GetZ(v) };
110 case Y:
return {
GetZ(v),
GetX(v) };
111 case Z:
return {
GetX(v),
GetY(v) };
119 const Vec3 u = Normalized(
Math::Abs(
GetZ(n)) > 0.9f ? Vec3{ 1,0,0 } : CrossProduct(Vec3{ 0,0,1 }, n));
120 const Vec3 v = CrossProduct(n, u);
121 auto project = [&](
const Vec3& p) ->
Vec2
123 return { DotProduct(p, u), DotProduct(p, v) };
127 pts2.reserve(poly.size());
129 pts2.push_back(project(inPositions[idx]));
133 if (GetPolygonArea(pts2) < 0.0f)
135 std::reverse(poly.begin(), poly.end());
136 std::reverse(pts2.begin(), pts2.end());
148 nodes.reserve(poly.size());
149 for (
size_t i = 0; i < poly.size(); ++i)
151 nodes.push_back({ poly[i], pts2[i],
152 int(i == 0 ? poly.size() - 1 : i - 1),
153 int((i + 1) % poly.size()) });
156 auto isConvex = [&](
int i)
158 const Vec2& a = nodes[nodes[i].Prev].P;
159 const Vec2& b = nodes[i].P;
160 const Vec2& c = nodes[nodes[i].Next].P;
161 return CrossProduct(
Vec2{ b.
X - a.
X, b.
Y - a.
Y },
162 Vec2{ c.
X - b.
X, c.
Y - b.
Y }) >= 0.0f;
165 int remaining = int(nodes.size());
166 while (remaining > 3)
170 float bestQuality = -1.0f;
171 for (
int i = 0; i < nodes.size(); ++i)
173 if (nodes[i].Idx == -1)
179 const Vec2& a = nodes[nodes[i].Prev].P;
180 const Vec2& b = nodes[i].P;
181 const Vec2& c = nodes[nodes[i].Next].P;
184 for (
int j = 0; j < nodes.size() && ear; ++j)
186 if (nodes[j].Idx == -1 || j == i ||
187 j == nodes[i].Prev || j == nodes[i].Next)
190 ear &= !IsPointInTri(nodes[j].P, a, b, c);
195 const float q = GetMinAngleDeg(a, b, c);
207 outTris.emplace_back(
209 IndexType(nodes[nodes[best].Prev].Idx),
210 IndexType(nodes[best].Idx),
211 IndexType(nodes[nodes[best].Next].Idx)
215 const int prev = nodes[best].Prev;
216 const int next = nodes[best].Next;
217 nodes[prev].Next = next;
218 nodes[next].Prev = prev;
219 nodes[best].Idx = -1;
226 for (
const Node& node : nodes)
234 outTris.emplace_back(