mirror of
https://github.com/gittrahan/support-fins.git
synced 2026-10-19 02:10:52 -05:00
76 lines
2.9 KiB
JavaScript
76 lines
2.9 KiB
JavaScript
/**
|
|
* Closed-solid emitters shared by the wall builders (web/prop/) and the wall
|
|
* cutouts (cutout.js). Pure mesh math: each takes cross-sections or a polygon
|
|
* and pushes outward-wound triangles, as vertex triples, onto `out`.
|
|
*/
|
|
|
|
/**
|
|
* Bridge a run of cross-sections into one closed solid and push its triangles.
|
|
* Each section is a ring of `k` vertices in the same order; consecutive rings
|
|
* are joined with quads and the two ends are fan-capped. Caps assume the
|
|
* section is convex, which both sections below are (a rectangle, and a
|
|
* rectangle with a tapered top).
|
|
*
|
|
* Wound OUTWARD. Inherited from M3, where this emitted every triangle backwards:
|
|
* the shell was closed and consistent -- euler 2, no boundary edges -- but its
|
|
* volume came out NEGATIVE, so every normal faced into the solid. M3's own check
|
|
* only asked whether the mesh was watertight, which it was, so this survived
|
|
* being called validated. A slicer would read it as a hole rather than a wall.
|
|
*/
|
|
export function ribbon(secs, out) {
|
|
const k = secs[0].length;
|
|
const tri = (a, b, c) => out.push(a, c, b);
|
|
for (let i = 0; i < secs.length - 1; i++) {
|
|
for (let j = 0; j < k; j++) {
|
|
const j2 = (j + 1) % k;
|
|
tri(secs[i][j], secs[i][j2], secs[i + 1][j2]);
|
|
tri(secs[i][j], secs[i + 1][j2], secs[i + 1][j]);
|
|
}
|
|
}
|
|
for (let j = 1; j < k - 1; j++) { // end caps
|
|
tri(secs[0][0], secs[0][j + 1], secs[0][j]);
|
|
const e = secs[secs.length - 1];
|
|
tri(e[0], e[j], e[j + 1]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Extrude a CCW polygon (in the a,b plane of the right-handed frame a,b,c) from
|
|
* c = lo to c = hi, emitting outward-wound triangles as vertex triples. The twin
|
|
* of the old fins.js `extrude` (since removed): the winding
|
|
* only comes out consistently outward when (a,b,c) is right-handed, which every
|
|
* caller below guarantees by construction.
|
|
*/
|
|
export function boxExtrude(poly, lo, hi, P, out) {
|
|
const n = poly.length;
|
|
const vlo = poly.map(([a, b]) => P(a, b, lo));
|
|
const vhi = poly.map(([a, b]) => P(a, b, hi));
|
|
for (let i = 0; i < n; i++) {
|
|
const j = (i + 1) % n;
|
|
out.push(vlo[i], vlo[j], vhi[j]);
|
|
out.push(vlo[i], vhi[j], vhi[i]);
|
|
}
|
|
for (let i = 1; i < n - 1; i++) {
|
|
out.push(vhi[0], vhi[i], vhi[i + 1]);
|
|
out.push(vlo[0], vlo[i + 1], vlo[i]);
|
|
}
|
|
}
|
|
|
|
/** boxExtrude with a different (same-size) outline at the top: a tine whose end leans
|
|
* with the part's surface. Same vertex order and faces as boxExtrude, so a tine is
|
|
* still one 36-vertex block (tests/_util.js tineBoxes). */
|
|
export function loftExtrude(polyLo, polyHi, lo, hi, P, out) {
|
|
const n = polyLo.length;
|
|
const vlo = polyLo.map(([a, b]) => P(a, b, lo));
|
|
const vhi = polyHi.map(([a, b]) => P(a, b, hi));
|
|
for (let i = 0; i < n; i++) {
|
|
const j = (i + 1) % n;
|
|
out.push(vlo[i], vlo[j], vhi[j]);
|
|
out.push(vlo[i], vhi[j], vhi[i]);
|
|
}
|
|
for (let i = 1; i < n - 1; i++) {
|
|
out.push(vhi[0], vhi[i], vhi[i + 1]);
|
|
out.push(vlo[0], vlo[i + 1], vlo[i]);
|
|
}
|
|
}
|