threedeescene
Version:
A wrapper for Three.js assisting the creation of Three.js apps
355 lines (320 loc) • 12 kB
JavaScript
var THREE = require('three'),
Helpers = require('./Helpers')
var standardController = function(){
var _this = this
this.listen(this.SPRITE_HIT_CHANGED, function(e){
_onHitEvent.call(_this, e);
});
};
var _onHitEvent = function(e){
this.getHit() ? _onMouseIn.call(this, e) : _onMouseOut.call(this, e) ;
};
var _onMouseIn = function(e){
this.setMaterial( this.getHoverMaterial() );
};
var _onMouseOut = function(e){
this.setMaterial( this._private.materialUnhovered );
};
var defaultMaterial = new THREE.MeshPhongMaterial();
defaultMaterial.shininess = 100;
defaultMaterial.shading = THREE.SmoothShading;
defaultMaterial.id = "defaultMaterial";
var defaultGeometry = new THREE.SphereGeometry( 1, 32, 32 );
ThreeDeeSprite = (function(modelURL, material, opt_initialiser, opt_controller){
var _scope = function(modelURL, material, opt_initialiser, opt_controller){
this._private = {
material:null,
materialDefault:null,
materialUnhovered:null,
materialHover:null,
blenderModel:null,
hit:false,
textureMap:null,
_imgTexture:null,
bumpMap:null,
bumpScale:.02,
_x:1,
_y:1,
_z:1,
_xRotation:0,
_yRotation:0,
_zRotation:0,
scale:{x:1, y:1, z:1},
_imgBump:null,
_spriteEventDispatcher: null,
_texturLoader: null,
data:{name:"The name of the sprite is default"}
};
/* Statics */
this.SPRITE_HIT_CHANGED = "spriteHitChanged";
this._private._spriteEventDispatcher = document.createElement("div");
this._private.materialDefault = defaultMaterial;
this._private.materialUnhovered = material ? material : defaultMaterial;
this._private.material = this._private.materialUnhovered;
this._private._opt_initialiser = opt_initialiser ? opt_initialiser : {};
for(var value in this._private._opt_initialiser){
//Underscore properties are not to be changed.
if(String(value).charAt(0) != '_') this._private[value] = this._private._opt_initialiser[value];
}
this._contoller = opt_controller ? opt_controller : standardController;
this._contoller.call(this);
this._private.modelURL = modelURL ? modelURL : null;
this._loader = new THREE.JSONLoader();
// was a default hover material set in the config?
if(!this.getHoverMaterial()){
var color = new THREE.Color( 1, 1, 0 );
var material = new THREE.MeshPhongMaterial();
material.emissive = color;
material.shininess = 100;
material.shading = THREE.SmoothShading;
this._private.materialHover = material;
}
_initSprite.call(this)
};
// internal business logic
var _initSprite = function(){
if(this._private.textureMap) _initTextureMap.call(this);
if(this._private.bumpMap) _initBumpmap.call(this);
this._private.modelURL ? _intModel.call(this) : _initDefaultModel.call(this);
};
var _intModel = function(){
var scope = this;
this._loader.load( this._private.modelURL, function(geometry){
_onGeometrySet.call(scope, geometry)
});
};
var _initDefaultModel = function(){
this._private._mesh = mesh = new THREE.Mesh(defaultGeometry, this._private.material);
_onGeometrySet.call(this, defaultGeometry)
};
var _onGeometrySet = function(geometry){
var mesh;
this._private._mesh = mesh = new THREE.Mesh(geometry, this._private.material);
for(var prop in this._private._opt_initialiser){
mesh[prop] = this._private._opt_initialiser[prop];
}
// position transforms need to be applied individually...
if(this._private._opt_initialiser.position){
this._private._x = this._private._opt_initialiser.position.x;
this._private._y = this._private._opt_initialiser.position.y;
this._private._z = this._private._opt_initialiser.position.z;
mesh.position.x = this._private._x;
mesh.position.y = this._private._y;
mesh.position.z = this._private._z;
}
// rotation transforms need to be applied individually...
if(this._private._opt_initialiser.rotation){
this._private._xRotation = this._private._opt_initialiser.rotation.x;
this._private._yRotation = this._private._opt_initialiser.rotation.y;
this._private._zRotation = this._private._opt_initialiser.rotation.z;
mesh.rotation.x = this._private._xRotation;
mesh.rotation.y = this._private._yRotation;
mesh.rotation.z = this._private._zRotation;
}
// ...and scale transforms need to be applied individually too
if(this._private._opt_initialiser.scale){
this._private.scale.x = this._private._opt_initialiser.scale.x;
this._private.scale.y = this._private._opt_initialiser.scale.y;
this._private.scale.z = this._private._opt_initialiser.scale.z;
mesh.scale.x = this._private.scale.x;
mesh.scale.y = this._private.scale.y;
mesh.scale.z = this._private.scale.z;
}
try{
this.addToScene();
}catch(err){
//console.log(err)
}
};
var _updatePosition = function(){
var mesh = this._private._mesh;
//
mesh.rotation.x = this._private._xRotation;
mesh.rotation.y = this._private._yRotation;
mesh.rotation.z = this._private._zRotation;
//
mesh.position.x = this._private._x;
mesh.position.y = this._private._y;
mesh.position.z = this._private._z;
//
mesh.scale.x = this._private.scale.x;
mesh.scale.y = this._private.scale.y;
mesh.scale.z = this._private.scale.z;
//
};
var _initTextureMap = function(){
var _this = this;
var tex = new THREE.TextureLoader();
tex.load(this.getTextureMap(), function(evt){
_this.getMaterial().map = evt;
_this.getMaterial().needsUpdate = true;
});
};
var _initBumpmap = function(){
var _this = this;
var tex = new THREE.TextureLoader();
tex.load(this.getBumpMap(), function(evt){
_this.getMaterial().bumpScale = _this.getBumpScale();
_this.getMaterial().bumpMap = evt;
_this.getMaterial().needsUpdate = true;
});
};
var _onSceneSet = function(){
// Due to the asynchronous way the models load this mesh may not yet be defined.
// If so the mesh should be added during the callback from the loader (this._loader.load... etc)
try{
this.addToScene();
}catch(e){
//---
}
};
var _onHitChanged = function(){
this.getDispatcher().dispatchEvent( this.getEvent(this.SPRITE_HIT_CHANGED, {data:this.getData(), target:this}) );
};
/* Methods */
_scope.prototype = {
/**
* Sets the Scene which the Sprite belongs to.
* @param value
*/
setScene:function(value){
this._private.scene = value;
_onSceneSet.call(this);
},
getController:function(){
return this._contoller
},
addToScene:function(){
if(!this._private._mesh || !this._private.scene.getScene()) return;
var _this = this;
_this._private.scene.getScene().add(_this._private._mesh);
this._private.scene.listen(_scope.FRAME_EVENT, function(){
this._contoller.call(this);
}.bind(this));
},
listen:function(event, opt_callback){
this.getDispatcher().addEventListener(event, function(e){
opt_callback(e);
});
return {unlisten:function(){this.getDispatcher().removeEventListener(event, opt_callback)}};
},
getMesh:function(){
return this._private._mesh
},
setMaterial:function(value){
this._private.material = value;
try{
this.getMesh().material = this.getMaterial();
}catch(err){
//--
// console.log("Error setting material ")
}
},
getMaterial:function(){
return this._private.material;
},
setDefaultMaterial:function(value){
this._private.materialDefault = value;
},
getDefaultMaterial:function(){
return this._private.materialDefault;
},
setHoverMaterial:function(value){
this._private.materialHover = value;
},
getHoverMaterial:function(){
return this._private.materialHover;
},
getHit:function(){
return this._private.hit
},
setHit:function(value){
if(this._private.hit != value){
this._private.hit = value;
_onHitChanged.call(this)
}
},
setX:function(value){
this._private._x = value;
_updatePosition.call(this);
},
getX:function(){
return this._private._x;
},
setY:function(value){
this._private._y = value;
_updatePosition.call(this);
},
getY:function(){
return this._private._y;
},
setZ:function(value){
this._private._z = value;
_updatePosition.call(this);
},
getZ:function(){
return this._private._z;
},
setXrotation:function(value){
this._private._xRotation = Helpers.checkNumberValid(value);
_updatePosition.call(this);
},
getXrotation:function(value){
return this._private._xRotation;
},
setYrotation:function(value){
this._private._yRotation = Helpers.checkNumberValid(value);;
_updatePosition.call(this);
},
getYrotation:function(value){
return this._private._yRotation;
},
setZrotation:function(value){
this._private._zRotation = Helpers.checkNumberValid(value);;
_updatePosition.call(this);
},
getZrotation:function(value){
return this._private._zRotation;
},
getData:function(){
return this._private.data;
},
setData:function(value){
this._private.data = value;
},
getTextureMap:function(){
return this._private.textureMap;
},
setTextureMap:function(value){
this._private.textureMap = value;
_initTextureMap.call(this);
},
getBumpScale:function(){
return this._private.bumpScale;
},
setBumpScale:function(value){
this._private.bumpScale = value;
_initBumpmap.call(this);
//var mesh = this.getMesh()
// mesh.material = this.getMaterial();
//mesh.updateMatrix();
},
setBumpMap:function(value ){
this._private.bumpMap = value;
_initBumpmap.call(this);
},
getBumpMap:function(){
return this._private.bumpMap;
},
getDispatcher:function(){
return this._private._spriteEventDispatcher
},
getEvent:function(eventName, payload){
return new CustomEvent(eventName, { 'detail': payload });
}
};
//
return _scope
})();
ThreeDeeSprite.SPRITE_HIT_CHANGED = "spriteHitChanged";
module.exports = ThreeDeeSprite;