@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
78 lines (71 loc) • 2.42 kB
text/typescript
import type {FaceData, OpenCascadeInstance, TopoDS_Face} from '../CadCommon';
import {CadGC} from '../CadCommon';
import {CadLoaderSync} from '../CadLoaderSync';
enum FaceOrientation {
BACKWARD = 0,
FORWARD = 1,
}
function faceOrientation(oc: OpenCascadeInstance, face: TopoDS_Face): FaceOrientation {
return face.Orientation_1() === oc.TopAbs_Orientation.TopAbs_FORWARD
? FaceOrientation.FORWARD
: FaceOrientation.BACKWARD;
}
const STRIDE = 3;
export function faceData(oc: OpenCascadeInstance, face: TopoDS_Face, index0 = 0): FaceData | void {
return CadGC.withGC((r) => {
const location = CadLoaderSync.TopLoc_Location;
const triangulation = oc.BRep_Tool.Triangulation(face, location, 0);
if (triangulation.IsNull()) {
return;
}
const transformation = location.Transformation();
const tri = triangulation.get();
const nbNodes = tri.NbNodes();
// init
const normalsArray = r(new oc.TColgp_Array1OfDir_2(1, nbNodes));
const pc = r(new oc.Poly_Connect_2(triangulation));
oc.StdPrs_ToolTriangulatedShape.Normal(face, pc, normalsArray);
const nbTriangles = tri.NbTriangles();
const faceData: FaceData = {
positions: new Array(nbNodes * 3),
normals: new Array(normalsArray.Length() * 3),
indices: new Array(nbTriangles * 3),
};
// positions
for (let i = 1; i <= nbNodes; i++) {
const p = tri.Node(i).Transformed(transformation);
const index = (i - 1) * STRIDE;
faceData.positions[index] = p.X();
faceData.positions[index + 1] = p.Y();
faceData.positions[index + 2] = p.Z();
}
// normals
for (let i = normalsArray.Lower(); i <= normalsArray.Upper(); i++) {
const d = normalsArray.Value(i).Transformed(transformation);
const index = (i - 1) * STRIDE;
faceData.normals[index] = d.X();
faceData.normals[index + 1] = d.Y();
faceData.normals[index + 2] = d.Z();
}
// indices
let trisCount = 0;
const orientation = faceOrientation(oc, face);
for (let nt = 1; nt <= nbTriangles; nt++) {
const t = tri.Triangle(nt);
let n1 = t.Value(1);
let n2 = t.Value(2);
const n3 = t.Value(3);
if (orientation == FaceOrientation.BACKWARD) {
const tmp = n1;
n1 = n2;
n2 = tmp;
}
const index = trisCount * STRIDE;
faceData.indices[index] = n1 - 1 + index0;
faceData.indices[index + 1] = n2 - 1 + index0;
faceData.indices[index + 2] = n3 - 1 + index0;
trisCount++;
}
return faceData;
});
}