mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-15 12:53:52 +01:00
148 lines
4.6 KiB
JavaScript
148 lines
4.6 KiB
JavaScript
import Vector from 'math/vector';
|
|
import {EDGE_AUX, FACE_CHUNK} from '../../../brep/stitching'
|
|
import {normalOfCCWSeq, normalOfCCWSeqTHREE} from '../../cad-utils';
|
|
import {TriangulateFace} from '../../tess/triangulation'
|
|
import {SceneSolid, SceneFace, WIREFRAME_MATERIAL} from './sceneObject'
|
|
import brepTess from '../../tess/brep-tess'
|
|
import tessellateSurface from '../../../brep/geom/surfaces/surfaceTess';
|
|
import NurbsSurface from '../../../brep/geom/surfaces/nurbsSurface';
|
|
import {BrepSurface} from '../../../brep/geom/surfaces/brepSurface';
|
|
import {createBoundingSurfaceFrom2DPoints} from '../../../brep/brep-builder';
|
|
import {Plane} from '../../../brep/geom/impl/plane';
|
|
|
|
const SMOOTH_RENDERING = false;
|
|
|
|
export class UnmanagedSceneSolid extends SceneSolid {
|
|
|
|
constructor(data, type, skin) {
|
|
super(type, undefined, skin);
|
|
this.createGeometry(data);
|
|
this.externalData = {};
|
|
}
|
|
|
|
createGeometry(data) {
|
|
const geometry = new THREE.Geometry();
|
|
geometry.dynamic = true;
|
|
this.mesh = new THREE.Mesh(geometry, this.material);
|
|
this.cadGroup.add(this.mesh);
|
|
this.createFaces(data.faces);
|
|
this.createEdges(data.faces);
|
|
this.createVertices();
|
|
}
|
|
|
|
createFaces(faces) {
|
|
const geom = this.mesh.geometry;
|
|
for (let faceData of faces) {
|
|
const sceneFace = new UnmanagedSceneFace(faceData, this);
|
|
this.sceneFaces.push(sceneFace);
|
|
let tessellation = faceData.tess;
|
|
const vec = arr => new THREE.Vector3().fromArray(arr);
|
|
for (let i = 0; i < tessellation.length; ++i) {
|
|
let off = geom.vertices.length;
|
|
let tr = tessellation[i], normales;
|
|
if (Array.isArray(tr)) {
|
|
if (SMOOTH_RENDERING && tr[1] && !tr[1].find(n => n[0] === null || n[1] === null || n[2] === null)) {
|
|
normales = tr[1].map(vec);
|
|
}
|
|
tr = tr[0];
|
|
}
|
|
tr.forEach(p => geom.vertices.push(vec(p)));
|
|
if (!normales && faceData.surface.TYPE === 'PLANE') {
|
|
normales = vec(faceData.surface.normal);
|
|
if (faceData.inverted) {
|
|
normales.negate();
|
|
}
|
|
} else {
|
|
if (faceData.inverted) {
|
|
if (Array.isArray(normales)) {
|
|
tr.forEach(n => n.negate())
|
|
} else {
|
|
normales.negate();
|
|
}
|
|
}
|
|
}
|
|
|
|
let testNormal = Array.isArray(normales) ? normalizedSumOfTHREE(normales) : normales;
|
|
let indices = [off, off + 1, off + 2];
|
|
let trNormal = normalOfCCWSeqTHREE(indices.map(i => geom.vertices[i]));
|
|
if (testNormal.dot(trNormal) < 0) {
|
|
indices.reverse();
|
|
}
|
|
let [a, b, c] = indices;
|
|
|
|
const face = sceneFace.createMeshFace(a, b, c, normales);
|
|
geom.faces.push(face);
|
|
}
|
|
}
|
|
geom.mergeVertices();
|
|
}
|
|
|
|
createEdges(faces) {
|
|
for (let faceData of faces) {
|
|
for (let loop of faceData.loops) {
|
|
for (let edgeData of loop) {
|
|
const line = new THREE.Line(new THREE.Geometry(), WIREFRAME_MATERIAL);
|
|
if (edgeData.tess) {
|
|
edgeData.tess.forEach(p => line.geometry.vertices.push(new THREE.Vector3().fromArray(p)));
|
|
}
|
|
this.wireframeGroup.add(line);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
createVertices() {
|
|
}
|
|
}
|
|
|
|
function normalizedSumOfTHREE(vecs) {
|
|
let out = new THREE.Vector3().copy();
|
|
vecs.forEach(v => out.add(v));
|
|
out.normalize();
|
|
return out;
|
|
}
|
|
|
|
class UnmanagedSceneFace extends SceneFace {
|
|
constructor(faceData, solid) {
|
|
super(solid, faceData.id);
|
|
let s = faceData.surface;
|
|
if (s.TYPE === 'B-SPLINE') {
|
|
this._surface = new BrepSurface(NurbsSurface.create(s.degU, s.degV, s.knotsU, s.knotsV, s.cp, s.weights), faceData.inverted);
|
|
} else if (s.TYPE === 'PLANE') {
|
|
//TODO create bounded nurbs from face vertices when they are available
|
|
let fakeBounds = [
|
|
new Vector(0,0,0), new Vector(0,100,0), new Vector(100,100,0), new Vector(100,0,0)
|
|
];
|
|
let normal = new Vector().set3(s.normal);
|
|
let plane = new Plane(normal, normal.dot(new Vector().set3(s.origin)));
|
|
if (faceData.inverted) {
|
|
plane = plane.invert();
|
|
}
|
|
this._surface = createBoundingSurfaceFrom2DPoints(fakeBounds, plane);
|
|
} else {
|
|
this._surface = null;
|
|
// throw 'unsupported surface type ' + s.TYPE;
|
|
}
|
|
if (this._surface !== null ) {
|
|
this.plane = this._surface.tangentPlaneInMiddle();
|
|
}
|
|
this.bounds = faceData.loops.map(l => l.map(e => new Vector().set3(e.inverted ? e.b : e.a)));
|
|
}
|
|
|
|
|
|
normal() {
|
|
return this.plane.normal;
|
|
}
|
|
|
|
depth() {
|
|
return this.plane.w;
|
|
}
|
|
|
|
surface() {
|
|
return this._surface;
|
|
}
|
|
|
|
getBounds() {
|
|
return this.bounds;
|
|
}
|
|
}
|