mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-07 17:04:58 +01:00
210 lines
6.6 KiB
JavaScript
210 lines
6.6 KiB
JavaScript
import Vector from '../../math/vector'
|
|
import {EDGE_AUX} from '../../brep/stitching'
|
|
import {normalOfCCWSeq} from '../cad-utils'
|
|
import {Triangulate} from '../../3d/triangulation'
|
|
import {SceneSolid, SceneFace, WIREFRAME_MATERIAL} from './scene-object'
|
|
|
|
const SMOOTH_RENDERING = true;
|
|
|
|
export class BREPSceneSolid extends SceneSolid {
|
|
|
|
constructor(shell, type, skin) {
|
|
super(type, undefined, skin);
|
|
this.shell = shell;
|
|
this.createGeometry();
|
|
}
|
|
|
|
createGeometry() {
|
|
const geometry = new THREE.Geometry();
|
|
geometry.dynamic = true;
|
|
this.mesh = new THREE.Mesh(geometry, this.material);
|
|
this.cadGroup.add(this.mesh);
|
|
this.createFaces();
|
|
this.createEdges();
|
|
this.createVertices();
|
|
}
|
|
|
|
createFaces() {
|
|
const geom = this.mesh.geometry;
|
|
const groups = triangulateToThree(this.shell, geom);
|
|
for (let g of groups) {
|
|
const sceneFace = new BREPSceneFace(g.brepFace, this);
|
|
this.sceneFaces.push(sceneFace);
|
|
for (let i = g.groupStart; i < g.groupEnd; i ++) {
|
|
const face = geom.faces[i];
|
|
sceneFace.registerMeshFace(face);
|
|
}
|
|
}
|
|
//geom.mergeVertices();
|
|
}
|
|
|
|
createEdges() {
|
|
const visited = new Set();
|
|
for (let face of this.shell.faces) {
|
|
for (let halfEdge of face.outerLoop.halfEdges) {
|
|
if (!visited.has(halfEdge.edge)) {
|
|
visited.add(halfEdge.edge);
|
|
if (halfEdge.edge.data[EDGE_AUX] === undefined) {
|
|
const line = new THREE.Line(undefined, WIREFRAME_MATERIAL);
|
|
const contour = [halfEdge.vertexA.point];
|
|
halfEdge.edge.curve.approximate(10, halfEdge.vertexA.point, halfEdge.vertexB.point, contour);
|
|
contour.push(halfEdge.vertexB.point);
|
|
for (let p of contour) {
|
|
line.geometry.vertices.push(p.three());
|
|
}
|
|
this.wireframeGroup.add(line);
|
|
line.__TCAD_EDGE = halfEdge.edge;
|
|
halfEdge.edge.data['scene.edge'] = line;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
createVertices() {
|
|
}
|
|
}
|
|
|
|
class BREPSceneFace extends SceneFace {
|
|
constructor(brepFace, solid) {
|
|
super(solid, brepFace.id);
|
|
brepFace.id = this.id;
|
|
this.brepFace = brepFace;
|
|
brepFace.data['scene.face'] = this;
|
|
}
|
|
|
|
|
|
normal() {
|
|
return this.brepFace.surface.normal;
|
|
}
|
|
|
|
depth() {
|
|
return this.brepFace.surface.w;
|
|
}
|
|
|
|
getBounds() {
|
|
const bounds = [];
|
|
for (let loop of this.brepFace.loops) {
|
|
bounds.push(loop.asPolygon().map(p => new Vector().setV(p)));
|
|
}
|
|
return bounds;
|
|
}
|
|
}
|
|
|
|
function triangulatePlaneFace(face) {
|
|
function v(data) {
|
|
return new Vector(data[0], data[1], data[2]);
|
|
}
|
|
function data(v) {
|
|
return [v.x, v.y, v.z];
|
|
}
|
|
const triangled = [];
|
|
const contours = [];
|
|
for (let loop of face.loops) {
|
|
const contour = [];
|
|
for (let he of loop.halfEdges) {
|
|
contour.push(he.vertexA.point);
|
|
he.edge.curve.approximate(10, he.vertexA.point, he.vertexB.point, contour);
|
|
}
|
|
contours.push(contour.map(point => data(point)));
|
|
}
|
|
let vertices = Triangulate(contours, data(face.surface.normal));
|
|
for (let i = 0; i < vertices.length; i += 3 ) {
|
|
var a = v(vertices[i]);
|
|
var b = v(vertices[i + 1]);
|
|
var c = v(vertices[i + 2]);
|
|
triangled.push([a, b, c]);
|
|
}
|
|
return triangled;
|
|
}
|
|
|
|
export function triangulateToThree(shell, geom) {
|
|
const result = [];
|
|
let gIdx = 0;
|
|
function addFace(face) {
|
|
face.materialIndex = gIdx ++;
|
|
geom.faces.push(face);
|
|
}
|
|
for (let brepFace of shell.faces) {
|
|
const groupStart = geom.faces.length;
|
|
if (brepFace.surface.constructor.name == 'Plane') {
|
|
const polygons = triangulatePlaneFace(brepFace);
|
|
for (let p = 0; p < polygons.length; ++p) {
|
|
const off = geom.vertices.length;
|
|
const poly = polygons[p];
|
|
const vLength = poly.length;
|
|
if (vLength < 3) continue;
|
|
const firstVertex = poly[0];
|
|
geom.vertices.push(threeV(firstVertex));
|
|
geom.vertices.push(threeV(poly[1]));
|
|
const normal = threeV(brepFace.surface.normal ? brepFace.surface.normal : normalOfCCWSeq(poly));
|
|
for (let i = 2; i < vLength; i++) {
|
|
geom.vertices.push(threeV(poly[i]));
|
|
const a = off;
|
|
const b = i - 1 + off;
|
|
const c = i + off;
|
|
const face = new THREE.Face3(a, b, c);
|
|
face.normal = normal;
|
|
addFace(face);
|
|
}
|
|
//view.setFaceColor(sceneFace, utils.isSmoothPiece(group.shared) ? 0xFF0000 : null);
|
|
}
|
|
} else if (brepFace.surface.constructor.name == 'NurbsSurface1') {
|
|
const off = geom.vertices.length;
|
|
const contours = [];
|
|
|
|
for (let loop of brepFace.loops) {
|
|
const points = [];
|
|
for (let he of loop.halfEdges) {
|
|
points.push(he.vertexA.point);
|
|
he.edge.curve.approximate(10, he.vertexA.point, he.vertexB.point, points);
|
|
}
|
|
const verb = brepFace.surface.verb;
|
|
const uvs = points.map(point => verb.closestParam(point.data()));
|
|
uvs.forEach(uv => uv.push(0)); // add z coord
|
|
contours.push(uvs);
|
|
//....TODO
|
|
for (let i = 0; i < tessedUVs.length; i += 3 ) {
|
|
var a = new Vector().set3(tessedUVs[i]);
|
|
var b = new Vector().set3(tessedUVs[i + 1]);
|
|
var c = new Vector().set3(tessedUVs[i + 2]);
|
|
const normalOrNormals = normalOfCCWSeq([a, b, c]).three();
|
|
const face = new THREE.Face3(off, off + 1, off + 2, normalOrNormals);
|
|
addFace(face);
|
|
}
|
|
}
|
|
} else if (brepFace.surface.constructor.name == 'NurbsSurface') {
|
|
const off = geom.vertices.length;
|
|
const tess = brepFace.surface.verb.tessellate({maxDepth: 3});
|
|
tess.points.forEach(p => geom.vertices.push(new THREE.Vector3().fromArray(p)));
|
|
for (let faceIndices of tess.faces) {
|
|
let normalOrNormals;
|
|
if (SMOOTH_RENDERING) {
|
|
normalOrNormals = faceIndices.map(function(x){
|
|
var vn = tess.normals[x];
|
|
return new THREE.Vector3( vn[0], vn[1], vn[2] );
|
|
});
|
|
} else {
|
|
normalOrNormals = normalOfCCWSeq(faceIndices.map(i => new Vector().set3(tess.points[i]))).three();
|
|
}
|
|
|
|
const face = new THREE.Face3(faceIndices[0] + off, faceIndices[1] + off, faceIndices[2] + off, normalOrNormals);
|
|
addFace(face);
|
|
}
|
|
} else {
|
|
throw 'unsupported;'
|
|
}
|
|
result.push(new FaceGroup(brepFace, groupStart, geom.faces.length));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
class FaceGroup {
|
|
constructor(brepFace, groupStart, groupEnd) {
|
|
this.brepFace = brepFace;
|
|
this.groupStart = groupStart;
|
|
this.groupEnd = groupEnd;
|
|
}
|
|
}
|
|
|
|
function threeV(v) {return new THREE.Vector3( v.x, v.y, v.z )}
|