ftn-stl-viewer
Version:
A component for viewing an STL object from a given URL by utilizing Three.js
307 lines (255 loc) • 9.57 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _Three = require('./Three');
var _Three2 = _interopRequireDefault(_Three);
var _reactDom = require('react-dom');
var _reactDom2 = _interopRequireDefault(_reactDom);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var OrbitControls = require('three-orbit-controls')(_Three2.default);
var DIRECTIONAL_LIGHT = 'directionalLight';
var Paint = function () {
function Paint() {
_classCallCheck(this, Paint);
this.loader = new _Three2.default.STLLoader();
this.scene = new _Three2.default.Scene();
this.renderer = new _Three2.default.WebGLRenderer({
antialias: true
});
this.reqNumber = 0;
}
_createClass(Paint, [{
key: 'init',
value: function init(context) {
this.component = context;
this.width = context.props.width;
this.height = context.props.height;
this.modelColor = context.props.modelColor;
this.backgroundColor = context.props.backgroundColor;
this.orbitControls = context.props.orbitControls;
this.rotate = context.props.rotate;
this.cameraX = context.props.cameraX;
this.cameraY = context.props.cameraY;
this.cameraZ = context.props.cameraZ;
this.rotationSpeeds = context.props.rotationSpeeds;
this.lights = context.props.lights;
this.lightColor = context.props.lightColor;
this.model = context.props.model;
if (this.mesh !== undefined) {
this.scene.remove(this.mesh);
this.mesh.geometry.dispose();
this.mesh.material.dispose();
this.scene.remove(this.grid);
}
if(this.camera){
var directionalLightObj = this.camera.getObjectByName(DIRECTIONAL_LIGHT);
if (directionalLightObj) {
this.camera.remove(directionalLightObj);
}
}
if (this.animationRequestId) {
cancelAnimationFrame(this.animationRequestId);
}
//Detector.addGetWebGLMessage();
this.distance = 10000;
this.reqNumber += 1;
this.addSTLToScene(this.reqNumber);
}
}, {
key: 'addLight',
value: function addLight(lights) {
var _directionalLight$pos;
var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
var directionalLight = new _Three2.default.DirectionalLight(this.lightColor);
(_directionalLight$pos = directionalLight.position).set.apply(_directionalLight$pos, _toConsumableArray(lights));
directionalLight.name = DIRECTIONAL_LIGHT + index;
directionalLight.position.normalize();
this.camera.add(directionalLight);
}
}, {
key: 'loadSTLFromUrl',
value: function loadSTLFromUrl(url, reqId) {
var _this = this;
return new Promise(function (resolve) {
_this.loader.crossOrigin = '';
_this.loader.loadFromUrl(url, function (geometry) {
if (_this.reqNumber !== reqId) {
return;
}
resolve(geometry);
});
});
}
}, {
key: 'loadFromFile',
value: function loadFromFile(file) {
var _this2 = this;
return new Promise(function (resolve) {
_this2.loader.loadFromFile(file, function (geometry) {
resolve(geometry);
});
});
}
}, {
key: 'addSTLToScene',
value: function addSTLToScene(reqId) {
var _this3 = this;
var loadPromise = void 0;
if (typeof this.model === 'string') {
loadPromise = this.loadSTLFromUrl(this.model, reqId);
} else if (this.model instanceof ArrayBuffer) {
loadPromise = this.loadFromFile(this.model);
} else {
return Promise.resolve(null);
}
return loadPromise.then(function (geometry) {
// Calculate mesh noramls for MeshLambertMaterial.
geometry.computeFaceNormals();
geometry.computeVertexNormals();
// Center the object
geometry.center();
var material = new _Three2.default.MeshLambertMaterial({
overdraw: true,
color: _this3.modelColor
});
if (geometry.hasColors) {
material = new _Three2.default.MeshPhongMaterial({
opacity: geometry.alpha,
vertexColors: _Three2.default.VertexColors
});
}
_this3.mesh = new _Three2.default.Mesh(geometry, material);
// Set the object's dimensions
geometry.computeBoundingBox();
_this3.xDims = geometry.boundingBox.max.x - geometry.boundingBox.min.x;
_this3.yDims = geometry.boundingBox.max.y - geometry.boundingBox.min.y;
_this3.zDims = geometry.boundingBox.max.z - geometry.boundingBox.min.z;
if (_this3.rotate) {
_this3.mesh.rotation.x = _this3.rotationSpeeds[0];
_this3.mesh.rotation.y = _this3.rotationSpeeds[1];
_this3.mesh.rotation.z = _this3.rotationSpeeds[2];
}
_this3.scene.add(_this3.mesh);
_this3.addCamera();
// lights processing
var hasMultipleLights = _this3.lights.reduce(function (acc, item) {
return acc && Array.isArray(item);
}, true);
if (hasMultipleLights) {
_this3.lights.forEach(_this3.addLight.bind(_this3));
} else {
_this3.addLight(_this3.lights);
}
_this3.addInteractionControls();
_this3.addToReactComponent();
// Start the animation
_this3.animate();
});
}
}, {
key: 'addCamera',
value: function addCamera() {
// Add the camera
this.camera = new _Three2.default.PerspectiveCamera(30, this.width / this.height, 1, this.distance);
if (this.cameraZ === null) {
this.cameraZ = Math.max(this.xDims * 3, this.yDims * 3, this.zDims * 3);
}
this.camera.position.set(this.cameraX, this.cameraY, this.cameraZ);
this.scene.add(this.camera);
this.camera.lookAt(this.mesh);
this.renderer.set;
this.renderer.setSize(this.width, this.height);
this.renderer.setClearColor(this.backgroundColor, 1);
}
}, {
key: 'addInteractionControls',
value: function addInteractionControls() {
// Add controls for mouse interaction
if (this.orbitControls) {
this.controls = new OrbitControls(this.camera, _reactDom2.default.findDOMNode(this.component));
this.controls.enableKeys = false;
this.controls.addEventListener('change', this.orbitRender.bind(this));
}
}
}, {
key: 'addToReactComponent',
value: function addToReactComponent() {
// Add to the React Component
_reactDom2.default.findDOMNode(this.component).replaceChild(this.renderer.domElement, _reactDom2.default.findDOMNode(this.component).firstChild);
}
/**
* Animate the scene
* @returns {void}
*/
}, {
key: 'animate',
value: function animate() {
// note: three.js includes requestAnimationFrame shim
if (this.rotate) {
this.animationRequestId = requestAnimationFrame(this.animate.bind(this));
}
if (this.orbitControls) {
this.controls.update();
}
this.render();
}
/**
* Render the scene after turning off the rotation
* @returns {void}
*/
}, {
key: 'orbitRender',
value: function orbitRender() {
if (this.rotate) {
this.rotate = false;
}
this.render();
}
/**
* Deallocate Mesh, renderer context.
* @returns {void}
*/
}, {
key: 'clean',
value: function clean() {
if (this.mesh !== undefined) {
this.mesh.geometry.dispose();
this.mesh.material.dispose();
this.scene.remove(this.mesh);
delete this.mesh;
}
if(this.camera){
var directionalLightObj = this.camera.getObjectByName(DIRECTIONAL_LIGHT);
if (directionalLightObj) {
this.camera.remove(directionalLightObj);
}
}
if (this.animationRequestId) {
cancelAnimationFrame(this.animationRequestId);
}
this.renderer.dispose();
this.renderer.forceContextLoss();
}
/**
* Render the scene
* @returns {void}
*/
}, {
key: 'render',
value: function render() {
if (this.mesh && this.rotate) {
this.mesh.rotation.x += this.rotationSpeeds[0];
this.mesh.rotation.y += this.rotationSpeeds[1];
this.mesh.rotation.z += this.rotationSpeeds[2];
}
this.renderer.render(this.scene, this.camera);
}
}]);
return Paint;
}();
exports.default = Paint;
module.exports = exports['default'];