Select Git revision
LEDNotifier.aps
-
Dean Camera authoredDean Camera authored
Lattice.js 35.04 KiB
/**
* 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: 20,
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) 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) 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(arg1, arg2, arg3, loadingFromFile){//do not clear cells if loading from file (cells array contains important metadata)
if (typeof loadingFromFile == "undefined") loadingFromFile = false;
var cellType = this.get("cellType");
var connectionType = this.get("connectionType");
if (!loadingFromFile && !this.get("shouldPreserveCells")) 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"){
if (!loadingFromFile) 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 (loadingFromFile || 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 = _.clone(cell.indices);
var parts = _.clone(cell.parts);
if (cell.parentOrientation) var parentOrientation = new THREE.Quaternion(cell.parentOrientation._x, cell.parentOrientation._y, cell.parentOrientation._z, cell.parentOrientation._w);
if (cell.parentPosition) var parentPos = cell.parentPosition;
if (cell.direction) var direction = new THREE.Vector3(cell.direction.x, cell.direction.y, cell.direction.z);
if (cell.destroy) cell.destroy();
var newCell = self._makeCellForLatticeType(index, scale, parentPos, parentOrientation, direction);
if (parts) {
//todo make this better
newCell.parts = newCell._initParts();
for (var i=0;i<newCell.parts.length;i++){
if (!parts[i]) {
newCell.parts[i].destroy();
newCell.parts[i] = null;
}
}
}
cells[x][y][z] = newCell;
});
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);
}
}
}
},
saveAsJSON: function(name){
if (!name) name = "lattice";
var data = JSON.stringify(_.omit(this.toJSON(), ["highlighter", "basePlane"]));
var blob = new Blob([data], {type: "text/plain;charset=utf-8"});
saveAs(blob, name + ".json");
},
loadFromJSON: function(data){
this.clearCells();
var data = JSON.parse(data);
var self = this;
_.each(_.keys(data), function(key){
self.set(key, data[key], {silent:true});
});
this.set("shouldPreserveCells", true, {silent:true});
this._updateLatticeType(null, null, null, true);
},
////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////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");
cells[0][0].push(this._makeCellForLatticeType({x:0,y:0,z:cells[0][0].length}, scale, parentCellPos, parentCellOrient, direction));
this.set("numCells", this.get("numCells")+1);
dmaGlobals.three.render();
},
_makeCellForLatticeType: function(index, scale, parentPosition, parentOrientation, direction){
return new DMAFreeFormOctaCell(index, scale, parentPosition, parentOrientation, direction);
},
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;
this.clearCells();
_.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){
return [
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})
];
},
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;
});
}
}
});