diff --git a/js/cam/assemblers/StockComponent.js b/js/cam/assemblers/StockComponent.js index 208f37a54e6686f9e14005a8575e4efae4485b30..a757424fca53699feb6d5bbdf203bb885b265964 100644 --- a/js/cam/assemblers/StockComponent.js +++ b/js/cam/assemblers/StockComponent.js @@ -27,7 +27,7 @@ define(['underscore', 'cam', 'three', 'component', 'lattice', 'threeModel'], StockComponent.prototype._makeCell = function(json, callback){ - lattice.makeCellForLatticeType(json, callback); + lattice.makeCellWithJSON(json, callback); }; StockComponent.prototype.getPosition = function(){ diff --git a/js/cells/DMACell.js b/js/cells/DMACell.js index d42e337de820235672b1c6496a12d9f22a9936a1..bc8c1be1c77426964d552b74c42ea1677020faf7 100644 --- a/js/cells/DMACell.js +++ b/js/cells/DMACell.js @@ -20,14 +20,24 @@ define(['underscore', 'three', 'threeModel', 'lattice', 'appState', 'globals', ' this.addChildren(this._buildMesh(), this.object3D);//build cell meshes if (this.superCell) this.superCell.addChildren(this.object3D);//add as child of supercell + if (!this.sparseCells) this.setMode(); + } + + DMACell.prototype.addToScene = function(superCell){ + if (!this.sparseCells) lattice.getUItarget().addHighlightableCell(this.object3D.children[0]);//add mesh as highlightable object, only for lowest level of hierarchy + if (!superCell || superCell === undefined) three.sceneAdd(this.object3D);//add object3d as child of scene if top level of hierarchy + if (this.sparseCells){ + var self = this; + this._loopCells(function(cell){ + cell.addToScene(self); + }); + } + }; - if (this.getAbsoluteIndex()){ - if (!this.cells) lattice.getUItarget().addHighlightableCell(this.object3D.children[0]);//add mesh as highlightable object, only for lowest level of hierarchy - if (!superCell || superCell === undefined) three.sceneAdd(this.object3D);//add object3d as child of scene if top level of hierarchy - } else this.hide();//stock cell - if (!this.cells) this.setMode(); - } + //add stock cell{ +// this.hide();//stock cell +// } @@ -37,7 +47,7 @@ define(['underscore', 'three', 'threeModel', 'lattice', 'appState', 'globals', ' DMACell.prototype._buildObject3D = function(){ var object3D = this._translateCell(this._rotateCell(new THREE.Object3D())); - if (!this.cells) object3D.myParent = this;//reference to get mouse raycasting back, only for lowest level of hierarchy + if (!this.sparseCells) object3D.myParent = this;//reference to get mouse raycasting back, only for lowest level of hierarchy object3D.name = "object3D"; return object3D; }; @@ -107,6 +117,24 @@ define(['underscore', 'three', 'threeModel', 'lattice', 'appState', 'globals', ' return superCellIndex.add(this.superCell.applyRotation(this.getIndex()).round()); }; + DMACell.prototype.getDimensions = function(){ + return new THREE.Vector3(1,1,1); + }; + + DMACell.prototype.getAbsoluteDimensions = function(){ + return this.getDimensions(); + }; + + DMACell.prototype.getBounds = function(){//todo need to accound for origin eventually + var index = this.getIndex(); + return {min: index, max: index}; + }; + + DMACell.prototype.getAbsoluteBounds = function(){ + var index = this.getAbsoluteIndex(); + return {min: index, max: index}; + }; + DMACell.prototype.getLatticeIndex = function(){ var parent = lattice.getUItarget(); return this.getAbsoluteIndex().sub(parent.get("cellsMin")); @@ -162,7 +190,7 @@ define(['underscore', 'three', 'threeModel', 'lattice', 'appState', 'globals', ' else threeMaterial = this.getMaterial(true); if (!threeMaterial) return;//no material object found - if (this.cells){ + if (this.sparseCells){ this._loopCells(function(cell){ if (cell) cell.setDeleteMode(state); }); @@ -296,7 +324,7 @@ define(['underscore', 'three', 'threeModel', 'lattice', 'appState', 'globals', ' setVisiblity(); break; case "part": - if (!this.cells && !this.parts) { + if (!this.sparseCells && !this.parts) { this._initParts(function(parts){ self.parts = parts; setVisiblity(); @@ -304,7 +332,7 @@ define(['underscore', 'three', 'threeModel', 'lattice', 'appState', 'globals', ' } else setVisiblity(); break; case "beam": - if (!this.cells && !this.beams) this.beams = this._initBeams(function(){ + if (!this.sparseCells && !this.beams) this.beams = this._initBeams(function(){ if (!this.nodes) this.nodes = self._initNodes(function(){ setVisiblity(); }); @@ -364,13 +392,21 @@ define(['underscore', 'three', 'threeModel', 'lattice', 'appState', 'globals', ' }); return geometry; } - if (!this.cells) return geometry; + if (!this.sparseCells) return geometry; this._loopCells(function(cell){ if (cell) geometry = geometry.concat(cell.getVisibleGeometry()); }); return geometry; }; + DMACell.prototype.getCells = function(){ + return null; + }; + + DMACell.prototype.getSparseCells = function(){ + return null; + }; + @@ -460,11 +496,12 @@ define(['underscore', 'three', 'threeModel', 'lattice', 'appState', 'globals', ' //destroy DMACell.prototype.destroy = function(){//todo remove reference from lattice.cells + console.log("destroy"); this.destroyParts(); if (this.object3D) { if (this.superCell) this.superCell.removeChildren(this.object3D); else if (this.index) three.sceneRemove(this.object3D); - if (!this.cells) lattice.getUItarget().removeHighlightableCell(this.object3D.children[0]);//remove mesh as highlightable object + if (!this.sparseCells) lattice.getUItarget().removeHighlightableCell(this.object3D.children[0]);//remove mesh as highlightable object this.object3D.myParent = null; // this.object3D.dispose(); // geometry.dispose(); @@ -492,7 +529,7 @@ define(['underscore', 'three', 'threeModel', 'lattice', 'appState', 'globals', ' materialID: this.getMaterialID() }; // if (this.material.sparseCells) return data;//material definition in material composites -// if (this.cells) data.cells = this.cells; +// if (this.sparseCells) data.cells = this.sparseCells; return data; }; diff --git a/js/cells/supercells/CompositeCell.js b/js/cells/supercells/CompositeCell.js index 408b55a0ac46a6c825e98e5be85275e9c861e7b7..f1f59c529184e834170b3e84e2dd6f143677f065 100644 --- a/js/cells/supercells/CompositeCell.js +++ b/js/cells/supercells/CompositeCell.js @@ -34,5 +34,9 @@ define(['underscore', 'three', 'threeModel', 'lattice', 'appState', 'superCell', return wireframe; }; + CompositeCell.prototype.getDimensions = function(){//override in gik super cell + return this.getMaterial().getDimensions(); + }; + return CompositeCell; }); \ No newline at end of file diff --git a/js/cells/supercells/DMASuperCell.js b/js/cells/supercells/DMASuperCell.js index 34112072a89128eb1cefe897789cbb3dbf8f33da..388d98c12579986ef592d70bb1d77c44afa786ec 100644 --- a/js/cells/supercells/DMASuperCell.js +++ b/js/cells/supercells/DMASuperCell.js @@ -16,8 +16,8 @@ define(['underscore', 'three', 'threeModel', 'lattice', 'appState', 'cell', 'mat var range; var material = this.getMaterial(); if (material.cellsMax) range = (new THREE.Vector3(1,1,1)).add(material.cellsMax).sub(material.cellsMin); - else range = this._getSuperCellRange(); - this.cells = this._makeChildCells(range, material); + else range = this.getDimensions(); + this.sparseCells = this._makeChildCells(range, material); DMACell.prototype.setMode.call(this, null, function(){ three.conditionalRender(); @@ -25,8 +25,38 @@ define(['underscore', 'three', 'threeModel', 'lattice', 'appState', 'cell', 'mat } DMASuperCell.prototype = Object.create(DMACell.prototype); - DMASuperCell.prototype._getSuperCellRange = function(){//override in gik super cell - return appState.get("superCellRange").clone(); + DMASuperCell.prototype.getOrigin = function(){ + return new THREE.Vector3(0,0,0); + }; + + DMASuperCell.prototype.getAbsoluteOrigin = function(){ + if (!this.superCell) return this.applyRotation(this.getOrigin()); + return this.applyAbsoluteRotation(this.getOrigin()).round(); + }; + + DMASuperCell.prototype.getAbsoluteDimensions = function(){ + var rotationPt = this.getOrigin().add(new THREE.Vector3(1,1,1)); + var dims = this.applyAbsoluteRotation(this.getDimensions().sub(rotationPt)).add(rotationPt); + _.each(dims, function(val, key){ + if (val < 0) dims[key] = -val; + }); + return dims.round(); + }; + + DMASuperCell.prototype.getBounds = function(){ + var origin = this.getOrigin(); + var index = this.getIndex(); + var min = index.clone().sub(origin); + var max = index.add(this.getDimensions()).sub(origin).sub(new THREE.Vector3(1,1,1)); + return {min: min, max: max}; + }; + + DMASuperCell.prototype.getAbsoluteBounds = function(){ + var origin = this.getAbsoluteOrigin(); + var index = this.getAbsoluteIndex(); + var min = index.clone().sub(origin); + var max = index.add(this.getAbsoluteDimensions()).sub(origin); + return {min: min, max: max}; }; DMASuperCell.prototype._makeChildCells = function(range, material){ @@ -116,16 +146,54 @@ define(['underscore', 'three', 'threeModel', 'lattice', 'appState', 'cell', 'mat }) }; + DMASuperCell.prototype.getCells = function(){ + return this._getCells(true); + }; + + DMASuperCell.prototype.getSparseCells = function(){ + return this._getCells(false); + }; + DMASuperCell.prototype._getCells = function(recursive){ + var size = this.getAbsoluteDimensions(); + var bounds = this.getAbsoluteBounds(); + console.log(size); + //create array of nulls + var cells = []; + for (var x=0;x<size.x;x++){ + cells.push([]); + for (var y=0;y<size.y;y++){ + cells[x].push([]); + for (var z=0;z<size.z;z++){ + cells[x][y].push(null); + } + } + } + + var overlap = false; + this._loopCells(function(cell, x, y, z){ + var overlappingCells = null; + if (recursive){ + overlappingCells = cell.addToDenseArray(cells, bounds.min); + } else { + overlappingCells = DMACell.prototype.addToDenseArray.call(cell, cells, bounds.min); + } + if (overlappingCells) overlap = true; + }); + if (overlap) { + console.warn("overlap detected"); + return [[[null]]]; + } + return cells; + }; - //parse DMASuperCell.prototype.addToDenseArray = function(cellsArray, min, forCAM){ if (forCAM && this._isBottomLayer()) return DMACell.prototype.addToDenseArray.call(this, cellsArray, min);//this gives back the bottom layer cell for assembly, not necessarily the lattice pitch var overlap = []; this._loopCells(function(cell){ - var overlappingCells = cell.addToDenseArray(cellsArray, min, forCAM) + var overlappingCells = cell.addToDenseArray(cellsArray, min, forCAM); if (overlappingCells) overlap = overlap.concat(overlappingCells); }); if (overlap.length>0) return overlap; @@ -139,7 +207,7 @@ define(['underscore', 'three', 'threeModel', 'lattice', 'appState', 'cell', 'mat DMASuperCell.prototype._loopCells = function(callback){ - var cells = this.cells; + var cells = this.sparseCells; if (!cells || cells === undefined) return; for (var x=0;x<cells.length;x++){ for (var y=0;y<cells[0].length;y++){ @@ -156,7 +224,7 @@ define(['underscore', 'three', 'threeModel', 'lattice', 'appState', 'cell', 'mat cell = null; }); DMACell.prototype.destroy.call(this); - this.cells = null; + this.sparseCells = null; }; DMASuperCell.prototype.destroyParts = function(){ diff --git a/js/cells/supercells/GIKSuperCell.js b/js/cells/supercells/GIKSuperCell.js index 45705e9f64d4a803cc377cd1a227ad5d512e3206..0cd8f4fb58b43c4db100fa9afcfba652bad39e1c 100644 --- a/js/cells/supercells/GIKSuperCell.js +++ b/js/cells/supercells/GIKSuperCell.js @@ -22,7 +22,7 @@ define(['underscore', 'three', 'threeModel', 'lattice', 'appState', 'superCell', } GIKSuperCell.prototype = Object.create(DMASuperCell.prototype); - GIKSuperCell.prototype._getSuperCellRange = function(){ + GIKSuperCell.prototype.getDimensions = function(){ if (this.length) return new THREE.Vector3(this.length, 1, 1); console.warn("no length property for gik super cell"); return null; @@ -95,7 +95,7 @@ define(['underscore', 'three', 'threeModel', 'lattice', 'appState', 'superCell', var sequence = ""; for (var i=0;i<this.length;i++){ if (i>0) sequence += "-";//linker - var seq = this.cells[i][0][0].getSequence(); + var seq = this.sparseCells[i][0][0].getSequence(); if (i==0) seq = seq.split('').reverse().join(''); sequence += seq; } diff --git a/js/lattice/Lattice.js b/js/lattice/Lattice.js index af00b43276e96daac2a090a35bb56df882d6819b..75079cf6107f92d3f60e07682798823383b5a629 100644 --- a/js/lattice/Lattice.js +++ b/js/lattice/Lattice.js @@ -14,8 +14,8 @@ define(['underscore', 'backbone', 'appState', 'globals', 'plist', 'materialsPlis scale: 1.0, cellType: "cube", - connectionType: "gik", - applicationType: "willGik", + connectionType: "face", + applicationType: "default", partType: null, aspectRatio: null, @@ -213,8 +213,7 @@ define(['underscore', 'backbone', 'appState', 'globals', 'plist', 'materialsPlis if (globals.basePlane) globals.basePlane.destroy(); if (globals.highlighter) globals.highlighter.destroy(); - console.log(cells); - if (cellsMax && cellsMin) this._checkForMatrixExpansion(cells, cellsMax, cellsMin); + if (cellsMax && cellsMin) this._checkForMatrixExpansion(cellsMax, cellsMin); var self = this; require([subclass], function(subclassObject){ @@ -389,7 +388,7 @@ define(['underscore', 'backbone', 'appState', 'globals', 'plist', 'materialsPlis //re-init cell; var json = cell.toJSON(); json.index = cell.getIndex(); - self.makeCellForLatticeType(json, function(newCell){ + self.makeCellWithJSON(json, function(newCell){ self.sparseCells[x][y][z] = newCell; cell.destroy(); }); diff --git a/js/lattice/LatticeBase.js b/js/lattice/LatticeBase.js index a94d420d628bf51e0a73e95443220256405e8718..ad090915b5f001b19cbb802d19e7ec6d4f7fa058 100644 --- a/js/lattice/LatticeBase.js +++ b/js/lattice/LatticeBase.js @@ -68,7 +68,7 @@ define(['underscore', 'backbone', 'appState', 'globals', 'plist', 'three', 'thre var cellsMax = this.get("cellsMax"); var cellsMin = this.get("cellsMin"); - if (cellsMax && cellsMin) this._checkForMatrixExpansion(cells, cellsMax, cellsMin); + if (cellsMax && cellsMin) this._checkForMatrixExpansion(cellsMax, cellsMin); var self = this; require([subclass], function(subclassObject){ @@ -96,7 +96,7 @@ define(['underscore', 'backbone', 'appState', 'globals', 'plist', 'three', 'thre //add/remove cells - makeCellForLatticeType: function(json, callback){ + makeCellWithJSON: function(json, callback){ var subclassFile = this.getCellSubclassFile(); require(['materials'], function(materials){ var materialID = json.materialID || appState.get("materialType"); @@ -110,21 +110,21 @@ define(['underscore', 'backbone', 'appState', 'globals', 'plist', 'three', 'thre addCellsInRange: function(range){//add a block of cells (extrude) - this._checkForMatrixExpansion(this.sparseCells, range.max, range.min); + this._checkForMatrixExpansion(range.max, range.min); var cellsMin = this.get("cellsMin"); var relativeMin = (new THREE.Vector3()).subVectors(range.min, cellsMin); var relativeMax = (new THREE.Vector3()).subVectors(range.max, this.get("cellsMin")); - var materialName = appState.get("materialType"); + var materialID = appState.get("materialType"); 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 (!this.sparseCells[x][y][z]) { var self = this; - this.makeCellForLatticeType({ + this.makeCellWithJSON({ index: (new THREE.Vector3(x, y, z)).add(cellsMin), - materialName: materialName + materialID: materialID }, function(cell){ self.sparseCells[x][y][z] = cell; self.set("numCells", self.get("numCells")+1); @@ -136,20 +136,67 @@ define(['underscore', 'backbone', 'appState', 'globals', 'plist', 'three', 'thre three.render(); }, - addCellAtIndex: function(index, noRender, noCheck){//no render no check from fill/load + addCellAtIndex: function(index){ + var self = this; + this.makeCellWithJSON({index: index, materialID:appState.get("materialType")}, function(cell){ + var bounds = cell.getAbsoluteBounds(); + self._checkForMatrixExpansion(bounds.max, bounds.min); + + var relIndex = new THREE.Vector3().subVectors(index, self.get("cellsMin")); + var flattenedCells = cell.getCells(); + if (self.cells[relIndex.x][relIndex.y][relIndex.z] !== null || + (flattenedCells !== null && self._checkForCellOverlap(flattenedCells, relIndex))){ + console.warn("overlap detected, addCellAtIndex operation cancelled"); + cell.destroy(); + return; + } + + if (flattenedCells === null) flattenedCells = [[[cell]]]; + self.sparseCells[relIndex.x][relIndex.y][relIndex.z] = cell; + self._loopCells(flattenedCells, function(flatCell, x, y, z){ + self.cells[relIndex.x+x][relIndex.y+y][relIndex.z+z] = flatCell; + }); + console.log(self.cells); + console.log(self.sparseCells); + + cell.addToScene(); + }); + +// this._checkForMatrixExpansion(index, index); +// +// var relIndex = (new THREE.Vector3()).subVectors(index, this.get("cellsMin") || index); +// if (!noRender || noRender === undefined) three.setRenderFlag(); +// this._addCellWithJSON({index: index, materialID:appState.get("materialType")}); + }, + - if (!noCheck || noCheck === undefined) this._checkForMatrixExpansion(this.sparseCells, index, index); +// _booleanAddCells: function(cellsJSON, offset){ +// if (offset === undefined) offset = new THREE.Vector3(0,0,0); +// if (this._checkForCellOverlap(cellsJSON, offset)){ +// console.warn("collision detected, operation cancelled"); +// return; +// } +// }, - var relIndex = (new THREE.Vector3()).subVectors(index, this.get("cellsMin") || index); - if (!noRender || noRender === undefined) three.setRenderFlag(); - this._addCellWithJSON({index: index, materialName:appState.get("materialType")}, relIndex); + _checkForCellOverlap: function(cells, offset){ + var existingCells = this.cells; + var overlapDetected = false; + var self = this; + this._loopCells(cells, function(cell, x, y, z){ + if (overlapDetected) return; + var index = new THREE.Vector3(x, y, z).add(offset); + if (index > self.get("cellsMax")) return; + if (existingCells[index.x][index.y][index.z]) overlapDetected = true; + }); + return overlapDetected; }, _addCellWithJSON: function(json, index){ var self = this; if (!this.sparseCells[index.x][index.y][index.z]) { - this.makeCellForLatticeType(json, function(cell){ + this.makeCellWithJSON(json, function(cell){ self.sparseCells[index.x][index.y][index.z] = cell; + self.cells[index.x][index.y][index.z] = cell; self.set("numCells", self.get("numCells")+1); }); } else console.warn("already a cell there"); @@ -186,7 +233,7 @@ define(['underscore', 'backbone', 'appState', 'globals', 'plist', 'three', 'thre cell.destroy(); this.sparseCells[index.x][index.y][index.z] = null; - this._checkForMatrixContraction(this.sparseCells); + this._checkForMatrixContraction(); this.set("numCells", this.get("numCells")-1); three.render(); @@ -232,30 +279,30 @@ define(['underscore', 'backbone', 'appState', 'globals', 'plist', 'three', 'thre //cells array - _checkForMatrixExpansion: function(cells, indicesMax, indicesMin){ - - if (!cells) { - console.warn("no cells specified in matrix expansion"); - cells = this.sparseCells; - } + _checkForMatrixExpansion: function(indicesMax, indicesMin){ if (!this.get("cellsMax") || !this.get("cellsMin")){ this.set("cellsMax", indicesMax); this.set("cellsMin", indicesMin); - this._expandCellsArray(cells, (new THREE.Vector3()).subVectors(indicesMax, indicesMin), false); + var size = (new THREE.Vector3()).subVectors(indicesMax, indicesMin); + this._expandCellsArray(this.cells, size, false); + this._expandCellsArray(this.sparseCells, size, false); return; } - var lastMax = this.get("cellsMax"); var lastMin = this.get("cellsMin"); var newMax = this._updateCellsMax(indicesMax, lastMax); var newMin = this._updateCellsMin(indicesMin, lastMin); if (newMax) { - this._expandCellsArray(cells, (new THREE.Vector3()).subVectors(newMax, lastMax), false); + var size = (new THREE.Vector3()).subVectors(newMax, lastMax); + this._expandCellsArray(this.cells, size, false); + this._expandCellsArray(this.sparseCells, size, false); this.set("cellsMax", newMax); } if (newMin) { - this._expandCellsArray(cells, (new THREE.Vector3()).subVectors(lastMin, newMin), true); + var size = (new THREE.Vector3()).subVectors(lastMin, newMin); + this._expandCellsArray(this.cells, size, true); + this._expandCellsArray(this.sparseCells, size, true); this.set("cellsMin", newMin); } }, @@ -336,19 +383,22 @@ define(['underscore', 'backbone', 'appState', 'globals', 'plist', 'three', 'thre return false; }, - _checkForMatrixContraction: function(cells, deletedIndex){//this could be more efficient + _checkForMatrixContraction: function(deletedIndex){//this could be more efficient var cellsMax = this.get("cellsMax"); var cellsMin = this.get("cellsMin"); - if (!cells || !cellsMin || !cellsMax) { + if (!cellsMin || !cellsMax) { console.warn("missing param for cells contraction"); return; } - var newMin = this._contractCellsArray(cells, true, cellsMin.clone(), cellsMax.clone()); + var newMin = this._contractCellsArray(this.cells, true, cellsMin.clone(), cellsMax.clone()); var newMax = null; if (newMin) newMax = this._contractCellsArray(cells, false, newMin.clone(), cellsMax.clone()); + //todo handle sparse cells + + this.set("cellsMax", newMax, {silent:true}); this.set("cellsMin", newMin); @@ -360,7 +410,10 @@ define(['underscore', 'backbone', 'appState', 'globals', 'plist', 'three', 'thre _contractCellsArray: function(cells, fromFront, cellsMin, cellsMax){ - if (cellsMax.x < cellsMin.x || cellsMax.y < cellsMin.y || cellsMax.z < cellsMin.z) return null; + if (cellsMax.x < cellsMin.x || cellsMax.y < cellsMin.y || cellsMax.z < cellsMin.z) { + console.warn("something weird happened"); + return null; + } var xTrim = true; var yTrim = true; diff --git a/js/materials/DMACompositeMaterial.js b/js/materials/DMACompositeMaterial.js index 695ba038cf985ec0e689dfef35f931c5852e43f8..b747f16f1e5372186a724454e028ed2632091927 100644 --- a/js/materials/DMACompositeMaterial.js +++ b/js/materials/DMACompositeMaterial.js @@ -28,6 +28,14 @@ define(['material'], function(DMAMaterial){ return this.compositeChildren.indexOf(id)>-1; }; + DMACompositeMaterial.prototype.getCells = function(){ + return [[[null]]] + }; + + DMACompositeMaterial.prototype.getSparseCells = function(){ + return this.sparseCells; + }; + DMACompositeMaterial.prototype.toJSON = function(){ return { name: this.name,