/** * Created by aghassaei on 2/1/15. */ Highlighter = Backbone.View.extend({ mesh: null, highlightedObject: null, direction: null, initialize: function(){ var geometry = this._makeGeometry(); this.mesh = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({ // side:THREE.DoubleSide, transparent:true, opacity:0.4, color:0xffffff // vertexColors:THREE.FaceColors })); globals.three.sceneAdd(this.mesh, "highlighter"); this.hide(); //bind events this.listenTo(globals.lattice, "change:superCellRange", this._superCellParamDidChange); this.listenTo(globals.appState, "change:superCellIndex", this._superCellParamDidChange); }, /////////////////////////////////////////////////////////////////////////////////// /////////////////////////////VISIBILITY//////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////// hide: function(){ this._setVisibility(false); }, show: function(forceRender){ this._setVisibility(true, forceRender); }, _setVisibility: function(visible, forceRender){ visible = globals.appState.get("highlighterIsVisible") && visible; if (forceRender || this.isVisible() != visible){ this.mesh.visible = visible; globals.three.render(); } this.mesh.visible = visible; }, isVisible: function(){ return this.mesh.visible; }, setNothingHighlighted: function(){ this.highlightedObject = null; this.direction = null; this.position = null; this.hide(); }, highlight: function(intersection){ if (!intersection.object) return; var highlighted = intersection.object; if (!(highlighted.parent instanceof THREE.Scene)) highlighted = highlighted.parent;//cell mesh parent is object3d if (!highlighted.myParent) { console.warn("no parent for highlighted object"); return; } this.highlightedObject = highlighted.myParent; var highlightedPos = this.highlightedObject.calcHighlighterPosition(intersection.face, intersection.point); this.position = highlightedPos.position;//todo used just for gik if (!highlightedPos.direction) {//may be hovering over a face that we shouldn't highlight this.hide(); return; } this.direction = highlightedPos.direction; this._setPosition(highlightedPos.position, this.direction);//position of center point this._setRotation(this.direction); this.show(true); }, /////////////////////////////////////////////////////////////////////////////////// /////////////////////////////POSITION/SCALE//////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////// getHighlightedObjectPosition: function(){//origin selection if (this.highlightedObject instanceof DMACell) { var position = this.highlightedObject.getPosition(); return { x:parseFloat(position.x.toFixed(4)), y:parseFloat(position.y.toFixed(4)), z:parseFloat(position.z.toFixed(4)) }; } return null; }, _setPosition: function(position){ this.mesh.position.set(position.x, position.y, position.z); }, _setRotation: function(direction){ this.mesh.rotation.set(direction.y*Math.PI/2, direction.x*Math.PI/2, 0); }, _superCellParamDidChange: function(){ if (this.updateGikLength) this.updateGikLength(); }, /////////////////////////////////////////////////////////////////////////////////// /////////////////////////////ADD REMOVE//////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////// _getNextCellPosition: function(){//add direction vector to current index var newIndex = _.clone(this.highlightedObject.getIndex()); var direction = this.direction; _.each(_.keys(newIndex), function(key){ newIndex[key] = Math.round(newIndex[key] + direction[key]); }); return newIndex; }, addRemoveVoxel: function(shouldAdd){ if (shouldAdd){ if (!this.isVisible() || !this.highlightedObject) return; if (globals.lattice.get("connectionType") == "freeformFace"){ //todo make this work for baseplane globals.lattice.addFreeFormCell(this.mesh.position.clone(), this.highlightedObject.getOrientation(), this.direction, this.highlightedObject.getType()); return; } globals.lattice.addCellAtIndex(this._getNextCellPosition()); } else { if (!this.highlightedObject) return; if (!(this.highlightedObject instanceof DMACell)) return; globals.lattice.removeCell(this.highlightedObject); } this.setNothingHighlighted(); }, destroy: function(){ this.setNothingHighlighted(); globals.three.sceneRemove(this.mesh, null); this.mesh = null; this.stopListening(); } }); /////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////OCTA////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////// OctaFaceHighlighter = Highlighter.extend({ _makeGeometry: function(){ var rad = 1/Math.sqrt(3); var geometry = new THREE.CylinderGeometry(rad, rad, 0.01, 3);//short triangular prism geometry.applyMatrix(new THREE.Matrix4().makeRotationX(-Math.PI/2)); return geometry; }, _setRotation: function(){ this.mesh.rotation.set(0,0,(this.highlightedObject.getIndex().z+1)%2*Math.PI); } }); OctaEdgeHighlighter = Highlighter.extend({ _makeGeometry: function(){ return new THREE.SphereGeometry(0.2); }, _setRotation: function(){} }); OctaVertexHighlighter = Highlighter.extend({ _makeGeometry: function(){ return new THREE.SphereGeometry(0.2); } }); OctaFreeFormHighlighter = Highlighter.extend({ _makeGeometry: function(){ return new THREE.SphereGeometry(0.2); }, _setRotation: function(){} }); /////////////////////////////////////////////////////////////////////////////////// /////////////////////////////CUBE ///////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////// CubeHighlighter = Highlighter.extend({ _makeGeometry: function(){ return new THREE.BoxGeometry(1,1,0.01); } }); GIKHighlighter = Highlighter.extend({ _makeGeometry: function(){ return new THREE.BoxGeometry(1,1,globals.lattice.zScale(0)); }, _setPosition: function(position, direction){ this.mesh.position.set(position.x+direction.x/2, position.y+direction.y/2, position.z+globals.lattice.zScale()*direction.z/2); }, _setRotation: function(direction){ if (!this.highlightedObject) return; var index = this.highlightedObject.getIndex(); var superCellIndex = globals.appState.get("superCellIndex"); if ((index.z%2 == 0 && Math.abs(direction.z) > 0.9) || (index.z%2 != 0 && Math.abs(direction.z) < 0.1)) this.mesh.rotation.set(0, 0, Math.PI/2); else this.mesh.rotation.set(0,0,0); this.mesh.translateX(superCellIndex - this.mesh.scale.x/2 + 0.5); }, updateGikLength: function(){ if (!this.mesh) return; this.mesh.scale.set(globals.lattice.get("superCellRange").x, globals.lattice.get("superCellRange").y, globals.lattice.get("superCellRange").z); globals.three.render(); if (!this.direction) return; this._setPosition(this.position, this.direction);//position of center point this._setRotation(this.direction); globals.three.render(); }, _getNextCellPosition: function(){//add direction vector to current index var newIndex = this.highlightedObject.getIndex(); var direction = this.direction; _.each(_.keys(newIndex), function(key){ newIndex[key] = Math.round(newIndex[key] + direction[key]); }); var offset = globals.appState.get("superCellIndex"); if (newIndex.z%2 == 0) newIndex.x -= offset; else newIndex.y -= offset; return newIndex; } }); TruncatedCubeHighlighter = Highlighter.extend({ _makeGeometry: function(){ return new THREE.BoxGeometry(1,1,0.01); }, _setRotation: function(direction){ this.mesh.rotation.set(direction.y*Math.PI/2, direction.x*Math.PI/2, Math.PI/4); } });