past3d/pastebin/static/js/thingview.js/thingiview.js

985 lines
32 KiB
JavaScript

var Thingiview = function(containerId, gridsize, gridunit) {
this.scope = this;
this.containerId = containerId;
this.gridsize = gridsize;
this.gridunit = gridunit;
this.init();
}
Thingiview.prototype.init = function() {
this.container = document.getElementById(this.containerId);
// this.stats = null;
this.camera = null;
this.scene = null;
this.renderer = null;
this.object = null;
this.plane = null;
this.ambientLight = null;
this.directionalLight = null;
this.pointLight = null;
this.targetXRotation = 0;
this.targetXRotationOnMouseDown = 0;
this.mouseX = 0;
this.mouseXOnMouseDown = 0;
this.targetYRotation = 0;
this.targetYRotationOnMouseDown = 0;
this.mouseY = 0;
this.mouseYOnMouseDown = 0;
this.mouseDown = false;
this.mouseOver = false;
this.windowHalfX = window.innerWidth / 2;
this.windowHalfY = window.innerHeight / 2
this.view = null;
this.infoMessage = null;
this.progressBar = null;
this.alertBox = null;
this.timer = null;
this.rotateTimer = null;
this.rotateListener = null;
this.wasRotating = null;
this.cameraView = 'diagonal';
this.cameraZoom = 0;
this.rotate = false;
this.backgroundColor = '#606060';
this.objectMaterial = 'solid';
this.objectColor = 0xffffff;
this.showPlane = true;
this.isWebGl = false;
if (document.defaultView && document.defaultView.getComputedStyle) {
this.width = parseFloat(document.defaultView.getComputedStyle(this.container,null).getPropertyValue('width'));
this.height = parseFloat(document.defaultView.getComputedStyle(this.container,null).getPropertyValue('height'));
} else {
this.width = parseFloat(this.container.currentStyle.width);
this.height = parseFloat(this.container.currentStyle.height);
}
this.geometry;
}
Thingiview.prototype.initScene = function() {
this.container.style.position = 'relative';
this.container.innerHTML = '';
this.camera = new THREE.PerspectiveCamera(45, this.width/ this.height, 1, 100000);
this.camera.up = new THREE.Vector3(0, 0, 1);
this.camera.target = new THREE.Vector3(0, 0, 0);
this.camera.updateMatrix();
this.scene = new THREE.Scene();
this.ambientLight = new THREE.AmbientLight(0x202020);
this.scene.add(this.ambientLight);
this.directionalLight = new THREE.DirectionalLight(0xffffff, 0.75);
this.directionalLight.position.x = 1;
this.directionalLight.position.y = 1;
this.directionalLight.position.z = 2;
this.directionalLight.position.normalize();
this.scene.add(this.directionalLight);
this.pointLight = new THREE.PointLight(0xffffff, 0.3);
this.pointLight.position.x = 0;
this.pointLight.position.y = -25;
this.pointLight.position.z = 10;
this.scene.add(this.pointLight);
this.progressBar = document.createElement('div');
this.progressBar.style.position = 'absolute';
this.progressBar.style.top = '0px';
this.progressBar.style.left = '0px';
this.progressBar.style.backgroundColor = 'red';
this.progressBar.style.padding = '5px';
this.progressBar.style.display = 'none';
this.progressBar.style.overflow = 'visible';
this.progressBar.style.whiteSpace = 'nowrap';
this.progressBar.style.zIndex = 100;
this.container.appendChild(this.progressBar);
alertBox = document.createElement('div');
alertBox.id = 'alertBox';
alertBox.style.position = 'absolute';
alertBox.style.top = '25%';
alertBox.style.left = '25%';
alertBox.style.width = '50%';
alertBox.style.height = '50%';
alertBox.style.backgroundColor = '#dddddd';
alertBox.style.padding = '10px';
// alertBox.style.overflowY = 'scroll';
alertBox.style.display = 'none';
alertBox.style.zIndex = 100;
this.container.appendChild(alertBox);
// load a blank object
// this.loadSTLString('');
if (this.showPlane) {
this.loadPlaneGeometry();
}
this.setCameraView(this.cameraView);
this.setObjectMaterial(this.objectMaterial);
testCanvas = document.createElement('canvas');
try {
if (testCanvas.getContext('experimental-webgl')) {
// this.showPlane = false;
isWebGl = true;
this.renderer = new THREE.WebGLRenderer();
// this.renderer = new THREE.CanvasRenderer();
} else {
this.renderer = new THREE.CanvasRenderer();
}
} catch(e) {
this.renderer = new THREE.CanvasRenderer();
// log("failed webgl detection");
}
// this.renderer.setSize(this.container.innerWidth, this.container.innerHeight);
this.renderer.setSize(this.width, this.height);
this.renderer.domElement.style.backgroundColor = this.backgroundColor;
this.container.appendChild(this.renderer.domElement);
// stats = new Stats();
// stats.domElement.style.position = 'absolute';
// stats.domElement.style.top = '0px';
// this.container.appendChild(stats.domElement);
// TODO: figure out how to get the render window to resize when window resizes
// window.addEventListener('resize', onContainerResize(), false);
// this.container.addEventListener('resize', onContainerResize(), false);
// this.renderer.domElement.addEventListener('mousemove', onRendererMouseMove, false);
window.addEventListener('mousemove', (function(self) {
return function(event) {
self.onRendererMouseMove(event);
}
})(this), false);
this.renderer.domElement.addEventListener('mouseover', (function(self) {
return function(event) {
self.onRendererMouseOver(event);
}
})(this), false);
this.renderer.domElement.addEventListener('mouseout', (function(self) {
return function(event) {
self.onRendererMouseOut(event);
}
})(this), false);
this.renderer.domElement.addEventListener('mousedown', (function(self) {
return function(event) {
self.onRendererMouseDown(event);
}
})(this), false);
// this.renderer.domElement.addEventListener('mouseup', this.onRendererMouseUp, false);
window.addEventListener('mouseup', (function(self) {
return function(event) {
self.onRendererMouseUp(event);
}
})(this), false);
this.renderer.domElement.addEventListener('touchstart', (function(self) {
return function(event) {
self.onRendererTouchStart(event);
}
})(this), false);
this.renderer.domElement.addEventListener('touchend', (function(self) {
return function(event) {
self.onRendererTouchEnd(event);
}
})(this), false);
this.renderer.domElement.addEventListener('touchmove', (function(self) {
return function(event) {
self.onRendererTouchMove(event);
}
})(this), false);
this.renderer.domElement.addEventListener('DOMMouseScroll', (function(self) {
return function(event) {
self.onRendererScroll(event);
}
})(this), false);
this.renderer.domElement.addEventListener('mousewheel', (function(self) {
return function(event) {
self.onRendererScroll(event);
}
})(this), false);
this.renderer.domElement.addEventListener('gesturechange', (function(self) {
return function(event) {
self.onRendererGestureChange(event);
}
})(this), false);
}
// FIXME
// onContainerResize = function(event) {
// width = parseFloat(document.defaultView.getComputedStyle(this.container,null).getPropertyValue('width'));
// height = parseFloat(document.defaultView.getComputedStyle(this.container,null).getPropertyValue('height'));
//
// // log("resized width: " + width + ", height: " + height);
//
// if (this.renderer) {
// this.renderer.setSize(width, height);
// camera.projectionMatrix = THREE.Matrix4.makePerspective(70, width / height, 1, 10000);
// this.sceneLoop();
// }
// };
Thingiview.prototype.onRendererScroll = function(event) {
event.preventDefault();
var rolled = 0;
if (event.wheelDelta === undefined) {
// Firefox
// The measurement units of the detail and wheelDelta properties are different.
rolled = -40 * event.detail;
} else {
rolled = event.wheelDelta;
}
if (rolled > 0) {
// up
this.scope.setCameraZoom(+10);
} else {
// down
this.scope.setCameraZoom(-10);
}
}
Thingiview.prototype.onRendererGestureChange = function(event) {
event.preventDefault();
if (event.scale > 1) {
this.scope.setCameraZoom(+5);
} else {
this.scope.setCameraZoom(-5);
}
}
Thingiview.prototype.onRendererMouseOver = function(event) {
this.mouseOver = true;
// targetRotation = object.rotation.z;
if (this.timer == null) {
// log('starting loop');
this.timer = setInterval((function(self) {
return function() {
self.sceneLoop();
}
})(this), 1000/60);
}
}
Thingiview.prototype.onRendererMouseDown = function(event) {
// log("down");
event.preventDefault();
this.mouseDown = true;
if(this.scope.getRotation()){
this.wasRotating = true;
this.setRotation(false);
} else {
this.wasRotating = false;
}
mouseXOnMouseDown = event.clientX - this.windowHalfX;
mouseYOnMouseDown = event.clientY - this.windowHalfY;
this.targetXRotationOnMouseDown = this.targetXRotation;
this.targetYRotationOnMouseDown = this.targetYRotation;
}
Thingiview.prototype.onRendererMouseMove = function(event) {
// log("move");
if (this.mouseDown) {
mouseX = event.clientX - this.windowHalfX;
// this.targetXRotation = this.targetXRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.02;
xrot = this.targetXRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.02;
mouseY = event.clientY - this.windowHalfY;
// this.targetYRotation = this.targetYRotationOnMouseDown + (mouseY - mouseYOnMouseDown) * 0.02;
yrot = this.targetYRotationOnMouseDown + (mouseY - mouseYOnMouseDown) * 0.02;
this.targetXRotation = xrot;
this.targetYRotation = yrot;
}
}
Thingiview.prototype.onRendererMouseUp = function(event) {
// log("up");
if (this.mouseDown) {
this.mouseDown = false;
if (!this.mouseOver) {
clearInterval(this.timer);
this.timer = null;
}
if (this.wasRotating) {
this.setRotation(true);
}
}
}
Thingiview.prototype.onRendererMouseOut = function(event) {
if (!this.mouseDown) {
clearInterval(this.timer);
this.timer = null;
}
this.mouseOver = false;
}
Thingiview.prototype.onRendererTouchStart = function(event) {
this.targetXRotation = this.object.rotation.z;
this.targetYRotation = this.object.rotation.x;
this.timer = setInterval((function(self) {
return function() {
self.sceneLoop();
}
})(this), 1000/60);
if (event.touches.length == 1) {
event.preventDefault();
mouseXOnMouseDown = event.touches[0].pageX - this.windowHalfX;
this.targetXRotationOnMouseDown = this.targetXRotation;
mouseYOnMouseDown = event.touches[0].pageY - this.windowHalfY;
this.targetYRotationOnMouseDown = this.targetYRotation;
}
}
Thingiview.prototype.onRendererTouchEnd = function(event) {
clearInterval(this.timer);
this.timer = null;
// this.targetXRotation = this.object.rotation.z;
// this.targetYRotation = this.object.rotation.x;
}
Thingiview.prototype.onRendererTouchMove = function(event) {
if (event.touches.length == 1) {
event.preventDefault();
mouseX = event.touches[0].pageX - this.windowHalfX;
this.targetXRotation = this.targetXRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.05;
mouseY = event.touches[0].pageY - this.windowHalfY;
this.targetYRotation = this.targetYRotationOnMouseDown + (mouseY - mouseYOnMouseDown) * 0.05;
}
}
Thingiview.prototype.sceneLoop = function() {
if (this.object) {
// if (view == 'bottom') {
// if (this.showPlane) {
// this.plane.rotation.z = this.object.rotation.z -= (targetRotation + this.object.rotation.z) * 0.05;
// } else {
// this.object.rotation.z -= (targetRotation + this.object.rotation.z) * 0.05;
// }
// } else {
// if (this.showPlane) {
// this.plane.rotation.z = this.object.rotation.z += (targetRotation - this.object.rotation.z) * 0.05;
// } else {
// this.object.rotation.z += (targetRotation - this.object.rotation.z) * 0.05;
// }
// }
if (this.showPlane) {
this.plane.rotation.z = this.object.rotation.z = (this.targetXRotation - this.object.rotation.z) * 0.2;
this.plane.rotation.x = this.object.rotation.x = (this.targetYRotation - this.object.rotation.x) * 0.2;
} else {
this.object.rotation.z = (this.targetXRotation - this.object.rotation.z) * 0.2;
this.object.rotation.x = (this.targetYRotation - this.object.rotation.x) * 0.2;
}
// log(this.object.rotation.x);
this.camera.lookAt(this.camera.target);
this.camera.updateMatrix();
this.object.updateMatrix();
if (this.showPlane) {
this.plane.updateMatrix();
}
this.renderer.render(this.scene, this.camera);
// stats.update();
}
}
Thingiview.prototype.rotateLoop = function() {
// targetRotation += 0.01;
this.targetXRotation += 0.05;
this.sceneLoop();
}
Thingiview.prototype.getShowPlane = function(){
return this.showPlane;
}
Thingiview.prototype.setShowPlane = function(show) {
this.showPlane = show;
if (show) {
log("Showing plane");
if (this.scene && !this.plane) {
this.loadPlaneGeometry();
}
this.scene.add(this.plane);
this.plane.updateMatrix();
} else {
log("Hiding plane");
if (this.scene && this.plane) {
this.scene.remove(this.plane);
}
}
this.sceneLoop();
}
Thingiview.prototype.getRotation = function() {
return this.rotateTimer !== null;
}
Thingiview.prototype.setRotation = function(rotate) {
log("Rotation set to " + rotate)
clearInterval(this.rotateTimer);
if (rotate) {
this.rotateTimer = setInterval((function(self) {
return function() {
self.rotateLoop();
}
})(this), 1000/60);
} else {
this.rotateTimer = null;
}
this.scope.onSetRotation();
}
Thingiview.prototype.onSetRotation = function(callback) {
if(callback === undefined){
if(this.rotateListener !== null){
try{
this.rotateListener(this.scope.getRotation());
} catch(ignored) {}
}
} else {
this.rotateListener = callback;
}
}
Thingiview.prototype.setCameraView = function(dir) {
this.cameraView = dir;
this.targetXRotation = 0;
this.targetYRotation = 0;
if (this.object) {
this.object.rotation.x = 0;
this.object.rotation.y = 0;
this.object.rotation.z = 0;
}
if (this.showPlane && this.object) {
this.plane.rotation.x = this.object.rotation.x;
this.plane.rotation.y = this.object.rotation.y;
this.plane.rotation.z = this.object.rotation.z;
}
if (dir == 'top') {
// camera.position.y = 0;
// this.camera.position.z = 100;
// this.camera.target.z = 0;
if (this.showPlane) {
this.plane.flipSided = false;
}
} else if (dir == 'side') {
// this.camera.position.y = -70;
// this.camera.position.z = 70;
// this.camera.target.z = 0;
this.targetYRotation = -4.5;
if (this.showPlane) {
this.plane.flipSided = false;
}
} else if (dir == 'bottom') {
// this.camera.position.y = 0;
// this.camera.position.z = -100;
// this.camera.target.z = 0;
if (this.showPlane) {
this.plane.flipSided = true;
}
} else {
// this.camera.position.y = -70;
// this.camera.position.z = 70;
// this.camera.target.z = 0;
if (this.showPlane) {
this.plane.flipSided = false;
}
}
mouseX = this.targetXRotation;
mouseXOnMouseDown = this.targetXRotation;
mouseY = this.targetYRotation;
mouseYOnMouseDown = this.targetYRotation;
this.scope.centerCamera();
this.sceneLoop();
}
Thingiview.prototype.setCameraZoom = function(factor) {
this.cameraZoom = factor;
if (this.cameraView == 'bottom') {
if (this.camera.position.z + factor > 0) {
factor = 0;
}
} else {
if (this.camera.position.z - factor < 0) {
factor = 0;
}
}
if (this.cameraView == 'top') {
this.camera.position.z -= factor;
} else if (this.cameraView == 'bottom') {
this.camera.position.z += factor;
} else if (this.cameraView == 'side') {
this.camera.position.y += factor;
this.camera.position.z -= factor;
} else {
this.camera.position.y += factor;
this.camera.position.z -= factor;
}
this.sceneLoop();
}
Thingiview.prototype.getObjectMaterial = function() {
return this.objectMaterial;
}
Thingiview.prototype.setObjectMaterial = function(type) {
this.objectMaterial = type;
this.loadObjectGeometry();
}
Thingiview.prototype.setBackgroundColor = function(color) {
backgroundColor = color
if (this.renderer) {
this.renderer.domElement.style.backgroundColor = color;
}
}
Thingiview.prototype.setObjectColor = function(color) {
this.objectColor = parseInt(color.replace(/\#/g, ''), 16);
this.loadObjectGeometry();
}
Thingiview.prototype.loadSTL = function(url) {
this.scope.newWorker('loadSTL', url);
}
Thingiview.prototype.loadOBJ = function(url) {
this.scope.newWorker('loadOBJ', url);
}
Thingiview.prototype.loadSTLString = function(STLString) {
this.scope.newWorker('loadSTLString', STLString);
}
Thingiview.prototype.loadSTLBinary = function(STLBinary) {
this.scope.newWorker('loadSTLBinary', STLBinary);
}
Thingiview.prototype.loadOBJString = function(OBJString) {
this.scope.newWorker('loadOBJString', OBJString);
}
Thingiview.prototype.loadJSON = function(url) {
this.scope.newWorker('loadJSON', url);
}
Thingiview.prototype.loadPLY = function(url) {
this.scope.newWorker('loadPLY', url);
}
Thingiview.prototype.loadPLYString = function(PLYString) {
this.scope.newWorker('loadPLYString', PLYString);
}
Thingiview.prototype.loadPLYBinary = function(PLYBinary) {
this.scope.newWorker('loadPLYBinary', PLYBinary);
}
Thingiview.prototype.centerCamera = function() {
if (this.geometry) {
// Using method from http://msdn.microsoft.com/en-us/library/bb197900(v=xnagamestudio.10).aspx
// log("bounding sphere radius = " + this.geometry.boundingSphere.radius);
// look at the center of the object
this.camera.target.x = this.geometry.center_x;
this.camera.target.y = this.geometry.center_y;
this.camera.target.z = this.geometry.center_z;
// set camera position to center of sphere
this.camera.position.x = this.geometry.center_x;
this.camera.position.y = this.geometry.center_y;
this.camera.position.z = this.geometry.center_z;
// find distance to center
distance = this.geometry.boundingSphere.radius / Math.sin((this.camera.fov/2) * (Math.PI / 180));
// zoom backwards about half that distance, I don't think I'm doing the math or backwards vector calculation correctly?
// this.scope.setCameraZoom(-distance/1.8);
// this.scope.setCameraZoom(-distance/1.5);
this.scope.setCameraZoom(-distance/1.2);
this.directionalLight.position.x = this.geometry.min_y * 2;
this.directionalLight.position.y = this.geometry.min_y * 2;
this.directionalLight.position.z = this.geometry.max_z * 2;
this.pointLight.position.x = this.geometry.center_y;
this.pointLight.position.y = this.geometry.center_y;
this.pointLight.position.z = this.geometry.max_z * 2;
} else {
// set to any valid position so it doesn't fail before geometry is available
this.camera.position.y = -70;
this.camera.position.z = 70;
this.camera.target.z = 0;
}
}
Thingiview.prototype.loadArray = function(array) {
log("loading array...");
this.geometry = new STLGeometry(array);
this.loadObjectGeometry();
this.setRotation(false);
this.setRotation(true);
this.centerCamera();
log("finished loading " + this.geometry.faces.length + " faces.");
}
Thingiview.prototype.newWorker = function(cmd, param) {
var wasRotating = this.getRotation();
this.setRotation(false);
var worker = new WorkerFacade(thingiurlbase + '/thingiloader.js');
worker.scope = this;
worker.onmessage = function(event) {
if (event.data.status == "complete") {
this.scope.progressBar.innerHTML = 'Initializing geometry...';
// this.scene.removeObject(this.object);
this.scope.geometry = new STLGeometry(event.data.content);
this.scope.loadObjectGeometry();
this.scope.progressBar.innerHTML = '';
this.scope.progressBar.style.display = 'none';
this.scope.setRotation(wasRotating);
log("finished loading " + this.scope.geometry.faces.length + " faces.");
this.scope.centerCamera();
} else if (event.data.status == "complete_points") {
this.scope.progressBar.innerHTML = 'Initializing points...';
this.scope.geometry = new THREE.Geometry();
var material = new THREE.ParticleBasicMaterial( { color: 0xff0000, opacity: 1 } );
// material = new THREE.ParticleBasicMaterial( { size: 35, sizeAttenuation: false} );
// material.color.setHSV( 1.0, 0.2, 0.8 );
for (i in event.data.content[0]) {
// for (var i=0; i<10; i++) {
vector = new THREE.Vector3( event.data.content[0][i][0], event.data.content[0][i][1], event.data.content[0][i][2] );
this.scope.geometry.vertices.push(vector);
}
particles = new THREE.ParticleSystem( this.geometry, material );
particles.sortParticles = true;
particles.updateMatrix();
this.scope.scene.add( particles );
this.scope.camera.lookAt(this.camera.target);
this.scope.camera.updateMatrix();
this.scope.renderer.render(this.scene, this.camera);
this.scope.progressBar.innerHTML = '';
this.scope.progressBar.style.display = 'none';
this.scope.setRotation(wasRotating);
log("finished loading " + event.data.content[0].length + " points.");
// this.scope.centerCamera();
} else if (event.data.status == "progress") {
this.scope.progressBar.style.display = 'block';
this.scope.progressBar.style.width = event.data.content;
// log(event.data.content);
} else if (event.data.status == "message") {
this.scope.progressBar.style.display = 'block';
this.scope.progressBar.innerHTML = event.data.content;
log(event.data.content);
} else if (event.data.status == "alert") {
this.scope.displayAlert(event.data.content);
} else {
alert('Error: ' + event.data);
log('Unknown Worker Message: ' + event.data);
}
}
worker.onerror = function(error) {
log(error);
error.preventDefault();
}
worker.postMessage({'cmd':cmd, 'param':param});
}
Thingiview.prototype.displayAlert = function(msg) {
msg = msg + "<br/><br/><center><input type=\"button\" value=\"Ok\" onclick=\"document.getElementById('alertBox').style.display='none'\"></center>"
alertBox.innerHTML = msg;
alertBox.style.display = 'block';
// log(msg);
}
Thingiview.prototype.loadPlaneGeometry = function() {
var material = new THREE.LineBasicMaterial({color:0xafafaf});
this.plane = new THREE.Object3D();
for (var i=-this.gridsize/2; i<= this.gridsize/2; i += this.gridunit) {
var geometry = new THREE.Geometry();
geometry.vertices.push(new THREE.Vector3 (i, -this.gridsize/2, 0));
geometry.vertices.push(new THREE.Vector3 (i, this.gridsize/2, 0));
var line = new THREE.Line(geometry, material);
this.plane.add(line);
geometry = new THREE.Geometry();
geometry.vertices.push(new THREE.Vector3 (-this.gridsize/2, i, 0));
geometry.vertices.push(new THREE.Vector3 (this.gridsize/2, i, 0));
line = new THREE.Line(geometry, material);
this.plane.add(line);
}
}
Thingiview.prototype.loadObjectGeometry = function() {
if (this.scene && this.geometry) {
if (this.objectMaterial == 'wireframe') {
// material = new THREE.MeshColorStrokeMaterial(this.objectColor, 1, 1);
material = new THREE.MeshBasicMaterial({color:this.objectColor,wireframe:true});
} else {
if (this.isWebGl) {
// material = new THREE.MeshPhongMaterial(this.objectColor, this.objectColor, 0xffffff, 50, 1.0);
// material = new THREE.MeshColorFillMaterial(this.objectColor);
// material = new THREE.MeshLambertMaterial({color:this.objectColor});
material = new THREE.MeshLambertMaterial({color:this.objectColor, shading: THREE.FlatShading});
} else {
// material = new THREE.MeshColorFillMaterial(this.objectColor);
material = new THREE.MeshLambertMaterial({color:this.objectColor, shading: THREE.FlatShading});
}
}
// scene.removeObject(this.object);
if (this.object) {
// shouldn't be needed, but this fixes a bug with webgl not removing previous object when loading a new one dynamically
this.object.materials = [new THREE.MeshBasicMaterial({color:0xffffff, opacity:0})];
this.scene.remove(this.object);
// this.object.geometry = geometry;
// this.object.materials = [material];
}
this.object = new THREE.Mesh(this.geometry, material);
this.scene.add(this.object);
if (this.objectMaterial != 'wireframe') {
this.object.overdraw = true;
this.object.doubleSided = true;
}
this.object.updateMatrix();
this.targetXRotation = 0;
this.targetYRotation = 0;
this.sceneLoop();
}
}
var STLGeometry = function(stlArray) {
// log("building geometry...");
THREE.Geometry.call(this);
var scope = this;
// var vertexes = stlArray[0];
// var normals = stlArray[1];
// var faces = stlArray[2];
for (var i=0; i<stlArray[0].length; i++) {
v(stlArray[0][i][0], stlArray[0][i][1], stlArray[0][i][2]);
}
for (var i=0; i<stlArray[1].length; i++) {
f3(stlArray[1][i][0], stlArray[1][i][1], stlArray[1][i][2]);
}
function v(x, y, z) {
// log("adding vertex: " + x + "," + y + "," + z);
scope.vertices.push( new THREE.Vector3( x, y, z ) );
}
function f3(a, b, c) {
// log("adding face: " + a + "," + b + "," + c)
scope.faces.push( new THREE.Face3( a, b, c ) );
}
// log("computing centroids...");
this.computeCentroids();
// log("computing normals...");
// this.computeNormals();
this.computeFaceNormals();
// log("finished building geometry");
scope.min_x = 0;
scope.min_y = 0;
scope.min_z = 0;
scope.max_x = 0;
scope.max_y = 0;
scope.max_z = 0;
for (var v = 0, vl = scope.vertices.length; v < vl; v ++) {
scope.max_x = Math.max(scope.max_x, scope.vertices[v].x);
scope.max_y = Math.max(scope.max_y, scope.vertices[v].y);
scope.max_z = Math.max(scope.max_z, scope.vertices[v].z);
scope.min_x = Math.min(scope.min_x, scope.vertices[v].x);
scope.min_y = Math.min(scope.min_y, scope.vertices[v].y);
scope.min_z = Math.min(scope.min_z, scope.vertices[v].z);
}
scope.center_x = (scope.max_x + scope.min_x)/2;
scope.center_y = (scope.max_y + scope.min_y)/2;
scope.center_z = (scope.max_z + scope.min_z)/2;
for (var v = 0, vl = scope.vertices.length; v < vl; v ++) {
scope.vertices[v].x -= scope.center_x;
scope.vertices[v].y -= scope.center_y;
}
scope.max_x -= scope.center_x;
scope.max_y -= scope.center_y;
scope.min_x -= scope.center_x;
scope.min_y -= scope.center_y;
scope.center_x = 0;
scope.center_y = 0;
}
STLGeometry.prototype = new THREE.Geometry();
STLGeometry.prototype.constructor = STLGeometry;
function log(msg) {
if (console) {
console.log(msg);
}
}
/* A facade for the Web Worker API that fakes it in case it's missing.
Good when web workers aren't supported in the browser, but it's still fast enough, so execution doesn't hang too badly (e.g. Opera 10.5).
By Stefan Wehrmeyer, licensed under MIT
*/
var WorkerFacade;
if(!!window.Worker){
WorkerFacade = (function(){
return function(path){
return new window.Worker(path);
};
}());
} else {
WorkerFacade = (function(){
var workers = {}, masters = {}, loaded = false;
var that = function(path){
var theworker = {}, loaded = false, callings = [];
theworker.postToWorkerFunction = function(args){
try{
workers[path]({"data":args});
}catch(err){
theworker.onerror(err);
}
};
theworker.postMessage = function(params){
if(!loaded){
callings.push(params);
return;
}
theworker.postToWorkerFunction(params);
};
masters[path] = theworker;
var scr = document.createElement("SCRIPT");
scr.src = path;
scr.type = "text/javascript";
scr.onload = function(){
loaded = true;
while(callings.length > 0){
theworker.postToWorkerFunction(callings[0]);
callings.shift();
}
};
document.body.appendChild(scr);
var binaryscr = document.createElement("SCRIPT");
binaryscr.src = thingiurlbase + '/binaryReader.js';
binaryscr.type = "text/javascript";
document.body.appendChild(binaryscr);
return theworker;
};
that.fake = true;
that.add = function(pth, worker){
workers[pth] = worker;
return function(param){
masters[pth].onmessage({"data": param});
};
};
that.toString = function(){
return "FakeWorker('"+path+"')";
};
return that;
}());
}
/* Then just use WorkerFacade instead of Worker (or alias it)
The Worker code must should use a custom function (name it how you want) instead of postMessage.
Put this at the end of the Worker:
if(typeof(window) === "undefined"){
onmessage = nameOfWorkerFunction;
customPostMessage = postMessage;
} else {
customPostMessage = WorkerFacade.add("path/to/thisworker.js", nameOfWorkerFunction);
}
*/