UNPKG

kaleidoscopejs

Version:
1,948 lines (1,794 loc) 517 kB
var utils = { isiOS: function isiOS() { return /(ipad|iphone|ipod)/ig.test(navigator.userAgent); }, isEdge: function isEdge() { return /(Edge)/ig.test(navigator.userAgent); }, shouldUseAudioDriver: function shouldUseAudioDriver() { var isOldiOSOnIphone = /iphone.*(7|8|9)_[0-9]/i.test(navigator.userAgent); var isWebView = /(iPhone|iPod).*AppleWebKit(?!.*Safari)/i.test(navigator.userAgent); return isOldiOSOnIphone || isWebView; }, shouldUseCanvasInBetween: function shouldUseCanvasInBetween() { return /trident|edge/i.test(navigator.userAgent); } }; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; } function _get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); } // File:src/Three.js /** * @author mrdoob / http://mrdoob.com/ */ var THREE = { REVISION: '75' }; // var threejs360 = THREE; // 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]; } }); } if (Object.assign === undefined) { // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign Object.defineProperty(Object, 'assign', { writable: true, configurable: true, value: function (target) { if (target === undefined || target === null) { throw new TypeError("Cannot convert first argument to object"); } var to = Object(target); for (var i = 1, n = arguments.length; i !== n; ++i) { var nextSource = arguments[i]; if (nextSource === undefined || nextSource === null) continue; nextSource = Object(nextSource); var keysArray = Object.keys(nextSource); for (var nextIndex = 0, len = keysArray.length; nextIndex !== len; ++nextIndex) { var nextKey = keysArray[nextIndex]; var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey); if (desc !== undefined && desc.enumerable) { to[nextKey] = nextSource[nextKey]; } } } return to; } }); } // 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; // Tone Mapping modes THREE.NoToneMapping = 0; // do not do any tone mapping, not even exposure (required for special purpose passes.) THREE.LinearToneMapping = 1; // only apply exposure. THREE.ReinhardToneMapping = 2; THREE.Uncharted2ToneMapping = 3; // John Hable THREE.CineonToneMapping = 4; // optimized filmic operator by Jim Hejl and Richard Burgess-Dawson // Mapping modes THREE.UVMapping = 300; THREE.CubeReflectionMapping = 301; THREE.CubeRefractionMapping = 302; THREE.EquirectangularReflectionMapping = 303; THREE.EquirectangularRefractionMapping = 304; THREE.SphericalReflectionMapping = 305; THREE.CubeUVReflectionMapping = 306; THREE.CubeUVRefractionMapping = 307; // 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; // ETC compressed texture formats THREE.RGB_ETC1_Format = 2151; // Loop styles for AnimationAction THREE.LoopOnce = 2200; THREE.LoopRepeat = 2201; THREE.LoopPingPong = 2202; // Interpolation THREE.InterpolateDiscrete = 2300; THREE.InterpolateLinear = 2301; THREE.InterpolateSmooth = 2302; // Interpolant ending modes THREE.ZeroCurvatureEnding = 2400; THREE.ZeroSlopeEnding = 2401; THREE.WrapAroundEnding = 2402; // Triangle Draw modes THREE.TrianglesDrawMode = 0; THREE.TriangleStripDrawMode = 1; THREE.TriangleFanDrawMode = 2; // Texture Encodings THREE.LinearEncoding = 3000; // No encoding at all. THREE.sRGBEncoding = 3001; THREE.GammaEncoding = 3007; // uses GAMMA_FACTOR, for backwards compatibility with WebGLRenderer.gammaInput/gammaOutput // The following Texture Encodings are for RGB-only (no alpha) HDR light emission sources. // These encodings should not specified as output encodings except in rare situations. THREE.RGBEEncoding = 3002; // AKA Radiance. THREE.LogLuvEncoding = 3003; THREE.RGBM7Encoding = 3004; THREE.RGBM16Encoding = 3005; THREE.RGBDEncoding = 3006; // MaxRange is 256. // File:src/math/Math.js /** * @author alteredq / http://alteredqualia.com/ * @author mrdoob / http://mrdoob.com/ */ THREE.Math = { generateUUID: function () { // http://www.broofa.com/Tools/Math.uuid.htm var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split(''); var uuid = new Array(36); var rnd = 0, r; return function () { for (var i = 0; i < 36; i++) { if (i === 8 || i === 13 || i === 18 || i === 23) { uuid[i] = '-'; } else if (i === 14) { uuid[i] = '4'; } else { if (rnd <= 0x02) rnd = 0x2000000 + Math.random() * 0x1000000 | 0; r = rnd & 0xf; rnd = rnd >> 4; uuid[i] = chars[i === 19 ? r & 0x3 | 0x8 : r]; } } return uuid.join(''); }; }(), clamp: function (value, min, max) { return Math.max(min, Math.min(max, value)); }, // compute euclidian modulo of m % n // https://en.wikipedia.org/wiki/Modulo_operation euclideanModulo: function (n, m) { return (n % m + m) % m; }, // Linear mapping from range <a1, a2> to range <b1, b2> mapLinear: function (x, a1, a2, b1, b2) { return b1 + (x - a1) * (b2 - b1) / (a2 - a1); }, // http://en.wikipedia.org/wiki/Smoothstep smoothstep: function (x, min, max) { if (x <= min) return 0; if (x >= max) return 1; x = (x - min) / (max - min); return x * x * (3 - 2 * x); }, smootherstep: function (x, min, max) { if (x <= min) return 0; if (x >= max) return 1; x = (x - min) / (max - min); return x * x * x * (x * (x * 6 - 15) + 10); }, random16: function () { return Math.random(); }, // Random integer from <low, high> interval randInt: function (low, high) { return low + Math.floor(Math.random() * (high - low + 1)); }, // Random float from <low, high> interval randFloat: function (low, high) { return low + Math.random() * (high - low); }, // Random float from <-range/2, range/2> interval randFloatSpread: function (range) { return range * (0.5 - Math.random()); }, degToRad: function () { var degreeToRadiansFactor = Math.PI / 180; return function (degrees) { return degrees * degreeToRadiansFactor; }; }(), radToDeg: function () { var radianToDegreesFactor = 180 / Math.PI; return function (radians) { return radians * radianToDegreesFactor; }; }(), isPowerOfTwo: function (value) { return (value & value - 1) === 0 && value !== 0; }, nearestPowerOfTwo: function (value) { return Math.pow(2, Math.round(Math.log(value) / Math.LN2)); }, nextPowerOfTwo: function (value) { value--; value |= value >> 1; value |= value >> 2; value |= value >> 4; value |= value >> 8; value |= value >> 16; value++; return value; } }; // 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; }, setScalar: function (scalar) { this.r = scalar; this.g = scalar; this.b = scalar; }, 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; } 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); } } 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, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 }; // File:src/math/Vector2.js /** * @author mrdoob / http://mrdoob.com/ * @author philogb / http://blog.thejit.org/ * @author egraether / http://egraether.com/ * @author zz85 / http://www.lab4games.net/zz85/blog */ THREE.Vector2 = function (x, y) { this.x = x || 0; this.y = y || 0; }; THREE.Vector2.prototype = { constructor: THREE.Vector2, get width() { return this.x; }, set width(value) { this.x = value; }, get height() { return this.y; }, set height(value) { this.y = value; }, // set: function (x, y) { this.x = x; this.y = y; return this; }, setScalar: function (scalar) { this.x = scalar; this.y = scalar; return this; }, setX: function (x) { this.x = x; return this; }, setY: function (y) { this.y = y; return this; }, setComponent: function (index, value) { switch (index) { case 0: this.x = value; break; case 1: this.y = value; break; default: throw new Error('index is out of range: ' + index); } }, getComponent: function (index) { switch (index) { case 0: return this.x; case 1: return this.y; default: throw new Error('index is out of range: ' + index); } }, clone: function () { return new this.constructor(this.x, this.y); }, copy: function (v) { this.x = v.x; this.y = v.y; return this; }, add: function (v, w) { if (w !== undefined) { return this.addVectors(v, w); } this.x += v.x; this.y += v.y; return this; }, addScalar: function (s) { this.x += s; this.y += s; return this; }, addVectors: function (a, b) { this.x = a.x + b.x; this.y = a.y + b.y; return this; }, addScaledVector: function (v, s) { this.x += v.x * s; this.y += v.y * s; return this; }, sub: function (v, w) { if (w !== undefined) { return this.subVectors(v, w); } this.x -= v.x; this.y -= v.y; return this; }, subScalar: function (s) { this.x -= s; this.y -= s; return this; }, subVectors: function (a, b) { this.x = a.x - b.x; this.y = a.y - b.y; return this; }, multiply: function (v) { this.x *= v.x; this.y *= v.y; return this; }, multiplyScalar: function (scalar) { if (isFinite(scalar)) { this.x *= scalar; this.y *= scalar; } else { this.x = 0; this.y = 0; } return this; }, divide: function (v) { this.x /= v.x; this.y /= v.y; return this; }, divideScalar: function (scalar) { return this.multiplyScalar(1 / scalar); }, min: function (v) { this.x = Math.min(this.x, v.x); this.y = Math.min(this.y, v.y); return this; }, max: function (v) { this.x = Math.max(this.x, v.x); this.y = Math.max(this.y, v.y); return this; }, clamp: function (min, max) { // This function assumes min < max, if this assumption isn't true it will not operate correctly this.x = Math.max(min.x, Math.min(max.x, this.x)); this.y = Math.max(min.y, Math.min(max.y, this.y)); return this; }, clampScalar: function () { var min, max; return function clampScalar(minVal, maxVal) { if (min === undefined) { min = new THREE.Vector2(); max = new THREE.Vector2(); } min.set(minVal, minVal); max.set(maxVal, maxVal); return this.clamp(min, max); }; }(), clampLength: function (min, max) { var length = this.length(); this.multiplyScalar(Math.max(min, Math.min(max, length)) / length); return this; }, floor: function () { this.x = Math.floor(this.x); this.y = Math.floor(this.y); return this; }, ceil: function () { this.x = Math.ceil(this.x); this.y = Math.ceil(this.y); return this; }, round: function () { this.x = Math.round(this.x); this.y = Math.round(this.y); return this; }, roundToZero: function () { this.x = this.x < 0 ? Math.ceil(this.x) : Math.floor(this.x); this.y = this.y < 0 ? Math.ceil(this.y) : Math.floor(this.y); return this; }, negate: function () { this.x = -this.x; this.y = -this.y; return this; }, dot: function (v) { return this.x * v.x + this.y * v.y; }, lengthSq: function () { return this.x * this.x + this.y * this.y; }, length: function () { return Math.sqrt(this.x * this.x + this.y * this.y); }, lengthManhattan: function () { return Math.abs(this.x) + Math.abs(this.y); }, normalize: function () { return this.divideScalar(this.length()); }, angle: function () { // computes the angle in radians with respect to the positive x-axis var angle = Math.atan2(this.y, this.x); if (angle < 0) angle += 2 * Math.PI; return angle; }, distanceTo: function (v) { return Math.sqrt(this.distanceToSquared(v)); }, distanceToSquared: function (v) { var dx = this.x - v.x, dy = this.y - v.y; return dx * dx + dy * dy; }, setLength: function (length) { return this.multiplyScalar(length / this.length()); }, lerp: function (v, alpha) { this.x += (v.x - this.x) * alpha; this.y += (v.y - this.y) * alpha; return this; }, lerpVectors: function (v1, v2, alpha) { this.subVectors(v2, v1).multiplyScalar(alpha).add(v1); return this; }, equals: function (v) { return v.x === this.x && v.y === this.y; }, fromArray: function (array, offset) { if (offset === undefined) offset = 0; this.x = array[offset]; this.y = array[offset + 1]; return this; }, toArray: function (array, offset) { if (array === undefined) array = []; if (offset === undefined) offset = 0; array[offset] = this.x; array[offset + 1] = this.y; return array; }, fromAttribute: function (attribute, index, offset) { if (offset === undefined) offset = 0; index = index * attribute.itemSize + offset; this.x = attribute.array[index]; this.y = attribute.array[index + 1]; return this; }, rotateAround: function (center, angle) { var c = Math.cos(angle), s = Math.sin(angle); var x = this.x - center.x; var y = this.y - center.y; this.x = x * c - y * s + center.x; this.y = x * s + y * c + center.y; return this; } }; // File:src/math/Vector3.js /** * @author mrdoob / http://mrdoob.com/ * @author *kile / http://kile.stravaganza.org/ * @author philogb / http://blog.thejit.org/ * @author mikael emtinger / http://gomo.se/ * @author egraether / http://egraether.com/ * @author WestLangley / http://github.com/WestLangley */ THREE.Vector3 = function (x, y, z) { this.x = x || 0; this.y = y || 0; this.z = z || 0; }; THREE.Vector3.prototype = { constructor: THREE.Vector3, set: function (x, y, z) { this.x = x; this.y = y; this.z = z; return this; }, setScalar: function (scalar) { this.x = scalar; this.y = scalar; this.z = scalar; return this; }, setX: function (x) { this.x = x; return this; }, setY: function (y) { this.y = y; return this; }, setZ: function (z) { this.z = z; return this; }, setComponent: function (index, value) { switch (index) { case 0: this.x = value; break; case 1: this.y = value; break; case 2: this.z = value; break; default: throw new Error('index is out of range: ' + index); } }, getComponent: function (index) { switch (index) { case 0: return this.x; case 1: return this.y; case 2: return this.z; default: throw new Error('index is out of range: ' + index); } }, clone: function () { return new this.constructor(this.x, this.y, this.z); }, copy: function (v) { this.x = v.x; this.y = v.y; this.z = v.z; return this; }, add: function (v, w) { if (w !== undefined) { return this.addVectors(v, w); } this.x += v.x; this.y += v.y; this.z += v.z; return this; }, addScalar: function (s) { this.x += s; this.y += s; this.z += s; return this; }, addVectors: function (a, b) { this.x = a.x + b.x; this.y = a.y + b.y; this.z = a.z + b.z; return this; }, addScaledVector: function (v, s) { this.x += v.x * s; this.y += v.y * s; this.z += v.z * s; return this; }, sub: function (v, w) { if (w !== undefined) { return this.subVectors(v, w); } this.x -= v.x; this.y -= v.y; this.z -= v.z; return this; }, subScalar: function (s) { this.x -= s; this.y -= s; this.z -= s; return this; }, subVectors: function (a, b) { this.x = a.x - b.x; this.y = a.y - b.y; this.z = a.z - b.z; return this; }, multiply: function (v, w) { if (w !== undefined) { return this.multiplyVectors(v, w); } this.x *= v.x; this.y *= v.y; this.z *= v.z; return this; }, multiplyScalar: function (scalar) { if (isFinite(scalar)) { this.x *= scalar; this.y *= scalar; this.z *= scalar; } else { this.x = 0; this.y = 0; this.z = 0; } return this; }, multiplyVectors: function (a, b) { this.x = a.x * b.x; this.y = a.y * b.y; this.z = a.z * b.z; return this; }, applyEuler: function () { var quaternion; return function applyEuler(euler) { if (quaternion === undefined) quaternion = new THREE.Quaternion(); this.applyQuaternion(quaternion.setFromEuler(euler)); return this; }; }(), applyAxisAngle: function () { var quaternion; return function applyAxisAngle(axis, angle) { if (quaternion === undefined) quaternion = new THREE.Quaternion(); this.applyQuaternion(quaternion.setFromAxisAngle(axis, angle)); return this; }; }(), applyMatrix3: function (m) { var x = this.x; var y = this.y; var z = this.z; var e = m.elements; this.x = e[0] * x + e[3] * y + e[6] * z; this.y = e[1] * x + e[4] * y + e[7] * z; this.z = e[2] * x + e[5] * y + e[8] * z; return this; }, applyMatrix4: function (m) { // input: THREE.Matrix4 affine matrix var x = this.x, y = this.y, z = this.z; var e = m.elements; this.x = e[0] * x + e[4] * y + e[8] * z + e[12]; this.y = e[1] * x + e[5] * y + e[9] * z + e[13]; this.z = e[2] * x + e[6] * y + e[10] * z + e[14]; return this; }, applyProjection: function (m) { // input: THREE.Matrix4 projection matrix var x = this.x, y = this.y, z = this.z; var e = m.elements; var d = 1 / (e[3] * x + e[7] * y + e[11] * z + e[15]); // perspective divide this.x = (e[0] * x + e[4] * y + e[8] * z + e[12]) * d; this.y = (e[1] * x + e[5] * y + e[9] * z + e[13]) * d; this.z = (e[2] * x + e[6] * y + e[10] * z + e[14]) * d; return this; }, applyQuaternion: function (q) { var x = this.x; var y = this.y; var z = this.z; var qx = q.x; var qy = q.y; var qz = q.z; var qw = q.w; // calculate quat * vector var ix = qw * x + qy * z - qz * y; var iy = qw * y + qz * x - qx * z; var iz = qw * z + qx * y - qy * x; var iw = -qx * x - qy * y - qz * z; // calculate result * inverse quat this.x = ix * qw + iw * -qx + iy * -qz - iz * -qy; this.y = iy * qw + iw * -qy + iz * -qx - ix * -qz; this.z = iz * qw + iw * -qz + ix * -qy - iy * -qx; return this; }, project: function () { var matrix; return function project(camera) { if (matrix === undefined) matrix = new THREE.Matrix4(); matrix.multiplyMatrices(camera.projectionMatrix, matrix.getInverse(camera.matrixWorld)); return this.applyProjection(matrix); }; }(), unproject: function () { var matrix; return function unproject(camera) { if (matrix === undefined) matrix = new THREE.Matrix4(); matrix.multiplyMatrices(camera.matrixWorld, matrix.getInverse(camera.projectionMatrix)); return this.applyProjection(matrix); }; }(), transformDirection: function (m) { // input: THREE.Matrix4 affine matrix // vector interpreted as a direction var x = this.x, y = this.y, z = this.z; var e = m.elements; this.x = e[0] * x + e[4] * y + e[8] * z; this.y = e[1] * x + e[5] * y + e[9] * z; this.z = e[2] * x + e[6] * y + e[10] * z; this.normalize(); return this; }, divide: function (v) { this.x /= v.x; this.y /= v.y; this.z /= v.z; return this; }, divideScalar: function (scalar) { return this.multiplyScalar(1 / scalar); }, min: function (v) { this.x = Math.min(this.x, v.x); this.y = Math.min(this.y, v.y); this.z = Math.min(this.z, v.z); return this; }, max: function (v) { this.x = Math.max(this.x, v.x); this.y = Math.max(this.y, v.y); this.z = Math.max(this.z, v.z); return this; }, clamp: function (min, max) { // This function assumes min < max, if this assumption isn't true it will not operate correctly this.x = Math.max(min.x, Math.min(max.x, this.x)); this.y = Math.max(min.y, Math.min(max.y, this.y)); this.z = Math.max(min.z, Math.min(max.z, this.z)); return this; }, clampScalar: function () { var min, max; return function clampScalar(minVal, maxVal) { if (min === undefined) { min = new THREE.Vector3(); max = new THREE.Vector3(); } min.set(minVal, minVal, minVal); max.set(maxVal, maxVal, maxVal); return this.clamp(min, max); }; }(), clampLength: function (min, max) { var length = this.length(); this.multiplyScalar(Math.max(min, Math.min(max, length)) / length); return this; }, floor: function () { this.x = Math.floor(this.x); this.y = Math.floor(this.y); this.z = Math.floor(this.z); return this; }, ceil: function () { this.x = Math.ceil(this.x); this.y = Math.ceil(this.y); this.z = Math.ceil(this.z); return this; }, round: function () { this.x = Math.round(this.x); this.y = Math.round(this.y); this.z = Math.round(this.z); return this; }, roundToZero: function () { this.x = this.x < 0 ? Math.ceil(this.x) : Math.floor(this.x); this.y = this.y < 0 ? Math.ceil(this.y) : Math.floor(this.y); this.z = this.z < 0 ? Math.ceil(this.z) : Math.floor(this.z); return this; }, negate: function () { this.x = -this.x; this.y = -this.y; this.z = -this.z; return this; }, dot: function (v) { return this.x * v.x + this.y * v.y + this.z * v.z; }, lengthSq: function () { return this.x * this.x + this.y * this.y + this.z * this.z; }, length: function () { return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); }, lengthManhattan: function () { return Math.abs(this.x) + Math.abs(this.y) + Math.abs(this.z); }, normalize: function () { return this.divideScalar(this.length()); }, setLength: function (length) { return this.multiplyScalar(length / this.length()); }, lerp: function (v, alpha) { this.x += (v.x - this.x) * alpha; this.y += (v.y - this.y) * alpha; this.z += (v.z - this.z) * alpha; return this; }, lerpVectors: function (v1, v2, alpha) { this.subVectors(v2, v1).multiplyScalar(alpha).add(v1); return this; }, cross: function (v, w) { if (w !== undefined) { return this.crossVectors(v, w); } var x = this.x, y = this.y, z = this.z; this.x = y * v.z - z * v.y; this.y = z * v.x - x * v.z; this.z = x * v.y - y * v.x; return this; }, crossVectors: function (a, b) { var ax = a.x, ay = a.y, az = a.z; var bx = b.x, by = b.y, bz = b.z; this.x = ay * bz - az * by; this.y = az * bx - ax * bz; this.z = ax * by - ay * bx; return this; }, projectOnVector: function () { var v1, dot; return function projectOnVector(vector) { if (v1 === undefined) v1 = new THREE.Vector3(); v1.copy(vector).normalize(); dot = this.dot(v1); return this.copy(v1).multiplyScalar(dot); }; }(), projectOnPlane: function () { var v1; return function projectOnPlane(planeNormal) { if (v1 === undefined) v1 = new THREE.Vector3(); v1.copy(this).projectOnVector(planeNormal); return this.sub(v1); }; }(), reflect: function () { // reflect incident vector off plane orthogonal to normal // normal is assumed to have unit length var v1; return function reflect(normal) { if (v1 === undefined) v1 = new THREE.Vector3(); return this.sub(v1.copy(normal).multiplyScalar(2 * this.dot(normal))); }; }(), angleTo: function (v) { var theta = this.dot(v) / Math.sqrt(this.lengthSq() * v.lengthSq()); // clamp, to handle numerical problems return Math.acos(THREE.Math.clamp(theta, -1, 1)); }, distanceTo: function (v) { return Math.sqrt(this.distanceToSquared(v)); }, distanceToSquared: function (v) { var dx = this.x - v.x; var dy = this.y - v.y; var dz = this.z - v.z; return dx * dx + dy * dy + dz * dz; }, setFromSpherical: function (s) { var sinPhiRadius = Math.sin(s.phi) * s.radius; this.x = sinPhiRadius * Math.sin(s.theta); this.y = Math.cos(s.phi) * s.radius; this.z = sinPhiRadius * Math.cos(s.theta); return this; }, setFromMatrixPosition: function (m) { return this.setFromMatrixColumn(m, 3); }, setFromMatrixScale: function (m) { var sx = this.setFromMatrixColumn(m, 0).length(); var sy = this.setFromMatrixColumn(m, 1).length(); var sz = this.setFromMatrixColumn(m, 2).length(); this.x = sx; this.y = sy; this.z = sz; return this; }, setFromMatrixColumn: function (m, index) { if (typeof m === 'number') { m = arguments[1]; index = arguments[0]; } return this.fromArray(m.elements, index * 4); }, equals: function (v) { return v.x === this.x && v.y === this.y && v.z === this.z; }, fromArray: function (array, offset) { if (offset === undefined) offset = 0; this.x = array[offset]; this.y = array[offset + 1]; this.z = array[offset + 2]; return this; }, toArray: function (array, offset) { if (array === undefined) array = []; if (offset === undefined) offset = 0; array[offset] = this.x; array[offset + 1] = this.y; array[offset + 2] = this.z; return array; }, fromAttribute: function (attribute, index, offset) { if (offset === undefined) offset = 0; index = index * attribute.itemSize + offset; this.x = attribute.array[index]; this.y = attribute.array[index + 1]; this.z = attribute.array[index + 2]; return this; } }; // File:src/math/Vector4.js /** * @author supereggbert / http://www.paulbrunt.co.uk/ * @author philogb / http://blog.thejit.org/ * @author mikael emtinger / http://gomo.se/ * @author egraether / http://egraether.com/ * @author WestLangley / http://github.com/WestLangley */ THREE.Vector4 = function (x, y, z, w) { this.x = x || 0; this.y = y || 0; this.z = z || 0; this.w = w !== undefined ? w : 1; }; THREE.Vector4.prototype = { constructor: THREE.Vector4, set: function (x, y, z, w) { this.x = x; this.y = y; this.z = z; this.w = w; return this; }, setScalar: function (scalar) { this.x = scalar; this.y = scalar; this.z = scalar; this.w = scalar; return this; }, setX: function (x) { this.x = x; return this; }, setY: function (y) { this.y = y; return this; }, setZ: function (z) { this.z = z; return this; }, setW: function (w) { this.w = w; return this; }, setComponent: function (index, value) { switch (index) { case 0: this.x = value; break; case 1: this.y = value; break; case 2: this.z = value; break; case 3: this.w = value; break; default: throw new Error('index is out of range: ' + index); } }, getComponent: function (index) { switch (index) { case 0: return this.x; case 1: return this.y; case 2: return this.z; case 3: return this.w; default: throw new Error('index is out of range: ' + index); } }, clone: function () { return new this.constructor(this.x, this.y, this.z, this.w); }, copy: function (v) { this.x = v.x; this.y = v.y; this.z = v.z; this.w = v.w !== undefined ? v.w : 1; return this; }, add: function (v, w) { if (w !== undefined) { return this.addVectors(v, w); } this.x += v.x; this.y += v.y; this.z += v.z; this.w += v.w; return this; }, addScalar: function (s) { this.x += s; this.y += s; this.z += s; this.w += s; return this; }, addVectors: function (a, b) { this.x = a.x + b.x; this.y = a.y + b.y; this.z = a.z + b.z; this.w = a.w + b.w; return this; }, addScaledVector: function (v, s) { this.x += v.x * s; this.y += v.y * s; this.z += v.z * s; this.w += v.w * s; return this; }, sub: function (v, w) { if (w !== undefined) { return this.subVectors(v, w); } this.x -= v.x; this.y -= v.y; this.z -= v.z; this.w -= v.w; return this; }, subScalar: function (s) { this.x -= s; this.y -= s; this.z -= s; this.w -= s; return this; }, subVectors: function (a, b) { this.x = a.x - b.x; this.y = a.y - b.y; this.z = a.z - b.z; this.w = a.w - b.w; return this; }, multiplyScalar: function (scalar) { if (isFinite(scalar)) { this.x *= scalar; this.y *= scalar; this.z *= scalar; this.w *= scalar; } else { this.x = 0; this.y = 0; this.z = 0; this.w = 0; } return this; }, applyMatrix4: function (m) { var x = this.x; var y = this.y; var z = this.z; var w = this.w; var e = m.elements; this.x = e[0] * x + e[4] * y + e[8] * z + e[12] * w; this.y = e[1] * x + e[5] * y + e[9] * z + e[13] * w; this.z = e[2] * x + e[6] * y + e[10] * z + e[14] * w; this.w = e[3] * x + e[7] * y + e[11] * z + e[15] * w; return this; }, divideScalar: function (scalar) { return this.multiplyScalar(1 / scalar); }, setAxisAngleFromQuaternion: function (q) { // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm // q is assumed to be normalized this.w = 2 * Math.acos(q.w); var s = Math.sqrt(1 - q.w * q.w); if (s < 0.0001) { this.x = 1; this.y = 0; this.z = 0; } else { this.x = q.x / s; this.y = q.y / s; this.z = q.z / s; } return this; }, setAxisAngleFromRotationMatrix: function (m) { // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) var angle, x, y, z, // variables for result epsilon = 0.01, // margin to allow for rounding errors epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees te = m.elements, m11 = te[0], m12 = te[4], m13 = te[8], m21 = te[1], m22 = te[5], m23 = te[9], m31 = te[2], m32 = te[6], m33 = te[10]; if (Math.abs(m12 - m21) < epsilon && Math.abs(m13 - m31) < epsilon && Math.abs(m23 - m32) < epsilon) { // singularity found // first check for identity matrix which must have +1 for all terms // in leading diagonal and zero in other terms if (Math.abs(m12 + m21) < epsilon2 && Math.abs(m13 + m31) < epsilon2 && Math.abs(m23 + m32) < epsilon2 && Math.abs(m11 + m22 + m33 - 3) < epsilon2) { // this singularity is identity matrix so angle = 0 this.set(1, 0, 0, 0); return this; // zero angle, arbitrary axis } // otherwise this singularity is angle = 180 angle = Math.PI; var xx = (m11 + 1) / 2; var yy = (m22 + 1) / 2; var zz = (m33 + 1) / 2; var xy = (m12 + m21) / 4; var xz = (m13 + m31) / 4; var yz = (m23 + m32) / 4; if (xx > yy && xx > zz) { // m11 is the largest diagonal term if (xx < epsilon) { x = 0; y = 0.707106781; z = 0.707106781; } else { x = Math.sqrt(xx); y = xy / x; z = xz / x; } } else if (yy > zz) { // m22 is the largest diagonal term if (yy < epsilon) { x = 0.707106781; y = 0; z = 0.707106781;