mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-06 08:25:19 +01:00
144 lines
No EOL
4.5 KiB
JavaScript
144 lines
No EOL
4.5 KiB
JavaScript
import libtess from 'libtess'
|
|
import {Point} from '../../../../modules/geom/point'
|
|
import {Vertex} from '../../brep/topo/vertex'
|
|
import Vector from 'math/vector';
|
|
|
|
function initTesselator() {
|
|
// function called for each vertex of tesselator output
|
|
function vertexCallback(data, polyVertArray) {
|
|
polyVertArray.push(data);
|
|
}
|
|
// callback for when segments intersect and must be split
|
|
function combinecallback(coords, data, weight) {
|
|
// console.log('combine callback');
|
|
return [coords[0], coords[1], coords[2]];
|
|
}
|
|
function edgeCallback(flag) {
|
|
// don't really care about the flag, but need no-strip/no-fan behavior
|
|
// console.log('edge flag: ' + flag);
|
|
}
|
|
|
|
var tessy = new libtess.GluTesselator();
|
|
// tessy.gluTessProperty(libtess.gluEnum.GLU_TESS_WINDING_RULE, libtess.windingRule.GLU_TESS_WINDING_POSITIVE);
|
|
tessy.gluTessCallback(libtess.gluEnum.GLU_TESS_VERTEX_DATA, vertexCallback);
|
|
tessy.gluTessCallback(libtess.gluEnum.GLU_TESS_BEGIN, begincallback);
|
|
tessy.gluTessCallback(libtess.gluEnum.GLU_TESS_ERROR, errorcallback);
|
|
tessy.gluTessCallback(libtess.gluEnum.GLU_TESS_COMBINE, combinecallback);
|
|
tessy.gluTessCallback(libtess.gluEnum.GLU_TESS_EDGE_FLAG, edgeCallback);
|
|
|
|
return tessy;
|
|
}
|
|
|
|
function begincallback(type) {
|
|
if (type !== libtess.primitiveType.GL_TRIANGLES) {
|
|
console.log('expected TRIANGLES but got type: ' + type);
|
|
}
|
|
}
|
|
|
|
function errorcallback(errno) {
|
|
console.log('error callback');
|
|
console.log('error number: ' + errno);
|
|
}
|
|
|
|
|
|
export function Triangulate(contours, normal) {
|
|
const tessy = initTesselator();
|
|
// libtess will take 3d verts and flatten to a plane for tesselation
|
|
// since only doing 2d tesselation here, provide z=1 normal to skip
|
|
// iterating over verts only to get the same answer.
|
|
// comment out to test normal-generation code
|
|
//tessy.gluTessNormal(0, 0, 1);
|
|
tessy.gluTessNormal(normal[0], normal[1], normal[2]);
|
|
|
|
const triangleVerts = [];
|
|
tessy.gluTessBeginPolygon(triangleVerts);
|
|
|
|
for (let contour of contours) {
|
|
tessy.gluTessBeginContour();
|
|
for (let coords of contour) {
|
|
tessy.gluTessVertex(coords, coords);
|
|
}
|
|
tessy.gluTessEndContour();
|
|
}
|
|
|
|
// finish polygon (and time triangulation process)
|
|
tessy.gluTessEndPolygon();
|
|
return triangleVerts;
|
|
}
|
|
|
|
export function TriangulatePolygons(polygons, normal, toArray, fromArray) {
|
|
const triangled = [];
|
|
const contours = [];
|
|
for (let poly of polygons) {
|
|
contours.push(poly.map(point => toArray(point)));
|
|
}
|
|
|
|
let vertices = Triangulate(contours, toArray(normal));
|
|
for (let i = 0; i < vertices.length; i += 3 ) {
|
|
var a = fromArray(vertices[i]);
|
|
var b = fromArray(vertices[i + 1]);
|
|
var c = fromArray(vertices[i + 2]);
|
|
triangled.push([a, b, c]);
|
|
}
|
|
return triangled;
|
|
}
|
|
|
|
export function TriangulateFace(face) {
|
|
function arr(v) {
|
|
return [v.x, v.y, v.z];
|
|
}
|
|
|
|
function vertexCallback(data, out) {
|
|
out.push(data);
|
|
}
|
|
function combinecallback(coords, data, weight) {
|
|
//throw 'should never happen cuz brep is non-manifold'
|
|
}
|
|
function edgeCallback(flag) {
|
|
}
|
|
|
|
var tessy = new libtess.GluTesselator();
|
|
// tessy.gluTessProperty(libtess.gluEnum.GLU_TESS_WINDING_RULE, libtess.windingRule.GLU_TESS_WINDING_POSITIVE);
|
|
tessy.gluTessCallback(libtess.gluEnum.GLU_TESS_VERTEX_DATA, vertexCallback);
|
|
tessy.gluTessCallback(libtess.gluEnum.GLU_TESS_BEGIN, begincallback);
|
|
tessy.gluTessCallback(libtess.gluEnum.GLU_TESS_ERROR, errorcallback);
|
|
tessy.gluTessCallback(libtess.gluEnum.GLU_TESS_COMBINE, combinecallback);
|
|
tessy.gluTessCallback(libtess.gluEnum.GLU_TESS_EDGE_FLAG, edgeCallback);
|
|
|
|
const normal = arr(face.surface.normal);
|
|
tessy.gluTessNormal(normal[0], normal[1], normal[2]);
|
|
|
|
const vertices = [];
|
|
tessy.gluTessBeginPolygon(vertices);
|
|
|
|
for (let loop of face.loops) {
|
|
tessy.gluTessBeginContour();
|
|
for (let e of loop.halfEdges) {
|
|
if (e.edge.curve.isLine) {
|
|
tessy.gluTessVertex(arr(e.vertexA.point), e.vertexA);
|
|
} else if (e.edge.curve.verb) {
|
|
tessy.gluTessVertex(arr(e.vertexA.point), e.vertexA);
|
|
let points = e.edge.curve.tessellate();
|
|
if (e.inverted) {
|
|
points.reverse();
|
|
}
|
|
points.shift();
|
|
points.forEach(v => tessy.gluTessVertex(v, {point: new Vector().set3(v)}));
|
|
}
|
|
tessy.gluTessVertex(arr(e.vertexA.point), e.vertexA);
|
|
}
|
|
tessy.gluTessEndContour();
|
|
}
|
|
|
|
tessy.gluTessEndPolygon();
|
|
|
|
const triangled = [];
|
|
|
|
for (let i = 0; i < vertices.length; i += 3 ) {
|
|
var a = vertices[i];
|
|
var b = vertices[i + 1];
|
|
var c = vertices[i + 2];
|
|
triangled.push([a, b, c]);
|
|
}
|
|
return triangled;
|
|
} |