/** * Created by aghassaei on 1/31/15. */ BasePlane = Backbone.Model.extend({ defaults: { zIndex: 0, mesh: [], dimX: 100, dimY: 100, material: new THREE.MeshBasicMaterial({color:0x000000, transparent:true, opacity:0.2, wireframe:true}) }, initialize: function(){ //bind events this.listenTo(this, "change:zIndex", this._renderZIndexChange); //draw mesh this.set("mesh", this._makeBasePlaneMesh()); var self = this; _.each(this.get("mesh"), function(mesh){ globals.three.sceneAdd(mesh, self._checkIsHighlightable(mesh)); }); globals.three.render(); }, updateXYSeparation: function(xySep) {}, getOrientation: function(){ return new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0,0,1), Math.PI); }, /////////////////////////////////////////////////////////////////////////////////// //////////////////////HIGHLIGHTER FUNCTIONALITY//////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////// _checkIsHighlightable: function(mesh){ if (mesh.type == "Mesh") return "basePlane";//don't try to highlight wireframe parts of baseplane return null; }, /////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////DEALLOC//////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////// _removeMesh: function(){ var self = this; _.each(this.get("mesh"), function(mesh){ if (mesh.myParent) mesh.myParent = null; globals.three.sceneRemove(mesh, self._checkIsHighlightable(mesh)); }); globals.three.render(); }, destroy: function(){ this.stopListening(); this.set("zIndex", null, {silent:true}); this._removeMesh(); this.set("mesh", null, {silent:true}); this.set("material", null, {silent:true}); this.set("unitGeometry", null, {silent:true}); this.set("dimX", null, {silent:true}); this.set("dimY", null, {silent:true}); } }); /////////////////////////////////////////////////////////////////////////////////// /////////////////////////////OCTA FACE///////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////// OctaBasePlane = BasePlane.extend({ _makeBasePlaneMesh: function(){ var geometry = new THREE.Geometry(); geometry.vertices = this._calcOctaFaceVertices(0.0); var faces = geometry.faces; var dimX = this.get("dimX"); var dimY = this.get("dimY"); var currentOffset = 0; for (var j=-dimX;j<=dimX;j++){ for (var i=-dimY;i<=dimY;i++){ currentOffset++; if (j == -dimX || i == -dimY) continue; if (Math.abs(j)%2==1){ faces.push(new THREE.Face3(3*currentOffset-4, 3*currentOffset-8-6*dimY, 3*currentOffset-6-6*dimY));//pt, base, base } else { faces.push(new THREE.Face3(3*currentOffset-1, 3*currentOffset-8-6*dimY, 3*currentOffset-6-6*dimY));//pt, base, base } } } geometry.computeFaceNormals(); var mesh = new THREE.Mesh(geometry, this.get("material")); mesh.myParent = this;//reference used for intersection highlighting return [mesh]; }, getType: function(){//todo hack from freeform octa, get rid of this eventually return "octa"; }, _renderZIndexChange: function(){ var zIndex = this.get("zIndex"); var xScale = globals.lattice.xScale(); var yScale = globals.lattice.yScale(); var zScale = globals.lattice.zScale(); _.each(this.get("mesh"), function(mesh){ mesh.position.set(xScale*(zIndex%2)/2, -yScale/3*(zIndex%2), zIndex*zScale); mesh.rotation.set(Math.PI*(zIndex%2),0,0) }); globals.three.render(); }, _calcOctaFaceVertices: function(xySep){ var vertices = []; var xScale = globals.lattice.xScale(); var yScale = globals.lattice.yScale(); var dimX = this.get("dimX"); var dimY = this.get("dimY"); var baseVertOffset = xySep/Math.sqrt(3); var pointVertOffset = 2*baseVertOffset; var horizontalOffset = xySep; for (var j=-dimX;j<=dimX;j++){ for (var i=-dimY;i<=dimY;i++){ var xOffset = 0; if (Math.abs(j)%2!=0) { xOffset = 1/2*xScale; } vertices.push(new THREE.Vector3(i*xScale + xOffset - horizontalOffset, j*yScale + baseVertOffset, 0)); vertices.push(new THREE.Vector3(i*xScale + xOffset + horizontalOffset, j*yScale + baseVertOffset, 0)); vertices.push(new THREE.Vector3(i*xScale + xOffset, j*yScale - pointVertOffset, 0)); } } return vertices; }, updateXYSeparation: function(xySep){ var geometry = this.get("mesh")[0].geometry; geometry.vertices = this._calcOctaFaceVertices(xySep); geometry.verticesNeedUpdate = true; }, calcHighlighterPosition: function(face, position){ position.z = 0; var index = globals.lattice.getIndexForPosition(position); if (index.z%2 != 0) index.x -= 1; index.z = this.get("zIndex") - 1;//pretend we're on the top of the cell underneath the baseplane var position = globals.lattice.getPositionForIndex(index); position.z += globals.lattice.zScale()/2; return {index: index, direction: new THREE.Vector3(0,0,1), position:position}; } }); /////////////////////////////////////////////////////////////////////////////////// /////////////////////////////CUBE GRID///////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////// SquareBasePlane = BasePlane.extend({ _makeBasePlaneMesh: function(){ var scale = globals.lattice.xScale(); var dimX = this.get("dimX")*scale; var dimY = this.get("dimY")*scale; var geometry = new THREE.Geometry(); for ( var i = - dimX; i <= dimX; i += scale ) { geometry.vertices.push( new THREE.Vector3(-dimX, i, 0)); geometry.vertices.push( new THREE.Vector3(dimX, i, 0)); geometry.vertices.push( new THREE.Vector3(i, -dimX, 0)); geometry.vertices.push( new THREE.Vector3(i, dimX, 0)); } var planeGeometry = new THREE.Geometry(); planeGeometry.vertices.push( new THREE.Vector3(-dimX, -dimX, 0)); planeGeometry.vertices.push( new THREE.Vector3(dimX, -dimX, 0)); planeGeometry.vertices.push( new THREE.Vector3(-dimX, dimX, 0)); planeGeometry.vertices.push( new THREE.Vector3(dimX, dimX, 0)); planeGeometry.faces.push(new THREE.Face3(0, 1, 3)); planeGeometry.faces.push(new THREE.Face3(0, 3, 2)); planeGeometry.computeFaceNormals(); var mesh = new THREE.Mesh(planeGeometry, new THREE.MeshBasicMaterial({color:0x000000, transparent:true, opacity:0.0})); mesh.myParent = this;//reference used for intersection highlighting return [mesh, new THREE.Line(geometry, new THREE.LineBasicMaterial({color:0x000000, transparent:true, linewidth:2, opacity:this.get("material").opacity}), THREE.LinePieces)]; }, _renderZIndexChange: function(){ var zIndex = this.get("zIndex"); var zScale = globals.lattice.zScale(); _.each(this.get("mesh"), function(mesh){ mesh.position.set(0, 0, zIndex*zScale); }); globals.three.render(); }, calcHighlighterPosition: function(face, position){ var index = globals.lattice.getIndexForPosition(position); index.z = this.get("zIndex") - 1;//pretend we're on the top of the cell underneath the baseplane var latticePosition = globals.lattice.getPositionForIndex(index); latticePosition.z += globals.lattice.zScale()/2; return {index: index, direction: new THREE.Vector3(0,0,1), position:latticePosition}; } }); /////////////////////////////////////////////////////////////////////////////////// //////////////////////////OCTA EDGE ROT//////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////// RotEdgeOctaBasePlane = SquareBasePlane.extend({ calcHighlighterPosition: function(face, position){ var index = globals.lattice.getIndexForPosition(position); index.z = this.get("zIndex") - 1;//pretend we're on the top of the cell underneath the baseplane var latticePosition = globals.lattice.getPositionForIndex(index); latticePosition.x -= globals.lattice.xScale()/2; latticePosition.y -= globals.lattice.yScale()/2; return {index: index, direction: new THREE.Vector3(0,0,1), position:latticePosition}; } });