diff --git a/js/fea/DmaCell.js b/js/fea/DmaCell.js index 314f156ee714b5bd81e464dd1da5bce33c93cd28..1c9f0b07ee487bfc70e0572601a555a3535de3c5 100644 --- a/js/fea/DmaCell.js +++ b/js/fea/DmaCell.js @@ -13,7 +13,6 @@ function DMACell(indices, scale, lattice) { this.parts = this._initParts(indices.z); this.updateForScale(scale); - dmaGlobals.three.sceneAdd(this.cellMesh, "cell"); this.drawForMode(dmaGlobals.appState.get("cellMode")); } @@ -101,21 +100,15 @@ DMACell.prototype.destroy = function(){ (function () { - var unitCellGeo1 = new THREE.OctahedronGeometry(1/Math.sqrt(2)); - unitCellGeo1.applyMatrix(new THREE.Matrix4().makeRotationZ(-3*Math.PI/12)); - unitCellGeo1.applyMatrix(new THREE.Matrix4().makeRotationX(Math.asin(2/Math.sqrt(2)/Math.sqrt(3)))); -// var unitOctHeight = 2/Math.sqrt(6); -// unitCellGeo1.applyMatrix(new THREE.Matrix4().makeTranslation(0,0,unitOctHeight/2)); - - var unitCellGeo2 = unitCellGeo1.clone(); - - unitCellGeo2.applyMatrix(new THREE.Matrix4().makeRotationZ(Math.PI)); + var unitCellGeo = new THREE.OctahedronGeometry(1/Math.sqrt(2)); + unitCellGeo.applyMatrix(new THREE.Matrix4().makeRotationZ(-3*Math.PI/12)); + unitCellGeo.applyMatrix(new THREE.Matrix4().makeRotationX(Math.asin(2/Math.sqrt(2)/Math.sqrt(3)))); var cellMaterials = [new THREE.MeshNormalMaterial(), new THREE.MeshBasicMaterial({color:0x000000, wireframe:true})]; - function DMASideOctaCell(mode, indices, scale, lattice){ - DMACell.call(this, mode, indices, scale, lattice); + function DMASideOctaCell(indices, scale, lattice){ + DMACell.call(this, indices, scale, lattice); } DMASideOctaCell.prototype = Object.create(DMACell.prototype); @@ -129,12 +122,10 @@ DMACell.prototype.destroy = function(){ DMASideOctaCell.prototype._buildCellMesh = function(zIndex){//abstract mesh representation of cell var mesh; - if (zIndex%2==0){ - mesh = THREE.SceneUtils.createMultiMaterialObject(unitCellGeo1, cellMaterials); - } else { - mesh = THREE.SceneUtils.createMultiMaterialObject(unitCellGeo2, cellMaterials); - } + mesh = THREE.SceneUtils.createMultiMaterialObject(unitCellGeo, cellMaterials); + if (zIndex%2!=0) mesh.rotation.set(0, 0, Math.PI); mesh.myParent = this;//we need a reference to this instance from the mesh for intersection selection stuff + dmaGlobals.three.sceneAdd(mesh, "cell"); return mesh; }; @@ -150,6 +141,49 @@ DMACell.prototype.destroy = function(){ self.DMASideOctaCell = DMASideOctaCell; + /////////////////////////////////////////////////TETRA CELL//////////////////////////////////// + + var unitTetraCellGeo = new THREE.TetrahedronGeometry(Math.sqrt(3/8)); + unitTetraCellGeo.applyMatrix(new THREE.Matrix4().makeRotationZ(Math.PI/4)); + unitTetraCellGeo.applyMatrix(new THREE.Matrix4().makeRotationX((Math.PI-Math.atan(2*Math.sqrt(2)))/2)); + unitTetraCellGeo.applyMatrix(new THREE.Matrix4().makeTranslation(0,0,1/Math.sqrt(8)/2)); + + function DMATetraCell(indices, scale, lattice){ + DMACell.call(this, indices, scale, lattice); + } + DMATetraCell.prototype = Object.create(DMACell.prototype); + + DMATetraCell.prototype._initParts = function(){ + return []; + }; + + DMATetraCell.prototype._buildCellMesh = function(zIndex){//abstract mesh representation of cell + var mesh; + mesh = THREE.SceneUtils.createMultiMaterialObject(unitTetraCellGeo, cellMaterials); + if (zIndex%2!=0) mesh.rotation.set(Math.PI,0,0); + + mesh.myParent = this;//we need a reference to this instance from the mesh for intersection selection stuff + dmaGlobals.three.sceneAdd(mesh, "inverseCell"); + mesh.visible = false; + return mesh; + }; + + DMATetraCell.prototype.calcHighlighterPosition = function(face){ + + var direction = face.normal; + if (face.normal.z<0.99) direction = null;//only highlight horizontal faces + + var position = dmaGlobals.lattice.getPositionForIndex(this.indices); + position.z += dmaGlobals.lattice.zScale()/2; + return {index: _.clone(this.indices), direction:direction, position:position}; + }; + + DMATetraCell.prototype.getPosition = function(){//need for part relay + return dmaGlobals.lattice.getInvCellPositionForIndex(this.indices); + }; + + self.DMATetraCell = DMATetraCell; + })(); /////////////////////////////////////////////////////////////////////////////////////////////// @@ -165,8 +199,8 @@ DMACell.prototype.destroy = function(){ new THREE.MeshBasicMaterial({color:0x000000, wireframe:true})]; - function DMAVertexOctaCell(mode, indices, scale, lattice){ - DMACell.call(this, mode, indices, scale, lattice); + function DMAVertexOctaCell(indices, scale, lattice){ + DMACell.call(this, indices, scale, lattice); } DMAVertexOctaCell.prototype = Object.create(DMACell.prototype); @@ -181,6 +215,7 @@ DMACell.prototype.destroy = function(){ DMAVertexOctaCell.prototype._buildCellMesh = function(zIndex){//abstract mesh representation of cell var mesh = THREE.SceneUtils.createMultiMaterialObject(unitCellGeo, cellMaterials); mesh.myParent = this;//we need a reference to this instance from the mesh for intersection selection stuff + dmaGlobals.three.sceneAdd(mesh, "cell"); return mesh; }; @@ -202,8 +237,8 @@ DMACell.prototype.destroy = function(){ new THREE.MeshBasicMaterial({color:0x000000, wireframe:true})]; - function DMACubeCell(mode, indices, scale, lattice){ - DMACell.call(this, mode, indices, scale, lattice); + function DMACubeCell(indices, scale, lattice){ + DMACell.call(this, indices, scale, lattice); } DMACubeCell.prototype = Object.create(DMACell.prototype); @@ -221,6 +256,7 @@ DMACell.prototype.destroy = function(){ // var wireframe = new THREE.BoxHelper(mesh); // wireframe.material.color.set(0x000000); // mesh.add(wireframe); + dmaGlobals.three.sceneAdd(mesh, "cell"); return mesh; }; diff --git a/js/models/Lattice.js b/js/models/Lattice.js index 05f4a9a6677f55ca7e60886e19b4b885c05518b3..8bf03b4f71e3cbe9beef870ae1f9843ea24bf45a 100644 --- a/js/models/Lattice.js +++ b/js/models/Lattice.js @@ -9,12 +9,15 @@ Lattice = Backbone.Model.extend({ scale: window.defaultLatticeScale, nodes: [], cells: [[[null]]],//3D matrix containing all cells and null, dynamic size - inverseCells: [[[null]]],//3d matrix containing all inverse 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 - highlighter: null,//highlights buildable surfaces + highlighter: null,//highlights build-able surfaces shouldPreserveCells: true//preserve cells when changing lattice type }, @@ -33,7 +36,7 @@ Lattice = Backbone.Model.extend({ addCellsInRange: function(range){//add a block of cells var scale = this.get("scale"); var cells = this.get("cells"); - this._checkForMatrixExpansion(cells, range.max, range.min); + this._checkForMatrixExpansion(cells, range.max, range.min, "cellsMax", "cellsMin"); var cellsMin = this.get("cellsMin"); var relativeMin = this._subtract(range.min, cellsMin); @@ -56,12 +59,13 @@ Lattice = Backbone.Model.extend({ var scale = this.get("scale"); var cells = this.get("cells"); - this._checkForMatrixExpansion(cells, indices, indices); + 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); + if (this._shouldHaveInverseCells()) this._addInverseCellsForIndex(indices); dmaGlobals.three.render(); } else console.warn("already a cell there"); @@ -177,19 +181,19 @@ Lattice = Backbone.Model.extend({ ///////////////////////////////CELLS ARRAY////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// - _checkForMatrixExpansion: function(cells, indicesMax, indicesMin){ + _checkForMatrixExpansion: function(cells, indicesMax, indicesMin, maxName, minName){ - var lastMax = this.get("cellsMax"); - var lastMin = this.get("cellsMin"); + 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("cellsMax", newMax); + this.set(maxName, newMax); } if (newMin) { this._expandCellsArray(cells, this._subtract(lastMin, newMin), true); - this.set("cellsMin", newMin); + this.set(minName, newMin); } }, @@ -409,7 +413,28 @@ Lattice = Backbone.Model.extend({ 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 (Math.abs(index.y%2) == 1) position.x -= this.xScale()/2; + if ((index.y%2) != 0) position.x -= this.xScale()/2; + return position; + }, + + getInvCellPositionForIndex: function(index){ + + var scale = this.get("scale"); + var position = _.clone(index); + + var oddZ = (position.z%2 != 0); + position.z /= 2; + var xScale = this.xScale(scale); + if (oddZ){ + position.x = (position.x)*xScale; + position.y = position.y*this.yScale(scale); + position.z = (position.z+0.5)*this.zScale(scale); + } else { + position.x = (position.x+0.5)*xScale; + position.y = (position.y)*this.yScale(scale)-scale/Math.sqrt(3)/2; + position.z = (position.z)*this.zScale(scale); + } + if ((index.y%2) != 0) position.x -= this.xScale()/2; return position; }, @@ -432,6 +457,41 @@ Lattice = Backbone.Model.extend({ return new DMASideOctaCell(indices, scale, this); }, + _makeInvCellForLatticeType: function(indices, scale){ + return new DMATetraCell(indices, scale, this); + }, + + _shouldHaveInverseCells: function(){ + return true; + }, + + _addInverseCellsForIndex: function(index){ + + index = _.clone(index); + index.z*=2; + 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:1,z:0}), + + this._add(index, {x:0,y:0,z:1}), + this._add(index, {x:1,y:0,z:1}), + this._add(index, {x:1,y:1,z:1}) + ]; + + 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); + } + }); + }, + _undo: function(){//remove all the mixins, this will help with debugging later this.stopListening(this, "columnSeparation"); this.set("columnSeparation", null); @@ -449,51 +509,6 @@ Lattice = Backbone.Model.extend({ OctaEdgeLattice: { - _initLatticeType: function(){ - - //bind events - this.set("columnSeparation", 0.0, {silent:true}); - 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"); - this.get("basePlane").updateColSeparation(colSep); - this._iterCells(this.get("cells"), function(cell){ - if (cell) cell.updateForScale(scale); - }); - dmaGlobals.three.render(); - }, - - getIndexForPosition: function(absPosition){ - var position = this._indexForPosition(absPosition); - if (position.z%2 == 1) position.y += 1; - 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){ - return new DMASideOctaCell(indices, scale, this); - }, - _undo: function(){//remove all the mixins, this will help with debugging later this.stopListening(this, "columnSeparation"); this.set("columnSeparation", null); @@ -512,35 +527,6 @@ Lattice = Backbone.Model.extend({ 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); - }, - - 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 DMASideOctaCell(indices, scale, this); - }, - _undo: function(){//remove all the mixins, this will help with debugging later var self = this; _.each(_.keys(this.OctaVertexLattice), function(key){ @@ -591,6 +577,10 @@ Lattice = Backbone.Model.extend({ return new DMACubeCell(indices, scale, this); }, + _shouldHaveInverseCells: function(){ + return false; + }, + _undo: function(){//remove all the mixins, this will help with debugging later var self = this; _.each(_.keys(this.CubeLattice), function(key){