jsketcher/web/app/cad/scene/wrappers/brepSceneObject.js
2020-05-19 01:48:19 -07:00

232 lines
6.6 KiB
JavaScript

import Vector from 'math/vector';
import {SceneEdge, SceneFace, SceneSolid} from './sceneObject';
import brepTess from '../../tess/brep-tess';
import tessellateSurface from '../../../brep/geom/surfaces/surfaceTess';
import {setAttribute} from '../../../../../modules/scene/objectData';
import * as vec from 'math/vec';
import {perpendicularVector} from '../../../math/math';
const SMOOTH_RENDERING = true;
export class BREPSceneSolid extends SceneSolid {
constructor(shell, type, skin) {
super(type, undefined, skin);
this.shell = shell;
this.externals = this.shell.data.externals;
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;
for (let brepFace of this.shell.faces) {
const sceneFace = new BREPSceneFace(brepFace, this);
this.sceneFaces.push(sceneFace);
let off = geom.faces.length;
if (brepFace.data.tesselation) {
tessDataToGeom(brepFace.data.tesselation.data, geom)
} else {
brepFaceToGeom(brepFace, geom);
}
for (let i = off; i < geom.faces.length; i++) {
sceneFace.registerMeshFace(geom.faces[i]);
}
}
geom.mergeVertices();
}
createEdges() {
for (let edge of this.shell.edges) {
this.createEdge(edge);
}
}
createEdge(edge) {
const doEdge = (edge, aux, width, color, opacity) => {
const geometry = new THREE.Geometry();
const scaleTargets = [];
geometry.dynamic = true;
let materialParams = {
color,
vertexColors: THREE.FaceColors,
shininess: 0,
visible: !aux,
morphTargets: true
};
if (opacity !== undefined) {
materialParams.transparent = true;
materialParams.opacity = opacity;
}
let tess = edge.data.tesselation ? edge.data.tesselation : edge.curve.tessellateToData();
let base = null;
for (let i = 1; i < tess.length; i++) {
let a = tess[i - 1];
let b = tess[i];
let ab = vec._normalize(vec.sub(b, a));
let dirs = [];
dirs[0] = perpendicularVector(ab);
dirs[1] = vec.cross(ab, dirs[0]);
dirs[2] = vec.negate(dirs[0]);
dirs[3] = vec.negate(dirs[1]);
dirs.forEach(d => vec._mul(d, width));
if (base === null) {
base = dirs.map(d => vec.add(a, d));
}
let lid = dirs.map(d => vec.add(b, d));
let off = geometry.vertices.length;
base.forEach(p => geometry.vertices.push(vThree(p)));
lid.forEach(p => geometry.vertices.push(vThree(p)));
function addScaleTargets(points, origin) {
points.forEach(p => scaleTargets.push(vThree(vec._add(vec._mul(vec.sub(p, origin), 10), origin))));
}
addScaleTargets(base, a);
addScaleTargets(lid, b);
base = lid;
[
[0, 4, 3],
[3, 4, 7],
[2, 3, 7],
[7, 6, 2],
[0, 1, 5],
[5, 4, 0],
[1, 2, 6],
[6, 5, 1],
].forEach(([a, b, c]) => geometry.faces.push(new THREE.Face3(a + off, b + off, c + off)));
}
geometry.morphTargets.push( { name: "scaleTargets", vertices: scaleTargets } );
geometry.computeFaceNormals();
let mesh = new THREE.Mesh(geometry, new THREE.MeshPhongMaterial(materialParams));
this.wireframeGroup.add(mesh);
// mesh.morphTargetInfluences[ 0 ] = 0.2;
return mesh;
};
let sceneEdge = new SceneEdge(null, this);
sceneEdge.externals = edge.data.externals;
this.sceneEdges.push(sceneEdge);
let representation = doEdge(edge, false, 1, 0x2B3856);
let marker = doEdge(edge, true, 3, 0xFA8072, 0.8);
setAttribute(representation, 'edge', sceneEdge);
setAttribute(marker, 'edge', sceneEdge);
sceneEdge.representation = representation;
sceneEdge.marker = marker;
}
createVertices() {
}
}
class BREPSceneFace extends SceneFace {
constructor(brepFace, solid) {
super(solid, brepFace.id);
brepFace.id = this.id;
this.brepFace = brepFace;
this.externals = this.brepFace.data.externals;
}
normal() {
return this.brepFace.surface.normalInMiddle();
}
depth() {
return this.brepFace.surface.tangentPlaneInMiddle().w;
}
surface() {
return this.brepFace.surface;
}
getBounds() {
const bounds = [];
for (let loop of this.brepFace.loops) {
bounds.push(loop.asPolygon().map(p => new Vector().setV(p)));
}
return bounds;
}
}
export function tessDataToGeom(tessellation, geom) {
for (let [tr, normales] of tessellation) {
let off = geom.vertices.length;
tr.forEach(p => geom.vertices.push(vThree(p)));
if (normales && SMOOTH_RENDERING) {
normales = normales.map(vThree)
} else {
normales = vThree(vec.normal3(tr));
}
const face = new THREE.Face3(off, off + 1, off + 2, normales);
geom.faces.push(face);
}
}
export function brepFaceToGeom(brepFace, geom) {
const polygons = brepTess(brepFace);
return surfaceAndPolygonsToGeom(brepFace.surface, polygons, geom);
}
export function surfaceAndPolygonsToGeom(surface, polygons, geom) {
const isPlane = surface.simpleSurface && surface.simpleSurface.isPlane;
let normalOrNormals;
if (isPlane) {
normalOrNormals = surface.normalInMiddle().three();
}
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(firstVertex.three());
geom.vertices.push(poly[1].three());
for (let i = 2; i < vLength; i++) {
geom.vertices.push(poly[i].three());
const a = off;
const b = i - 1 + off;
const c = i + off;
if (!isPlane) {
normalOrNormals = [firstVertex, poly[i - 1], poly[i]].map(v => surface.normal(v));
}
const face = new THREE.Face3(a, b, c, normalOrNormals);
geom.faces.push(face);
}
//view.setFaceColor(sceneFace, utils.isSmoothPiece(group.shared) ? 0xFF0000 : null);
}
}
export function surfaceToThreeGeom(srf, geom) {
const off = geom.vertices.length;
const tess = tessellateSurface(srf);
tess.points.forEach(p => geom.vertices.push(new THREE.Vector3().fromArray(p)));
for (let faceIndices of tess.faces) {
const face = new THREE.Face3(faceIndices[0] + off, faceIndices[1] + off, faceIndices[2] + off);
geom.faces.push(face);
}
}
const vThree = arr => new THREE.Vector3().fromArray(arr);