mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-26 10:23:05 +01:00
external engines support
This commit is contained in:
parent
ea95b54430
commit
8b8142db76
10 changed files with 214 additions and 20 deletions
45
web/app/cad/craft/enginesPlugin.js
Normal file
45
web/app/cad/craft/enginesPlugin.js
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import {STORAGE_GLOBAL_PREFIX} from '../projectPlugin';
|
||||
|
||||
const ENGINES_STORAGE_PREFIX = `${STORAGE_GLOBAL_PREFIX}.CraftEngines`;
|
||||
|
||||
let engines = [];
|
||||
|
||||
export function activate({services}) {
|
||||
let enginesStr = services.storage.get(ENGINES_STORAGE_PREFIX);
|
||||
if (enginesStr) {
|
||||
engines = JSON.parse(enginesStr);
|
||||
}
|
||||
|
||||
function registerEngine(id, url){
|
||||
engines.push({id, url});
|
||||
services.storage.set(ENGINES_STORAGE_PREFIX, JSON.stringify(engines));
|
||||
startEngine(engines[engines.length - 1]);
|
||||
}
|
||||
|
||||
function engineReady(id, handler) {
|
||||
let engine = engines.find(e => e.id === id);
|
||||
if (!engine) {
|
||||
console.warn(`engine "${id}" not registered`);
|
||||
} else {
|
||||
engine.handler = handler;
|
||||
console.info(`engine "${id}" is ready`);
|
||||
}
|
||||
}
|
||||
|
||||
services.craftEngines = {
|
||||
registerEngine,
|
||||
getRegisteredEngines: () => engines,
|
||||
engineReady
|
||||
};
|
||||
|
||||
engines.forEach(e => e.handler = NO_OP_HANDLER);
|
||||
engines.forEach(startEngine);
|
||||
}
|
||||
|
||||
function startEngine({id, url}) {
|
||||
let engineScript = document.createElement('script');
|
||||
engineScript.setAttribute('src', url);
|
||||
document.head.appendChild(engineScript);
|
||||
}
|
||||
|
||||
const NO_OP_HANDLER = () => null;
|
||||
|
|
@ -22,7 +22,9 @@ export function activate(context) {
|
|||
};
|
||||
actions.push(opAction);
|
||||
|
||||
registry[id] = descriptor;
|
||||
registry[id] = Object.assign({}, descriptor, {
|
||||
run: request => runOperation(request, descriptor, context)
|
||||
});
|
||||
}
|
||||
|
||||
function registerOperations(operations) {
|
||||
|
|
@ -48,3 +50,12 @@ export function activate(context) {
|
|||
}
|
||||
}
|
||||
|
||||
function runOperation(request, descriptor, context) {
|
||||
for (let engine of context.services.craftEngines.getRegisteredEngines()) {
|
||||
let handler = engine.handler(descriptor.id);
|
||||
if (handler) {
|
||||
return handler(request);
|
||||
}
|
||||
}
|
||||
return descriptor.run(request)
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ import {toLoops} from '../brep/brep-io';
|
|||
import {contributeComponent} from './dom/components/ContributedComponents';
|
||||
import BrepDebuggerWindow, {BREP_DEBUG_WINDOW_VISIBLE} from '../brep/debug/debugger/BrepDebuggerWindow';
|
||||
import curveTess from '../brep/geom/impl/curve/curve-tess';
|
||||
import tessellateSurface from '../brep/geom/surfaces/surfaceTess';
|
||||
|
||||
|
||||
export function activate({bus, services}) {
|
||||
|
|
@ -172,6 +173,34 @@ function addGlobalDebugActions({viewer, cadScene, cadRegistry}) {
|
|||
AddSurfaceNormal: (surface) => {
|
||||
__DEBUG__.AddNormal(surface.pointInMiddle(), surface.normalInMiddle());
|
||||
},
|
||||
AddTessDump: (triangles, color) => {
|
||||
const vec = arr => new THREE.Vector3().fromArray(arr);
|
||||
color = color || 0xffffff;
|
||||
const geometry = new THREE.Geometry();
|
||||
for (let i = 0; i < triangles.length; ++i) {
|
||||
let off = geometry.vertices.length;
|
||||
let tr = triangles[i], normales;
|
||||
if (Array.isArray(tr)) {
|
||||
normales = tr[1];
|
||||
tr = tr[0];
|
||||
if (normales.find(n => n[0] === null || n[1] === null || n[2] === null)) {
|
||||
normales = undefined;
|
||||
}
|
||||
}
|
||||
tr.forEach(p => geometry.vertices.push(vec(p)));
|
||||
const face = new THREE.Face3(off, off + 1, off + 2, normales && normales.map(vec));
|
||||
geometry.faces.push(face);
|
||||
}
|
||||
geometry.computeFaceNormals();
|
||||
const mesh = new THREE.Mesh(geometry, createSolidMaterial({
|
||||
vertexColors: THREE.FaceColors,
|
||||
color: 0xB0C4DE,
|
||||
shininess: 0,
|
||||
side: THREE.DoubleSide
|
||||
}));
|
||||
debugVolumeGroup.add(mesh);
|
||||
viewer.render();
|
||||
},
|
||||
HideSolids: () => {
|
||||
cadRegistry.getAllShells().forEach(s => s.cadGroup.traverse(o => o.visible = false));
|
||||
viewer.render();
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import * as MenuPlugin from '../dom/menu/menuPlugin';
|
|||
import * as KeyboardPlugin from '../keyboard/keyboardPlugin';
|
||||
import * as WizardPlugin from '../craft/wizard/wizardPlugin';
|
||||
import * as OperationPlugin from '../craft/operationPlugin';
|
||||
import * as CraftEnginesPlugin from '../craft/enginesPlugin';
|
||||
import * as CadRegistryPlugin from '../craft/cadRegistryPlugin';
|
||||
import * as CraftPlugin from '../craft/craftPlugin';
|
||||
import * as StoragePlugin from '../storagePlugin';
|
||||
|
|
@ -35,6 +36,7 @@ export default function startApplication(callback) {
|
|||
UiEntryPointsPlugin,
|
||||
KeyboardPlugin,
|
||||
WizardPlugin,
|
||||
CraftEnginesPlugin,
|
||||
OperationPlugin,
|
||||
CadRegistryPlugin,
|
||||
CraftPlugin,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import {setSketchPrecision} from './sketch/sketchReader';
|
||||
import {runSandbox} from './sandbox';
|
||||
|
||||
const STORAGE_PREFIX = "TCAD.projects.";
|
||||
export const STORAGE_GLOBAL_PREFIX = 'TCAD';
|
||||
const STORAGE_PREFIX = `${STORAGE_GLOBAL_PREFIX}.projects.`;
|
||||
|
||||
|
||||
export function activate(context) {
|
||||
|
|
|
|||
|
|
@ -96,7 +96,6 @@ export function triangulateToThree(shell, geom) {
|
|||
let gIdx = 0;
|
||||
|
||||
function addFace(face) {
|
||||
face.materialIndex = gIdx++;
|
||||
geom.faces.push(face);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,22 +28,14 @@ export class SceneSolid {
|
|||
}
|
||||
|
||||
addLineToScene(a, b) {
|
||||
var lg = new THREE.Geometry();
|
||||
let lg = new THREE.Geometry();
|
||||
lg.vertices.push(a);
|
||||
lg.vertices.push(b);
|
||||
var line = new THREE.Line(lg, WIREFRAME_MATERIAL);
|
||||
let line = new THREE.Line(lg, WIREFRAME_MATERIAL);
|
||||
this.wireframeGroup.add(line);
|
||||
return line;
|
||||
}
|
||||
|
||||
createGeometry() {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
dropGeometry() {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
|
||||
dispose() {
|
||||
this.material.dispose();
|
||||
this.mesh.geometry.dispose();
|
||||
|
|
@ -103,8 +95,8 @@ export class SceneFace {
|
|||
return this._basis;
|
||||
}
|
||||
|
||||
createMeshFace(a, b, c) {
|
||||
const face = new THREE.Face3(a, b, c);
|
||||
createMeshFace(a, b, c, normales) {
|
||||
const face = new THREE.Face3(a, b, c, normales);
|
||||
this.registerMeshFace(face);
|
||||
return face;
|
||||
}
|
||||
|
|
|
|||
108
web/app/cad/scene/wrappers/unmanagedSceneObject.js
Normal file
108
web/app/cad/scene/wrappers/unmanagedSceneObject.js
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
import Vector from 'math/vector';
|
||||
import {EDGE_AUX, FACE_CHUNK} from '../../../brep/stitching'
|
||||
import {normalOfCCWSeq} 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';
|
||||
|
||||
const SMOOTH_RENDERING = false;
|
||||
|
||||
export class UnmanagedSceneSolid extends SceneSolid {
|
||||
|
||||
constructor(data, type, skin) {
|
||||
super(type, undefined, Object.assign({side : THREE.DoubleSide}, skin));
|
||||
this.createGeometry(data);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
const face = sceneFace.createMeshFace(off, off + 1, off + 2, normales);
|
||||
geom.faces.push(face);
|
||||
}
|
||||
}
|
||||
if (!SMOOTH_RENDERING) {
|
||||
geom.computeFaceNormals();
|
||||
}
|
||||
//geom.mergeVertices();
|
||||
}
|
||||
|
||||
createEdges(faces) {
|
||||
for (let faceData of faces) {
|
||||
for (let edgeData of faceData.edges) {
|
||||
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() {
|
||||
}
|
||||
}
|
||||
|
||||
class UnmanagedSceneFace extends SceneFace {
|
||||
constructor(faceData, solid) {
|
||||
super(solid, faceData.id);
|
||||
this.surface = faceData.surface;
|
||||
// if (this.surface.TYPE === 'B-SPLINE') {
|
||||
// let s = this.surface;
|
||||
// let nurbs = new NurbsSurface(verb.geom.NurbsSurface.byKnotsControlPointsWeights(s.degU, s.degV, s.knotsU, s.knotsV, s.cp, s.weights));
|
||||
// __DEBUG__.AddParametricSurface(nurbs);
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
normal() {
|
||||
return this.surface.normalInMiddle();
|
||||
}
|
||||
|
||||
depth() {
|
||||
return this.surface.tangentPlaneInMiddle().w;
|
||||
}
|
||||
|
||||
surface() {
|
||||
return this.surface;
|
||||
}
|
||||
|
||||
getBounds() {
|
||||
return [
|
||||
this.surface.southEastPoint(),
|
||||
this.surface.southWestPoint(),
|
||||
this.surface.northWestPoint(),
|
||||
this.surface.northEastPoint()
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -13,6 +13,7 @@ import {Point} from '../../brep/geom/point';
|
|||
import BrepCurve from '../../brep/geom/curves/brepCurve';
|
||||
import {Plane} from '../../brep/geom/impl/plane';
|
||||
import pip from '../tess/pip';
|
||||
import {UnmanagedSceneSolid} from '../scene/wrappers/unmanagedSceneObject';
|
||||
|
||||
export default {
|
||||
brep: {
|
||||
|
|
@ -29,5 +30,8 @@ export default {
|
|||
HalfEdge, Edge, Loop, Face, Shell, Vertex
|
||||
},
|
||||
IO,
|
||||
},
|
||||
scene: {
|
||||
UnmanagedSceneSolid
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
import TPI from './tpi';
|
||||
import * as SceneGraph from 'scene/sceneGraph';
|
||||
import {BREPSceneSolid} from "../scene/wrappers/brepSceneObject";
|
||||
import {BREPSceneSolid} from '../scene/wrappers/brepSceneObject';
|
||||
|
||||
/*
|
||||
* TPI stands for the Test Program Interface
|
||||
|
|
@ -9,13 +8,17 @@ export function activate({bus, services}) {
|
|||
|
||||
function addShellOnScene(shell, skin) {
|
||||
const sceneSolid = new BREPSceneSolid(shell, undefined, skin);
|
||||
addOnScene(sceneSolid, skin);
|
||||
return sceneSolid;
|
||||
}
|
||||
function addOnScene(sceneSolid, skin) {
|
||||
services.cadRegistry.update(null, [sceneSolid]);
|
||||
services.viewer.render();
|
||||
return sceneSolid;
|
||||
}
|
||||
services.tpi = Object.assign({
|
||||
bus,
|
||||
services,
|
||||
addShellOnScene
|
||||
addShellOnScene,
|
||||
addOnScene
|
||||
}, TPI);
|
||||
}
|
||||
Loading…
Reference in a new issue