-
Amanda Ghassaei authoredAmanda Ghassaei authored
DMACell.js 12.93 KiB
/**
* Created by aghassaei on 5/26/15.
*/
define(['underscore', 'three', 'threeModel', 'lattice', 'appState', 'globals'],
function(_, THREE, three, lattice, appState, globals){
var wireframeMaterial = new THREE.MeshBasicMaterial({color:0x000000, wireframe:true});
function DMACell(json, superCell){
if (json.index) this.index = new THREE.Vector3(json.index.x, json.index.y, json.index.z);
if (superCell) this.superCell = superCell;
this.material = json.material || lattice.get("materialType");
//object 3d is parent to all 3d elements owned by cell: cell mesh and wireframe, parts, beams, nodes, etc
this.object3D = this._buildObject3D();
this.addChildren(this._buildMesh(), this.object3D);//build cell meshes
if (this.superCell) this.superCell.addChildren(this.object3D);//add as child of supercell
if (this.index){
if (!this.cells) lattice.getUItarget().addHighlightableCell(this.object3D.children[0]);//add mesh as highlightable object, only for lowest level of hierarchy
if (!superCell || superCell === undefined) three.sceneAdd(this.object3D);//add object3d as child of scene if top level of hierarchy
} else this.hide();//stock cell
if (!this.cells && ( !superCell || superCell === undefined)) this.setMode();
}
//make 3d stuff
DMACell.prototype._buildObject3D = function(){
var object3D = this._translateCell(this._rotateCell(new THREE.Object3D()));
if (!this.cells) object3D.myParent = this;//reference to get mouse raycasting back, only for lowest level of hierarchy
object3D.name = "object3D";
return object3D;
};
DMACell.prototype.getObject3D = function(){//careful, used for stock sim only for now todo need this?
return this.object3D;
};
DMACell.prototype._rotateCell = function(object3D){
return object3D;//by default, no mesh transformations
};
DMACell.prototype._translateCell = function(object3D){
if (!this.index) return object3D;
var position = lattice.getPositionForIndex(this.index);
object3D.position.set(position.x, position.y, position.z);
return object3D;
};
DMACell.prototype._buildMesh = function(){
var geometry = this._getGeometry();
var meshes = [];
var mesh = new THREE.Mesh(geometry, this.getMaterial());
mesh.name = this._getMeshName();
meshes.push(mesh);
var wireframe = this._buildWireframe(mesh, geometry);
if (!wireframe) return meshes;
wireframe.name = this._getMeshName();
meshes.push(wireframe);
return meshes;
};
DMACell.prototype._getMeshName = function(){
return "cell";
};
DMACell.prototype._buildWireframe = function(mesh, geometry){//for "cell" view
return new THREE.Mesh(geometry, wireframeMaterial);
};
//position/index/rotation
DMACell.prototype.getIndex = function(){
if (!this.index) {
console.warn("no index for this cell");
return null;
}
return this.index.clone();
};
DMACell.prototype.getAbsoluteIndex = function(){
if (!this.index) {
console.warn("no index for this cell");
return null;
}
if (!this.superCell) return this.getIndex();
return this.superCell.getAbsoluteIndex().add(this.superCell.applyRotation(this.getIndex()));
};
DMACell.prototype.getPosition = function(){
return this.object3D.position.clone();
};
DMACell.prototype.getAbsolutePosition = function(){
if (!this.superCell) return this.getPosition();
return this.superCell.getAbsolutePosition().add(this.superCell.applyRotation(this.getPosition()));
};
DMACell.prototype.getOrientation = function(){
return this.object3D.quaternion.clone();
};
DMACell.prototype.getAbsoluteOrientation = function(){
if (!this.superCell) return this.getOrientation();
return this.getOrientation().multiply(this.superCell.getAbsoluteOrientation());//order matters!
};
DMACell.prototype.getEuler = function(){
return this.object3D.rotation.clone();
};
DMACell.prototype.applyRotation = function(vector){//
vector.applyQuaternion(this.getAbsoluteOrientation());
return vector;
};
DMACell.prototype.applyAbsoluteRotation = function(vector){
vector.applyQuaternion(this.getAbsoluteOrientation());
};
//highlighting
DMACell.prototype.calcHighlighterParams = function(face, point){//this works for rectalinear, override in subclasses
var direction = face.normal.clone().applyQuaternion(this.getAbsoluteOrientation());
var position = this.getAbsolutePosition();
var self = this;
_.each(_.keys(position), function(key){
position[key] += direction[key]*self.axisScale(key)/2;
});
return {direction:direction, position:position};
};
DMACell.prototype.setDeleteMode = function(state){
var material;
if (state) material = globals.materials.deleteMaterial;
else material = this.getMaterial();
if (!material) return;//cell may be deleted by now
if (this.object3D.children[0].material == material) return;
if (this.cells){
this._loopCells(function(cell){
if (cell) cell.setDeleteMode(state);
});
}
if (this.parts){
_.each(this.parts, function(part){
if (part) part.setMaterial(material);
});
}
this.object3D.children[0].material = material;
three.render();
};
DMACell.prototype.getParent = function(){
if (this.superCell) return this.superCell.getParent();
return this;
};
//children
DMACell.prototype.addChildren = function(children, object3D){//accepts an array or a single mesh
this._addRemoveChildren(true, children, object3D);
};
DMACell.prototype.removeChildren = function(children, object3D){//accepts an array or a single mesh
this._addRemoveChildren(false, children, object3D);
};
DMACell.prototype._addRemoveChildren = function(shouldAdd, children, object3D){//accepts an array or a single mesh
if (object3D === undefined) object3D = this.object3D;
if (children.constructor === Array){
_.each(children, function(child){
if (shouldAdd) object3D.add(child);
else object3D.remove(child);
});
} else if (shouldAdd) object3D.add(children);
else object3D.remove(children);
};
//visibility
DMACell.prototype.hide = function(){
this.object3D.visible = false;
};
DMACell.prototype.show = function(mode){
this.object3D.visible = true;
this.setMode(mode);
};
DMACell.prototype.getMaterial = function(){
if (!this.material) return null;
var materialClass = lattice.get("materialClass");
if (!globals.materials[materialClass]) {
console.warn("no material class found of type " + materialClass);
return null;
}
var material = globals.materials[materialClass].materials[this.material];
if (!material){
console.warn("no material "+ this.material + " found for class "+ materialClass);
return null;
}
return material;
};
DMACell.prototype.setOpacity = function(opacity){
};
DMACell.prototype.setMode = function(mode, callback){
if (!mode || mode === undefined) mode = appState.get("cellMode");
var self = this;
switch(mode) {
case "supercell":
if (!this.superCell) mode = "cell";//top level item
setVisiblity();
break;
case "cell":
setVisiblity();
break;
case "part":
if (!this.parts) {
this._initParts(function(parts){
self.parts = parts;
setVisiblity();
});
} else setVisiblity();
break;
case "beam":
// if (!this.beams) this.beams = this._initBeams();
setVisiblity();
break;
case "node":
// if (!this.nodes) this.nodes = this._initNodes();
setVisiblity();
break;
default:
break;
}
function setVisiblity(){
var visible = !(self.superCell && self.cells);//middle layers are always hidden
_.each(self.object3D.children, function(child){
if (child.name == "object3D") return;
child.visible = visible && (child.name == mode);
});
if (callback) {
callback();
return;
}
if (!self.superCell) three.conditionalRender();
}
};
//subcomponents
DMACell.prototype._initParts = function(callback){
callback();//override in subclasses
};
//scale
DMACell.prototype.axisScale = function(axis){
switch (axis){
case "x":
return this.xScale();
case "y":
return this.yScale();
case "z":
return this.zScale();
default:
console.warn(axis + " axis not recognized");
break;
}
return null;
};
DMACell.prototype.xScale = function(){
return lattice.xScale(0);
};
DMACell.prototype.yScale = function(){
return lattice.yScale(0);
};
DMACell.prototype.zScale = function(){
return lattice.zScale(0);
};
//destroy
DMACell.prototype.destroy = function(){
this.destroyParts();
if (this.object3D) {
if (this.superCell) this.superCell.removeChildren(this.object3D);
else if (this.index) three.sceneRemove(this.object3D);
if (!this.cells) lattice.getUItarget().removeHighlightableCell(this.object3D.children[0]);//remove mesh as highlightable object
this.object3D.myParent = null;
// this.object3D.dispose();
// geometry.dispose();
// material.dispose();
this.object3D = null;
}
this.nodes = null;
this.beams = null;
this.superCell = null;
this.material = null;
this.index = null;
};
DMACell.prototype.destroyParts = function(){
if (!this.parts) return;
_.each(this.parts, function(part){
if (part) part.destroy();
});
this.parts = null;
};
DMACell.prototype.toJSON = function(){
var data = {
material: this.material
};
if (globals.materials.compositeMaterials[this.material]) return data;//material definition in material composites
if (this.cells) data.cells = this.cells;
return data;
};
return DMACell;
});
//DMACell.prototype.removePart = function(index){
// this.parts[index].destroy();
// this.parts[index] = null;
// var hasAnyParts = false;//check if all parts have been deleted
// _.each(this.parts, function(part){
// if (part) hasAnyParts = true;
// });
// if (!hasAnyParts) lattice.removeCell(this);//if all parts are gone, remove cell
//};
//DMACell.prototype._initNodes = function(vertices){
// var position = this.getPosition();
// var orientation = this.getOrientation();
// var nodes = [];
// for (var i=0;i<vertices.length;i++){
// var vertex = vertices[i].clone();
// vertex.applyQuaternion(orientation);
// vertex.add(position);
// nodes.push(new DmaNode(vertex, i));
// }
// return nodes;
//};
//
//
//DMACell.prototype._initBeams = function(nodes, faces){
// var beams = [];
// var self = this;
// var addBeamFunc = function(index1, index2){
// var duplicate = false;
// _.each(beams, function(beam){
// var index = beam.getIndex();
// if (index[0] == index1 && index[1] == index2) duplicate = true;
// });
// if (duplicate) return;
// var diff = nodes[index1].getPosition();
// diff.sub(nodes[index2].getPosition());
// if (diff.length() > self.getScale()*1.01) return;
// if (index2>index1) {
// beams.push(new DmaBeam(nodes[index1], nodes[index2], self));
// }
// };
// for (var i=0;i<nodes.length;i++){
// _.each(faces, function(face){
// if (face.a == i) {
// addBeamFunc(i, face.b);
// addBeamFunc(i, face.c);
// } else if (face.b == i){
// addBeamFunc(i, face.a);
// addBeamFunc(i, face.c);
// } else if (face.c == i){
// addBeamFunc(i, face.a);
// addBeamFunc(i, face.b);
// }
// })
// }
// return beams;
//};