/** * Created by aghassaei on 1/16/15. */ Lattice = Backbone.Model.extend({ defaults: { nodes: [], cells: [[[null]]],//3D matrix containing all cells and null, dynamic size cellsMin: {x:0, y:0, z:0},//min position of cells matrix cellsMax: {x:0, y:0, z:0},//max position of cells matrix inverseCells: [[[null]]],//3d matrix containing all inverse cells and null, dynamic size inverseCellsMin: {x:0, y:0, z:0},//min position of inverse cells matrix inverseCellsMax: {x:0, y:0, z:0},//max position of inverse cells matrix numCells: 0, numInvCells: 0, basePlane: null,//plane to build from scale: window.defaultLatticeScale, highlighter: null,//highlights build-able surfaces shouldPreserveCells: true,//preserve cells when changing lattice type //spacing for connectors/joints columnSeparation: 0.0,//todo get rid of this xSeparation: 0.0, ySeparation: 0.0, zSeparation: 0.0, cellMode: "cell",//show cells vs parts inverseMode: false,//show negative space cellType: "octa", connectionType: "face", partType: "triangle" }, //pass in fillGeometry initialize: function(){ //bind events this.listenTo(this, "change:scale", this._scaleDidChange); this.listenTo(this, "change:inverseMode change:cellMode", this._updateForMode); this.listenTo(this, "change:cellType change:connectionType", this._updateLatticeType); }, //////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////ADD/REMOVE CELLS///////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// addCellsInRange: function(range){//add a block of cells (extrude) var scale = this.get("scale"); var cells = this.get("cells"); this._checkForMatrixExpansion(cells, range.max, range.min, "cellsMax", "cellsMin"); var cellsMin = this.get("cellsMin"); var relativeMin = this._subtract(range.min, cellsMin); var relativeMax = this._subtract(range.max, this.get("cellsMin")); for (var x=relativeMin.x;x<=relativeMax.x;x++){ for (var y=relativeMin.y;y<=relativeMax.y;y++){ for (var z=relativeMin.z;z<=relativeMax.z;z++){ if (!cells[x][y][z]) { cells[x][y][z] = this._makeCellForLatticeType(this._add({x:x, y:y, z:z}, cellsMin), scale); this.set("numCells", this.get("numCells")+1); } else console.warn("already a cell there"); } } } dmaGlobals.three.render(); }, addCellAtIndex: function(indices){ var scale = this.get("scale"); var cells = this.get("cells"); this._checkForMatrixExpansion(cells, indices, indices, "cellsMax", "cellsMin"); var index = this._subtract(indices, this.get("cellsMin")); if (!cells[index.x][index.y][index.z]) { cells[index.x][index.y][index.z] = this._makeCellForLatticeType(indices, scale); this.set("numCells", this.get("numCells")+1); dmaGlobals.three.render(); } else console.warn("already a cell there"); }, _addInverseCellsForIndex: function(index){ var inverseIndicesToAdd = this._inverseIndicesToAdd(_.clone(index)); var invCells = this.get("inverseCells"); var scale = this.get("scale"); var self = this; _.each(inverseIndicesToAdd, function(invIndex){ self._checkForMatrixExpansion(invCells, invIndex, invIndex, "inverseCellsMax", "inverseCellsMin"); var indexRel = self._subtract(invIndex, self.get("inverseCellsMin")); if (!invCells[indexRel.x][indexRel.y][indexRel.z]) { invCells[indexRel.x][indexRel.y][indexRel.z] = self._makeInvCellForLatticeType(invIndex, scale); self.set("numInvCells", self.get("numInvCells")+1); } }); }, _indexForPosition: function(absPosition){ var position = {}; var scale = this.get("scale"); position.x = Math.floor(absPosition.x/this.xScale(scale)); position.y = Math.floor(absPosition.y/this.yScale(scale)); position.z = Math.floor(absPosition.z/this.zScale(scale)); return position; }, _positionForIndex: function(index){ var scale = this.get("scale"); var position = _.clone(index); position.x = (position.x+0.5)*this.xScale(scale); position.y = (position.y+0.5)*this.yScale(scale); position.z = (position.z+0.5)*this.zScale(scale); return position; }, // removeCellAtIndex: function(indices){ // // var index = this._subtract(indices, this.get("cellsMin")); // var cells = this.get("cells"); // if (index.x<cells.length && index.y<cells[0].length && index.z<cells[0][0].length){ // this.removeCell(cells[index.x][index.y][index.z]); // } // }, removeCell: function(cell){ if (!cell) return; var index = this._subtract(cell.indices, this.get("cellsMin")); var cells = this.get("cells"); cell.destroy(); cells[index.x][index.y][index.z] = null; //todo shrink cells matrix if needed this.set("numCells", this.get("numCells")-1); dmaGlobals.three.render(); }, //todo send clear all to three anddestroy without sceneRemove to cell clearCells: function(){ this._iterCells(this.get("cells"), function(cell){ if (cell) cell.destroy(); }); this.set("cells", [[[null]]]); this._clearInverseCells(); this.set("cellsMax", {x:0, y:0, z:0}); this.set("cellsMin", {x:0, y:0, z:0}); this.set("nodes", []); this.set("numCells", 0); if (this.get("basePlane")) this.get("basePlane").set("zIndex", 0); dmaGlobals.three.render(); }, _clearInverseCells: function(){ this._iterCells(this.get("inverseCells"), function(cell){ if (cell) cell.destroy(); }); this.set("inverseCells", [[[null]]]); this.set("inverseCellsMin", {x:0, y:0, z:0}); this.set("inverseCellsMax", {x:0, y:0, z:0}); this.set("numInvCells", 0); }, //////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////FILL GEOMETRY//////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// subtractMesh: function(mesh){ //todo this is specific to octa face var scale = this.get("scale"); var xScale = this.xScale(scale); var yScale = this.yScale(scale); var zScale = this.zScale(scale); var cells = this.get("cells"); var cellsMin = this.get("cellsMin"); var allVertexPos = mesh.geometry.attributes.position.array; var zHeight = 0; for (var x=0;x<cells.length;x++){ for (var y=0;y<cells[0].length;y++){ var firstCell = null; for (var z=0;z<cells[0][0].length;z++){ firstCell = cells[x][y][z]; if (firstCell) break; } if (!firstCell) continue;//nothing in col var origin = this._positionForIndex(firstCell.indices); // firstCell._calcPosition(0, this._add({x:x,y:y,z:z}, cellsMin)); zHeight = this._findIntersectionsInWindow(xScale/2, yScale/2, origin, allVertexPos) || zHeight; zHeight = Math.floor(zHeight/zScale); for (var z=0;z<zHeight;z++){ var cell = cells[x][y][z]; if (cell) cell.destroy(); cells[x][y][z] = null; } } } dmaGlobals.three.render(); }, _findIntersectionsInWindow: function(windowX, windowY, origin, allVertexPos){ for (var i=0;i<allVertexPos.length;i+=3){ if (allVertexPos[i] > origin.x-windowX && allVertexPos[i] < origin.x+windowX && allVertexPos[i+1] > origin.y-windowY && allVertexPos[i+1] < origin.y+windowY){ return allVertexPos[i+2]; } } return null }, //////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////CELLS ARRAY////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// _checkForMatrixExpansion: function(cells, indicesMax, indicesMin, maxName, minName){ var lastMax = this.get(maxName); var lastMin = this.get(minName); var newMax = this._updateCellsMax(indicesMax, lastMax); var newMin = this._updateCellsMin(indicesMin, lastMin); if (newMax) { this._expandCellsArray(cells, this._subtract(newMax, lastMax), false); this.set(maxName, newMax); } if (newMin) { this._expandCellsArray(cells, this._subtract(lastMin, newMin), true); this.set(minName, newMin); } }, _expandCellsArray: function(cells, expansion, fromFront){ _.each(_.keys(expansion), function(key){ if (expansion[key] == 0) return;//no expansion on this axis var cellsX = cells.length; var cellsY = cells[0].length; var cellsZ = cells[0][0].length; if (key=="x"){ for (var x=0;x<expansion[key];x++){ var newLayer = []; for (var y=0;y<cellsY;y++){ var newCol = []; for (var z=0;z<cellsZ;z++){ newCol.push(null); } newLayer.push(newCol); } if (fromFront) cells.unshift(newLayer); else cells.push(newLayer); } } else if (key=="y"){ for (var x=0;x<cellsX;x++){ for (var y=0;y<expansion[key];y++){ var newCol = []; for (var z=0;z<cellsZ;z++){ newCol.push(null); } if (fromFront) cells[x].unshift(newCol); else cells[x].push(newCol); } } } else if (key=="z"){ for (var x=0;x<cellsX;x++){ for (var y=0;y<cellsY;y++){ for (var z=0;z<expansion[key];z++){ if (fromFront) cells[x][y].unshift(null); else cells[x][y].push(null); } } } } }); }, _updateCellsMin: function(newPosition, currentMin){ var newMin = {}; var hasChanged = false; _.each(_.keys(newPosition), function(key){ if (newPosition[key]<currentMin[key]){ hasChanged = true; newMin[key] = newPosition[key]; } else { newMin[key] = currentMin[key]; } }); if (hasChanged) return newMin; return false; }, _updateCellsMax: function(newPosition, currentMax){ var newMax = {}; var hasChanged = false; _.each(_.keys(newPosition), function(key){ if (newPosition[key]>currentMax[key]){ hasChanged = true; newMax[key] = newPosition[key]; } else { newMax[key] = currentMax[key]; } }); if (hasChanged) return newMax; return false; }, _subtract: function(pos1, pos2){ return {x:pos1.x-pos2.x, y:pos1.y-pos2.y, z:pos1.z-pos2.z}; }, _add: function(pos1, pos2){ return {x:pos1.x+pos2.x, y:pos1.y+pos2.y, z:pos1.z+pos2.z}; }, //////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////EVENTS////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// _updateForMode: function(){ var cellMode = this.get("cellMode"); var inverseMode = this.get("inverseMode"); var scale = this.get("scale"); this._iterCells(this.get("cells"), function(cell){ if (cell) cell.drawForMode(scale, cellMode, inverseMode); }); this._iterCells(this.get("inverseCells"), function(cell){ if (cell) cell.drawForMode(scale, cellMode, inverseMode); }); dmaGlobals.three.render(); }, _scaleDidChange: function(){ var scale = this.get("scale"); this.get("basePlane").updateScale(scale); this.get("highlighter").updateScale(scale); var cellMode = this.get("cellMode"); this._iterCells(this.get("cells"), function(cell){ if (cell) cell.updateForScale(scale, cellMode); }); this._iterCells(this.get("inverseCells"), function(cell){ if (cell) cell.updateForScale(scale, cellMode); }); dmaGlobals.three.render(); }, previewScaleChange: function(scale){ this.get("basePlane").updateScale(scale); }, //////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////CONNECTION TYPE////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// _updateLatticeType: function(){ var cellType = this.get("cellType"); var connectionType = this.get("connectionType"); if (!this.get("shouldPreserveCells") || this.previous("connectionType") == "freeformFace") this.clearCells(); if (this._undo) this._undo(); if (this.get("basePlane")) this.get("basePlane").destroy(); if (this.get("highlighter")) this.get("highlighter").destroy(); if (cellType == "octa"){ if (connectionType == "face"){ _.extend(this, this.OctaFaceLattice); } else if (connectionType == "freeformFace"){ this.clearCells(); _.extend(this, this.OctaFreeFormFaceLattice); } else if (connectionType == "edge"){ _.extend(this, this.OctaFaceLattice); _.extend(this, this.OctaEdgeLattice); } else if (connectionType == "edgeRot"){ _.extend(this, this.OctaRotEdgeLattice); } else if (connectionType == "vertex"){ _.extend(this, this.OctaVertexLattice); } } else if (cellType == "cube"){ _.extend(this, this.CubeLattice); } this._initLatticeType(); if (this.get("shouldPreserveCells")){ var self = this; var scale = this.get("scale"); var cells = this.get("cells"); this._clearInverseCells(); this._loopCells(cells, function(cell, x, y, z){ if (!cell) return; var index = cell.indices; cell.destroy(); cells[x][y][z] = self._makeCellForLatticeType(index, scale) }); dmaGlobals.three.render(); } }, //////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////UTILS/////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// _iterCells: function(cells, callback){ _.each(cells, function(cellLayer){ _.each(cellLayer, function(cellColumn){ _.each(cellColumn, function(cell){ callback(cell, cellColumn, cellLayer); }); }); }); }, _loopCells: function(cells, callback){ for (var x=0;x<cells.length;x++){ for (var y=0;y<cells[0].length;y++){ for (var z=0;z<cells[0][0].length;z++){ callback(cells[x][y][z], x, y, z); } } } }, //////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////FACE CONN OCTA LATTICE//////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////// OctaFaceLattice: { _initLatticeType: function(){ //bind events this.set("columnSeparation", 0.0); this.listenTo(this, "change:columnSeparation", this._changeColSeparation); this.set("basePlane", new OctaBasePlane({scale:this.get("scale")})); this.set("highlighter", new OctaFaceHighlighter({scale:this.get("scale")})); }, _changeColSeparation: function(){ var colSep = this.get("columnSeparation"); var scale = this.get("scale"); var cellMode = this.get("cellMode"); this.get("basePlane").updateColSeparation(colSep); this._iterCells(this.get("cells"), function(cell){ if (cell) cell.updateForScale(scale, cellMode); }); dmaGlobals.three.render(); }, getIndexForPosition: function(absPosition){ var scale = this.get("scale"); var yIndex = Math.floor(absPosition.y/this.yScale(scale)); if (yIndex%2 != 0) absPosition.x += this.xScale(scale)/2; var index = this._indexForPosition(absPosition); if (index.z%2 == 1) index.y += 1; return index; }, getPositionForIndex: function(index){ var scale = this.get("scale"); var position = _.clone(index); var xScale = this.xScale(scale); position.x = (position.x+1/2)*xScale; position.y = position.y*this.yScale(scale)+scale/Math.sqrt(3)/2; position.z = (position.z+0.5)*this.zScale(scale); if ((index.y%2) != 0) position.x -= this.xScale(scale)/2; return position; }, getInvCellPositionForIndex: function(index){ var scale = this.get("scale"); var position = _.clone(index); var oddZ = position.z%2 != 0; var upPoint = (position.z%4 == 0 || Math.abs(position.z%4) == 3); position.z = Math.floor(position.z/2); if (!upPoint){ position.x = (position.x)*this.xScale(scale); position.y = position.y*this.yScale(scale); } else { position.x = (position.x+0.5)*this.xScale(scale); position.y = (position.y)*this.yScale(scale)-scale/Math.sqrt(3)/2; } if (oddZ){ position.z = (position.z + 1)*this.zScale(scale); } else { position.z = (position.z)*this.zScale(scale); } // if (Math.abs(index.z%4) == 1 || Math.abs(index.z%4) == 2) position.z += this.zScale(scale); if ((index.y%2) != 0) { if (!upPoint){ position.x += this.xScale(scale)/2; } else { position.x -= this.xScale(scale)/2; } } return position; }, xScale: function(scale){ if (!scale) scale = this.get("scale"); var colSep = this.get("columnSeparation"); return scale*(1+2*colSep); }, yScale: function(scale){ return this.xScale(scale)/2*Math.sqrt(3); }, zScale: function(scale){ if (!scale) scale = this.get("scale"); return 2*scale/Math.sqrt(6); }, _makeCellForLatticeType: function(indices, scale){ this._addInverseCellsForIndex(indices); return new DMAFaceOctaCell(indices, scale); }, _makeInvCellForLatticeType: function(indices, scale){ return new DMATetraFaceCell(indices, scale); }, _inverseIndicesToAdd: function(index){ var oddZ = index.z%2 != 0; index = _.clone(index); index.z*=2; var z0 = 0; if (oddZ) z0 = 1; if (this.get("connectionType") == "edge") z0 = 0; var z1 = Math.abs(z0-1); var inverseIndicesToAdd; if (index.y%2 == 0){ inverseIndicesToAdd = [ this._add(index, {x:0,y:0,z:z0}), this._add(index, {x:0,y:1,z:z0}), this._add(index, {x:1,y:1,z:z0}), this._add(index, {x:0,y:0,z:z1}), this._add(index, {x:0,y:1,z:z1}), this._add(index, {x:1,y:0,z:z1}) ]; } else { inverseIndicesToAdd = [ this._add(index, {x:0,y:0,z:z0}), this._add(index, {x:-1,y:1,z:z0}), this._add(index, {x:0,y:1,z:z0}), this._add(index, {x:-1,y:0,z:z1}), this._add(index, {x:0,y:1,z:z1}), this._add(index, {x:0,y:0,z:z1}) ]; } return inverseIndicesToAdd; }, _undo: function(){//remove all the mixins, this will help with debugging later this.stopListening(this, "change:columnSeparation"); var self = this; _.each(_.keys(this.OctaFaceLattice), function(key){ self[key] = null; }); } }, //////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////FACE CONN OCTA FREEFORM//////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////// OctaFreeFormFaceLattice: { _initLatticeType: function(){ //bind events this.set("basePlane", new OctaBasePlane({scale:this.get("scale")})); this.set("highlighter", new OctaFreeFormHighlighter({scale:this.get("scale")})); }, addFreeFormCell: function(parentCellPos, parentCellOrient, direction){ var scale = this.get("scale"); var cells = this.get("cells"); // console.log(parentCellPos); // console.log(parentCellOrient); // console.log(direction); cells[0][0].push(new DMAFreeFormOctaCell({x:0,y:0,z:cells[0][0].length}, scale, parentCellPos, parentCellOrient, direction)); this.set("numCells", this.get("numCells")+1); dmaGlobals.three.render(); }, getIndexForPosition: function(absPosition){//only used by baseplane var scale = this.get("scale"); var yIndex = Math.floor(absPosition.y/this.yScale(scale)); if (yIndex%2 != 0) absPosition.x += this.xScale(scale)/2; var index = this._indexForPosition(absPosition); if (index.z%2 == 1) index.y += 1; return index; }, getPositionForIndex: function(index){//only used by baseplane var scale = this.get("scale"); var position = _.clone(index); var xScale = this.xScale(scale); position.x = (position.x+1/2)*xScale; position.y = position.y*this.yScale(scale)+scale/Math.sqrt(3)/2; position.z = (position.z+0.5)*this.zScale(scale); if ((index.y%2) != 0) position.x -= this.xScale(scale)/2; return position; }, xScale: function(scale){ if (!scale) scale = this.get("scale"); var colSep = this.get("columnSeparation"); return scale*(1+2*colSep); }, yScale: function(scale){ return this.xScale(scale)/2*Math.sqrt(3); }, zScale: function(scale){ if (!scale) scale = this.get("scale"); return 2*scale/Math.sqrt(6); }, _undo: function(){//remove all the mixins, this will help with debugging later var self = this; _.each(_.keys(this.OctaFreeFormFaceLattice), function(key){ self[key] = null; }); } }, //////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////EDGE CONN OCTA LATTICE//////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////// OctaEdgeLattice: { _initLatticeType: function(){ //bind events this.set("columnSeparation", 0.0); // this.listenTo(this, "change:columnSeparation", this._changeColSeparation); this.set("basePlane", new OctaBasePlane({scale:this.get("scale")})); this.set("highlighter", new OctaEdgeHighlighter({scale:this.get("scale")})); }, getIndexForPosition: function(absPosition){ //todo finish this var scale = this.get("scale"); var yIndex = Math.floor(absPosition.y/this.yScale(scale)); if (yIndex%2 != 0) absPosition.x += this.xScale(scale)/2; var yScale = scale/Math.sqrt(3); var index = this._indexForPosition(absPosition); if (index.z%3 == 1) { absPosition.x -= this.xScale(scale)/2; absPosition.y += yScale/2; } else if (index.z%3 == 2){ absPosition.y += yScale; } var index = this._indexForPosition(absPosition); return index; }, getPositionForIndex: function(index){ var scale = this.get("scale"); var position = _.clone(index); var xScale = this.xScale(scale); var yScale = scale/Math.sqrt(3); position.x = (position.x+1/2)*xScale; position.y = position.y*this.yScale(scale)+yScale/2; position.z = (position.z+0.5)*this.zScale(scale); if (index.y%2 != 0) position.x -= this.xScale(scale)/2; if (index.z%3 == 1) { position.x += this.xScale(scale)/2; position.y -= yScale/2; } else if (index.z%3 == 2){ position.y -= yScale; } return position; }, _makeCellForLatticeType: function(indices, scale){ this._addInverseCellsForIndex(indices); return new DMAEdgeOctaCell(indices, scale); }, _makeInvCellForLatticeType: function(indices, scale){ return new DMATetraEdgeCell(indices, scale); }, getInvCellPositionForIndex: function(index){ var scale = this.get("scale"); var position = _.clone(index); var oddZ = position.z%2 != 0; position.z = Math.floor(position.z/2); var yScale = scale/Math.sqrt(3); if (oddZ){ position.x = (position.x)*this.xScale(scale); position.y = position.y*this.yScale(scale); } else { position.x = (position.x+0.5)*this.xScale(scale); position.y = (position.y)*this.yScale(scale)-yScale/2; } if (oddZ){ position.z = (position.z + 1)*this.zScale(scale); } else { position.z = (position.z)*this.zScale(scale); } if ((index.y%2) != 0) { if (oddZ){ position.x += this.xScale(scale)/2; } else { position.x -= this.xScale(scale)/2; } } var zLayer = Math.floor(index.z/2)%3; if (zLayer == 1) { position.x += this.xScale(scale)/2; position.y -= yScale/2; } else if (zLayer == 2){ position.y -= yScale; } return position; }, _undo: function(){//remove all the mixins, this will help with debugging later var self = this; _.each(_.keys(this.OctaEdgeLattice), function(key){ self[key] = null; }); _.each(_.keys(this.OctaFaceLattice), function(key){ self[key] = null; }); } }, OctaRotEdgeLattice: { _initLatticeType: function(){ //bind events this.set("basePlane", new SquareBasePlane({scale:this.get("scale")})); this.set("highlighter", new OctaVertexHighlighter({scale:this.get("scale")})); }, getIndexForPosition: function(absPosition){ return this._indexForPosition(absPosition); }, getPositionForIndex: function(index){ return this._positionForIndex(index); }, _makeCellForLatticeType: function(indices, scale){ // this._addInverseCellsForIndex(indices); return new DMAVertexOctaCell(indices, scale); }, xScale: function(scale){ if (!scale) scale = this.get("scale"); return scale*Math.sqrt(2); }, yScale: function(scale){ return this.xScale(scale); }, zScale: function(scale){ return this.xScale(scale); }, _undo: function(){//remove all the mixins, this will help with debugging later var self = this; _.each(_.keys(this.OctaRotEdgeLattice), function(key){ self[key] = null; }); } }, //////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////VERTEX CONN OCTA LATTICE////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////// OctaVertexLattice: { _initLatticeType: function(){ //bind events this.set("basePlane", new SquareBasePlane({scale:this.get("scale")})); this.set("highlighter", new OctaVertexHighlighter({scale:this.get("scale")})); }, getIndexForPosition: function(absPosition){ return this._indexForPosition(absPosition); }, getPositionForIndex: function(index){ return this._positionForIndex(index); }, getInvCellPositionForIndex: function(index){ var position = this._positionForIndex(index); var scale = this.get("scale"); position.x -= this.xScale(scale)/2; position.y -= this.yScale(scale)/2; position.z -= this.zScale(scale)/2; return position; }, _inverseIndicesToAdd: function(index){ var inverseIndicesToAdd = [ this._add(index, {x:0,y:0,z:0}), this._add(index, {x:0,y:1,z:0}), this._add(index, {x:1,y:0,z:0}), this._add(index, {x:1,y:1,z:0}), this._add(index, {x:0,y:0,z:1}), this._add(index, {x:0,y:1,z:1}), this._add(index, {x:1,y:0,z:1}), this._add(index, {x:1,y:1,z:1}) ]; return inverseIndicesToAdd; }, xScale: function(scale){ if (!scale) scale = this.get("scale"); return scale*Math.sqrt(2); }, yScale: function(scale){ return this.xScale(scale); }, zScale: function(scale){ return this.xScale(scale); }, _makeCellForLatticeType: function(indices, scale){ this._addInverseCellsForIndex(indices); return new DMAVertexOctaCell(indices, scale); }, _makeInvCellForLatticeType: function(indices, scale){ return new DMATruncCubeCell(indices, scale); }, _undo: function(){//remove all the mixins, this will help with debugging later var self = this; _.each(_.keys(this.OctaVertexLattice), function(key){ self[key] = null; }); } }, //////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////CUBE LATTICE////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////// CubeLattice: { _initLatticeType: function(){ //bind events this.set("basePlane", new SquareBasePlane({scale:this.get("scale")})); this.set("highlighter", new CubeHighlighter({scale:this.get("scale")})); }, getIndexForPosition: function(absPosition){ return this._indexForPosition(absPosition); }, getPositionForIndex: function(index){ return this._positionForIndex(index); }, xScale: function(scale){ if (!scale) scale = this.get("scale"); return scale; }, yScale: function(scale){ return this.xScale(scale); }, zScale: function(scale){ return this.xScale(scale); }, _makeCellForLatticeType: function(indices, scale){ return new DMACubeCell(indices, scale); }, _undo: function(){//remove all the mixins, this will help with debugging later var self = this; _.each(_.keys(this.CubeLattice), function(key){ self[key] = null; }); } } });