From 94456d869ef6a3b1f462a8ae2b303fabf608e0b6 Mon Sep 17 00:00:00 2001 From: Amanda Ghassaei <amandaghassaei@gmail.com> Date: Mon, 23 Feb 2015 14:40:35 -0500 Subject: [PATCH] highlighter working again --- js/fea/DmaCell.js | 30 +++++++++-- js/main.js | 15 ++++-- js/models/AppState.js | 5 +- js/models/BasePlane.js | 32 +++++++++-- js/models/Lattice.js | 23 +++++--- js/threeViews/Highlighter.js | 101 ++++++++++++----------------------- js/threeViews/ThreeView.js | 54 +++++++++---------- 7 files changed, 143 insertions(+), 117 deletions(-) diff --git a/js/fea/DmaCell.js b/js/fea/DmaCell.js index 5b7bd1e2..241e1612 100644 --- a/js/fea/DmaCell.js +++ b/js/fea/DmaCell.js @@ -5,7 +5,7 @@ //a Cell, a unit piece of the lattice -function DMACell(mode, indices, scale, lattice) { +function DMACell(indices, scale, lattice) { this.indices = indices; this.lattice = lattice;//need ref back to lattice @@ -14,7 +14,7 @@ function DMACell(mode, indices, scale, lattice) { this.updateForScale(scale); window.three.sceneAdd(this.cellMesh, "cell"); - this.drawForMode(mode); + this.drawForMode(window.appState.get("cellMode")); } DMACell.prototype.removePart = function(index){ @@ -70,7 +70,15 @@ DMACell.prototype.getScale = function(){//need for part relay DMACell.prototype.getPosition = function(){//need for part relay return this._calcPosition(this.getScale(), this.indices); -} +}; + +DMACell.prototype.getIndex = function(){ + return _.clone(this.indices); +}; + +DMACell.prototype.canRemove = function(){ + return true;//tells highlighter that a cell is something that can be deleted +}; DMACell.prototype.destroy = function(){ if (this.cellMesh) { @@ -148,6 +156,22 @@ DMACell.prototype.destroy = function(){ return mesh; }; + DMASideOctaCell.prototype.getHighlighterVertices = function(face){ + if (face.normal.z<0.99) return null;//only highlight horizontal faces + + //the vertices don't include the position transformation applied to cell. Add these to create highlighter vertices + var mesh = this.cellMesh.children[0]; + var vertices = mesh.geometry.vertices; + var newVertices = [vertices[face.a].clone(), vertices[face.b].clone(), vertices[face.c].clone()]; + var scale = this.cellMesh.scale.x; + var position = (new THREE.Vector3()).setFromMatrixPosition(mesh.matrixWorld); + _.each(newVertices, function(vertex){//apply scale + vertex.multiplyScalar(scale); + vertex.add(position); + }); + return newVertices; + } + self.DMASideOctaCell = DMASideOctaCell; })(); diff --git a/js/main.js b/js/main.js index 316d0df3..6e90f8d9 100644 --- a/js/main.js +++ b/js/main.js @@ -5,17 +5,24 @@ $(function(){ + //setup persistent global variables + //init web workers window.workers = persistentWorkers(8); //init threeJS and geometry models window.three = new ThreeModel(); - //setup ui - var appState = new AppState(); - var highlighter = new Highlighter({model:appState.get("lattice")}); + window.lattice = new Lattice(); + window.appState = new AppState({lattice:window.lattice}); + + + + //ui new NavBar({model:appState}); //threeJS View - new ThreeView({model:window.three, appState:appState, highlighter:highlighter}); + new ThreeView({model:window.three, appState:appState}); + + window.lattice.addCellAtIndex({x:0,y:0,z:0});//add a cell }); diff --git a/js/models/AppState.js b/js/models/AppState.js index 0563a71d..16ac7e4b 100644 --- a/js/models/AppState.js +++ b/js/models/AppState.js @@ -50,7 +50,7 @@ AppState = Backbone.Model.extend({ extrudeMode: false }, - initialize: function(){ + initialize: function(options){ _.bindAll(this, "_handleKeyStroke"); @@ -65,9 +65,8 @@ AppState = Backbone.Model.extend({ this.listenTo(this, "change:cellMode", this._cellModeDidChange); this.listenTo(this, "change:cellType change:connectionType", this._updateLatticetype); - this.set("lattice", new Lattice({appState:this})); + this.set("lattice", options.lattice); this.get("lattice").updateLatticeType(this.get("cellType"), this.get("connectionType")); - this.get("lattice").addCellAtIndex({x:0,y:0,z:0}); this.set("menuWrapper", new MenuWrapper({model: this, lattice:this.get("lattice")})); }, diff --git a/js/models/BasePlane.js b/js/models/BasePlane.js index 4b53f068..99cfa238 100644 --- a/js/models/BasePlane.js +++ b/js/models/BasePlane.js @@ -57,6 +57,7 @@ BasePlane = Backbone.Model.extend({ _removeMesh: function(){ var self = this; _.each(this.get("mesh"), function(mesh){ + if (mesh.myParent) mesh.myParent = null; window.three.sceneRemove(mesh, self._checkIsHighlightable(mesh)); }); window.three.render(); @@ -67,6 +68,10 @@ BasePlane = Backbone.Model.extend({ return null; }, + canRemove: function(){ + return false;//tells highlighter that the baseplane is not something to be deleted + }, + destroy: function(){ this.stopListening(); this.set("zIndex", null, {silent:true}); @@ -118,7 +123,9 @@ OctaBasePlane = BasePlane.extend({ } geometry.computeFaceNormals(); - return [new THREE.Mesh(geometry, this.get("material"))]; + var mesh = new THREE.Mesh(geometry, this.get("material")); + mesh.myParent = this;//reference used for intersection highlighting + return [mesh]; }, _calcOctaFaceVertices: function(colSep){ @@ -156,6 +163,24 @@ OctaBasePlane = BasePlane.extend({ var geometry = this.get("mesh")[0].geometry; geometry.vertices = this._calcOctaFaceVertices(colSep); geometry.verticesNeedUpdate = true; + }, + + getHighlighterVertices: function(face){ + //the vertices don't include the position transformation applied to cell. Add these to create highlighter vertices + var mesh = this.get("mesh")[0]; + var vertices = mesh.geometry.vertices; + var newVertices = [vertices[face.a].clone(), vertices[face.b].clone(), vertices[face.c].clone()]; + var scale = mesh.scale.x; + var position = (new THREE.Vector3()).setFromMatrixPosition(mesh.matrixWorld); + _.each(newVertices, function(vertex){//apply scale + vertex.multiplyScalar(scale); + vertex.add(position); + }); + return newVertices; + }, + + getIndex: function(face){ + return window.lattice.getIndexForPosition(face.geometry.vertices[0]); } }); @@ -190,8 +215,9 @@ SquareBasePlane = BasePlane.extend({ planeGeometry.faces.push(new THREE.Face3(0, 3, 2)); planeGeometry.computeFaceNormals(); - return [new THREE.Mesh(planeGeometry, new THREE.MeshBasicMaterial({color:0x000000, transparent:true, opacity:0.0, side:THREE.DoubleSide})), - new THREE.Line(geometry, new THREE.LineBasicMaterial({color:0x000000, transparent:true, linewidth:1, opacity:this.get("material").opacity}), THREE.LinePieces)]; + var mesh = new THREE.Mesh(planeGeometry, new THREE.MeshBasicMaterial({color:0x000000, transparent:true, opacity:0.0, side:THREE.DoubleSide})); + mesh.myParent = this;//reference used for intersection highlighting + return [mesh, new THREE.Line(geometry, new THREE.LineBasicMaterial({color:0x000000, transparent:true, linewidth:1, opacity:this.get("material").opacity}), THREE.LinePieces)]; } }); \ No newline at end of file diff --git a/js/models/Lattice.js b/js/models/Lattice.js index 527e6cdf..87b1fd53 100644 --- a/js/models/Lattice.js +++ b/js/models/Lattice.js @@ -22,8 +22,6 @@ Lattice = Backbone.Model.extend({ //bind events this.listenTo(this, "change:scale", this._scaleDidChange); - - this.appState = options.appState; }, //////////////////////////////////////////////////////////////////////////////////// @@ -67,6 +65,15 @@ Lattice = Backbone.Model.extend({ }, + 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")); @@ -341,7 +348,7 @@ Lattice = Backbone.Model.extend({ window.three.render(); }, - addCellAtPosition: function(absPosition){ + getIndexForPosition: function(absPosition){ //calc indices in cell matrix var scale = this.get("scale"); @@ -352,10 +359,10 @@ Lattice = Backbone.Model.extend({ var position = {}; position.x = Math.round(absPosition.x/latticeScale); position.y = Math.round(absPosition.y/triHeight); - position.z = Math.round(absPosition.z/octHeight); + position.z = Math.round(absPosition.z/octHeight)-1; if (position.z%2 == 1) position.y += 1; - this.addCellAtIndex(position); + return position; }, getScale: function(){ @@ -363,7 +370,7 @@ Lattice = Backbone.Model.extend({ }, _makeCellForLatticeType: function(indices, scale){ - return new DMASideOctaCell(this.appState.get("cellMode"), indices, scale, this); + return new DMASideOctaCell(indices, scale, this); }, _undo: function(){//remove all the mixins, this will help with debugging later @@ -427,7 +434,7 @@ Lattice = Backbone.Model.extend({ }, _makeCellForLatticeType: function(indices, scale){ - return new DMASideOctaCell(this.appState.get("cellMode"), indices, scale, this); + return new DMASideOctaCell(indices, scale, this); }, _undo: function(){//remove all the mixins, this will help with debugging later @@ -480,7 +487,7 @@ Lattice = Backbone.Model.extend({ }, _makeCellForLatticeType: function(indices, scale){ - return new DMASideOctaCell(this.appState.get("cellMode"), indices, scale, this); + return new DMASideOctaCell(indices, scale, this); }, _undo: function(){//remove all the mixins, this will help with debugging later diff --git a/js/threeViews/Highlighter.js b/js/threeViews/Highlighter.js index 7b234b9b..1a890e67 100644 --- a/js/threeViews/Highlighter.js +++ b/js/threeViews/Highlighter.js @@ -5,8 +5,7 @@ Highlighter = Backbone.View.extend({ mesh: null, - intersectedFace: null, - intersectedCell: null,//current cell we are intersecting + highlightedObject: null, initialize: function(){ @@ -24,100 +23,66 @@ Highlighter = Backbone.View.extend({ vertexColors:THREE.FaceColors })); window.three.sceneAdd(this.mesh, null); - this._hide(); + this.hide(); }, - _hide: function(){ + hide: function(){ this._setVisibility(false); }, - _show: function(forceRender){ + show: function(forceRender){ this._setVisibility(true, forceRender); }, _setVisibility: function(visible, forceRender){ - if (this.isVisible() != visible){ + if (forceRender || this.isVisible() != visible){ this.mesh.visible = visible; window.three.render(); - } else if (forceRender){ - window.three.render(); } + this.mesh.visible = visible; }, - highlightCell: function(object, face){ - - if (object.parent && object.parent.myParent) { - this.intersectedCell = object.parent.myParent; - } else { - this.intersectedCell = null;//we're on the base plane - } - -// if (this.isVisible() && this._isHighlighting(face)) return;//nothing has changed - - this.intersectedFace = face; - - if (face.normal.z<0.99){//only highlight horizontal faces - this._hide(); + highlight: function(intersection){ + if (!intersection.object) return; + var highlightable = intersection.object; + if (!(highlightable.parent instanceof THREE.Scene)) highlightable = highlightable.parent;//cell mesh parent is object3d + if (!highlightable.myParent) console.warn("no parent for highlightable object"); + + this.highlightedObject = highlightable.myParent; + this.highlightedFace = intersection.face; + var newVertices = highlightable.myParent.getHighlighterVertices(intersection.face); + if (!newVertices) { + this.hide(); return; } - - //update highlighter - this._highlightFace(object, face); - this._show(true); - }, - - - setNoCellIntersections: function(){ - this.intersectedCell = null; - this._hide(); + this.mesh.geometry.vertices = newVertices; + this.mesh.geometry.verticesNeedUpdate = true; +// this.mesh.geometry.normalsNeedUpdate = true; +// this.mesh.geometry.computeFaceNormals(); +// this.mesh.geometry.computeVertexNormals(); + this.mesh.geometry.computeBoundingSphere(); + this.show(true); }, isVisible: function(){ return this.mesh.visible; }, - _isHighlighting: function(face){ - return this.intersectedFace == face; - }, - - _highlightFace: function(object, face){ - this.mesh.geometry.vertices = this._calcNewHighlighterVertices(object, face); - this.mesh.geometry.verticesNeedUpdate = true; - }, - - _calcNewHighlighterVertices: function(object, face){ - //the vertices don't include the position transformation applied to cell. Add these to create highlighter vertices - var vertices = object.geometry.vertices; - var newVertices = [vertices[face.a].clone(), vertices[face.b].clone(), vertices[face.c].clone()]; - var scale = this.model.get("scale"); - var position = (new THREE.Vector3()).setFromMatrixPosition(object.matrixWorld); - _.each(newVertices, function(vertex){//apply scale - vertex.multiplyScalar(scale); - vertex.add(position); - }); - return newVertices; - }, - - _getNextCellPosition: function(){ - return this.mesh.geometry.vertices[0]; - }, - - _getNextCellVertices: function(){//offset vertices with +1 in z - var vertices = _.clone(this.intersectedCell.indices); - vertices.z += 1; - return vertices; + _getNextCellPosition: function(indices){//add one to z index + indices.z += 1; + return indices; }, addRemoveVoxel: function(shouldAdd){ if (shouldAdd){ - if (!this.isVisible()) return; - if (this.intersectedFace && !this.intersectedCell) this.model.addCellAtPosition(this._getNextCellPosition());//baseplane - else this.model.addCellAtIndex(this._getNextCellVertices()); + if (!this.isVisible() || !this.highlightedObject) return; + window.lattice.addCellAtIndex(this._getNextCellPosition(this.highlightedObject.getIndex(this.mesh))); } else { - if (this.intersectedFace && !this.intersectedCell) return;//baseplane - this.model.removeCell(this.intersectedCell); + if (!this.highlightedObject || !this.highlightedObject.canRemove()) return; + window.lattice.removeCellAtIndex(this.highlightedObject.getIndex(this.mesh)); } - this._hide(); + this.hide(); + this.highlightedObject = null; } }); \ No newline at end of file diff --git a/js/threeViews/ThreeView.js b/js/threeViews/ThreeView.js index 3e290b18..1a2e0990 100644 --- a/js/threeViews/ThreeView.js +++ b/js/threeViews/ThreeView.js @@ -12,12 +12,11 @@ ThreeView = Backbone.View.extend({ }, mouseIsDown: false,//store state of mouse click inside this el - extrudeVisualizer: ExtrudeVisualizer(), //intersections/object highlighting mouseProjection: new THREE.Raycaster(), highlighter: null, - currentIntersectedPart:null, + currentIntersectedPart: null, el: "#threeContainer", @@ -38,7 +37,7 @@ ThreeView = Backbone.View.extend({ this.$el.append(this.model.domElement);//render only once //init highlighter - this.highlighter = options.highlighter; + this.highlighter = new Highlighter(); this.model.render(); this._animate(); @@ -63,7 +62,7 @@ ThreeView = Backbone.View.extend({ //////////////////////////////////////////////////////////////////////////////// _mouseOut: function(){ - this.highlighter.setNoCellIntersections(); + this.highlighter.hide(); this._setNoPartIntersections(); }, @@ -80,25 +79,36 @@ ThreeView = Backbone.View.extend({ _mouseMoved: function(e){ if (this.mouseIsDown && this.controls.enabled) {//in the middle of a camera move - this.highlighter.setNoCellIntersections(); + this.highlighter.hide(); this._setNoPartIntersections(); return; } //make projection vector var vector = new THREE.Vector2(2*(e.pageX-this.$el.offset().left)/this.$el.width()-1, 1-2*(e.pageY-this.$el.offset().top)/this.$el.height()); - var camera = this.model.camera; - this.mouseProjection.setFromCamera(vector, camera); - - //check if we're intersecting anything - var cellIntersections = this.mouseProjection.intersectObjects(this.model.cells.concat(this.model.basePlane), true); - console.log(this.model.basePlane); - if (cellIntersections.length == 0) {//no intersections - this.highlighter.setNoCellIntersections(); + this.mouseProjection.setFromCamera(vector, this.model.camera); + + //check if we're in the same spot + if (this.highlighter.isVisible()){ + if(this.mouseProjection.intersectObject(this.highlighter.mesh, false).length > 0) return; + } + + var intersections = this.mouseProjection.intersectObjects(this.model.cells.concat(this.model.basePlane), true); + if (intersections.length == 0) {//no intersections + this.highlighter.hide(); this._setNoPartIntersections(); return; } - this._handleCellIntersections(cellIntersections[0]); + + this.highlighter.highlight(intersections[0]); + + if (this.mouseIsDown) { + if (this.appState.get("deleteMode")){ + this.highlighter.addRemoveVoxel(false); + } else if (this.appState.get("shift")){ + this.highlighter.addRemoveVoxel(true); + } + } if (this.appState.get("cellMode") == "part"){//additionally check for part intersections in part mode var partIntersections = this.mouseProjection.intersectObjects(this.model.parts, false); @@ -106,7 +116,7 @@ ThreeView = Backbone.View.extend({ this._setNoPartIntersections(); return; } - this._handlePartIntersections(partIntersections, cellIntersections[0].distance); + this._handlePartIntersections(partIntersections, intersections[0].distance); } }, @@ -128,25 +138,13 @@ ThreeView = Backbone.View.extend({ this._setNoPartIntersections(); return; } - this.highlighter.setNoCellIntersections(); + this.highlighter.hide(); if (part!= this.currentIntersectedPart){ if (this.currentIntersectedPart) this.currentIntersectedPart.unhighlight(); part.highlight(); this.currentIntersectedPart = part; window.three.render(); } - }, - - _handleCellIntersections: function(intersection){ - - this.highlighter.highlightCell(intersection.object, intersection.face); - - if (!this.mouseIsDown) return; - if (this.appState.get("deleteMode")){ - this.highlighter.addRemoveVoxel(false); - } else if (this.appState.get("shift")){ - this.highlighter.addRemoveVoxel(true); - } } }); \ No newline at end of file -- GitLab