diff --git a/index.js b/index.js
index 86a95fb..54d517b 100644
--- a/index.js
+++ b/index.js
@@ -1,3 +1,4 @@
+import 'babel-polyfill'
import React from 'react';
import { Interface } from 'doodle3d-slicer';
import doodleURL from '!url-loader!./models/Doodle_2.d3sketch';
@@ -9,6 +10,8 @@ import preset from 'jss-preset-default';
import normalize from 'normalize-jss';
import JSONToSketchData from 'doodle3d-core/shape/JSONToSketchData';
import createSceneData from 'doodle3d-core/d3/createSceneData.js';
+import { generateExportMesh } from 'doodle3d-core/utils/exportUtils.js';
+import { Matrix4 } from 'three/src/math/Matrix4.js';
injectTapEventPlugin();
@@ -23,10 +26,10 @@ jss.createStyleSheet({
}
}).attach();
-function init(sketch) {
+function init(mesh) {
render((
-
+
), document.getElementById('app'));
}
@@ -35,4 +38,5 @@ fetch(doodleURL)
.then(resonse => resonse.json())
.then(json => JSONToSketchData(json))
.then(file => createSceneData(file))
+ .then(sketch => generateExportMesh(sketch, { offsetSingleWalls: false, matrix: new Matrix4() }))
.then(init);
diff --git a/package.json b/package.json
index 0586c76..6b3e0c8 100644
--- a/package.json
+++ b/package.json
@@ -16,9 +16,7 @@
},
"dependencies": {
"@doodle3d/clipper-js": "^1.0.7",
- "@doodle3d/doodle3d-core": "github:doodle3d/doodle3d-core",
"babel-plugin-transform-export-extensions": "^6.22.0",
- "babel-runtime": "^6.26.0",
"file-saver": "^1.3.3",
"lodash": "^4.17.4",
"material-ui": "^0.19.4",
@@ -39,11 +37,13 @@
"babel-plugin-transform-es2015-classes": "^6.24.1",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-plugin-transform-runtime": "^6.23.0",
+ "babel-runtime": "^6.26.0",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.6.1",
"babel-preset-es2015": "6.24.1",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-0": "^6.24.1",
+ "@doodle3d/doodle3d-core": "github:doodle3d/doodle3d-core",
"html-webpack-plugin": "^2.29.0",
"html-webpack-template": "^6.0.2",
"imports-loader": "^0.7.1",
diff --git a/src/interface/index.js b/src/interface/index.js
index 05307bc..912a083 100644
--- a/src/interface/index.js
+++ b/src/interface/index.js
@@ -2,6 +2,7 @@ import _ from 'lodash';
import React from 'react';
import { Quaternion } from 'three/src/math/Quaternion.js';
import { Vector3 } from 'three/src/math/Vector3.js';
+import { Mesh } from 'three/src/objects/Mesh.js';
import PropTypes from 'proptypes';
import { placeOnGround, createScene, fetchProgress, slice, TabTemplate } from './utils.js';
import injectSheet from 'react-jss';
@@ -78,10 +79,7 @@ const styles = {
class Interface extends React.Component {
static propTypes = {
- sketch: PropTypes.shape({
- data: PropTypes.string,
- appVersion: PropTypes.string
- }),
+ mesh: PropTypes.shape({ isMesh: PropTypes.oneOf([true]) }).isRequired,
classes: PropTypes.objectOf(PropTypes.string),
defaultSettings: PropTypes.object.isRequired,
printers: PropTypes.object.isRequired,
@@ -110,7 +108,6 @@ class Interface extends React.Component {
super(props);
const { defaultPrinter, defaultQuality, defaultMaterial, printers, quality, material, defaultSettings } = props;
this.state = {
- controlMode: 'translate',
showFullScreen: false,
isSlicing: false,
error: null,
@@ -135,7 +132,10 @@ class Interface extends React.Component {
}
componentWillUnmount() {
- if (this.state.editorControls) this.state.editorControls.dispose();
+ const { editorControls, mesh: { material }, renderer } = this.state;
+ editorControls.dispose();
+ material.dispose();
+ renderer.dispose();
}
resetMesh = () => {
@@ -175,15 +175,18 @@ class Interface extends React.Component {
};
slice = async () => {
- const { mesh, settings, isSlicing, printers, quality, material } = this.state;
- const { name, sketch } = this.props;
+ const { settings, isSlicing, printers, quality, mesh: { matrix }, material } = this.state;
+ const { name, mesh } = this.props;
if (isSlicing) return;
this.setState({ isSlicing: true, progress: { action: '', slicing: 0, uploading: 0 }, error: null });
+ const exportMesh = new Mesh(mesh.geometry, mesh.material);
+ exportMesh.applyMatrix(matrix);
+
try {
- await slice(name, sketch, mesh.matrix, settings, printers, quality, material, progress => {
+ await slice(name, exportMesh, settings, printers, quality, material, progress => {
this.setState({ progress: { ...this.state.progress, ...progress } });
});
} catch (error) {
@@ -220,7 +223,7 @@ class Interface extends React.Component {
window.requestAnimationFrame(() => {
const { setSize } = this.state;
const { pixelRatio } = this.props;
- setSize(width, height, pixelRatio);
+ if (setSize) setSize(width, height, pixelRatio);
});
};
@@ -233,9 +236,10 @@ class Interface extends React.Component {
const { isSlicing, progress, settings, printers, quality, material, showFullScreen, error } = this.state;
const percentage = progress ? (progress.uploading + progress.slicing) / 2.0 * 100.0 : 0.0;
+ const style = { ...(showFullScreen ? {} : { maxWidth: 'inherit', width: '100%', height: '100%' }) };
const settingsPanel = (
-
+
{
+ const matrix = new Matrix4().makeTranslation(centerY, 0, centerX).multiply(mesh.matrix);
+ const { gcode } = sliceGeometry(settings, mesh.geometry, mesh.material, matrix, true, false, ({ progress }) => {
updateProgress({
action: progress.action,
slicing: progress.done / progress.total
diff --git a/src/sliceActions/generateGeometry.js b/src/sliceActions/generateGeometry.js
deleted file mode 100644
index 06c17db..0000000
--- a/src/sliceActions/generateGeometry.js
+++ /dev/null
@@ -1,28 +0,0 @@
-import { generateExportMesh } from 'doodle3d-core/utils/exportUtils.js';
-import { Matrix4 } from 'three/src/math/Matrix4.js';
-import { Mesh } from 'three/src/objects/Mesh.js';
-import { Geometry } from 'three/src/core/Geometry.js';
-import { FrontSide, DoubleSide } from 'three/src/constants.js';
-import { BoxGeometry } from 'three/src/geometries/BoxGeometry.js';
-
-export default function generateGeometry(sketch, matrix) {
- const { geometry, material } = generateExportMesh(sketch, {
- unionGeometry: false,
- offsetSingleWalls: false,
- matrix
- });
-
- const open = material.map(({ side }) => {
- switch (side) {
- case FrontSide:
- return false;
- case DoubleSide:
- return true;
- default:
- return false;
- }
- });
-
- geometry.computeFaceNormals();
- return { geometry, open };
-}
diff --git a/src/sliceActions/intersectionsToShapes.js b/src/sliceActions/intersectionsToShapes.js
index dd35e7e..0993d1e 100644
--- a/src/sliceActions/intersectionsToShapes.js
+++ b/src/sliceActions/intersectionsToShapes.js
@@ -1,9 +1,9 @@
import { subtract, normal, normalize, dot, distanceTo, clone } from './helpers/VectorUtils.js';
-export default function intersectionsToShapes(intersectionLayers, faces, open, settings) {
+export default function intersectionsToShapes(intersectionLayers, faces, openObjectIndexes, settings) {
const layers = [];
- for (let layer = 1; layer < intersectionLayers.length; layer ++) {
+ for (let layer = 0; layer < intersectionLayers.length; layer ++) {
const fillShapes = [];
const lineShapesOpen = [];
const lineShapesClosed = [];
@@ -43,7 +43,7 @@ export default function intersectionsToShapes(intersectionLayers, faces, open, s
for (const objectIndex in shapes) {
const shape = shapes[objectIndex];
- const openShape = open[objectIndex];
+ const openShape = openObjectIndexes[objectIndex];
const lines = [shape.lineSegments.pop()];
diff --git a/src/sliceActions/slice.js b/src/sliceActions/slice.js
index 471c110..57b8232 100644
--- a/src/sliceActions/slice.js
+++ b/src/sliceActions/slice.js
@@ -1,4 +1,3 @@
-import 'babel-polyfill'
import { Color } from 'three/src/math/Color.js';
import { BufferGeometry } from 'three/src/core/BufferGeometry.js';
import { BufferAttribute } from 'three/src/core/BufferAttribute.js';
@@ -16,12 +15,11 @@ import addBrim from './addBrim.js';
import optimizePaths from './optimizePaths.js';
import shapesToSlices from './shapesToSlices.js';
import slicesToGCode from './slicesToGCode.js';
-import generateGeometry from './generateGeometry.js';
import applyPrecision from './applyPrecision.js';
// // import removePrecision from './removePrecision.js';
-export default function(settings, sketch, matrix, constructLinePreview, onProgress) {
- const totalStages = 12;
+export default function(settings, geometry, openObjectIndexes, constructLinePreview, onProgress) {
+ const totalStages = 11;
let current = -1;
const updateProgress = (action) => {
current ++;
@@ -36,9 +34,6 @@ export default function(settings, sketch, matrix, constructLinePreview, onProgre
}
};
- updateProgress('Generating geometry');
- const { geometry, open } = generateGeometry(sketch, matrix);
-
updateProgress('Constructing unique lines from geometry');
const { lines, faces } = createLines(geometry, settings);
@@ -46,7 +41,7 @@ export default function(settings, sketch, matrix, constructLinePreview, onProgre
const layers = calculateLayersIntersections(lines, settings);
updateProgress('Constructing shapes from intersections');
- const shapes = intersectionsToShapes(layers, faces, open, settings);
+ const shapes = intersectionsToShapes(layers, faces, openObjectIndexes, settings);
applyPrecision(shapes);
diff --git a/src/slicer.js b/src/slicer.js
index 54ecf01..ead168b 100644
--- a/src/slicer.js
+++ b/src/slicer.js
@@ -2,23 +2,63 @@ import { VertexColors } from 'three/src/constants.js';
import { BufferAttribute } from 'three/src/core/BufferAttribute.js';
import { LineBasicMaterial } from 'three/src/materials/LineBasicMaterial.js';
import { LineSegments } from 'three/src/objects/LineSegments.js';
-import _slice from './sliceActions/slice.js';
+import slice from './sliceActions/slice.js';
import SlicerWorker from './slicer.worker.js';
-import sketchDataToJSON from 'doodle3d-core/shape/sketchDataToJSON';
+import { FrontSide, DoubleSide } from 'three/src/constants.js';
+import { BufferGeometry } from 'three/src/core/BufferGeometry.js'
-export function slice(settings, sketch, matrix, sync = false, constructLinePreview = false, onProgress) {
- if (sync) {
- return sliceSync(settings, sketch, matrix, constructLinePreview, onProgress);
+export function sliceMesh(settings, mesh, sync = false, constructLinePreview = false, onProgress) {
+ if (!mesh || !mesh.isMesh) {
+ throw new Error('Provided mesh is not intance of THREE.Mesh');
+ }
+
+ mesh.updateMatrix();
+ const { geometry, matrix, material } = mesh;
+ return sliceGeometry(settings, geometry, material, matrix, sync, constructLinePreview, onProgress);
+}
+
+export function sliceGeometry(settings, geometry, materials, matrix, sync = false, constructLinePreview = false, onProgress) {
+ if (!geometry) {
+ throw new Error('Missing required geometry argument');
+ } else if (geometry.isBufferGeometry) {
+ geometry = new Geometry().fromBufferGeometry(geometry);
+ } else if (geometry.isGeometry) {
+ geometry = geometry.clone();
} else {
- return sliceAsync(settings, sketch, matrix, constructLinePreview, onProgress);
+ throw new Error('Geometry is not an instance of BufferGeometry or Geometry');
+ }
+
+ if (geometry.faces.length === 0) {
+ throw new Error('Geometry does not contain any data');
+ }
+
+ if (matrix && matrix.isMatrix4) {
+ geometry.applyMatrix(matrix);
+ }
+
+ const openObjectIndexes = materials instanceof Array ? materials.map(({ side }) => {
+ switch (side) {
+ case FrontSide:
+ return false;
+ case DoubleSide:
+ return true;
+ default:
+ return false;
+ }
+ }) : [false];
+
+ if (sync) {
+ return sliceSync(settings, geometry, openObjectIndexes, constructLinePreview, onProgress);
+ } else {
+ return sliceAsync(settings, geometry, openObjectIndexes, constructLinePreview, onProgress);
}
}
-export function sliceSync(settings, sketch, matrix, constructLinePreview, onProgress) {
- return _slice(settings, sketch, matrix, constructLinePreview, onProgress);
+function sliceSync(settings, geometry, openObjectIndexes, constructLinePreview, onProgress) {
+ return slice(settings, geometry, openObjectIndexes, constructLinePreview, onProgress);
}
-export function sliceAsync(settings, sketch, matrix, constructLinePreview, onProgress) {
+function sliceAsync(settings, geometry, openObjectIndexes, constructLinePreview, onProgress) {
return new Promise((resolve, reject) => {
// create the slicer worker
const slicerWorker = new SlicerWorker();
@@ -61,11 +101,10 @@ export function sliceAsync(settings, sketch, matrix, constructLinePreview, onPro
});
// send geometry and settings to worker to start the slicing progress
- matrix = matrix.toArray();
- sketch = sketchDataToJSON(sketch);
+ geometry = geometry.toJSON();
slicerWorker.postMessage({
message: 'SLICE',
- data: { settings, sketch, matrix, constructLinePreview }
+ data: { settings, geometry, openObjectIndexes, constructLinePreview }
});
});
}
diff --git a/src/slicer.worker.js b/src/slicer.worker.js
index 9de8a49..0168b7b 100644
--- a/src/slicer.worker.js
+++ b/src/slicer.worker.js
@@ -1,7 +1,7 @@
+import 'core-js'; // polyfills
import slice from './sliceActions/slice.js';
import { Matrix4 } from 'three/src/math/Matrix4.js';
-import JSONToSketchData from 'doodle3d-core/shape/JSONToSketchData';
-import createSceneData from 'doodle3d-core/d3/createSceneData.js';
+import { JSONLoader } from 'three/src/loaders/JSONLoader.js';
const onProgress = progress => {
self.postMessage({
@@ -10,17 +10,18 @@ const onProgress = progress => {
});
}
+const loader = new JSONLoader();
+
self.addEventListener('message', async (event) => {
const { message, data } = event.data;
switch (message) {
case 'SLICE': {
+ const { settings, geometry: JSONGeometry, constructLinePreview, openObjectIndexes } = data;
+ const { geometry } = loader.parse(JSONGeometry.data);
+
+ const gcode = slice(settings, geometry, openObjectIndexes, constructLinePreview, onProgress);
+
const buffers = [];
- const { settings, sketch: sketchData, matrix: matrixArray, constructLinePreview } = data;
- const sketch = createSceneData(await JSONToSketchData(sketchData));
- const matrix = new Matrix4().fromArray(matrixArray);
-
- const gcode = slice(settings, sketch, matrix, constructLinePreview, onProgress);
-
if (gcode.linePreview) {
const position = gcode.linePreview.geometry.getAttribute('position').array;
const color = gcode.linePreview.geometry.getAttribute('color').array;