/** * Created by fab on 3/16/15. */ function Machine() { this.hasStock = false; this._setDefaults(); this.meshes = {}; this.material = new THREE.MeshLambertMaterial({color:0xaaaaaa, shading: THREE.FlatShading, transparent:true, opacity:1}); this.cell = this._makeStockCell(); var self = this; this._buildMeshes(function(meshes){ self.meshes = meshes; _.each(_.values(meshes), function(mesh){ globals.three.sceneAdd(mesh); }); if (self.setMachinePosition) self.setMachinePosition(); self.setVisibility(); }); this.setVisibility(false); } Machine.prototype._setDefaults = function(){ globals.cam.set("camProcess", "gcode"); globals.cam.set("stockFixed", false); globals.cam.set("originPosition", {x:0,y:0,z:0}); var boundingBox = globals.lattice.calculateBoundingBox(); var rapidHeight = parseFloat((boundingBox.max.z + 2*globals.lattice.zScale()).toFixed(4)); globals.cam.set("rapidHeight", rapidHeight); globals.cam.set("stockPosition", {x:0,y:0,z:0}); globals.cam.set("stockSeparation", globals.lattice.xScale()); }; Machine.prototype.setVisibility = function(visible){ if (visible == null || visible === undefined) { if (globals.cam) visible = globals.cam.isVisible(); else visible = false; } if (visible && this.hasStock) this.cell.draw(); else this.cell.hide(); this._setAlpha(); this._setMeshesVisiblity(visible); globals.three.render(); }; Machine.prototype._setAlpha = function(){ //todo make stock transparent if (globals.appState.get("currentTab") == "cam"){ this.material.opacity = 0.5; } else { this.material.opacity = 1; } }; Machine.prototype._setMeshesVisiblity = function(visible){ _.each(_.values(this.meshes), function(mesh){ mesh.visible = visible; }); if (visible) this.setScale(globals.lattice.get("scale")); }; Machine.prototype.setScale = function(scale){ _.each(_.values(this.meshes), function(mesh){ mesh.scale.set(scale, scale, scale); }); } Machine.prototype._makeStockCell = function(){ if (globals.lattice.makeSuperCell) return globals.lattice.makeSuperCell(); return globals.lattice.makeCellForLatticeType({}, globals.lattice.get("scale")); }; Machine.prototype.updateCellType = function(){ if (this.cell) this.cell.destroy(); this.cell = this._makeStockCell(); this.setVisibility(); }; Machine.prototype.updatePartType = function(){ this.cell.destroyParts(); this.cell.draw(); this.setVisibility(); }; Machine.prototype.pickUpStock = function(){ this.hasStock = true; this.cell.draw(); }; Machine.prototype.releaseStock = function(index){ this.hasStock = false; globals.lattice.showCellAtIndex(JSON.parse(index)); this.cell.hide(); }; Machine.prototype.pause = function(){ }; Machine.prototype.moveTo = function(x, y, z, speed, wcs, callback){ x = this._makeAbsPosition(x, wcs.x); y = this._makeAbsPosition(y, wcs.y); z = this._makeAbsPosition(z, wcs.z); this._moveTo(x, y, z, speed, wcs, callback); }; Machine.prototype._moveTo = function(x, y, z, speed, wcs, callback){ var totalThreads = 3; function sketchyCallback(){ totalThreads -= 1; if (totalThreads > 0) return; callback(); } var startingPos = this.cell.getPosition(); speed = this._normalizeSpeed(startingPos, x, y, this._reorganizeSpeed(speed)); this._moveAxis(startingPos.x, x, "x", speed.x, sketchyCallback); this._moveAxis(startingPos.y, y, "y", speed.y, sketchyCallback); this._moveAxis(startingPos.z, z, "z", speed.z, sketchyCallback); }; Machine.prototype._makeAbsPosition = function(target, wcs){ if (target == "" || target == null || target === undefined) return null; return parseFloat(target)+wcs; }; Machine.prototype._reorganizeSpeed = function(speed){ var newSpeed = {}; newSpeed.x = speed.xy; newSpeed.y = speed.xy; newSpeed.z = speed.z; return newSpeed; } Machine.prototype._normalizeSpeed = function(startingPos, x, y, speed){//xy moves need speed normalization var normSpeed = {}; if (x == "" || y == "") return speed; var deltaX = x-startingPos.x; var deltaY = y-startingPos.y; var totalDistance = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2)); if (totalDistance == 0) return speed; normSpeed.x = Math.abs(deltaX/totalDistance*speed.x); normSpeed.y = Math.abs(deltaY/totalDistance*speed.y); normSpeed.z = speed.z; return normSpeed; }; Machine.prototype._animateObjects = function(objects, axis, speed, startingPos, target, callback){ var increment = speed/25*globals.cam.get("simSpeed"); if (increment == 0) { if (callback) callback(); return; } var direction = 1; if (target-startingPos < 0) direction = -1; increment = Math.max(increment, 0.00001)*direction;//need to put a min on the increment - other wise this stall out with floating pt tol this._incrementalMove(objects, axis, increment, startingPos, target, direction, callback); }; Machine.prototype._incrementalMove = function(objects, axis, increment, currentPos, target, direction, callback){ var self = this; setTimeout(function(){ if ((target-currentPos)*direction <= 0) { if (callback) callback(); return; } var nextPos = currentPos + increment; if (Math.abs(target-currentPos) < Math.abs(increment)) nextPos = target;//don't overshoot self._setPosition(objects, nextPos, axis); self._incrementalMove(objects, axis, increment, nextPos, target, direction, callback) }, 10); }; Machine.prototype._setPosition = function(objects, nextPos, axis){ _.each(objects, function(object){ if (object instanceof DMACell || object instanceof DMASuperCell) object.moveTo(nextPos, axis); else object.position[axis] = nextPos; }); }; /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////POST PROCESS////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// Machine.prototype.postProcess = function(data, exporter){//override in subclasses var rapidHeight = globals.cam.get("rapidHeight"); var safeHeight = globals.cam.get("safeHeight"); var wcs = globals.cam.get("originPosition"); var stockPosition = globals.cam.get("stockPosition"); var stockNum = 0;//position of stock in stock array var multStockPositions = globals.cam.get("multipleStockPositions"); var stockSeparation = globals.cam.get("stockSeparation"); var stockArraySize = globals.cam.get("stockArraySize"); var self = this; globals.lattice.rasterCells(globals.cam._getOrder(globals.cam.get("camStrategy")), function(cell){ if (!cell) return; var thisStockPosition = _.clone(stockPosition); if (multStockPositions) { thisStockPosition.x += stockNum % stockArraySize.y * stockSeparation; thisStockPosition.y -= Math.floor(stockNum / stockArraySize.y) * stockSeparation; stockNum += 1; if (stockNum >= stockArraySize.x * stockArraySize.y) stockNum = 0; } data += self._postMoveXY(exporter, stockPosition.x-wcs.x, stockPosition.y-wcs.y); data += self._postPickUpStock(exporter, thisStockPosition, rapidHeight, wcs, safeHeight); var cellPosition = cell.getPosition(); data += self._postMoveXY(exporter, cellPosition.x-wcs.x, cellPosition.y-wcs.y); data += self._postReleaseStock(cellPosition, cell, exporter, rapidHeight, wcs, safeHeight); data += "\n"; }); return data; }; Machine.prototype._postMoveXY = function(exporter, x, y){ return exporter.rapidXY(x, y); }; Machine.prototype._postPickUpStock = function(exporter, stockPosition, rapidHeight, wcs, safeHeight){ var data = ""; data += exporter.rapidZ(stockPosition.z-wcs.z+safeHeight); data += exporter.moveZ(stockPosition.z-wcs.z); data += exporter.addComment("get stock"); data += exporter.moveZ(stockPosition.z-wcs.z+safeHeight); data += exporter.rapidZ(rapidHeight); return data; }; Machine.prototype._postReleaseStock = function(cellPosition, cell, exporter, rapidHeight, wcs, safeHeight){ var data = ""; data += exporter.rapidZ(cellPosition.z-wcs.z+safeHeight); data += exporter.moveZ(cellPosition.z-wcs.z); data += exporter.addComment(JSON.stringify(cell.indices)); data += exporter.moveZ(cellPosition.z-wcs.z+safeHeight); data += exporter.rapidZ(rapidHeight); return data; }; /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////DEALLOCATE//////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// Machine.prototype.destroy = function(){ this.cell.destroy(); _.each(_.values(this.meshes), function(mesh){ globals.three.sceneRemove(mesh); mesh = null; }); this.meshes = null; this.position = null; this.material = null; }; /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////SHOPBOT/////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// function Shopbot(){ Machine.call(this); } Shopbot.prototype = Object.create(Machine.prototype); Shopbot.prototype._setDefaults = function(){ Machine.prototype._setDefaults.call(this); globals.cam.set("camProcess", "shopbot"); var boundingBox = globals.lattice.calculateBoundingBox(); var yPos = parseFloat((boundingBox.max.y + 3*globals.lattice.yScale()).toFixed(4)); globals.cam.set("stockPosition", {x:0,y:yPos,z:0}); }; Shopbot.prototype._buildMeshes = function(callback){ var meshes = {}; var material = this.material; (new THREE.STLLoader()).load("assets/stls/shopbot/shopbotEndEffector.stl", function(geometry){ geometry.computeBoundingBox(); var unitScale = 0.5/geometry.boundingBox.max.y; geometry.applyMatrix(new THREE.Matrix4().makeScale(unitScale, unitScale, unitScale)); geometry.applyMatrix(new THREE.Matrix4().makeTranslation(0,0,1.13-Math.sqrt(2)/2)); var mesh = new THREE.Mesh(geometry, material); mesh.visible = false; meshes.endEffector = mesh; callback(meshes); }); }; Shopbot.prototype._moveAxis = function(startingPos, target, axis, speed, callback){ if (target == null || target === undefined) { callback(); return; } this._animateObjects([this.meshes.endEffector, this.cell], axis, speed, startingPos, target, callback); }; /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////GOD/////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// function God(){ Machine.call(this); } God.prototype = Object.create(Machine.prototype); God.prototype._setDefaults = function(){ Machine.prototype._setDefaults.call(this); var boundingBox = globals.lattice.calculateBoundingBox(); var zPos = parseFloat((boundingBox.max.z + 5*globals.lattice.zScale()).toFixed(4)); globals.cam.set("stockPosition", {x:0,y:0,z:zPos}); }; God.prototype._buildMeshes = function(callback){ callback({}); }; God.prototype._moveTo = function(x, y, z, speed, wcs, callback){ var startingPos = this.cell.getPosition(); if (z != "" && z != null && z !== undefined){ if (z>startingPos.z){//ignore z up moves this._setPosition(_.values(this.meshes).concat(this.cell), z, "z"); callback(); return; } } else { this._setPosition(_.values(this.meshes).concat(this.cell), x, "x"); this._setPosition(_.values(this.meshes).concat(this.cell), y, "y"); callback(); return; } Machine.prototype._moveTo.call(this, x, y, z, speed, wcs, callback); }; God.prototype._moveAxis = function(startingPos, target, axis, speed, callback){ if (target == null || target === undefined) { callback(); return; } this._animateObjects([this.cell], axis, speed, startingPos, target, callback); }; God.prototype._postPickUpStock = function(exporter, stockPosition, rapidHeight, wcs, safeHeight){ var data = ""; data += exporter.rapidZ(stockPosition.z-wcs.z+safeHeight); data += exporter.moveZ(stockPosition.z-wcs.z); return data; }; God.prototype._postReleaseStock = function(cellPosition, cell, exporter, rapidHeight, wcs, safeHeight){ var data = ""; var cellPosition = cell.getPosition(); data += exporter.rapidXY(cellPosition.x-wcs.x, cellPosition.y-wcs.y); data += exporter.addComment("get stock"); data += exporter.rapidZ(cellPosition.z-wcs.z+safeHeight); data += exporter.moveZ(cellPosition.z-wcs.z); data += exporter.addComment(JSON.stringify(cell.indices)); data += exporter.moveZ(cellPosition.z-wcs.z+safeHeight); return data; };