threedeescene
Version:
A wrapper for Three.js assisting the creation of Three.js apps
1,681 lines (1,262 loc) • 927 kB
JavaScript
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/ };
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {
var ThreeDeeSprite = __webpack_require__(1);
var THREE = __webpack_require__(2);
var OrbitControls = __webpack_require__(4)(THREE);
var ColorHelpers = __webpack_require__(5);
var Helpers = __webpack_require__(3);
/*Get requestAnimationFrame working for all browsers */
window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.oRequestAnimationFrame;
/**
* Created by grahamclapham on 05/06/2014.
* Dependencies ThreeJs (http://threejs.org/) and Three.js OrbitControls.js (https://github.com/mrdoob/three.js/blob/master/examples/js/controls/OrbitControls.js)
*/
ThreeDeeScene = function (opt_target, opt_initialiser) {
var _scope = function () {
this._private = {
//APP
target: null,
width: 100,
height: 100,
fullscreen: true,
backgroundColour: 0xcccccc,
_aspect: null,
_scene: null,
_playing: true,
//LIGHTS
_light: null,
lightColour: 0xffffff,
_lightAmbient: null,
ambientColour: 0xffffff,
_lights: [],
//CAMERA
fov: 15, //— Camera frustum vertical field of view.
near: 0.1, //— Camera frustum near plane.
far: 20000, //— Camera frustum far plane.
_camera: null,
cameraX: 0,
cameraY: 0,
cameraZ: 15,
//ACTION
_sprites: [],
_materials: [],
_datum: [],
_scene: new THREE.Scene(),
_mouse: new THREE.Vector2(),
//_projector : new THREE.Projector(),
_raycaster: new THREE.Raycaster(),
_bufferGeometry: new THREE.BufferGeometry(),
_renderer: new THREE.WebGLRenderer({ antialias: true, alpha: true, shadowMapEnabled: true }),
_orbitControl: null,
orbit: true, // is the scene controlled by an mouse controlled orbiter?
_dispatcher: null,
_frameEvent: null
};
_setUp.apply(this, arguments);
};
/* Constants */
_scope.HOVERED = "hovered";
_scope.CLICKED = "clicked";
_scope.FRAME_EVENT = "frameEvent";
var _setUp = function () {
//First, have you got a config object?
// If so apply all the properties.
if (arguments[1] && typeof arguments[1] == 'object') {
_onConfigSet.call(this, arguments[1]);
}
// test to see if the first item is a DOM element
if (arguments[0] && arguments[0].nodeType === 1) {
this.setTarget(arguments[0]);
}
};
var _onConfigSet = function () {
for (var value in arguments[0]) {
//Underscore properties are not to be changed.
if (String(value).charAt(0) != '_') this._private[value] = arguments[0][value];
//console.log("THE VALUE ",value," -- ",arguments[0][value]);
}
};
////
var _onTargetSet = function () {
_initScene.call(this);
};
/////
var _initScene = function () {
//this.getRenderer().setClearColor(this.getBackgroundColour(),.0);
this._private._dispatcher = document.createElement("div");
this._private._frameEvent = new CustomEvent(_scope.FRAME_EVENT, { 'detail': "frameEntered" });
this._private._clickEvent = new CustomEvent(_scope.CLICKED, { 'detail': "clicked" });
if (this.getTarget()) this._private.target.appendChild(this.getRenderer().domElement);
_initCamera.call(this);
_initLights.call(this);
_initMaterials.call(this);
_initAnimation.call(this);
// console.log("FULLSCREEN IS SET TO ", this.getFullScreen());
if (this.getFullScreen()) {
_initWindowResize.call(this);
_onWindowResize.call(this);
} else {
_setFixedSize.call(this);
}
var scope = this;
this.getTarget().addEventListener('mousemove', function (e) {
scope.documentMouseMove(e);
}, false);
this.getTarget().addEventListener('mousedown', function (e) {
scope.documentMouseDown(e);
}, false);
};
var _setFixedSize = function () {
this.getRenderer().setSize(this.getWidth(), this.getHeight());
this._private._camera.aspect = this.getWidth() / this.getHeight();
this._private._camera.updateProjectionMatrix();
};
//////
var _initCamera = function () {
// Create a camera, zoom it out from the model a bit, and add it to the scene.
this._private._camera = new THREE.PerspectiveCamera(this.getFov(), this._private._aspect, this.getNear(), this.getFar());
this._private._camera.position.x = this._private.cameraX;
this._private._camera.position.y = this._private.cameraY;
this._private._camera.position.z = this._private.cameraZ;
//this.getCamera().position.set(-50,6,0);
this._private._scene.add(this.getCamera());
};
var _refreshCamera = function () {
this._private._camera.position.x = this._private.cameraX;
this._private._camera.position.y = this._private.cameraY;
this._private._camera.position.z = this._private.cameraZ;
this._private._camera.near = this._private.near;
this._private._camera.far = this._private.far;
this._private._camera.fov = this._private.fov;
this._private._camera.updateProjectionMatrix();
};
/////
var _initLights = function () {
// Create a light, set its position, and add it to the scene.
var _light = this._private._light = new THREE.PointLight(this.getLightColour());
_light.position.set(-100, 200, 100);
_light.castShadow = true;
_light.shadowMapWidth = 2048;
_light.shadowMapHeight = 2048;
_light.shadowCameraFov = 45;
this._private._scene.add(_light);
// ...and now the ambient light
var _lightAmbient = this._private._lightAmbient = new THREE.DirectionalLight(this.getAmbientLightColour(), 1);
_lightAmbient.position.set(100, -700, -300);
this._private._scene.add(_lightAmbient);
};
/*
Default materials - if none are set
*/
var _initMaterials = function () {
this._private._materials[0] = new THREE.MeshPhongMaterial({ color: 0xccff33 });
};
var _initAnimation = function () {
if (this._private.orbit) this._private._orbitControl = new OrbitControls(this._private._camera, this._private._renderer.domElement);
requestAnimationFrame(this.animate.bind(this));
};
var _onSpriteAdded = function (sp) {
// console.log("SpriteAdded ")
sp.setScene(this);
};
var _initWindowResize = function () {
var _this = this;
this._private._windowListener = window.addEventListener('resize', function () {
if (_this.getFullScreen()) _onWindowResize.call(_this);
});
};
var _onDocumentMouseMove = function () {
for (var i = 0; i < this._private._sprites.length; i++) {
_hitTest.call(this, i);
}
};
var _hitTest = function (index) {
this._private._vector = new THREE.Vector3(this._private._mouse.x, this._private._mouse.y, 1);
var direction = new THREE.Vector3(0, 0, -1).transformDirection(this._private._camera.matrixWorld);
this._private._raycaster.setFromCamera(this._private._mouse, this._private._camera);
var __sprite = this._private._sprites[index];
var mesh = __sprite.getMesh();
var intersects = [];
try {
intersects = this._private._raycaster.intersectObject(mesh);
} catch (err) {
// console.log("Intersects error: ", err);
}
if (intersects.length > 0) {
var intersect = intersects[0];
__sprite.setHit(true);
} else {
__sprite.setHit(false);
}
};
var _onWindowResize = function () {
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight;
this._private._renderer.setSize(WIDTH, HEIGHT);
this._private._camera.aspect = WIDTH / HEIGHT;
this._private._camera.updateProjectionMatrix();
};
var _onSizeChanged = function () {
this.setFullScreen(false);
_setFixedSize.call(this);
};
// Renders the scene and updates the render as needed.
/* ENUMS */
/* Methods */
_scope.prototype = {
animate: function () {
if (!this.getPlaying()) return;
this._private._renderer.render(this._private._scene, this._private._camera);
//this.cube.rotation.y += 0.1;
this._private._dispatcher.dispatchEvent(this._private._frameEvent);
requestAnimationFrame(this.animate.bind(this));
},
listen: function (event, opt_callback) {
this._private._dispatcher.addEventListener(event, opt_callback);
},
addSprite: function (value) {
var alreadyAdded = false;
for (var sp in this._private._sprites) {
if (this._private._sprites[sp] == value) {
alreadyAdded = true;
}
}
if (!alreadyAdded) {
this._private._sprites.push(value);
_onSpriteAdded.call(this, value);
}
},
stripPx: function (value) {
var _s = String(value).replace("px", "");
var _n = parseFloat(_s);
return !isNaN(_n) ? _n : 0;
},
documentMouseMove: function (event, targ) {
event.preventDefault();
var el = this.getTarget();
var style = el.currentStyle || window.getComputedStyle(el);
var _xOffset = this.stripPx(style["padding-left"]);
var _yOffset = this.stripPx(style["padding-top"]);
var _rect = this.getTarget().getBoundingClientRect();
var xMouseCalc = (event.clientX - _rect.left - _xOffset) / window.innerWidth * 2 - 1;
var yMouseCalc = -((event.clientY - _rect.top - _yOffset) / window.innerHeight) * 2 + 1;
this._private._mouse.x = xMouseCalc;
this._private._mouse.y = yMouseCalc;
_onDocumentMouseMove.call(this);
},
documentMouseDown: function () {
// console.log("Mouse Down", this.getHovered());
this._private._dispatcher.dispatchEvent(this._private._clickEvent);
},
getHovered: function () {
var _hovered = [];
for (var sp in this._private._sprites) {
if (this._private._sprites[sp].getHit()) {
_hovered.push(this._private._sprites[sp]);
}
}
return _hovered;
},
getTarget: function () {
return this._private.target;
},
setTarget: function (value) {
if (Helpers.chekDomElementIsValid(value)) {
this._private.target = value;
_onTargetSet.apply(this);
} else {
throw new Error("The value passed must be a DOM element");
}
},
getWidth: function () {
return this._private.width;
},
setWidth: function (value) {
this._private.width = Helpers.checkNumberValid(value);
_onSizeChanged.call(this);
},
getHeight: function () {
return this._private.height;
},
setHeight: function (value) {
this._private.height = Helpers.checkNumberValid(value);
_onSizeChanged.call(this);
},
getCamera: function () {
return this._private._camera;
},
getCameraX: function () {
return this._private.cameraX;
},
setCameraX: function (value) {
this._private.cameraX = Helpers.checkNumberValid(value);
_refreshCamera.call(this);
},
getCameraY: function () {
return this._private.cameraY;
},
setCameraY: function (value) {
this._private.cameraY = Helpers.checkNumberValid(value);
_refreshCamera.call(this);
},
getCameraZ: function () {
return this._private.cameraZ;
},
setCameraZ: function (value) {
this._private.cameraZ = Helpers.checkNumberValid(value);
_refreshCamera.call(this);
},
getRenderer: function () {
return this._private._renderer;
},
getFov: function () {
return this._private.fov;
},
setFov: function (value) {
this._private.fov = Helpers.checkNumberValid(value);
_refreshCamera.call(this);
},
getNear: function () {
return this._private.near;
},
setNear: function (value) {
this._private.near = Helpers.checkNumberValid(value);
_refreshCamera.call(this);
},
getFar: function () {
return this._private.far;
},
setFar: function (value) {
this._private.far = Helpers.checkNumberValid(value);
_refreshCamera.call(this);
},
// in the short tern, just to ensure all number passed are not NaNs...
colourHelper: function (value) {
var _passed = true;
if (value.length) {
for (var i = 0; i < value.length; i++) {
if (isNaN(value[i])) _passed = false;
}
}
return _passed;
},
getBackgroundColour: function () {
return this._private.backgroundColour;
},
setBackgroundColour: function (value) {
this._private.backgroundColour = value;
},
getLightColour: function () {
return this._private.lightColour;
},
setLightColour: function (value) {
this._private.lightColour = value;
//console.log("New light col : ",value)
try {
this._private._light.color = new THREE.Color(value);
} catch (err) {
// console.log(err)
}
},
getAmbientLightColour: function () {
return this._private.ambientColour;
},
setAmbientLightColour: function (value) {
this._private.ambientColour = value;
// console.log("New ambient col : ",value)
try {
this._private._lightAmbient.color = new THREE.Color(value);
} catch (err) {
// console.log(err)
}
},
getScene: function () {
return this._private._scene;
},
getFullScreen: function () {
return this._private.fullscreen;
},
setFullScreen: function (value) {
this._private.fullscreen = value;
},
setPlaying: function (value) {
this._private._playing = value;
if (value) {
this.animate.call(this);
}
},
getPlaying: function () {
return this._private._playing;
}
};
return _scope;
}();
module.exports = { Scene: ThreeDeeScene, Sprite: ThreeDeeSprite, THREE: THREE, ColorHelpers: ColorHelpers };
/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {
var THREE = __webpack_require__(2),
Helpers = __webpack_require__(3);
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;
//
console.log("Update positions ", mesh.position.y = this._private._y);
};
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._private._spriteEventDispatcher.addEventListener(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;
}();
module.exports = ThreeDeeSprite;
/***/ },
/* 2 */
/***/ function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;var self = self || {};// File:src/Three.js
/**
* @author mrdoob / http://mrdoob.com/
*/
var THREE = { REVISION: '73' };
//
if ( true ) {
!(__WEBPACK_AMD_DEFINE_FACTORY__ = (THREE), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
} else if ( 'undefined' !== typeof exports && 'undefined' !== typeof module ) {
module.exports = THREE;
}
// polyfills
if ( self.requestAnimationFrame === undefined || self.cancelAnimationFrame === undefined ) {
// Missing in Android stock browser.
( function () {
var lastTime = 0;
var vendors = [ 'ms', 'moz', 'webkit', 'o' ];
for ( var x = 0; x < vendors.length && ! self.requestAnimationFrame; ++ x ) {
self.requestAnimationFrame = self[ vendors[ x ] + 'RequestAnimationFrame' ];
self.cancelAnimationFrame = self[ vendors[ x ] + 'CancelAnimationFrame' ] || self[ vendors[ x ] + 'CancelRequestAnimationFrame' ];
}
if ( self.requestAnimationFrame === undefined && self.setTimeout !== undefined ) {
self.requestAnimationFrame = function ( callback ) {
var currTime = Date.now(), timeToCall = Math.max( 0, 16 - ( currTime - lastTime ) );
var id = self.setTimeout( function () {
callback( currTime + timeToCall );
}, timeToCall );
lastTime = currTime + timeToCall;
return id;
};
}
if ( self.cancelAnimationFrame === undefined && self.clearTimeout !== undefined ) {
self.cancelAnimationFrame = function ( id ) {
self.clearTimeout( id );
};
}
} )();
}
//
if ( self.performance === undefined ) {
self.performance = {};
}
if ( self.performance.now === undefined ) {
( function () {
var start = Date.now();
self.performance.now = function () {
return Date.now() - start;
}
} )();
}
//
if ( Number.EPSILON === undefined ) {
Number.EPSILON = Math.pow( 2, -52 );
}
//
if ( Math.sign === undefined ) {
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign
Math.sign = function ( x ) {
return ( x < 0 ) ? - 1 : ( x > 0 ) ? 1 : + x;
};
}
if ( Function.prototype.name === undefined && Object.defineProperty !== undefined ) {
// Missing in IE9-11.
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name
Object.defineProperty( Function.prototype, 'name', {
get: function () {
return this.toString().match( /^\s*function\s*(\S*)\s*\(/ )[ 1 ];
}
} );
}
// https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent.button
THREE.MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2 };
// GL STATE CONSTANTS
THREE.CullFaceNone = 0;
THREE.CullFaceBack = 1;
THREE.CullFaceFront = 2;
THREE.CullFaceFrontBack = 3;
THREE.FrontFaceDirectionCW = 0;
THREE.FrontFaceDirectionCCW = 1;
// SHADOWING TYPES
THREE.BasicShadowMap = 0;
THREE.PCFShadowMap = 1;
THREE.PCFSoftShadowMap = 2;
// MATERIAL CONSTANTS
// side
THREE.FrontSide = 0;
THREE.BackSide = 1;
THREE.DoubleSide = 2;
// shading
THREE.FlatShading = 1;
THREE.SmoothShading = 2;
// colors
THREE.NoColors = 0;
THREE.FaceColors = 1;
THREE.VertexColors = 2;
// blending modes
THREE.NoBlending = 0;
THREE.NormalBlending = 1;
THREE.AdditiveBlending = 2;
THREE.SubtractiveBlending = 3;
THREE.MultiplyBlending = 4;
THREE.CustomBlending = 5;
// custom blending equations
// (numbers start from 100 not to clash with other
// mappings to OpenGL constants defined in Texture.js)
THREE.AddEquation = 100;
THREE.SubtractEquation = 101;
THREE.ReverseSubtractEquation = 102;
THREE.MinEquation = 103;
THREE.MaxEquation = 104;
// custom blending destination factors
THREE.ZeroFactor = 200;
THREE.OneFactor = 201;
THREE.SrcColorFactor = 202;
THREE.OneMinusSrcColorFactor = 203;
THREE.SrcAlphaFactor = 204;
THREE.OneMinusSrcAlphaFactor = 205;
THREE.DstAlphaFactor = 206;
THREE.OneMinusDstAlphaFactor = 207;
// custom blending source factors
//THREE.ZeroFactor = 200;
//THREE.OneFactor = 201;
//THREE.SrcAlphaFactor = 204;
//THREE.OneMinusSrcAlphaFactor = 205;
//THREE.DstAlphaFactor = 206;
//THREE.OneMinusDstAlphaFactor = 207;
THREE.DstColorFactor = 208;
THREE.OneMinusDstColorFactor = 209;
THREE.SrcAlphaSaturateFactor = 210;
// depth modes
THREE.NeverDepth = 0;
THREE.AlwaysDepth = 1;
THREE.LessDepth = 2;
THREE.LessEqualDepth = 3;
THREE.EqualDepth = 4;
THREE.GreaterEqualDepth = 5;
THREE.GreaterDepth = 6;
THREE.NotEqualDepth = 7;
// TEXTURE CONSTANTS
THREE.MultiplyOperation = 0;
THREE.MixOperation = 1;
THREE.AddOperation = 2;
// Mapping modes
THREE.UVMapping = 300;
THREE.CubeReflectionMapping = 301;
THREE.CubeRefractionMapping = 302;
THREE.EquirectangularReflectionMapping = 303;
THREE.EquirectangularRefractionMapping = 304;
THREE.SphericalReflectionMapping = 305;
// Wrapping modes
THREE.RepeatWrapping = 1000;
THREE.ClampToEdgeWrapping = 1001;
THREE.MirroredRepeatWrapping = 1002;
// Filters
THREE.NearestFilter = 1003;
THREE.NearestMipMapNearestFilter = 1004;
THREE.NearestMipMapLinearFilter = 1005;
THREE.LinearFilter = 1006;
THREE.LinearMipMapNearestFilter = 1007;
THREE.LinearMipMapLinearFilter = 1008;
// Data types
THREE.UnsignedByteType = 1009;
THREE.ByteType = 1010;
THREE.ShortType = 1011;
THREE.UnsignedShortType = 1012;
THREE.IntType = 1013;
THREE.UnsignedIntType = 1014;
THREE.FloatType = 1015;
THREE.HalfFloatType = 1025;
// Pixel types
//THREE.UnsignedByteType = 1009;
THREE.UnsignedShort4444Type = 1016;
THREE.UnsignedShort5551Type = 1017;
THREE.UnsignedShort565Type = 1018;
// Pixel formats
THREE.AlphaFormat = 1019;
THREE.RGBFormat = 1020;
THREE.RGBAFormat = 1021;
THREE.LuminanceFormat = 1022;
THREE.LuminanceAlphaFormat = 1023;
// THREE.RGBEFormat handled as THREE.RGBAFormat in shaders
THREE.RGBEFormat = THREE.RGBAFormat; //1024;
// DDS / ST3C Compressed texture formats
THREE.RGB_S3TC_DXT1_Format = 2001;
THREE.RGBA_S3TC_DXT1_Format = 2002;
THREE.RGBA_S3TC_DXT3_Format = 2003;
THREE.RGBA_S3TC_DXT5_Format = 2004;
// PVRTC compressed texture formats
THREE.RGB_PVRTC_4BPPV1_Format = 2100;
THREE.RGB_PVRTC_2BPPV1_Format = 2101;
THREE.RGBA_PVRTC_4BPPV1_Format = 2102;
THREE.RGBA_PVRTC_2BPPV1_Format = 2103;
// Loop styles for AnimationAction
THREE.LoopOnce = 2200;
THREE.LoopRepeat = 2201;
THREE.LoopPingPong = 2202;
// DEPRECATED
THREE.Projector = function () {
console.error( 'THREE.Projector has been moved to /examples/js/renderers/Projector.js.' );
this.projectVector = function ( vector, camera ) {
console.warn( 'THREE.Projector: .projectVector() is now vector.project().' );
vector.project( camera );
};
this.unprojectVector = function ( vector, camera ) {
console.warn( 'THREE.Projector: .unprojectVector() is now vector.unproject().' );
vector.unproject( camera );
};
this.pickingRay = function ( vector, camera ) {
console.error( 'THREE.Projector: .pickingRay() is now raycaster.setFromCamera().' );
};
};
THREE.CanvasRenderer = function () {
console.error( 'THREE.CanvasRenderer has been moved to /examples/js/renderers/CanvasRenderer.js' );
this.domElement = document.createElement( 'canvas' );
this.clear = function () {};
this.render = function () {};
this.setClearColor = function () {};
this.setSize = function () {};
};
// File:src/math/Color.js
/**
* @author mrdoob / http://mrdoob.com/
*/
THREE.Color = function ( color ) {
if ( arguments.length === 3 ) {
return this.fromArray( arguments );
}
return this.set( color );
};
THREE.Color.prototype = {
constructor: THREE.Color,
r: 1, g: 1, b: 1,
set: function ( value ) {
if ( value instanceof THREE.Color ) {
this.copy( value );
} else if ( typeof value === 'number' ) {
this.setHex( value );
} else if ( typeof value === 'string' ) {
this.setStyle( value );
}
return this;
},
setHex: function ( hex ) {
hex = Math.floor( hex );
this.r = ( hex >> 16 & 255 ) / 255;
this.g = ( hex >> 8 & 255 ) / 255;
this.b = ( hex & 255 ) / 255;
return this;
},
setRGB: function ( r, g, b ) {
this.r = r;
this.g = g;
this.b = b;
return this;
},
setHSL: function () {
function hue2rgb( p, q, t ) {
if ( t < 0 ) t += 1;
if ( t > 1 ) t -= 1;
if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t;
if ( t < 1 / 2 ) return q;
if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t );
return p;
}
return function ( h, s, l ) {
// h,s,l ranges are in 0.0 - 1.0
h = THREE.Math.euclideanModulo( h, 1 );
s = THREE.Math.clamp( s, 0, 1 );
l = THREE.Math.clamp( l, 0, 1 );
if ( s === 0 ) {
this.r = this.g = this.b = l;
} else {
var p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s );
var q = ( 2 * l ) - p;
this.r = hue2rgb( q, p, h + 1 / 3 );
this.g = hue2rgb( q, p, h );
this.b = hue2rgb( q, p, h - 1 / 3 );
}
return this;
};
}(),
setStyle: function ( style ) {
function handleAlpha( string ) {
if ( string === undefined ) return;
if ( parseFloat( string ) < 1 ) {
console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' );
}
}
var m;
if ( m = /^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec( style ) ) {
// rgb / hsl
var color;
var name = m[ 1 ];
var components = m[ 2 ];
switch ( name ) {
case 'rgb':
case 'rgba':
if ( color = /^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
// rgb(255,0,0) rgba(255,0,0,0.5)
this.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255;
this.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255;
this.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255;
handleAlpha( color[ 5 ] );
return this;
}
if ( color = /^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
// rgb(100%,0%,0%) rgba(100%,0%,0%,0.5)
this.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100;
this.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100;
this.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100;
handleAlpha( color[ 5 ] );
return this;
}
break;
case 'hsl':
case 'hsla':
if ( color = /^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
// hsl(120,50%,50%) hsla(120,50%,50%,0.5)
var h = parseFloat( color[ 1 ] ) / 360;
var s = parseInt( color[ 2 ], 10 ) / 100;
var l = parseInt( color[ 3 ], 10 ) / 100;
handleAlpha( color[ 5 ] );
return this.setHSL( h, s, l );
}
break;
}
} else if ( m = /^\#([A-Fa-f0-9]+)$/.exec( style ) ) {
// hex color
var hex = m[ 1 ];
var size = hex.length;
if ( size === 3 ) {
// #ff0
this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255;
this.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255;
this.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255;
return this;
} else if ( size === 6 ) {
// #ff0000
this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255;
this.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255;
this.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255;
return this;
}
}
if ( style && style.length > 0 ) {
// color keywords
var hex = THREE.ColorKeywords[ style ];
if ( hex !== undefined ) {
// red
this.setHex( hex );
} else {
// unknown color
console.warn( 'THREE.Color: Unknown color ' + style );
}
}
return this;
},
clone: function () {
return new this.constructor( this.r, this.g, this.b );
},
copy: function ( color ) {
this.r = color.r;
this.g = color.g;
this.b = color.b;
return this;
},
copyGammaToLinear: function ( color, gammaFactor ) {
if ( gammaFactor === undefined ) gammaFactor = 2.0;
this.r = Math.pow( color.r, gammaFactor );
this.g = Math.pow( color.g, gammaFactor );
this.b = Math.pow( color.b, gammaFactor );
return this;
},
copyLinearToGamma: function ( color, gammaFactor ) {
if ( gammaFactor === undefined ) gammaFactor = 2.0;
var safeInverse = ( gammaFactor > 0 ) ? ( 1.0 / gammaFactor ) : 1.0;
this.r = Math.pow( color.r, safeInverse );
this.g = Math.pow( color.g, safeInverse );
this.b = Math.pow( color.b, safeInverse );
return this;
},
convertGammaToLinear: function () {
var r = this.r, g = this.g, b = this.b;
this.r = r * r;
this.g = g * g;
this.b = b * b;
return this;
},
convertLinearToGamma: function () {
this.r = Math.sqrt( this.r );
this.g = Math.sqrt( this.g );
this.b = Math.sqrt( this.b );
return this;
},
getHex: function () {
return ( this.r * 255 ) << 16 ^ ( this.g * 255 ) << 8 ^ ( this.b * 255 ) << 0;
},
getHexString: function () {
return ( '000000' + this.getHex().toString( 16 ) ).slice( - 6 );
},
getHSL: function ( optionalTarget ) {
// h,s,l ranges are in 0.0 - 1.0
var hsl = optionalTarget || { h: 0, s: 0, l: 0 };
var r = this.r, g = this.g, b = this.b;
var max = Math.max( r, g, b );
var min = Math.min( r, g, b );
var hue, saturation;
var lightness = ( min + max ) / 2.0;
if ( min === max ) {
hue = 0;
saturation = 0;
} else {
var delta = max - min;
saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min );
switch ( max ) {
case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break;
case g: hue = ( b - r ) / delta + 2; break;
case b: hue = ( r - g ) / delta + 4; break;
}
hue /= 6;
}
hsl.h = hue;
hsl.s = saturation;
hsl.l = lightness;
return hsl;
},
getStyle: function () {
return 'rgb(' + ( ( this.r * 255 ) | 0 ) + ',' + ( ( this.g * 255 ) | 0 ) + ',' + ( ( this.b * 255 ) | 0 ) + ')';
},
offsetHSL: function ( h, s, l ) {
var hsl = this.getHSL();
hsl.h += h; hsl.s += s; hsl.l += l;
this.setHSL( hsl.h, hsl.s, hsl.l );
return this;
},
add: function ( color ) {
this.r += color.r;
this.g += color.g;
this.b += color.b;
return this;
},
addColors: function ( color1, color2 ) {
this.r = color1.r + color2.r;
this.g = color1.g + color2.g;
this.b = color1.b + color2.b;
return this;
},
addScalar: function ( s ) {
this.r += s;
this.g += s;
this.b += s;
return this;
},
multiply: function ( color ) {
this.r *= color.r;
this.g *= color.g;
this.b *= color.b;
return this;
},
multiplyScalar: function ( s ) {
this.r *= s;
this.g *= s;
this.b *= s;
return this;
},
lerp: function ( color, alpha ) {
this.r += ( color.r - this.r ) * alpha;
this.g += ( color.g - this.g ) * alpha;
this.b += ( color.b - this.b ) * alpha;
return this;
},
equals: function ( c ) {
return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b );
},
fromArray: function ( array, offset ) {
if ( offset === undefined ) offset = 0;
this.r = array[ offset ];
this.g = array[ offset + 1 ];
this.b = array[ offset + 2 ];
return this;
},
toArray: function ( array, offset ) {
if ( array === undefined ) array = [];
if ( offset === undefined ) offset = 0;
array[ offset ] = this.r;
array[ offset + 1 ] = this.g;
array[ offset + 2 ] = this.b;
return array;
}
};
THREE.ColorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF,
'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2,
'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50,
'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B,
'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B,
'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F,
'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3,
'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222,
'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700,
'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4,
'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00,
'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3,
'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA,
'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32,
'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3,
'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC,
'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD,
'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6,
'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9,
'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F,
'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE,
'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA,
'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0,
'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF,