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