diff --git a/.lgtm.yml b/.lgtm.yml new file mode 100644 index 00000000000000..19321e09943a2b --- /dev/null +++ b/.lgtm.yml @@ -0,0 +1,13 @@ +path_classifiers: + library: + - "editor/js/libs/**/*.*" + - "examples/jsm/libs/**/*.*" + - "examples/js/libs/**/*.*" + - "examples/jsm/loaders/ifc/**/*.*" + - "examples/js/loaders/ifc/**/*.*" + test: + - exclude: / + docs: + - exclude: / + generated: + - "build/*.*" \ No newline at end of file diff --git a/LICENSE b/LICENSE index 5303437e406ed2..b90fa96a3200d2 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright © 2010-2021 three.js authors +Copyright © 2010-2022 three.js authors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/build/three.js b/build/three.js index 61208ad851f837..f1092cc0d1a8fe 100644 --- a/build/three.js +++ b/build/three.js @@ -9,7 +9,7 @@ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.THREE = {})); })(this, (function (exports) { 'use strict'; - const REVISION = '136dev'; + const REVISION = '137dev'; const MOUSE = { LEFT: 0, MIDDLE: 1, @@ -113,7 +113,6 @@ const RGBAFormat = 1023; const LuminanceFormat = 1024; const LuminanceAlphaFormat = 1025; - const RGBEFormat = RGBAFormat; const DepthFormat = 1026; const DepthStencilFormat = 1027; const RedFormat = 1028; @@ -148,20 +147,6 @@ const RGBA_ASTC_12x10_Format = 37820; const RGBA_ASTC_12x12_Format = 37821; const RGBA_BPTC_Format = 36492; - const SRGB8_ALPHA8_ASTC_4x4_Format = 37840; - const SRGB8_ALPHA8_ASTC_5x4_Format = 37841; - const SRGB8_ALPHA8_ASTC_5x5_Format = 37842; - const SRGB8_ALPHA8_ASTC_6x5_Format = 37843; - const SRGB8_ALPHA8_ASTC_6x6_Format = 37844; - const SRGB8_ALPHA8_ASTC_8x5_Format = 37845; - const SRGB8_ALPHA8_ASTC_8x6_Format = 37846; - const SRGB8_ALPHA8_ASTC_8x8_Format = 37847; - const SRGB8_ALPHA8_ASTC_10x5_Format = 37848; - const SRGB8_ALPHA8_ASTC_10x6_Format = 37849; - const SRGB8_ALPHA8_ASTC_10x8_Format = 37850; - const SRGB8_ALPHA8_ASTC_10x10_Format = 37851; - const SRGB8_ALPHA8_ASTC_12x10_Format = 37852; - const SRGB8_ALPHA8_ASTC_12x12_Format = 37853; const LoopOnce = 2200; const LoopRepeat = 2201; const LoopPingPong = 2202; @@ -178,11 +163,6 @@ const TriangleFanDrawMode = 2; const LinearEncoding = 3000; const sRGBEncoding = 3001; - const GammaEncoding = 3007; - const RGBEEncoding = 3002; - const RGBM7Encoding = 3004; - const RGBM16Encoding = 3005; - const RGBDEncoding = 3006; const BasicDepthPacking = 3200; const RGBADepthPacking = 3201; const TangentSpaceNormalMap = 0; @@ -214,6 +194,9 @@ const StreamCopyUsage = 35042; const GLSL1 = '100'; const GLSL3 = '300 es'; + const _SRGBFormat = 1034; // fallback for WebGL 1 + + const _SRGBAFormat = 1035; // fallback for WebGL 1 /** * https://github.com/mrdoob/eventdispatcher.js/ @@ -1106,303 +1089,857 @@ function createElementNS(name) { return document.createElementNS('http://www.w3.org/1999/xhtml', name); } - /** - * cyrb53 hash for string from: https://stackoverflow.com/a/52171480 - * - * Public Domain, @bryc - https://stackoverflow.com/users/815680/bryc - * - * It is roughly similar to the well-known MurmurHash/xxHash algorithms. It uses a combination - * of multiplication and Xorshift to generate the hash, but not as thorough. As a result it's - * faster than either would be in JavaScript and significantly simpler to implement. Keep in - * mind this is not a secure algorithm, if privacy/security is a concern, this is not for you. - * - * @param {string} str - * @param {number} seed, default 0 - * @returns number - */ - - - function hashString(str, seed = 0) { - let h1 = 0xdeadbeef ^ seed, - h2 = 0x41c6ce57 ^ seed; - for (let i = 0, ch; i < str.length; i++) { - ch = str.charCodeAt(i); - h1 = Math.imul(h1 ^ ch, 2654435761); - h2 = Math.imul(h2 ^ ch, 1597334677); - } + const _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, + 'rebeccapurple': 0x663399, + '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 + }; + const _hslA = { + h: 0, + s: 0, + l: 0 + }; + const _hslB = { + h: 0, + s: 0, + l: 0 + }; - h1 = Math.imul(h1 ^ h1 >>> 16, 2246822507) ^ Math.imul(h2 ^ h2 >>> 13, 3266489909); - h2 = Math.imul(h2 ^ h2 >>> 16, 2246822507) ^ Math.imul(h1 ^ h1 >>> 13, 3266489909); - return 4294967296 * (2097151 & h2) + (h1 >>> 0); + 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; } - let _canvas; - - class ImageUtils { - static getDataURL(image) { - if (/^data:/i.test(image.src)) { - return image.src; - } - - if (typeof HTMLCanvasElement == 'undefined') { - return image.src; - } - - let canvas; - - if (image instanceof HTMLCanvasElement) { - canvas = image; - } else { - if (_canvas === undefined) _canvas = createElementNS('canvas'); - _canvas.width = image.width; - _canvas.height = image.height; - - const context = _canvas.getContext('2d'); + function SRGBToLinear(c) { + return c < 0.04045 ? c * 0.0773993808 : Math.pow(c * 0.9478672986 + 0.0521327014, 2.4); + } - if (image instanceof ImageData) { - context.putImageData(image, 0, 0); - } else { - context.drawImage(image, 0, 0, image.width, image.height); - } + function LinearToSRGB(c) { + return c < 0.0031308 ? c * 12.92 : 1.055 * Math.pow(c, 0.41666) - 0.055; + } - canvas = _canvas; + class Color { + constructor(r, g, b) { + if (g === undefined && b === undefined) { + // r is THREE.Color, hex or string + return this.set(r); } - if (canvas.width > 2048 || canvas.height > 2048) { - console.warn('THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons', image); - return canvas.toDataURL('image/jpeg', 0.6); - } else { - return canvas.toDataURL('image/png'); - } + return this.setRGB(r, g, b); } - } - - let textureId = 0; - - class Texture extends EventDispatcher { - constructor(image = Texture.DEFAULT_IMAGE, mapping = Texture.DEFAULT_MAPPING, wrapS = ClampToEdgeWrapping, wrapT = ClampToEdgeWrapping, magFilter = LinearFilter, minFilter = LinearMipmapLinearFilter, format = RGBAFormat, type = UnsignedByteType, anisotropy = 1, encoding = LinearEncoding) { - super(); - Object.defineProperty(this, 'id', { - value: textureId++ - }); - this.uuid = generateUUID(); - this.name = ''; - this.image = image; - this.mipmaps = []; - this.mapping = mapping; - this.wrapS = wrapS; - this.wrapT = wrapT; - this.magFilter = magFilter; - this.minFilter = minFilter; - this.anisotropy = anisotropy; - this.format = format; - this.internalFormat = null; - this.type = type; - this.offset = new Vector2(0, 0); - this.repeat = new Vector2(1, 1); - this.center = new Vector2(0, 0); - this.rotation = 0; - this.matrixAutoUpdate = true; - this.matrix = new Matrix3(); - this.generateMipmaps = true; - this.premultiplyAlpha = false; - this.flipY = true; - this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml) - // Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap. - // - // Also changing the encoding after already used by a Material will not automatically make the Material - // update. You need to explicitly call Material.needsUpdate to trigger it to recompile. + set(value) { + if (value && value.isColor) { + this.copy(value); + } else if (typeof value === 'number') { + this.setHex(value); + } else if (typeof value === 'string') { + this.setStyle(value); + } - this.encoding = encoding; - this.userData = {}; - this.version = 0; - this.onUpdate = null; - this.isRenderTargetTexture = false; + return this; } - updateMatrix() { - this.matrix.setUvTransform(this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y); + setScalar(scalar) { + this.r = scalar; + this.g = scalar; + this.b = scalar; + return this; } - clone() { - return new this.constructor().copy(this); + setHex(hex) { + hex = Math.floor(hex); + this.r = (hex >> 16 & 255) / 255; + this.g = (hex >> 8 & 255) / 255; + this.b = (hex & 255) / 255; + return this; } - copy(source) { - this.name = source.name; - this.image = source.image; - this.mipmaps = source.mipmaps.slice(0); - this.mapping = source.mapping; - this.wrapS = source.wrapS; - this.wrapT = source.wrapT; - this.magFilter = source.magFilter; - this.minFilter = source.minFilter; - this.anisotropy = source.anisotropy; - this.format = source.format; - this.internalFormat = source.internalFormat; - this.type = source.type; - this.offset.copy(source.offset); - this.repeat.copy(source.repeat); - this.center.copy(source.center); - this.rotation = source.rotation; - this.matrixAutoUpdate = source.matrixAutoUpdate; - this.matrix.copy(source.matrix); - this.generateMipmaps = source.generateMipmaps; - this.premultiplyAlpha = source.premultiplyAlpha; - this.flipY = source.flipY; - this.unpackAlignment = source.unpackAlignment; - this.encoding = source.encoding; - this.userData = JSON.parse(JSON.stringify(source.userData)); + setRGB(r, g, b) { + this.r = r; + this.g = g; + this.b = b; return this; } - toJSON(meta) { - const isRootObject = meta === undefined || typeof meta === 'string'; + setHSL(h, s, l) { + // h,s,l ranges are in 0.0 - 1.0 + h = euclideanModulo(h, 1); + s = clamp(s, 0, 1); + l = clamp(l, 0, 1); - if (!isRootObject && meta.textures[this.uuid] !== undefined) { - return meta.textures[this.uuid]; + if (s === 0) { + this.r = this.g = this.b = l; + } else { + const p = l <= 0.5 ? l * (1 + s) : l + s - l * s; + const 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); } - const output = { - metadata: { - version: 4.5, - type: 'Texture', - generator: 'Texture.toJSON' - }, - uuid: this.uuid, - name: this.name, - mapping: this.mapping, - repeat: [this.repeat.x, this.repeat.y], - offset: [this.offset.x, this.offset.y], - center: [this.center.x, this.center.y], - rotation: this.rotation, - wrap: [this.wrapS, this.wrapT], - format: this.format, - type: this.type, - encoding: this.encoding, - minFilter: this.minFilter, - magFilter: this.magFilter, - anisotropy: this.anisotropy, - flipY: this.flipY, - premultiplyAlpha: this.premultiplyAlpha, - unpackAlignment: this.unpackAlignment - }; - - if (this.image !== undefined) { - // TODO: Move to THREE.Image - const image = this.image; - - if (image.uuid === undefined) { - image.uuid = generateUUID(); // UGH - } - - if (!isRootObject && meta.images[image.uuid] === undefined) { - let url; - - if (Array.isArray(image)) { - // process array of images e.g. CubeTexture - url = []; + return this; + } - for (let i = 0, l = image.length; i < l; i++) { - // check cube texture with data textures - if (image[i].isDataTexture) { - url.push(serializeImage(image[i].image)); - } else { - url.push(serializeImage(image[i])); - } - } - } else { - // process single image - url = serializeImage(image); - } + setStyle(style) { + function handleAlpha(string) { + if (string === undefined) return; - meta.images[image.uuid] = { - uuid: image.uuid, - url: url - }; + if (parseFloat(string) < 1) { + console.warn('THREE.Color: Alpha component of ' + style + ' will be ignored.'); } - - output.image = image.uuid; - } - - if (JSON.stringify(this.userData) !== '{}') output.userData = this.userData; - - if (!isRootObject) { - meta.textures[this.uuid] = output; } - return output; - } + let m; - dispose() { - this.dispatchEvent({ - type: 'dispose' - }); - } + if (m = /^((?:rgb|hsl)a?)\(([^\)]*)\)/.exec(style)) { + // rgb / hsl + let color; + const name = m[1]; + const components = m[2]; - transformUv(uv) { - if (this.mapping !== UVMapping) return uv; - uv.applyMatrix3(this.matrix); + switch (name) { + case 'rgb': + case 'rgba': + if (color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\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[4]); + return this; + } - if (uv.x < 0 || uv.x > 1) { - switch (this.wrapS) { - case RepeatWrapping: - uv.x = uv.x - Math.floor(uv.x); - break; + if (color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\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[4]); + return this; + } - case ClampToEdgeWrapping: - uv.x = uv.x < 0 ? 0 : 1; break; - case MirroredRepeatWrapping: - if (Math.abs(Math.floor(uv.x) % 2) === 1) { - uv.x = Math.ceil(uv.x) - uv.x; - } else { - uv.x = uv.x - Math.floor(uv.x); + case 'hsl': + case 'hsla': + if (color = /^\s*(\d*\.?\d+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components)) { + // hsl(120,50%,50%) hsla(120,50%,50%,0.5) + const h = parseFloat(color[1]) / 360; + const s = parseInt(color[2], 10) / 100; + const l = parseInt(color[3], 10) / 100; + handleAlpha(color[4]); + return this.setHSL(h, s, l); } break; } - } - - if (uv.y < 0 || uv.y > 1) { - switch (this.wrapT) { - case RepeatWrapping: - uv.y = uv.y - Math.floor(uv.y); - break; - - case ClampToEdgeWrapping: - uv.y = uv.y < 0 ? 0 : 1; - break; - - case MirroredRepeatWrapping: - if (Math.abs(Math.floor(uv.y) % 2) === 1) { - uv.y = Math.ceil(uv.y) - uv.y; - } else { - uv.y = uv.y - Math.floor(uv.y); - } + } else if (m = /^\#([A-Fa-f\d]+)$/.exec(style)) { + // hex color + const hex = m[1]; + const size = hex.length; - break; + 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 (this.flipY) { - uv.y = 1 - uv.y; + if (style && style.length > 0) { + return this.setColorName(style); } - return uv; + return this; } - set needsUpdate(value) { - if (value === true) this.version++; - } + setColorName(style) { + // color keywords + const hex = _colorKeywords[style.toLowerCase()]; - } + if (hex !== undefined) { + // red + this.setHex(hex); + } else { + // unknown color + console.warn('THREE.Color: Unknown color ' + style); + } - Texture.DEFAULT_IMAGE = undefined; - Texture.DEFAULT_MAPPING = UVMapping; + return this; + } + + clone() { + return new this.constructor(this.r, this.g, this.b); + } + + copy(color) { + this.r = color.r; + this.g = color.g; + this.b = color.b; + return this; + } + + copySRGBToLinear(color) { + this.r = SRGBToLinear(color.r); + this.g = SRGBToLinear(color.g); + this.b = SRGBToLinear(color.b); + return this; + } + + copyLinearToSRGB(color) { + this.r = LinearToSRGB(color.r); + this.g = LinearToSRGB(color.g); + this.b = LinearToSRGB(color.b); + return this; + } + + convertSRGBToLinear() { + this.copySRGBToLinear(this); + return this; + } + + convertLinearToSRGB() { + this.copyLinearToSRGB(this); + return this; + } + + getHex() { + return this.r * 255 << 16 ^ this.g * 255 << 8 ^ this.b * 255 << 0; + } + + getHexString() { + return ('000000' + this.getHex().toString(16)).slice(-6); + } + + getHSL(target) { + // h,s,l ranges are in 0.0 - 1.0 + const r = this.r, + g = this.g, + b = this.b; + const max = Math.max(r, g, b); + const min = Math.min(r, g, b); + let hue, saturation; + const lightness = (min + max) / 2.0; + + if (min === max) { + hue = 0; + saturation = 0; + } else { + const 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; + } + + target.h = hue; + target.s = saturation; + target.l = lightness; + return target; + } + + getStyle() { + return 'rgb(' + (this.r * 255 | 0) + ',' + (this.g * 255 | 0) + ',' + (this.b * 255 | 0) + ')'; + } + + offsetHSL(h, s, l) { + this.getHSL(_hslA); + _hslA.h += h; + _hslA.s += s; + _hslA.l += l; + this.setHSL(_hslA.h, _hslA.s, _hslA.l); + return this; + } + + add(color) { + this.r += color.r; + this.g += color.g; + this.b += color.b; + return this; + } + + addColors(color1, color2) { + this.r = color1.r + color2.r; + this.g = color1.g + color2.g; + this.b = color1.b + color2.b; + return this; + } + + addScalar(s) { + this.r += s; + this.g += s; + this.b += s; + return this; + } + + sub(color) { + this.r = Math.max(0, this.r - color.r); + this.g = Math.max(0, this.g - color.g); + this.b = Math.max(0, this.b - color.b); + return this; + } + + multiply(color) { + this.r *= color.r; + this.g *= color.g; + this.b *= color.b; + return this; + } + + multiplyScalar(s) { + this.r *= s; + this.g *= s; + this.b *= s; + return this; + } + + lerp(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; + } + + lerpColors(color1, color2, alpha) { + this.r = color1.r + (color2.r - color1.r) * alpha; + this.g = color1.g + (color2.g - color1.g) * alpha; + this.b = color1.b + (color2.b - color1.b) * alpha; + return this; + } + + lerpHSL(color, alpha) { + this.getHSL(_hslA); + color.getHSL(_hslB); + const h = lerp(_hslA.h, _hslB.h, alpha); + const s = lerp(_hslA.s, _hslB.s, alpha); + const l = lerp(_hslA.l, _hslB.l, alpha); + this.setHSL(h, s, l); + return this; + } + + equals(c) { + return c.r === this.r && c.g === this.g && c.b === this.b; + } + + fromArray(array, offset = 0) { + this.r = array[offset]; + this.g = array[offset + 1]; + this.b = array[offset + 2]; + return this; + } + + toArray(array = [], offset = 0) { + array[offset] = this.r; + array[offset + 1] = this.g; + array[offset + 2] = this.b; + return array; + } + + fromBufferAttribute(attribute, index) { + this.r = attribute.getX(index); + this.g = attribute.getY(index); + this.b = attribute.getZ(index); + + if (attribute.normalized === true) { + // assuming Uint8Array + this.r /= 255; + this.g /= 255; + this.b /= 255; + } + + return this; + } + + toJSON() { + return this.getHex(); + } + + } + + Color.NAMES = _colorKeywords; + Color.prototype.isColor = true; + Color.prototype.r = 1; + Color.prototype.g = 1; + Color.prototype.b = 1; + + let _canvas; + + class ImageUtils { + static getDataURL(image) { + if (/^data:/i.test(image.src)) { + return image.src; + } + + if (typeof HTMLCanvasElement == 'undefined') { + return image.src; + } + + let canvas; + + if (image instanceof HTMLCanvasElement) { + canvas = image; + } else { + if (_canvas === undefined) _canvas = createElementNS('canvas'); + _canvas.width = image.width; + _canvas.height = image.height; + + const context = _canvas.getContext('2d'); + + if (image instanceof ImageData) { + context.putImageData(image, 0, 0); + } else { + context.drawImage(image, 0, 0, image.width, image.height); + } + + canvas = _canvas; + } + + if (canvas.width > 2048 || canvas.height > 2048) { + console.warn('THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons', image); + return canvas.toDataURL('image/jpeg', 0.6); + } else { + return canvas.toDataURL('image/png'); + } + } + + static sRGBToLinear(image) { + if (typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement || typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement || typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap) { + const canvas = createElementNS('canvas'); + canvas.width = image.width; + canvas.height = image.height; + const context = canvas.getContext('2d'); + context.drawImage(image, 0, 0, image.width, image.height); + const imageData = context.getImageData(0, 0, image.width, image.height); + const data = imageData.data; + + for (let i = 0; i < data.length; i++) { + data[i] = SRGBToLinear(data[i] / 255) * 255; + } + + context.putImageData(imageData, 0, 0); + return canvas; + } else if (image.data) { + const data = image.data.slice(0); + + for (let i = 0; i < data.length; i++) { + if (data instanceof Uint8Array || data instanceof Uint8ClampedArray) { + data[i] = Math.floor(SRGBToLinear(data[i] / 255) * 255); + } else { + // assuming float + data[i] = SRGBToLinear(data[i]); + } + } + + return { + data: data, + width: image.width, + height: image.height + }; + } else { + console.warn('THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.'); + return image; + } + } + + } + + let textureId = 0; + + class Texture extends EventDispatcher { + constructor(image = Texture.DEFAULT_IMAGE, mapping = Texture.DEFAULT_MAPPING, wrapS = ClampToEdgeWrapping, wrapT = ClampToEdgeWrapping, magFilter = LinearFilter, minFilter = LinearMipmapLinearFilter, format = RGBAFormat, type = UnsignedByteType, anisotropy = 1, encoding = LinearEncoding) { + super(); + Object.defineProperty(this, 'id', { + value: textureId++ + }); + this.uuid = generateUUID(); + this.name = ''; + this.image = image; + this.mipmaps = []; + this.mapping = mapping; + this.wrapS = wrapS; + this.wrapT = wrapT; + this.magFilter = magFilter; + this.minFilter = minFilter; + this.anisotropy = anisotropy; + this.format = format; + this.internalFormat = null; + this.type = type; + this.offset = new Vector2(0, 0); + this.repeat = new Vector2(1, 1); + this.center = new Vector2(0, 0); + this.rotation = 0; + this.matrixAutoUpdate = true; + this.matrix = new Matrix3(); + this.generateMipmaps = true; + this.premultiplyAlpha = false; + this.flipY = true; + this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml) + // Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap. + // + // Also changing the encoding after already used by a Material will not automatically make the Material + // update. You need to explicitly call Material.needsUpdate to trigger it to recompile. + + this.encoding = encoding; + this.userData = {}; + this.version = 0; + this.onUpdate = null; + this.isRenderTargetTexture = false; // indicates whether a texture belongs to a render target or not + + this.needsPMREMUpdate = false; // indicates whether this texture should be processed by PMREMGenerator or not (only relevant for render target textures) + } + + updateMatrix() { + this.matrix.setUvTransform(this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y); + } + + clone() { + return new this.constructor().copy(this); + } + + copy(source) { + this.name = source.name; + this.image = source.image; + this.mipmaps = source.mipmaps.slice(0); + this.mapping = source.mapping; + this.wrapS = source.wrapS; + this.wrapT = source.wrapT; + this.magFilter = source.magFilter; + this.minFilter = source.minFilter; + this.anisotropy = source.anisotropy; + this.format = source.format; + this.internalFormat = source.internalFormat; + this.type = source.type; + this.offset.copy(source.offset); + this.repeat.copy(source.repeat); + this.center.copy(source.center); + this.rotation = source.rotation; + this.matrixAutoUpdate = source.matrixAutoUpdate; + this.matrix.copy(source.matrix); + this.generateMipmaps = source.generateMipmaps; + this.premultiplyAlpha = source.premultiplyAlpha; + this.flipY = source.flipY; + this.unpackAlignment = source.unpackAlignment; + this.encoding = source.encoding; + this.userData = JSON.parse(JSON.stringify(source.userData)); + return this; + } + + toJSON(meta) { + const isRootObject = meta === undefined || typeof meta === 'string'; + + if (!isRootObject && meta.textures[this.uuid] !== undefined) { + return meta.textures[this.uuid]; + } + + const output = { + metadata: { + version: 4.5, + type: 'Texture', + generator: 'Texture.toJSON' + }, + uuid: this.uuid, + name: this.name, + mapping: this.mapping, + repeat: [this.repeat.x, this.repeat.y], + offset: [this.offset.x, this.offset.y], + center: [this.center.x, this.center.y], + rotation: this.rotation, + wrap: [this.wrapS, this.wrapT], + format: this.format, + type: this.type, + encoding: this.encoding, + minFilter: this.minFilter, + magFilter: this.magFilter, + anisotropy: this.anisotropy, + flipY: this.flipY, + premultiplyAlpha: this.premultiplyAlpha, + unpackAlignment: this.unpackAlignment + }; + + if (this.image !== undefined) { + // TODO: Move to THREE.Image + const image = this.image; + + if (image.uuid === undefined) { + image.uuid = generateUUID(); // UGH + } + + if (!isRootObject && meta.images[image.uuid] === undefined) { + let url; + + if (Array.isArray(image)) { + // process array of images e.g. CubeTexture + url = []; + + for (let i = 0, l = image.length; i < l; i++) { + // check cube texture with data textures + if (image[i].isDataTexture) { + url.push(serializeImage(image[i].image)); + } else { + url.push(serializeImage(image[i])); + } + } + } else { + // process single image + url = serializeImage(image); + } + + meta.images[image.uuid] = { + uuid: image.uuid, + url: url + }; + } + + output.image = image.uuid; + } + + if (JSON.stringify(this.userData) !== '{}') output.userData = this.userData; + + if (!isRootObject) { + meta.textures[this.uuid] = output; + } + + return output; + } + + dispose() { + this.dispatchEvent({ + type: 'dispose' + }); + } + + transformUv(uv) { + if (this.mapping !== UVMapping) return uv; + uv.applyMatrix3(this.matrix); + + if (uv.x < 0 || uv.x > 1) { + switch (this.wrapS) { + case RepeatWrapping: + uv.x = uv.x - Math.floor(uv.x); + break; + + case ClampToEdgeWrapping: + uv.x = uv.x < 0 ? 0 : 1; + break; + + case MirroredRepeatWrapping: + if (Math.abs(Math.floor(uv.x) % 2) === 1) { + uv.x = Math.ceil(uv.x) - uv.x; + } else { + uv.x = uv.x - Math.floor(uv.x); + } + + break; + } + } + + if (uv.y < 0 || uv.y > 1) { + switch (this.wrapT) { + case RepeatWrapping: + uv.y = uv.y - Math.floor(uv.y); + break; + + case ClampToEdgeWrapping: + uv.y = uv.y < 0 ? 0 : 1; + break; + + case MirroredRepeatWrapping: + if (Math.abs(Math.floor(uv.y) % 2) === 1) { + uv.y = Math.ceil(uv.y) - uv.y; + } else { + uv.y = uv.y - Math.floor(uv.y); + } + + break; + } + } + + if (this.flipY) { + uv.y = 1 - uv.y; + } + + return uv; + } + + set needsUpdate(value) { + if (value === true) this.version++; + } + + } + + Texture.DEFAULT_IMAGE = undefined; + Texture.DEFAULT_MAPPING = UVMapping; Texture.prototype.isTexture = true; function serializeImage(image) { @@ -2551,7 +3088,7 @@ } slerpQuaternions(qa, qb, t) { - this.copy(qa).slerp(qb, t); + return this.copy(qa).slerp(qb, t); } random() { @@ -3772,7 +4309,7 @@ } distanceSqToSegment(v0, v1, optionalPointOnRay, optionalPointOnSegment) { - // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteDistRaySegment.h + // from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteDistRaySegment.h // It returns the min distance between the ray and the segment // defined by v0 and v1 // It can also set two optional targets : @@ -3983,7 +4520,7 @@ intersectTriangle(a, b, c, backfaceCulling, target) { // Compute the offset origin, edges, and normal. - // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h + // from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h _edge1.subVectors(b, a); _edge2.subVectors(c, a); @@ -6153,761 +6690,193 @@ data.lightMapIntensity = this.lightMapIntensity; } - if (this.aoMap && this.aoMap.isTexture) { - data.aoMap = this.aoMap.toJSON(meta).uuid; - data.aoMapIntensity = this.aoMapIntensity; - } - - if (this.bumpMap && this.bumpMap.isTexture) { - data.bumpMap = this.bumpMap.toJSON(meta).uuid; - data.bumpScale = this.bumpScale; - } - - if (this.normalMap && this.normalMap.isTexture) { - data.normalMap = this.normalMap.toJSON(meta).uuid; - data.normalMapType = this.normalMapType; - data.normalScale = this.normalScale.toArray(); - } - - if (this.displacementMap && this.displacementMap.isTexture) { - data.displacementMap = this.displacementMap.toJSON(meta).uuid; - data.displacementScale = this.displacementScale; - data.displacementBias = this.displacementBias; - } - - if (this.roughnessMap && this.roughnessMap.isTexture) data.roughnessMap = this.roughnessMap.toJSON(meta).uuid; - if (this.metalnessMap && this.metalnessMap.isTexture) data.metalnessMap = this.metalnessMap.toJSON(meta).uuid; - if (this.emissiveMap && this.emissiveMap.isTexture) data.emissiveMap = this.emissiveMap.toJSON(meta).uuid; - if (this.specularMap && this.specularMap.isTexture) data.specularMap = this.specularMap.toJSON(meta).uuid; - if (this.specularIntensityMap && this.specularIntensityMap.isTexture) data.specularIntensityMap = this.specularIntensityMap.toJSON(meta).uuid; - if (this.specularColorMap && this.specularColorMap.isTexture) data.specularColorMap = this.specularColorMap.toJSON(meta).uuid; - - if (this.envMap && this.envMap.isTexture) { - data.envMap = this.envMap.toJSON(meta).uuid; - if (this.combine !== undefined) data.combine = this.combine; - } - - if (this.envMapIntensity !== undefined) data.envMapIntensity = this.envMapIntensity; - if (this.reflectivity !== undefined) data.reflectivity = this.reflectivity; - if (this.refractionRatio !== undefined) data.refractionRatio = this.refractionRatio; - - if (this.gradientMap && this.gradientMap.isTexture) { - data.gradientMap = this.gradientMap.toJSON(meta).uuid; - } - - if (this.transmission !== undefined) data.transmission = this.transmission; - if (this.transmissionMap && this.transmissionMap.isTexture) data.transmissionMap = this.transmissionMap.toJSON(meta).uuid; - if (this.thickness !== undefined) data.thickness = this.thickness; - if (this.thicknessMap && this.thicknessMap.isTexture) data.thicknessMap = this.thicknessMap.toJSON(meta).uuid; - if (this.attenuationDistance !== undefined) data.attenuationDistance = this.attenuationDistance; - if (this.attenuationColor !== undefined) data.attenuationColor = this.attenuationColor.getHex(); - if (this.size !== undefined) data.size = this.size; - if (this.shadowSide !== null) data.shadowSide = this.shadowSide; - if (this.sizeAttenuation !== undefined) data.sizeAttenuation = this.sizeAttenuation; - if (this.blending !== NormalBlending) data.blending = this.blending; - if (this.side !== FrontSide) data.side = this.side; - if (this.vertexColors) data.vertexColors = true; - if (this.opacity < 1) data.opacity = this.opacity; - if (this.format !== RGBAFormat) data.format = this.format; - if (this.transparent === true) data.transparent = this.transparent; - data.depthFunc = this.depthFunc; - data.depthTest = this.depthTest; - data.depthWrite = this.depthWrite; - data.colorWrite = this.colorWrite; - data.stencilWrite = this.stencilWrite; - data.stencilWriteMask = this.stencilWriteMask; - data.stencilFunc = this.stencilFunc; - data.stencilRef = this.stencilRef; - data.stencilFuncMask = this.stencilFuncMask; - data.stencilFail = this.stencilFail; - data.stencilZFail = this.stencilZFail; - data.stencilZPass = this.stencilZPass; // rotation (SpriteMaterial) - - if (this.rotation && this.rotation !== 0) data.rotation = this.rotation; - if (this.polygonOffset === true) data.polygonOffset = true; - if (this.polygonOffsetFactor !== 0) data.polygonOffsetFactor = this.polygonOffsetFactor; - if (this.polygonOffsetUnits !== 0) data.polygonOffsetUnits = this.polygonOffsetUnits; - if (this.linewidth && this.linewidth !== 1) data.linewidth = this.linewidth; - if (this.dashSize !== undefined) data.dashSize = this.dashSize; - if (this.gapSize !== undefined) data.gapSize = this.gapSize; - if (this.scale !== undefined) data.scale = this.scale; - if (this.dithering === true) data.dithering = true; - if (this.alphaTest > 0) data.alphaTest = this.alphaTest; - if (this.alphaToCoverage === true) data.alphaToCoverage = this.alphaToCoverage; - if (this.premultipliedAlpha === true) data.premultipliedAlpha = this.premultipliedAlpha; - if (this.wireframe === true) data.wireframe = this.wireframe; - if (this.wireframeLinewidth > 1) data.wireframeLinewidth = this.wireframeLinewidth; - if (this.wireframeLinecap !== 'round') data.wireframeLinecap = this.wireframeLinecap; - if (this.wireframeLinejoin !== 'round') data.wireframeLinejoin = this.wireframeLinejoin; - if (this.flatShading === true) data.flatShading = this.flatShading; - if (this.visible === false) data.visible = false; - if (this.toneMapped === false) data.toneMapped = false; - if (JSON.stringify(this.userData) !== '{}') data.userData = this.userData; // TODO: Copied from Object3D.toJSON - - function extractFromCache(cache) { - const values = []; - - for (const key in cache) { - const data = cache[key]; - delete data.metadata; - values.push(data); - } - - return values; - } - - if (isRoot) { - const textures = extractFromCache(meta.textures); - const images = extractFromCache(meta.images); - if (textures.length > 0) data.textures = textures; - if (images.length > 0) data.images = images; - } - - return data; - } - - clone() { - return new this.constructor().copy(this); - } - - copy(source) { - this.name = source.name; - this.fog = source.fog; - this.blending = source.blending; - this.side = source.side; - this.vertexColors = source.vertexColors; - this.opacity = source.opacity; - this.format = source.format; - this.transparent = source.transparent; - this.blendSrc = source.blendSrc; - this.blendDst = source.blendDst; - this.blendEquation = source.blendEquation; - this.blendSrcAlpha = source.blendSrcAlpha; - this.blendDstAlpha = source.blendDstAlpha; - this.blendEquationAlpha = source.blendEquationAlpha; - this.depthFunc = source.depthFunc; - this.depthTest = source.depthTest; - this.depthWrite = source.depthWrite; - this.stencilWriteMask = source.stencilWriteMask; - this.stencilFunc = source.stencilFunc; - this.stencilRef = source.stencilRef; - this.stencilFuncMask = source.stencilFuncMask; - this.stencilFail = source.stencilFail; - this.stencilZFail = source.stencilZFail; - this.stencilZPass = source.stencilZPass; - this.stencilWrite = source.stencilWrite; - const srcPlanes = source.clippingPlanes; - let dstPlanes = null; - - if (srcPlanes !== null) { - const n = srcPlanes.length; - dstPlanes = new Array(n); - - for (let i = 0; i !== n; ++i) { - dstPlanes[i] = srcPlanes[i].clone(); - } - } - - this.clippingPlanes = dstPlanes; - this.clipIntersection = source.clipIntersection; - this.clipShadows = source.clipShadows; - this.shadowSide = source.shadowSide; - this.colorWrite = source.colorWrite; - this.precision = source.precision; - this.polygonOffset = source.polygonOffset; - this.polygonOffsetFactor = source.polygonOffsetFactor; - this.polygonOffsetUnits = source.polygonOffsetUnits; - this.dithering = source.dithering; - this.alphaTest = source.alphaTest; - this.alphaToCoverage = source.alphaToCoverage; - this.premultipliedAlpha = source.premultipliedAlpha; - this.visible = source.visible; - this.toneMapped = source.toneMapped; - this.userData = JSON.parse(JSON.stringify(source.userData)); - return this; - } - - dispose() { - this.dispatchEvent({ - type: 'dispose' - }); - } - - set needsUpdate(value) { - if (value === true) this.version++; - } - - } - - Material.prototype.isMaterial = true; - - const _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, - 'rebeccapurple': 0x663399, - '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 - }; - const _hslA = { - h: 0, - s: 0, - l: 0 - }; - const _hslB = { - h: 0, - s: 0, - l: 0 - }; - - 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; - } - - function SRGBToLinear(c) { - return c < 0.04045 ? c * 0.0773993808 : Math.pow(c * 0.9478672986 + 0.0521327014, 2.4); - } - - function LinearToSRGB(c) { - return c < 0.0031308 ? c * 12.92 : 1.055 * Math.pow(c, 0.41666) - 0.055; - } - - class Color { - constructor(r, g, b) { - if (g === undefined && b === undefined) { - // r is THREE.Color, hex or string - return this.set(r); - } - - return this.setRGB(r, g, b); - } - - set(value) { - if (value && value.isColor) { - this.copy(value); - } else if (typeof value === 'number') { - this.setHex(value); - } else if (typeof value === 'string') { - this.setStyle(value); - } - - return this; - } - - setScalar(scalar) { - this.r = scalar; - this.g = scalar; - this.b = scalar; - return this; - } - - setHex(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(r, g, b) { - this.r = r; - this.g = g; - this.b = b; - return this; - } - - setHSL(h, s, l) { - // h,s,l ranges are in 0.0 - 1.0 - h = euclideanModulo(h, 1); - s = clamp(s, 0, 1); - l = clamp(l, 0, 1); - - if (s === 0) { - this.r = this.g = this.b = l; - } else { - const p = l <= 0.5 ? l * (1 + s) : l + s - l * s; - const 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(style) { - function handleAlpha(string) { - if (string === undefined) return; - - if (parseFloat(string) < 1) { - console.warn('THREE.Color: Alpha component of ' + style + ' will be ignored.'); - } - } - - let m; - - if (m = /^((?:rgb|hsl)a?)\(([^\)]*)\)/.exec(style)) { - // rgb / hsl - let color; - const name = m[1]; - const components = m[2]; - - switch (name) { - case 'rgb': - case 'rgba': - if (color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\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[4]); - return this; - } - - if (color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\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[4]); - return this; - } - - break; - - case 'hsl': - case 'hsla': - if (color = /^\s*(\d*\.?\d+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components)) { - // hsl(120,50%,50%) hsla(120,50%,50%,0.5) - const h = parseFloat(color[1]) / 360; - const s = parseInt(color[2], 10) / 100; - const l = parseInt(color[3], 10) / 100; - handleAlpha(color[4]); - return this.setHSL(h, s, l); - } - - break; - } - } else if (m = /^\#([A-Fa-f\d]+)$/.exec(style)) { - // hex color - const hex = m[1]; - const 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) { - return this.setColorName(style); - } - - return this; - } - - setColorName(style) { - // color keywords - const hex = _colorKeywords[style.toLowerCase()]; - - if (hex !== undefined) { - // red - this.setHex(hex); - } else { - // unknown color - console.warn('THREE.Color: Unknown color ' + style); - } - - return this; - } - - clone() { - return new this.constructor(this.r, this.g, this.b); - } - - copy(color) { - this.r = color.r; - this.g = color.g; - this.b = color.b; - return this; - } - - copyGammaToLinear(color, 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(color, gammaFactor = 2.0) { - const 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(gammaFactor) { - this.copyGammaToLinear(this, gammaFactor); - return this; - } - - convertLinearToGamma(gammaFactor) { - this.copyLinearToGamma(this, gammaFactor); - return this; - } - - copySRGBToLinear(color) { - this.r = SRGBToLinear(color.r); - this.g = SRGBToLinear(color.g); - this.b = SRGBToLinear(color.b); - return this; - } - - copyLinearToSRGB(color) { - this.r = LinearToSRGB(color.r); - this.g = LinearToSRGB(color.g); - this.b = LinearToSRGB(color.b); - return this; - } - - convertSRGBToLinear() { - this.copySRGBToLinear(this); - return this; - } - - convertLinearToSRGB() { - this.copyLinearToSRGB(this); - return this; - } - - getHex() { - return this.r * 255 << 16 ^ this.g * 255 << 8 ^ this.b * 255 << 0; - } - - getHexString() { - return ('000000' + this.getHex().toString(16)).slice(-6); - } - - getHSL(target) { - // h,s,l ranges are in 0.0 - 1.0 - const r = this.r, - g = this.g, - b = this.b; - const max = Math.max(r, g, b); - const min = Math.min(r, g, b); - let hue, saturation; - const lightness = (min + max) / 2.0; - - if (min === max) { - hue = 0; - saturation = 0; - } else { - const 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; + if (this.aoMap && this.aoMap.isTexture) { + data.aoMap = this.aoMap.toJSON(meta).uuid; + data.aoMapIntensity = this.aoMapIntensity; } - target.h = hue; - target.s = saturation; - target.l = lightness; - return target; - } + if (this.bumpMap && this.bumpMap.isTexture) { + data.bumpMap = this.bumpMap.toJSON(meta).uuid; + data.bumpScale = this.bumpScale; + } - getStyle() { - return 'rgb(' + (this.r * 255 | 0) + ',' + (this.g * 255 | 0) + ',' + (this.b * 255 | 0) + ')'; - } + if (this.normalMap && this.normalMap.isTexture) { + data.normalMap = this.normalMap.toJSON(meta).uuid; + data.normalMapType = this.normalMapType; + data.normalScale = this.normalScale.toArray(); + } - offsetHSL(h, s, l) { - this.getHSL(_hslA); - _hslA.h += h; - _hslA.s += s; - _hslA.l += l; - this.setHSL(_hslA.h, _hslA.s, _hslA.l); - return this; - } + if (this.displacementMap && this.displacementMap.isTexture) { + data.displacementMap = this.displacementMap.toJSON(meta).uuid; + data.displacementScale = this.displacementScale; + data.displacementBias = this.displacementBias; + } - add(color) { - this.r += color.r; - this.g += color.g; - this.b += color.b; - return this; - } + if (this.roughnessMap && this.roughnessMap.isTexture) data.roughnessMap = this.roughnessMap.toJSON(meta).uuid; + if (this.metalnessMap && this.metalnessMap.isTexture) data.metalnessMap = this.metalnessMap.toJSON(meta).uuid; + if (this.emissiveMap && this.emissiveMap.isTexture) data.emissiveMap = this.emissiveMap.toJSON(meta).uuid; + if (this.specularMap && this.specularMap.isTexture) data.specularMap = this.specularMap.toJSON(meta).uuid; + if (this.specularIntensityMap && this.specularIntensityMap.isTexture) data.specularIntensityMap = this.specularIntensityMap.toJSON(meta).uuid; + if (this.specularColorMap && this.specularColorMap.isTexture) data.specularColorMap = this.specularColorMap.toJSON(meta).uuid; - addColors(color1, color2) { - this.r = color1.r + color2.r; - this.g = color1.g + color2.g; - this.b = color1.b + color2.b; - return this; - } + if (this.envMap && this.envMap.isTexture) { + data.envMap = this.envMap.toJSON(meta).uuid; + if (this.combine !== undefined) data.combine = this.combine; + } - addScalar(s) { - this.r += s; - this.g += s; - this.b += s; - return this; - } + if (this.envMapIntensity !== undefined) data.envMapIntensity = this.envMapIntensity; + if (this.reflectivity !== undefined) data.reflectivity = this.reflectivity; + if (this.refractionRatio !== undefined) data.refractionRatio = this.refractionRatio; - sub(color) { - this.r = Math.max(0, this.r - color.r); - this.g = Math.max(0, this.g - color.g); - this.b = Math.max(0, this.b - color.b); - return this; - } + if (this.gradientMap && this.gradientMap.isTexture) { + data.gradientMap = this.gradientMap.toJSON(meta).uuid; + } - multiply(color) { - this.r *= color.r; - this.g *= color.g; - this.b *= color.b; - return this; - } + if (this.transmission !== undefined) data.transmission = this.transmission; + if (this.transmissionMap && this.transmissionMap.isTexture) data.transmissionMap = this.transmissionMap.toJSON(meta).uuid; + if (this.thickness !== undefined) data.thickness = this.thickness; + if (this.thicknessMap && this.thicknessMap.isTexture) data.thicknessMap = this.thicknessMap.toJSON(meta).uuid; + if (this.attenuationDistance !== undefined) data.attenuationDistance = this.attenuationDistance; + if (this.attenuationColor !== undefined) data.attenuationColor = this.attenuationColor.getHex(); + if (this.size !== undefined) data.size = this.size; + if (this.shadowSide !== null) data.shadowSide = this.shadowSide; + if (this.sizeAttenuation !== undefined) data.sizeAttenuation = this.sizeAttenuation; + if (this.blending !== NormalBlending) data.blending = this.blending; + if (this.side !== FrontSide) data.side = this.side; + if (this.vertexColors) data.vertexColors = true; + if (this.opacity < 1) data.opacity = this.opacity; + if (this.format !== RGBAFormat) data.format = this.format; + if (this.transparent === true) data.transparent = this.transparent; + data.depthFunc = this.depthFunc; + data.depthTest = this.depthTest; + data.depthWrite = this.depthWrite; + data.colorWrite = this.colorWrite; + data.stencilWrite = this.stencilWrite; + data.stencilWriteMask = this.stencilWriteMask; + data.stencilFunc = this.stencilFunc; + data.stencilRef = this.stencilRef; + data.stencilFuncMask = this.stencilFuncMask; + data.stencilFail = this.stencilFail; + data.stencilZFail = this.stencilZFail; + data.stencilZPass = this.stencilZPass; // rotation (SpriteMaterial) - multiplyScalar(s) { - this.r *= s; - this.g *= s; - this.b *= s; - return this; - } + if (this.rotation && this.rotation !== 0) data.rotation = this.rotation; + if (this.polygonOffset === true) data.polygonOffset = true; + if (this.polygonOffsetFactor !== 0) data.polygonOffsetFactor = this.polygonOffsetFactor; + if (this.polygonOffsetUnits !== 0) data.polygonOffsetUnits = this.polygonOffsetUnits; + if (this.linewidth && this.linewidth !== 1) data.linewidth = this.linewidth; + if (this.dashSize !== undefined) data.dashSize = this.dashSize; + if (this.gapSize !== undefined) data.gapSize = this.gapSize; + if (this.scale !== undefined) data.scale = this.scale; + if (this.dithering === true) data.dithering = true; + if (this.alphaTest > 0) data.alphaTest = this.alphaTest; + if (this.alphaToCoverage === true) data.alphaToCoverage = this.alphaToCoverage; + if (this.premultipliedAlpha === true) data.premultipliedAlpha = this.premultipliedAlpha; + if (this.wireframe === true) data.wireframe = this.wireframe; + if (this.wireframeLinewidth > 1) data.wireframeLinewidth = this.wireframeLinewidth; + if (this.wireframeLinecap !== 'round') data.wireframeLinecap = this.wireframeLinecap; + if (this.wireframeLinejoin !== 'round') data.wireframeLinejoin = this.wireframeLinejoin; + if (this.flatShading === true) data.flatShading = this.flatShading; + if (this.visible === false) data.visible = false; + if (this.toneMapped === false) data.toneMapped = false; + if (JSON.stringify(this.userData) !== '{}') data.userData = this.userData; // TODO: Copied from Object3D.toJSON - lerp(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; - } + function extractFromCache(cache) { + const values = []; - lerpColors(color1, color2, alpha) { - this.r = color1.r + (color2.r - color1.r) * alpha; - this.g = color1.g + (color2.g - color1.g) * alpha; - this.b = color1.b + (color2.b - color1.b) * alpha; - return this; - } + for (const key in cache) { + const data = cache[key]; + delete data.metadata; + values.push(data); + } - lerpHSL(color, alpha) { - this.getHSL(_hslA); - color.getHSL(_hslB); - const h = lerp(_hslA.h, _hslB.h, alpha); - const s = lerp(_hslA.s, _hslB.s, alpha); - const l = lerp(_hslA.l, _hslB.l, alpha); - this.setHSL(h, s, l); - return this; - } + return values; + } - equals(c) { - return c.r === this.r && c.g === this.g && c.b === this.b; - } + if (isRoot) { + const textures = extractFromCache(meta.textures); + const images = extractFromCache(meta.images); + if (textures.length > 0) data.textures = textures; + if (images.length > 0) data.images = images; + } - fromArray(array, offset = 0) { - this.r = array[offset]; - this.g = array[offset + 1]; - this.b = array[offset + 2]; - return this; + return data; } - toArray(array = [], offset = 0) { - array[offset] = this.r; - array[offset + 1] = this.g; - array[offset + 2] = this.b; - return array; + clone() { + return new this.constructor().copy(this); } - fromBufferAttribute(attribute, index) { - this.r = attribute.getX(index); - this.g = attribute.getY(index); - this.b = attribute.getZ(index); + copy(source) { + this.name = source.name; + this.fog = source.fog; + this.blending = source.blending; + this.side = source.side; + this.vertexColors = source.vertexColors; + this.opacity = source.opacity; + this.format = source.format; + this.transparent = source.transparent; + this.blendSrc = source.blendSrc; + this.blendDst = source.blendDst; + this.blendEquation = source.blendEquation; + this.blendSrcAlpha = source.blendSrcAlpha; + this.blendDstAlpha = source.blendDstAlpha; + this.blendEquationAlpha = source.blendEquationAlpha; + this.depthFunc = source.depthFunc; + this.depthTest = source.depthTest; + this.depthWrite = source.depthWrite; + this.stencilWriteMask = source.stencilWriteMask; + this.stencilFunc = source.stencilFunc; + this.stencilRef = source.stencilRef; + this.stencilFuncMask = source.stencilFuncMask; + this.stencilFail = source.stencilFail; + this.stencilZFail = source.stencilZFail; + this.stencilZPass = source.stencilZPass; + this.stencilWrite = source.stencilWrite; + const srcPlanes = source.clippingPlanes; + let dstPlanes = null; - if (attribute.normalized === true) { - // assuming Uint8Array - this.r /= 255; - this.g /= 255; - this.b /= 255; + if (srcPlanes !== null) { + const n = srcPlanes.length; + dstPlanes = new Array(n); + + for (let i = 0; i !== n; ++i) { + dstPlanes[i] = srcPlanes[i].clone(); + } } + this.clippingPlanes = dstPlanes; + this.clipIntersection = source.clipIntersection; + this.clipShadows = source.clipShadows; + this.shadowSide = source.shadowSide; + this.colorWrite = source.colorWrite; + this.precision = source.precision; + this.polygonOffset = source.polygonOffset; + this.polygonOffsetFactor = source.polygonOffsetFactor; + this.polygonOffsetUnits = source.polygonOffsetUnits; + this.dithering = source.dithering; + this.alphaTest = source.alphaTest; + this.alphaToCoverage = source.alphaToCoverage; + this.premultipliedAlpha = source.premultipliedAlpha; + this.visible = source.visible; + this.toneMapped = source.toneMapped; + this.userData = JSON.parse(JSON.stringify(source.userData)); return this; } - toJSON() { - return this.getHex(); + dispose() { + this.dispatchEvent({ + type: 'dispose' + }); + } + + set needsUpdate(value) { + if (value === true) this.version++; } } - Color.NAMES = _colorKeywords; - Color.prototype.isColor = true; - Color.prototype.r = 1; - Color.prototype.g = 1; - Color.prototype.b = 1; + Material.prototype.isMaterial = true; /** * parameters = { @@ -7354,7 +7323,7 @@ } // - let _id = 0; + let _id$1 = 0; const _m1 = /*@__PURE__*/new Matrix4(); @@ -7372,7 +7341,7 @@ constructor() { super(); Object.defineProperty(this, 'id', { - value: _id++ + value: _id$1++ }); this.uuid = generateUUID(); this.name = ''; @@ -9072,6 +9041,7 @@ renderer.render(scene, cameraNZ); renderer.setRenderTarget(currentRenderTarget); renderer.xr.enabled = currentXrEnabled; + renderTarget.texture.needsPMREMUpdate = true; } } @@ -9725,7 +9695,7 @@ var common = "#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal;\n#endif\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}"; - var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_maxMipLevel 8.0\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_maxTileSize 256.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\tfloat texelSize = 1.0 / ( 3.0 * cubeUV_maxTileSize );\n\t\tvec2 uv = getUV( direction, face ) * ( faceSize - 1.0 );\n\t\tvec2 f = fract( uv );\n\t\tuv += 0.5 - f;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tif ( mipInt < cubeUV_maxMipLevel ) {\n\t\t\tuv.y += 2.0 * cubeUV_maxTileSize;\n\t\t}\n\t\tuv.y += filterInt * 2.0 * cubeUV_minTileSize;\n\t\tuv.x += 3.0 * max( 0.0, cubeUV_maxTileSize - 2.0 * faceSize );\n\t\tuv *= texelSize;\n\t\tvec3 tl = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb;\n\t\tuv.x += texelSize;\n\t\tvec3 tr = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb;\n\t\tuv.y += texelSize;\n\t\tvec3 br = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb;\n\t\tuv.x -= texelSize;\n\t\tvec3 bl = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb;\n\t\tvec3 tm = mix( tl, tr, f.x );\n\t\tvec3 bm = mix( bl, br, f.x );\n\t\treturn mix( tm, bm, f.y );\n\t}\n\t#define r0 1.0\n\t#define v0 0.339\n\t#define m0 - 2.0\n\t#define r1 0.8\n\t#define v1 0.276\n\t#define m1 - 1.0\n\t#define r4 0.4\n\t#define v4 0.046\n\t#define m4 2.0\n\t#define r5 0.305\n\t#define v5 0.016\n\t#define m5 3.0\n\t#define r6 0.21\n\t#define v6 0.0038\n\t#define m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= r1 ) {\n\t\t\tmip = ( r0 - roughness ) * ( m1 - m0 ) / ( r0 - r1 ) + m0;\n\t\t} else if ( roughness >= r4 ) {\n\t\t\tmip = ( r1 - roughness ) * ( m4 - m1 ) / ( r1 - r4 ) + m1;\n\t\t} else if ( roughness >= r5 ) {\n\t\t\tmip = ( r4 - roughness ) * ( m5 - m4 ) / ( r4 - r5 ) + m4;\n\t\t} else if ( roughness >= r6 ) {\n\t\t\tmip = ( r5 - roughness ) * ( m6 - m5 ) / ( r5 - r6 ) + m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), m0, cubeUV_maxMipLevel );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif"; + var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_maxMipLevel 8.0\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_maxTileSize 256.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\tfloat texelSize = 1.0 / ( 3.0 * cubeUV_maxTileSize );\n\t\tvec2 uv = getUV( direction, face ) * ( faceSize - 1.0 ) + 0.5;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tif ( mipInt < cubeUV_maxMipLevel ) {\n\t\t\tuv.y += 2.0 * cubeUV_maxTileSize;\n\t\t}\n\t\tuv.y += filterInt * 2.0 * cubeUV_minTileSize;\n\t\tuv.x += 3.0 * max( 0.0, cubeUV_maxTileSize - 2.0 * faceSize );\n\t\tuv *= texelSize;\n\t\treturn texture2D( envMap, uv ).rgb;\n\t}\n\t#define r0 1.0\n\t#define v0 0.339\n\t#define m0 - 2.0\n\t#define r1 0.8\n\t#define v1 0.276\n\t#define m1 - 1.0\n\t#define r4 0.4\n\t#define v4 0.046\n\t#define m4 2.0\n\t#define r5 0.305\n\t#define v5 0.016\n\t#define m5 3.0\n\t#define r6 0.21\n\t#define v6 0.0038\n\t#define m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= r1 ) {\n\t\t\tmip = ( r0 - roughness ) * ( m1 - m0 ) / ( r0 - r1 ) + m0;\n\t\t} else if ( roughness >= r4 ) {\n\t\t\tmip = ( r1 - roughness ) * ( m4 - m1 ) / ( r1 - r4 ) + m1;\n\t\t} else if ( roughness >= r5 ) {\n\t\t\tmip = ( r4 - roughness ) * ( m5 - m4 ) / ( r4 - r5 ) + m4;\n\t\t} else if ( roughness >= r6 ) {\n\t\t\tmip = ( r5 - roughness ) * ( m6 - m5 ) / ( r5 - r6 ) + m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), m0, cubeUV_maxMipLevel );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif"; var defaultnormal_vertex = "vec3 transformedNormal = objectNormal;\n#ifdef USE_INSTANCING\n\tmat3 m = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( m[ 0 ], m[ 0 ] ), dot( m[ 1 ], m[ 1 ] ), dot( m[ 2 ], m[ 2 ] ) );\n\ttransformedNormal = m * transformedNormal;\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = ( modelViewMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif"; @@ -9733,15 +9703,15 @@ var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias );\n#endif"; - var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif"; + var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif"; var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif"; var encodings_fragment = "gl_FragColor = linearToOutputTexel( gl_FragColor );"; - var encodings_pars_fragment = "\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.rgb, vec3( gammaFactor ) ), value.a );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.rgb, vec3( 1.0 / gammaFactor ) ), value.a );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.a );\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * value.a * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.r, max( value.g, value.b ) );\n\tfloat M = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.r, max( value.g, value.b ) );\n\tfloat D = max( maxRange / maxRGB, 1.0 );\n\tD = clamp( floor( D ) / 255.0, 0.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}"; + var encodings_pars_fragment = "vec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}"; - var envmap_fragment = "#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t\tenvColor = envMapTexelToLinear( envColor );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 envColor = textureCubeUV( envMap, reflectVec, 0.0 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif"; + var envmap_fragment = "#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 envColor = textureCubeUV( envMap, reflectVec, 0.0 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif"; var envmap_common_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif"; @@ -9761,7 +9731,7 @@ var gradientmap_pars_fragment = "#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn vec3( texture2D( gradientMap, coord ).r );\n\t#else\n\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t#endif\n}"; - var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\tvec3 lightMapIrradiance = lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tlightMapIrradiance *= PI;\n\t#endif\n\treflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif"; + var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tlightMapIrradiance *= PI;\n\t#endif\n\treflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif"; var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif"; @@ -9779,13 +9749,13 @@ var lights_phong_pars_fragment = "varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )\t(0)"; - var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\t#ifdef SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULARINTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vUv ).a;\n\t\t#endif\n\t\t#ifdef USE_SPECULARCOLORMAP\n\t\t\tspecularColorFactor *= specularColorMapTexelToLinear( texture2D( specularColorMap, vUv ) ).rgb;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( ior - 1.0 ) / ( ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tmaterial.sheenColor *= sheenColorMapTexelToLinear( texture2D( sheenColorMap, vUv ) ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vUv ).a;\n\t#endif\n#endif"; + var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\t#ifdef SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULARINTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vUv ).a;\n\t\t#endif\n\t\t#ifdef USE_SPECULARCOLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vUv ).rgb;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( ior - 1.0 ) / ( ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vUv ).a;\n\t#endif\n#endif"; - var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n};\nvec3 clearcoatSpecular = vec3( 0.0 );\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\tvec3 FssEss = specularColor * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = specularColor + ( 1.0 - specularColor ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecular += ccIrradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.clearcoatNormal, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\treflectedLight.directSpecular += irradiance * BRDF_Sheen( directLight.direction, geometry.viewDir, geometry.normal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.roughness );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecular += clearcoatRadiance * EnvironmentBRDF( geometry.clearcoatNormal, geometry.viewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\tcomputeMultiscattering( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - ( singleScattering + multiScattering ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}"; + var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n};\nvec3 clearcoatSpecular = vec3( 0.0 );\nvec3 sheenSpecular = vec3( 0.0 );\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\tvec3 FssEss = specularColor * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = specularColor + ( 1.0 - specularColor ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecular += ccIrradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.clearcoatNormal, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * BRDF_Sheen( directLight.direction, geometry.viewDir, geometry.normal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.roughness );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecular += clearcoatRadiance * EnvironmentBRDF( geometry.clearcoatNormal, geometry.viewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * material.sheenColor * IBLSheenBRDF( geometry.normal, geometry.viewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\tcomputeMultiscattering( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - ( singleScattering + multiScattering ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}"; var lights_fragment_begin = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\n#ifdef USE_CLEARCOAT\n\tgeometry.clearcoatNormal = clearcoatNormal;\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\tirradiance += getLightProbeIrradiance( lightProbe, geometry.normal );\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry.normal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif"; - var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\t\tvec3 lightMapIrradiance = lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometry.normal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getIBLRadiance( geometry.viewDir, geometry.normal, material.roughness );\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif"; + var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometry.normal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getIBLRadiance( geometry.viewDir, geometry.normal, material.roughness );\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif"; var lights_fragment_end = "#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometry, material, reflectedLight );\n#endif"; @@ -9797,11 +9767,11 @@ var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n\t#else\n\t\tif ( isPerspectiveMatrix( projectionMatrix ) ) {\n\t\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\t\tgl_Position.z *= gl_Position.w;\n\t\t}\n\t#endif\n#endif"; - var map_fragment = "#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif"; + var map_fragment = "#ifdef USE_MAP\n\tvec4 sampledDiffuseColor = texture2D( map, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\tsampledDiffuseColor = vec4( mix( pow( sampledDiffuseColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), sampledDiffuseColor.rgb * 0.0773993808, vec3( lessThanEqual( sampledDiffuseColor.rgb, vec3( 0.04045 ) ) ) ), sampledDiffuseColor.w );\n\t#endif\n\tdiffuseColor *= sampledDiffuseColor;\n#endif"; var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif"; - var map_particle_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n#endif\n#ifdef USE_MAP\n\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif"; + var map_particle_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n#endif\n#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif"; var map_particle_pars_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tuniform mat3 uvTransform;\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif"; @@ -9875,7 +9845,7 @@ var transmission_fragment = "#ifdef USE_TRANSMISSION\n\tfloat transmissionAlpha = 1.0;\n\tfloat transmissionFactor = transmission;\n\tfloat thicknessFactor = thickness;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\ttransmissionFactor *= texture2D( transmissionMap, vUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tthicknessFactor *= texture2D( thicknessMap, vUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmission = getIBLVolumeRefraction(\n\t\tn, v, roughnessFactor, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, ior, thicknessFactor,\n\t\tattenuationColor, attenuationDistance );\n\ttotalDiffuse = mix( totalDiffuse, transmission.rgb, transmissionFactor );\n\ttransmissionAlpha = mix( transmissionAlpha, transmission.a, transmissionFactor );\n#endif"; - var transmission_pars_fragment = "#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tvec3 getVolumeTransmissionRay( vec3 n, vec3 v, float thickness, float ior, mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( float roughness, float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( vec2 fragCoord, float roughness, float ior ) {\n\t\tfloat framebufferLod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\treturn texture2DLodEXT( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n\t\t#else\n\t\t\treturn texture2D( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n\t\t#endif\n\t}\n\tvec3 applyVolumeAttenuation( vec3 radiance, float transmissionDistance, vec3 attenuationColor, float attenuationDistance ) {\n\t\tif ( attenuationDistance == 0.0 ) {\n\t\t\treturn radiance;\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance * radiance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( vec3 n, vec3 v, float roughness, vec3 diffuseColor, vec3 specularColor, float specularF90,\n\t\tvec3 position, mat4 modelMatrix, mat4 viewMatrix, mat4 projMatrix, float ior, float thickness,\n\t\tvec3 attenuationColor, float attenuationDistance ) {\n\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\trefractionCoords += 1.0;\n\t\trefractionCoords /= 2.0;\n\t\tvec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\tvec3 attenuatedColor = applyVolumeAttenuation( transmittedLight.rgb, length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor * diffuseColor, transmittedLight.a );\n\t}\n#endif"; + var transmission_pars_fragment = "#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat framebufferLod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\treturn texture2DLodEXT( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n\t\t#else\n\t\t\treturn texture2D( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n\t\t#endif\n\t}\n\tvec3 applyVolumeAttenuation( const in vec3 radiance, const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( attenuationDistance == 0.0 ) {\n\t\t\treturn radiance;\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance * radiance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\trefractionCoords += 1.0;\n\t\trefractionCoords /= 2.0;\n\t\tvec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\tvec3 attenuatedColor = applyVolumeAttenuation( transmittedLight.rgb, length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor * diffuseColor, transmittedLight.a );\n\t}\n#endif"; var uv_pars_fragment = "#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )\n\tvarying vec2 vUv;\n#endif"; @@ -9892,7 +9862,7 @@ var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION )\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif"; const vertex$g = "varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}"; - const fragment$g = "uniform sampler2D t2D;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\tgl_FragColor = mapTexelToLinear( texColor );\n\t#include \n\t#include \n}"; + const fragment$g = "uniform sampler2D t2D;\nvarying vec2 vUv;\nvoid main() {\n\tgl_FragColor = texture2D( t2D, vUv );\n\t#include \n\t#include \n}"; const vertex$f = "varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}"; const fragment$f = "#include \nuniform float opacity;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 vReflect = vWorldDirection;\n\t#include \n\tgl_FragColor = envColor;\n\tgl_FragColor.a *= opacity;\n\t#include \n\t#include \n}"; @@ -9904,19 +9874,19 @@ const fragment$d = "#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main () {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}"; const vertex$c = "varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}"; - const fragment$c = "uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tvec4 texColor = texture2D( tEquirect, sampleUV );\n\tgl_FragColor = mapTexelToLinear( texColor );\n\t#include \n\t#include \n}"; + const fragment$c = "uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\t#include \n\t#include \n}"; const vertex$b = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; const fragment$b = "uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; const vertex$a = "#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - const fragment$a = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\t\treflectedLight.indirectDiffuse += lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; + const fragment$a = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; const vertex$9 = "#define LAMBERT\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; const fragment$9 = "uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.indirectDiffuse += ( gl_FrontFacing ) ? vIndirectFront : vIndirectBack;\n\t#else\n\t\treflectedLight.indirectDiffuse += vIndirectFront;\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= BRDF_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; const vertex$8 = "#define MATCAP\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n}"; - const fragment$8 = "#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t\tmatcapColor = matcapTexelToLinear( matcapColor );\n\t#else\n\t\tvec4 matcapColor = vec4( 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; + const fragment$8 = "#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t#else\n\t\tvec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; const vertex$7 = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}"; const fragment$7 = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}"; @@ -9925,7 +9895,7 @@ const fragment$6 = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; const vertex$5 = "#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}"; - const fragment$5 = "#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULARINTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n\t#ifdef USE_SPECULARCOLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; + const fragment$5 = "#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULARINTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n\t#ifdef USE_SPECULARCOLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecular;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; const vertex$4 = "#define TOON\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}"; const fragment$4 = "#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; @@ -10564,7 +10534,7 @@ value: null }, sheenRoughness: { - value: 0 + value: 1 }, sheenRoughnessMap: { value: null @@ -10594,7 +10564,7 @@ value: new Color(0x000000) }, specularIntensity: { - value: 0 + value: 1 }, specularIntensityMap: { value: null @@ -11400,11 +11370,9 @@ const image = texture.image; if (image && image.height > 0) { - const currentRenderTarget = renderer.getRenderTarget(); const renderTarget = new WebGLCubeRenderTarget(image.height / 2); renderTarget.fromEquirectangularTexture(renderer, texture); cubemaps.set(texture, renderTarget); - renderer.setRenderTarget(currentRenderTarget); texture.addEventListener('dispose', onTextureDispose); return mapTextureMapping(renderTarget.texture, texture.mapping); } else { @@ -11560,15 +11528,6 @@ // samples and exit early, but not recompile the shader. const MAX_SAMPLES = 20; - const ENCODINGS = { - [LinearEncoding]: 0, - [sRGBEncoding]: 1, - [RGBEEncoding]: 2, - [RGBM7Encoding]: 3, - [RGBM16Encoding]: 4, - [RGBDEncoding]: 5, - [GammaEncoding]: 6 - }; const _flatCamera = /*@__PURE__*/new OrthographicCamera(); @@ -11640,23 +11599,23 @@ } /** * Generates a PMREM from an equirectangular texture, which can be either LDR - * (RGBFormat) or HDR (RGBEFormat). The ideal input image size is 1k (1024 x 512), + * or HDR. The ideal input image size is 1k (1024 x 512), * as this matches best with the 256 x 256 cubemap output. */ - fromEquirectangular(equirectangular) { - return this._fromTexture(equirectangular); + fromEquirectangular(equirectangular, renderTarget = null) { + return this._fromTexture(equirectangular, renderTarget); } /** * Generates a PMREM from an cubemap texture, which can be either LDR - * (RGBFormat) or HDR (RGBEFormat). The ideal input cube size is 256 x 256, + * or HDR. The ideal input cube size is 256 x 256, * as this matches best with the 256 x 256 cubemap output. */ - fromCubemap(cubemap) { - return this._fromTexture(cubemap); + fromCubemap(cubemap, renderTarget = null) { + return this._fromTexture(cubemap, renderTarget); } /** * Pre-compiles the cubemap shader. You can get faster start-up by invoking this method during @@ -11713,10 +11672,10 @@ _setViewport(outputTarget, 0, 0, outputTarget.width, outputTarget.height); } - _fromTexture(texture) { + _fromTexture(texture, renderTarget) { _oldTarget = this._renderer.getRenderTarget(); - const cubeUVRenderTarget = this._allocateTargets(texture); + const cubeUVRenderTarget = renderTarget || this._allocateTargets(texture); this._textureToCubeUV(texture, cubeUVRenderTarget); @@ -11730,12 +11689,12 @@ _allocateTargets(texture) { // warning: null texture is valid const params = { - magFilter: NearestFilter, - minFilter: NearestFilter, + magFilter: LinearFilter, + minFilter: LinearFilter, generateMipmaps: false, - type: UnsignedByteType, - format: RGBEFormat, - encoding: _isLDR(texture) ? texture.encoding : RGBEEncoding, + type: HalfFloatType, + format: RGBAFormat, + encoding: LinearEncoding, depthBuffer: false }; @@ -11760,11 +11719,9 @@ const forwardSign = [1, 1, 1, -1, -1, -1]; const renderer = this._renderer; const originalAutoClear = renderer.autoClear; - const outputEncoding = renderer.outputEncoding; const toneMapping = renderer.toneMapping; renderer.getClearColor(_clearColor); renderer.toneMapping = NoToneMapping; - renderer.outputEncoding = LinearEncoding; renderer.autoClear = false; const backgroundMaterial = new MeshBasicMaterial({ name: 'PMREM.Background', @@ -11815,19 +11772,10 @@ backgroundBox.geometry.dispose(); backgroundBox.material.dispose(); renderer.toneMapping = toneMapping; - renderer.outputEncoding = outputEncoding; renderer.autoClear = originalAutoClear; scene.background = background; } - _setEncoding(uniform, texture) { - if (this._renderer.capabilities.isWebGL2 === true && texture.format === RGBAFormat && texture.type === UnsignedByteType && texture.encoding === sRGBEncoding) { - uniform.value = ENCODINGS[LinearEncoding]; - } else { - uniform.value = ENCODINGS[texture.encoding]; - } - } - _textureToCubeUV(texture, cubeUVRenderTarget) { const renderer = this._renderer; const isCubeTexture = texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping; @@ -11851,10 +11799,6 @@ uniforms['texelSize'].value.set(1.0 / texture.image.width, 1.0 / texture.image.height); } - this._setEncoding(uniforms['inputEncoding'], texture); - - this._setEncoding(uniforms['outputEncoding'], cubeUVRenderTarget.texture); - _setViewport(cubeUVRenderTarget, 0, 0, 3 * SIZE_MAX, 2 * SIZE_MAX); renderer.setRenderTarget(cubeUVRenderTarget); @@ -11943,11 +11887,6 @@ blurUniforms['dTheta'].value = radiansPerPixel; blurUniforms['mipInt'].value = LOD_MAX - lodIn; - - this._setEncoding(blurUniforms['inputEncoding'], targetIn.texture); - - this._setEncoding(blurUniforms['outputEncoding'], targetIn.texture); - const outputSize = _sizeLods[lodOut]; const x = 3 * Math.max(0, SIZE_MAX - 2 * outputSize); const y = (lodOut === 0 ? 0 : 2 * SIZE_MAX) + 2 * outputSize * (lodOut > LOD_MAX - LOD_MIN ? lodOut - LOD_MAX + LOD_MIN : 0); @@ -11960,11 +11899,6 @@ } - function _isLDR(texture) { - if (texture === undefined || texture.type !== UnsignedByteType) return false; - return texture.encoding === LinearEncoding || texture.encoding === sRGBEncoding || texture.encoding === GammaEncoding; - } - function _createPlanes() { const _lodPlanes = []; const _sizeLods = []; @@ -12070,12 +12004,6 @@ }, 'poleAxis': { value: poleAxis - }, - 'inputEncoding': { - value: ENCODINGS[LinearEncoding] - }, - 'outputEncoding': { - value: ENCODINGS[LinearEncoding] } }, vertexShader: _getCommonVertexShader(), @@ -12096,8 +12024,6 @@ uniform float mipInt; uniform vec3 poleAxis; - ${_getEncodings()} - #define ENVMAP_TYPE_CUBE_UV #include @@ -12142,8 +12068,6 @@ } - gl_FragColor = linearToOutputTexel( gl_FragColor ); - } `, blending: NoBlending, @@ -12163,12 +12087,6 @@ }, 'texelSize': { value: texelSize - }, - 'inputEncoding': { - value: ENCODINGS[LinearEncoding] - }, - 'outputEncoding': { - value: ENCODINGS[LinearEncoding] } }, vertexShader: _getCommonVertexShader(), @@ -12184,8 +12102,6 @@ uniform sampler2D envMap; uniform vec2 texelSize; - ${_getEncodings()} - #include void main() { @@ -12197,20 +12113,18 @@ vec2 f = fract( uv / texelSize - 0.5 ); uv -= f * texelSize; - vec3 tl = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb; + vec3 tl = texture2D ( envMap, uv ).rgb; uv.x += texelSize.x; - vec3 tr = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb; + vec3 tr = texture2D ( envMap, uv ).rgb; uv.y += texelSize.y; - vec3 br = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb; + vec3 br = texture2D ( envMap, uv ).rgb; uv.x -= texelSize.x; - vec3 bl = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb; + vec3 bl = texture2D ( envMap, uv ).rgb; vec3 tm = mix( tl, tr, f.x ); vec3 bm = mix( bl, br, f.x ); gl_FragColor.rgb = mix( tm, bm, f.y ); - gl_FragColor = linearToOutputTexel( gl_FragColor ); - } `, blending: NoBlending, @@ -12226,12 +12140,6 @@ uniforms: { 'envMap': { value: null - }, - 'inputEncoding': { - value: ENCODINGS[LinearEncoding] - }, - 'outputEncoding': { - value: ENCODINGS[LinearEncoding] } }, vertexShader: _getCommonVertexShader(), @@ -12246,13 +12154,9 @@ uniform samplerCube envMap; - ${_getEncodings()} - void main() { - gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 ); - gl_FragColor.rgb = envMapTexelToLinear( textureCube( envMap, vec3( - vOutputDirection.x, vOutputDirection.yz ) ) ).rgb; - gl_FragColor = linearToOutputTexel( gl_FragColor ); + gl_FragColor = textureCube( envMap, vec3( - vOutputDirection.x, vOutputDirection.yz ) ); } `, @@ -12327,121 +12231,40 @@ ); } - function _getEncodings() { - return ( - /* glsl */ - ` - - uniform int inputEncoding; - uniform int outputEncoding; - - #include - - vec4 inputTexelToLinear( vec4 value ) { - - if ( inputEncoding == 0 ) { - - return value; - - } else if ( inputEncoding == 1 ) { - - return sRGBToLinear( value ); - - } else if ( inputEncoding == 2 ) { - - return RGBEToLinear( value ); - - } else if ( inputEncoding == 3 ) { - - return RGBMToLinear( value, 7.0 ); - - } else if ( inputEncoding == 4 ) { - - return RGBMToLinear( value, 16.0 ); - - } else if ( inputEncoding == 5 ) { - - return RGBDToLinear( value, 256.0 ); - - } else { - - return GammaToLinear( value, 2.2 ); - - } - - } - - vec4 linearToOutputTexel( vec4 value ) { - - if ( outputEncoding == 0 ) { - - return value; - - } else if ( outputEncoding == 1 ) { - - return LinearTosRGB( value ); - - } else if ( outputEncoding == 2 ) { - - return LinearToRGBE( value ); - - } else if ( outputEncoding == 3 ) { - - return LinearToRGBM( value, 7.0 ); - - } else if ( outputEncoding == 4 ) { - - return LinearToRGBM( value, 16.0 ); - - } else if ( outputEncoding == 5 ) { - - return LinearToRGBD( value, 256.0 ); - - } else { - - return LinearToGamma( value, 2.2 ); - - } - - } - - vec4 envMapTexelToLinear( vec4 color ) { - - return inputTexelToLinear( color ); - - } - ` - ); - } - function WebGLCubeUVMaps(renderer) { let cubeUVmaps = new WeakMap(); let pmremGenerator = null; function get(texture) { - if (texture && texture.isTexture && texture.isRenderTargetTexture === false) { + if (texture && texture.isTexture) { const mapping = texture.mapping; const isEquirectMap = mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping; - const isCubeMap = mapping === CubeReflectionMapping || mapping === CubeRefractionMapping; + const isCubeMap = mapping === CubeReflectionMapping || mapping === CubeRefractionMapping; // equirect/cube map to cubeUV conversion if (isEquirectMap || isCubeMap) { - // equirect/cube map to cubeUV conversion - if (cubeUVmaps.has(texture)) { - return cubeUVmaps.get(texture).texture; + if (texture.isRenderTargetTexture && texture.needsPMREMUpdate === true) { + texture.needsPMREMUpdate = false; + let renderTarget = cubeUVmaps.get(texture); + if (pmremGenerator === null) pmremGenerator = new PMREMGenerator(renderer); + renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular(texture, renderTarget) : pmremGenerator.fromCubemap(texture, renderTarget); + cubeUVmaps.set(texture, renderTarget); + return renderTarget.texture; } else { - const image = texture.image; - - if (isEquirectMap && image && image.height > 0 || isCubeMap && image && isCubeTextureComplete(image)) { - const currentRenderTarget = renderer.getRenderTarget(); - if (pmremGenerator === null) pmremGenerator = new PMREMGenerator(renderer); - const renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular(texture) : pmremGenerator.fromCubemap(texture); - cubeUVmaps.set(texture, renderTarget); - renderer.setRenderTarget(currentRenderTarget); - texture.addEventListener('dispose', onTextureDispose); - return renderTarget.texture; + if (cubeUVmaps.has(texture)) { + return cubeUVmaps.get(texture).texture; } else { - // image not yet ready. try the conversion next frame - return null; + const image = texture.image; + + if (isEquirectMap && image && image.height > 0 || isCubeMap && image && isCubeTextureComplete(image)) { + if (pmremGenerator === null) pmremGenerator = new PMREMGenerator(renderer); + const renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular(texture) : pmremGenerator.fromCubemap(texture); + cubeUVmaps.set(texture, renderTarget); + texture.addEventListener('dispose', onTextureDispose); + return renderTarget.texture; + } else { + // image not yet ready. try the conversion next frame + return null; + } } } } @@ -12902,6 +12725,14 @@ size: new Vector2(width, height) }; morphTextures.set(geometry, entry); + + function disposeTexture() { + texture.dispose(); + morphTextures.delete(geometry); + geometry.removeEventListener('dispose', disposeTexture); + } + + geometry.addEventListener('dispose', disposeTexture); } // @@ -13909,21 +13740,6 @@ case sRGBEncoding: return ['sRGB', '( value )']; - case RGBEEncoding: - return ['RGBE', '( value )']; - - case RGBM7Encoding: - return ['RGBM', '( value, 7.0 )']; - - case RGBM16Encoding: - return ['RGBM', '( value, 16.0 )']; - - case RGBDEncoding: - return ['RGBD', '( value, 256.0 )']; - - case GammaEncoding: - return ['Gamma', '( value, float( GAMMA_FACTOR ) )']; - default: console.warn('THREE.WebGLProgram: Unsupported encoding:', encoding); return ['Linear', '( value )']; @@ -13939,11 +13755,6 @@ return type.toUpperCase() + '\n\n' + errors + '\n\n' + addLineNumbers(gl.getShaderSource(shader)); } - function getTexelDecodingFunction(functionName, encoding) { - const components = getEncodingComponents(encoding); - return 'vec4 ' + functionName + '( vec4 value ) { return ' + components[0] + 'ToLinear' + components[1] + '; }'; - } - function getTexelEncodingFunction(functionName, encoding) { const components = getEncodingComponents(encoding); return 'vec4 ' + functionName + '( vec4 value ) { return LinearTo' + components[0] + components[1] + '; }'; @@ -14169,7 +13980,6 @@ const envMapTypeDefine = generateEnvMapTypeDefine(parameters); const envMapModeDefine = generateEnvMapModeDefine(parameters); const envMapBlendingDefine = generateEnvMapBlendingDefine(parameters); - const gammaFactorDefine = renderer.gammaFactor > 0 ? renderer.gammaFactor : 1.0; const customExtensions = parameters.isWebGL2 ? '' : generateExtensions(parameters); const customDefines = generateDefines(defines); const program = gl.createProgram(); @@ -14189,10 +13999,10 @@ prefixFragment += '\n'; } } else { - prefixVertex = [generatePrecision(parameters), '#define SHADER_NAME ' + parameters.shaderName, customDefines, parameters.instancing ? '#define USE_INSTANCING' : '', parameters.instancingColor ? '#define USE_INSTANCING_COLOR' : '', parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '', '#define GAMMA_FACTOR ' + gammaFactorDefine, '#define MAX_BONES ' + parameters.maxBones, parameters.useFog && parameters.fog ? '#define USE_FOG' : '', parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '', parameters.map ? '#define USE_MAP' : '', parameters.envMap ? '#define USE_ENVMAP' : '', parameters.envMap ? '#define ' + envMapModeDefine : '', parameters.lightMap ? '#define USE_LIGHTMAP' : '', parameters.aoMap ? '#define USE_AOMAP' : '', parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', parameters.bumpMap ? '#define USE_BUMPMAP' : '', parameters.normalMap ? '#define USE_NORMALMAP' : '', parameters.normalMap && parameters.objectSpaceNormalMap ? '#define OBJECTSPACE_NORMALMAP' : '', parameters.normalMap && parameters.tangentSpaceNormalMap ? '#define TANGENTSPACE_NORMALMAP' : '', parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '', parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '', parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '', parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '', parameters.specularMap ? '#define USE_SPECULARMAP' : '', parameters.specularIntensityMap ? '#define USE_SPECULARINTENSITYMAP' : '', parameters.specularColorMap ? '#define USE_SPECULARCOLORMAP' : '', parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', parameters.alphaMap ? '#define USE_ALPHAMAP' : '', parameters.transmission ? '#define USE_TRANSMISSION' : '', parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', parameters.sheenColorMap ? '#define USE_SHEENCOLORMAP' : '', parameters.sheenRoughnessMap ? '#define USE_SHEENROUGHNESSMAP' : '', parameters.vertexTangents ? '#define USE_TANGENT' : '', parameters.vertexColors ? '#define USE_COLOR' : '', parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', parameters.vertexUvs ? '#define USE_UV' : '', parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '', parameters.flatShading ? '#define FLAT_SHADED' : '', parameters.skinning ? '#define USE_SKINNING' : '', parameters.useVertexTexture ? '#define BONE_TEXTURE' : '', parameters.morphTargets ? '#define USE_MORPHTARGETS' : '', parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '', parameters.morphTargets && parameters.isWebGL2 ? '#define MORPHTARGETS_TEXTURE' : '', parameters.morphTargets && parameters.isWebGL2 ? '#define MORPHTARGETS_COUNT ' + parameters.morphTargetsCount : '', parameters.doubleSided ? '#define DOUBLE_SIDED' : '', parameters.flipSided ? '#define FLIP_SIDED' : '', parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '', parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ? '#define USE_LOGDEPTHBUF_EXT' : '', 'uniform mat4 modelMatrix;', 'uniform mat4 modelViewMatrix;', 'uniform mat4 projectionMatrix;', 'uniform mat4 viewMatrix;', 'uniform mat3 normalMatrix;', 'uniform vec3 cameraPosition;', 'uniform bool isOrthographic;', '#ifdef USE_INSTANCING', ' attribute mat4 instanceMatrix;', '#endif', '#ifdef USE_INSTANCING_COLOR', ' attribute vec3 instanceColor;', '#endif', 'attribute vec3 position;', 'attribute vec3 normal;', 'attribute vec2 uv;', '#ifdef USE_TANGENT', ' attribute vec4 tangent;', '#endif', '#if defined( USE_COLOR_ALPHA )', ' attribute vec4 color;', '#elif defined( USE_COLOR )', ' attribute vec3 color;', '#endif', '#if ( defined( USE_MORPHTARGETS ) && ! defined( MORPHTARGETS_TEXTURE ) )', ' attribute vec3 morphTarget0;', ' attribute vec3 morphTarget1;', ' attribute vec3 morphTarget2;', ' attribute vec3 morphTarget3;', ' #ifdef USE_MORPHNORMALS', ' attribute vec3 morphNormal0;', ' attribute vec3 morphNormal1;', ' attribute vec3 morphNormal2;', ' attribute vec3 morphNormal3;', ' #else', ' attribute vec3 morphTarget4;', ' attribute vec3 morphTarget5;', ' attribute vec3 morphTarget6;', ' attribute vec3 morphTarget7;', ' #endif', '#endif', '#ifdef USE_SKINNING', ' attribute vec4 skinIndex;', ' attribute vec4 skinWeight;', '#endif', '\n'].filter(filterEmptyLine).join('\n'); - prefixFragment = [customExtensions, generatePrecision(parameters), '#define SHADER_NAME ' + parameters.shaderName, customDefines, '#define GAMMA_FACTOR ' + gammaFactorDefine, parameters.useFog && parameters.fog ? '#define USE_FOG' : '', parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '', parameters.map ? '#define USE_MAP' : '', parameters.matcap ? '#define USE_MATCAP' : '', parameters.envMap ? '#define USE_ENVMAP' : '', parameters.envMap ? '#define ' + envMapTypeDefine : '', parameters.envMap ? '#define ' + envMapModeDefine : '', parameters.envMap ? '#define ' + envMapBlendingDefine : '', parameters.lightMap ? '#define USE_LIGHTMAP' : '', parameters.aoMap ? '#define USE_AOMAP' : '', parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', parameters.bumpMap ? '#define USE_BUMPMAP' : '', parameters.normalMap ? '#define USE_NORMALMAP' : '', parameters.normalMap && parameters.objectSpaceNormalMap ? '#define OBJECTSPACE_NORMALMAP' : '', parameters.normalMap && parameters.tangentSpaceNormalMap ? '#define TANGENTSPACE_NORMALMAP' : '', parameters.clearcoat ? '#define USE_CLEARCOAT' : '', parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '', parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '', parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '', parameters.specularMap ? '#define USE_SPECULARMAP' : '', parameters.specularIntensityMap ? '#define USE_SPECULARINTENSITYMAP' : '', parameters.specularColorMap ? '#define USE_SPECULARCOLORMAP' : '', parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', parameters.alphaMap ? '#define USE_ALPHAMAP' : '', parameters.alphaTest ? '#define USE_ALPHATEST' : '', parameters.sheen ? '#define USE_SHEEN' : '', parameters.sheenColorMap ? '#define USE_SHEENCOLORMAP' : '', parameters.sheenRoughnessMap ? '#define USE_SHEENROUGHNESSMAP' : '', parameters.transmission ? '#define USE_TRANSMISSION' : '', parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', parameters.vertexTangents ? '#define USE_TANGENT' : '', parameters.vertexColors || parameters.instancingColor ? '#define USE_COLOR' : '', parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', parameters.vertexUvs ? '#define USE_UV' : '', parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '', parameters.gradientMap ? '#define USE_GRADIENTMAP' : '', parameters.flatShading ? '#define FLAT_SHADED' : '', parameters.doubleSided ? '#define DOUBLE_SIDED' : '', parameters.flipSided ? '#define FLIP_SIDED' : '', parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '', parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '', parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ? '#define USE_LOGDEPTHBUF_EXT' : '', (parameters.extensionShaderTextureLOD || parameters.envMap) && parameters.rendererExtensionShaderTextureLod ? '#define TEXTURE_LOD_EXT' : '', 'uniform mat4 viewMatrix;', 'uniform vec3 cameraPosition;', 'uniform bool isOrthographic;', parameters.toneMapping !== NoToneMapping ? '#define TONE_MAPPING' : '', parameters.toneMapping !== NoToneMapping ? ShaderChunk['tonemapping_pars_fragment'] : '', // this code is required here because it is used by the toneMapping() function defined below + prefixVertex = [generatePrecision(parameters), '#define SHADER_NAME ' + parameters.shaderName, customDefines, parameters.instancing ? '#define USE_INSTANCING' : '', parameters.instancingColor ? '#define USE_INSTANCING_COLOR' : '', parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '', '#define MAX_BONES ' + parameters.maxBones, parameters.useFog && parameters.fog ? '#define USE_FOG' : '', parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '', parameters.map ? '#define USE_MAP' : '', parameters.envMap ? '#define USE_ENVMAP' : '', parameters.envMap ? '#define ' + envMapModeDefine : '', parameters.lightMap ? '#define USE_LIGHTMAP' : '', parameters.aoMap ? '#define USE_AOMAP' : '', parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', parameters.bumpMap ? '#define USE_BUMPMAP' : '', parameters.normalMap ? '#define USE_NORMALMAP' : '', parameters.normalMap && parameters.objectSpaceNormalMap ? '#define OBJECTSPACE_NORMALMAP' : '', parameters.normalMap && parameters.tangentSpaceNormalMap ? '#define TANGENTSPACE_NORMALMAP' : '', parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '', parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '', parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '', parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '', parameters.specularMap ? '#define USE_SPECULARMAP' : '', parameters.specularIntensityMap ? '#define USE_SPECULARINTENSITYMAP' : '', parameters.specularColorMap ? '#define USE_SPECULARCOLORMAP' : '', parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', parameters.alphaMap ? '#define USE_ALPHAMAP' : '', parameters.transmission ? '#define USE_TRANSMISSION' : '', parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', parameters.sheenColorMap ? '#define USE_SHEENCOLORMAP' : '', parameters.sheenRoughnessMap ? '#define USE_SHEENROUGHNESSMAP' : '', parameters.vertexTangents ? '#define USE_TANGENT' : '', parameters.vertexColors ? '#define USE_COLOR' : '', parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', parameters.vertexUvs ? '#define USE_UV' : '', parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '', parameters.flatShading ? '#define FLAT_SHADED' : '', parameters.skinning ? '#define USE_SKINNING' : '', parameters.useVertexTexture ? '#define BONE_TEXTURE' : '', parameters.morphTargets ? '#define USE_MORPHTARGETS' : '', parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '', parameters.morphTargets && parameters.isWebGL2 ? '#define MORPHTARGETS_TEXTURE' : '', parameters.morphTargets && parameters.isWebGL2 ? '#define MORPHTARGETS_COUNT ' + parameters.morphTargetsCount : '', parameters.doubleSided ? '#define DOUBLE_SIDED' : '', parameters.flipSided ? '#define FLIP_SIDED' : '', parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '', parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ? '#define USE_LOGDEPTHBUF_EXT' : '', 'uniform mat4 modelMatrix;', 'uniform mat4 modelViewMatrix;', 'uniform mat4 projectionMatrix;', 'uniform mat4 viewMatrix;', 'uniform mat3 normalMatrix;', 'uniform vec3 cameraPosition;', 'uniform bool isOrthographic;', '#ifdef USE_INSTANCING', ' attribute mat4 instanceMatrix;', '#endif', '#ifdef USE_INSTANCING_COLOR', ' attribute vec3 instanceColor;', '#endif', 'attribute vec3 position;', 'attribute vec3 normal;', 'attribute vec2 uv;', '#ifdef USE_TANGENT', ' attribute vec4 tangent;', '#endif', '#if defined( USE_COLOR_ALPHA )', ' attribute vec4 color;', '#elif defined( USE_COLOR )', ' attribute vec3 color;', '#endif', '#if ( defined( USE_MORPHTARGETS ) && ! defined( MORPHTARGETS_TEXTURE ) )', ' attribute vec3 morphTarget0;', ' attribute vec3 morphTarget1;', ' attribute vec3 morphTarget2;', ' attribute vec3 morphTarget3;', ' #ifdef USE_MORPHNORMALS', ' attribute vec3 morphNormal0;', ' attribute vec3 morphNormal1;', ' attribute vec3 morphNormal2;', ' attribute vec3 morphNormal3;', ' #else', ' attribute vec3 morphTarget4;', ' attribute vec3 morphTarget5;', ' attribute vec3 morphTarget6;', ' attribute vec3 morphTarget7;', ' #endif', '#endif', '#ifdef USE_SKINNING', ' attribute vec4 skinIndex;', ' attribute vec4 skinWeight;', '#endif', '\n'].filter(filterEmptyLine).join('\n'); + prefixFragment = [customExtensions, generatePrecision(parameters), '#define SHADER_NAME ' + parameters.shaderName, customDefines, parameters.useFog && parameters.fog ? '#define USE_FOG' : '', parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '', parameters.map ? '#define USE_MAP' : '', parameters.matcap ? '#define USE_MATCAP' : '', parameters.envMap ? '#define USE_ENVMAP' : '', parameters.envMap ? '#define ' + envMapTypeDefine : '', parameters.envMap ? '#define ' + envMapModeDefine : '', parameters.envMap ? '#define ' + envMapBlendingDefine : '', parameters.lightMap ? '#define USE_LIGHTMAP' : '', parameters.aoMap ? '#define USE_AOMAP' : '', parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', parameters.bumpMap ? '#define USE_BUMPMAP' : '', parameters.normalMap ? '#define USE_NORMALMAP' : '', parameters.normalMap && parameters.objectSpaceNormalMap ? '#define OBJECTSPACE_NORMALMAP' : '', parameters.normalMap && parameters.tangentSpaceNormalMap ? '#define TANGENTSPACE_NORMALMAP' : '', parameters.clearcoat ? '#define USE_CLEARCOAT' : '', parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '', parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '', parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '', parameters.specularMap ? '#define USE_SPECULARMAP' : '', parameters.specularIntensityMap ? '#define USE_SPECULARINTENSITYMAP' : '', parameters.specularColorMap ? '#define USE_SPECULARCOLORMAP' : '', parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', parameters.alphaMap ? '#define USE_ALPHAMAP' : '', parameters.alphaTest ? '#define USE_ALPHATEST' : '', parameters.sheen ? '#define USE_SHEEN' : '', parameters.sheenColorMap ? '#define USE_SHEENCOLORMAP' : '', parameters.sheenRoughnessMap ? '#define USE_SHEENROUGHNESSMAP' : '', parameters.transmission ? '#define USE_TRANSMISSION' : '', parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', parameters.decodeVideoTexture ? '#define DECODE_VIDEO_TEXTURE' : '', parameters.vertexTangents ? '#define USE_TANGENT' : '', parameters.vertexColors || parameters.instancingColor ? '#define USE_COLOR' : '', parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', parameters.vertexUvs ? '#define USE_UV' : '', parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '', parameters.gradientMap ? '#define USE_GRADIENTMAP' : '', parameters.flatShading ? '#define FLAT_SHADED' : '', parameters.doubleSided ? '#define DOUBLE_SIDED' : '', parameters.flipSided ? '#define FLIP_SIDED' : '', parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '', parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '', parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ? '#define USE_LOGDEPTHBUF_EXT' : '', (parameters.extensionShaderTextureLOD || parameters.envMap) && parameters.rendererExtensionShaderTextureLod ? '#define TEXTURE_LOD_EXT' : '', 'uniform mat4 viewMatrix;', 'uniform vec3 cameraPosition;', 'uniform bool isOrthographic;', parameters.toneMapping !== NoToneMapping ? '#define TONE_MAPPING' : '', parameters.toneMapping !== NoToneMapping ? ShaderChunk['tonemapping_pars_fragment'] : '', // this code is required here because it is used by the toneMapping() function defined below parameters.toneMapping !== NoToneMapping ? getToneMappingFunction('toneMapping', parameters.toneMapping) : '', parameters.dithering ? '#define DITHERING' : '', parameters.format === RGBFormat ? '#define OPAQUE' : '', ShaderChunk['encodings_pars_fragment'], // this code is required here because it is used by the various encoding/decoding function defined below - parameters.map ? getTexelDecodingFunction('mapTexelToLinear', parameters.mapEncoding) : '', parameters.matcap ? getTexelDecodingFunction('matcapTexelToLinear', parameters.matcapEncoding) : '', parameters.envMap ? getTexelDecodingFunction('envMapTexelToLinear', parameters.envMapEncoding) : '', parameters.emissiveMap ? getTexelDecodingFunction('emissiveMapTexelToLinear', parameters.emissiveMapEncoding) : '', parameters.specularColorMap ? getTexelDecodingFunction('specularColorMapTexelToLinear', parameters.specularColorMapEncoding) : '', parameters.sheenColorMap ? getTexelDecodingFunction('sheenColorMapTexelToLinear', parameters.sheenColorMapEncoding) : '', parameters.lightMap ? getTexelDecodingFunction('lightMapTexelToLinear', parameters.lightMapEncoding) : '', getTexelEncodingFunction('linearToOutputTexel', parameters.outputEncoding), parameters.depthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '', '\n'].filter(filterEmptyLine).join('\n'); + getTexelEncodingFunction('linearToOutputTexel', parameters.outputEncoding), parameters.depthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '', '\n'].filter(filterEmptyLine).join('\n'); } vertexShader = resolveIncludes(vertexShader); @@ -14309,9 +14119,98 @@ return this; } + let _id = 0; + + class WebGLShaderCache { + constructor() { + this.shaderCache = new Map(); + this.materialCache = new Map(); + } + + update(material) { + const vertexShader = material.vertexShader; + const fragmentShader = material.fragmentShader; + + const vertexShaderStage = this._getShaderStage(vertexShader); + + const fragmentShaderStage = this._getShaderStage(fragmentShader); + + const materialShaders = this._getShaderCacheForMaterial(material); + + if (materialShaders.has(vertexShaderStage) === false) { + materialShaders.add(vertexShaderStage); + vertexShaderStage.usedTimes++; + } + + if (materialShaders.has(fragmentShaderStage) === false) { + materialShaders.add(fragmentShaderStage); + fragmentShaderStage.usedTimes++; + } + + return this; + } + + remove(material) { + const materialShaders = this.materialCache.get(material); + + for (const shaderStage of materialShaders) { + shaderStage.usedTimes--; + if (shaderStage.usedTimes === 0) this.shaderCache.delete(shaderStage); + } + + this.materialCache.delete(material); + return this; + } + + getVertexShaderID(material) { + return this._getShaderStage(material.vertexShader).id; + } + + getFragmentShaderID(material) { + return this._getShaderStage(material.fragmentShader).id; + } + + dispose() { + this.shaderCache.clear(); + this.materialCache.clear(); + } + + _getShaderCacheForMaterial(material) { + const cache = this.materialCache; + + if (cache.has(material) === false) { + cache.set(material, new Set()); + } + + return cache.get(material); + } + + _getShaderStage(code) { + const cache = this.shaderCache; + + if (cache.has(code) === false) { + const stage = new WebGLShaderStage(); + cache.set(code, stage); + } + + return cache.get(code); + } + + } + + class WebGLShaderStage { + constructor() { + this.id = _id++; + this.usedTimes = 0; + } + + } + function WebGLPrograms(renderer, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping) { const _programLayers = new Layers(); + const _customShaders = new WebGLShaderCache(); + const programs = []; const isWebGL2 = capabilities.isWebGL2; const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer; @@ -14363,25 +14262,6 @@ } } - function getTextureEncodingFromMap(map) { - let encoding; - - if (map && map.isTexture) { - encoding = map.encoding; - } else if (map && map.isWebGLRenderTarget) { - console.warn('THREE.WebGLPrograms.getTextureEncodingFromMap: don\'t use render targets as textures. Use their .texture property instead.'); - encoding = map.texture.encoding; - } else { - encoding = LinearEncoding; - } - - if (isWebGL2 && map && map.isTexture && map.format === RGBAFormat && map.type === UnsignedByteType && map.encoding === sRGBEncoding) { - encoding = LinearEncoding; // disable inline decode for sRGB textures in WebGL 2 - } - - return encoding; - } - function getParameters(material, lights, shadows, scene, object) { const fog = scene.fog; const environment = material.isMeshStandardMaterial ? scene.environment : null; @@ -14400,6 +14280,7 @@ } let vertexShader, fragmentShader; + let customVertexShaderID, customFragmentShaderID; if (shaderID) { const shader = ShaderLib[shaderID]; @@ -14408,6 +14289,11 @@ } else { vertexShader = material.vertexShader; fragmentShader = material.fragmentShader; + + _customShaders.update(material); + + customVertexShaderID = _customShaders.getVertexShaderID(material); + customFragmentShaderID = _customShaders.getFragmentShaderID(material); } const currentRenderTarget = renderer.getRenderTarget(); @@ -14420,30 +14306,28 @@ vertexShader: vertexShader, fragmentShader: fragmentShader, defines: material.defines, + customVertexShaderID: customVertexShaderID, + customFragmentShaderID: customFragmentShaderID, isRawShaderMaterial: material.isRawShaderMaterial === true, glslVersion: material.glslVersion, precision: precision, instancing: object.isInstancedMesh === true, instancingColor: object.isInstancedMesh === true && object.instanceColor !== null, supportsVertexTextures: vertexTextures, - outputEncoding: currentRenderTarget !== null ? getTextureEncodingFromMap(currentRenderTarget.texture) : renderer.outputEncoding, + outputEncoding: currentRenderTarget !== null ? currentRenderTarget.texture.encoding : renderer.outputEncoding, map: !!material.map, - mapEncoding: getTextureEncodingFromMap(material.map), matcap: !!material.matcap, - matcapEncoding: getTextureEncodingFromMap(material.matcap), envMap: !!envMap, envMapMode: envMap && envMap.mapping, - envMapEncoding: getTextureEncodingFromMap(envMap), envMapCubeUV: !!envMap && (envMap.mapping === CubeUVReflectionMapping || envMap.mapping === CubeUVRefractionMapping), lightMap: !!material.lightMap, - lightMapEncoding: getTextureEncodingFromMap(material.lightMap), aoMap: !!material.aoMap, emissiveMap: !!material.emissiveMap, - emissiveMapEncoding: getTextureEncodingFromMap(material.emissiveMap), bumpMap: !!material.bumpMap, normalMap: !!material.normalMap, objectSpaceNormalMap: material.normalMapType === ObjectSpaceNormalMap, tangentSpaceNormalMap: material.normalMapType === TangentSpaceNormalMap, + decodeVideoTexture: !!material.map && material.map.isVideoTexture === true && material.map.encoding === sRGBEncoding, clearcoat: useClearcoat, clearcoatMap: useClearcoat && !!material.clearcoatMap, clearcoatRoughnessMap: useClearcoat && !!material.clearcoatRoughnessMap, @@ -14454,13 +14338,11 @@ specularMap: !!material.specularMap, specularIntensityMap: !!material.specularIntensityMap, specularColorMap: !!material.specularColorMap, - specularColorMapEncoding: getTextureEncodingFromMap(material.specularColorMap), alphaMap: !!material.alphaMap, alphaTest: useAlphaTest, gradientMap: !!material.gradientMap, sheen: material.sheen > 0, sheenColorMap: !!material.sheenColorMap, - sheenColorMapEncoding: getTextureEncodingFromMap(material.sheenColorMap), sheenRoughnessMap: !!material.sheenRoughnessMap, transmission: material.transmission > 0, transmissionMap: !!material.transmissionMap, @@ -14522,8 +14404,8 @@ if (parameters.shaderID) { array.push(parameters.shaderID); } else { - array.push(hashString(parameters.fragmentShader)); - array.push(hashString(parameters.vertexShader)); + array.push(parameters.customVertexShaderID); + array.push(parameters.customFragmentShaderID); } if (parameters.defines !== undefined) { @@ -14537,7 +14419,6 @@ getProgramCacheKeyParameters(array, parameters); getProgramCacheKeyBooleans(array, parameters); array.push(renderer.outputEncoding); - array.push(renderer.gammaFactor); } array.push(parameters.customProgramCacheKey); @@ -14547,12 +14428,7 @@ function getProgramCacheKeyParameters(array, parameters) { array.push(parameters.precision); array.push(parameters.outputEncoding); - array.push(parameters.mapEncoding); - array.push(parameters.matcapEncoding); array.push(parameters.envMapMode); - array.push(parameters.envMapEncoding); - array.push(parameters.lightMapEncoding); - array.push(parameters.emissiveMapEncoding); array.push(parameters.combine); array.push(parameters.vertexUvs); array.push(parameters.fogExp2); @@ -14572,8 +14448,6 @@ array.push(parameters.numClippingPlanes); array.push(parameters.numClipIntersection); array.push(parameters.format); - array.push(parameters.specularColorMapEncoding); - array.push(parameters.sheenColorMapEncoding); } function getProgramCacheKeyBooleans(array, parameters) { @@ -14637,6 +14511,7 @@ if (parameters.sheen) _programLayers.enable(19); if (parameters.sheenColorMap) _programLayers.enable(20); if (parameters.sheenRoughnessMap) _programLayers.enable(21); + if (parameters.decodeVideoTexture) _programLayers.enable(22); array.push(_programLayers.mask); } @@ -14686,14 +14561,24 @@ } } + function releaseShaderCache(material) { + _customShaders.remove(material); + } + + function dispose() { + _customShaders.dispose(); + } + return { getParameters: getParameters, getProgramCacheKey: getProgramCacheKey, getUniforms: getUniforms, acquireProgram: acquireProgram, releaseProgram: releaseProgram, + releaseShaderCache: releaseShaderCache, // Exposed for resource monitoring & error feedback via renderer.info: - programs: programs + programs: programs, + dispose: dispose }; } @@ -16569,7 +16454,7 @@ _gl.generateMipmap(target); } - function getInternalFormat(internalFormatName, glFormat, glType, encoding) { + function getInternalFormat(internalFormatName, glFormat, glType, encoding, isVideoTexture = false) { if (isWebGL2 === false) return glFormat; if (internalFormatName !== null) { @@ -16594,7 +16479,7 @@ if (glFormat === _gl.RGBA) { if (glType === _gl.FLOAT) internalFormat = _gl.RGBA32F; if (glType === _gl.HALF_FLOAT) internalFormat = _gl.RGBA16F; - if (glType === _gl.UNSIGNED_BYTE) internalFormat = encoding === sRGBEncoding ? _gl.SRGB8_ALPHA8 : _gl.RGBA8; + if (glType === _gl.UNSIGNED_BYTE) internalFormat = encoding === sRGBEncoding && isVideoTexture === false ? _gl.SRGB8_ALPHA8 : _gl.RGBA8; } if (internalFormat === _gl.R16F || internalFormat === _gl.R32F || internalFormat === _gl.RGBA16F || internalFormat === _gl.RGBA32F) { @@ -16870,11 +16755,12 @@ _gl.pixelStorei(_gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, _gl.NONE); const needsPowerOfTwo = textureNeedsPowerOfTwo(texture) && isPowerOfTwo$1(texture.image) === false; - const image = resizeImage(texture.image, needsPowerOfTwo, false, maxTextureSize); + let image = resizeImage(texture.image, needsPowerOfTwo, false, maxTextureSize); + image = verifyColorSpace(texture, image); const supportsMips = isPowerOfTwo$1(image) || isWebGL2, - glFormat = utils.convert(texture.format); + glFormat = utils.convert(texture.format, texture.encoding); let glType = utils.convert(texture.type), - glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType, texture.encoding); + glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType, texture.encoding, texture.isVideoTexture); setTextureParameters(textureType, texture, supportsMips); let mipmap; const mipmaps = texture.mipmaps; @@ -17083,11 +16969,13 @@ } else { cubeImage[i] = isDataTexture ? texture.image[i].image : texture.image[i]; } + + cubeImage[i] = verifyColorSpace(texture, cubeImage[i]); } const image = cubeImage[0], supportsMips = isPowerOfTwo$1(image) || isWebGL2, - glFormat = utils.convert(texture.format), + glFormat = utils.convert(texture.format, texture.encoding), glType = utils.convert(texture.type), glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType, texture.encoding); const useTexStorage = isWebGL2 && texture.isVideoTexture !== true; @@ -17187,7 +17075,7 @@ function setupFrameBufferTexture(framebuffer, renderTarget, texture, attachment, textureTarget) { - const glFormat = utils.convert(texture.format); + const glFormat = utils.convert(texture.format, texture.encoding); const glType = utils.convert(texture.type); const glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType, texture.encoding); const renderTargetProperties = properties.get(renderTarget); @@ -17256,7 +17144,7 @@ } else { // Use the first texture for MRT so far const texture = renderTarget.isWebGLMultipleRenderTargets === true ? renderTarget.texture[0] : renderTarget.texture; - const glFormat = utils.convert(texture.format); + const glFormat = utils.convert(texture.format, texture.encoding); const glType = utils.convert(texture.type); const glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType, texture.encoding); const samples = getRenderTargetSamples(renderTarget); @@ -17411,7 +17299,7 @@ _gl.bindRenderbuffer(_gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer); - const glFormat = utils.convert(texture.format); + const glFormat = utils.convert(texture.format, texture.encoding); const glType = utils.convert(texture.type); const glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType, texture.encoding); const samples = getRenderTargetSamples(renderTarget); @@ -17567,6 +17455,41 @@ texture.update(); } + } + + function verifyColorSpace(texture, image) { + const encoding = texture.encoding; + const format = texture.format; + const type = texture.type; + if (texture.isCompressedTexture === true || texture.format === _SRGBFormat || texture.format === _SRGBAFormat) return image; + + if (encoding !== LinearEncoding) { + // sRGB + if (encoding === sRGBEncoding && texture.isVideoTexture !== true) { + if (isWebGL2 === false) { + // in WebGL 1, try to use EXT_sRGB extension and unsized formats + if (extensions.has('EXT_sRGB') === true && (format === RGBFormat || format === RGBAFormat)) { + if (format === RGBFormat) texture.format = _SRGBFormat; + if (format === RGBAFormat) texture.format = _SRGBAFormat; // it's not possible to generate mips in WebGL 1 with the above formats + + texture.minFilter = LinearFilter; + texture.generateMipmaps = false; + } else { + // slow fallback (CPU decode) + image = ImageUtils.sRGBToLinear(image); + } + } else { + // in WebGL 2 uncompressed textures can only be sRGB encoded if they have the RGBA8 format + if (format !== RGBAFormat || type !== UnsignedByteType) { + console.warn('THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType.'); + } + } + } else { + console.error('THREE.WebGLTextures: Unsupported texture encoding:', encoding); + } + } + + return image; } // backwards compatibility @@ -17619,7 +17542,7 @@ function WebGLUtils(gl, extensions, capabilities) { const isWebGL2 = capabilities.isWebGL2; - function convert(p) { + function convert(p, encoding = null) { let extension; if (p === UnsignedByteType) return gl.UNSIGNED_BYTE; if (p === UnsignedShort4444Type) return gl.UNSIGNED_SHORT_4_4_4_4; @@ -17650,26 +17573,52 @@ if (p === LuminanceAlphaFormat) return gl.LUMINANCE_ALPHA; if (p === DepthFormat) return gl.DEPTH_COMPONENT; if (p === DepthStencilFormat) return gl.DEPTH_STENCIL; - if (p === RedFormat) return gl.RED; // WebGL2 formats. + if (p === RedFormat) return gl.RED; // WebGL 1 sRGB fallback + + if (p === _SRGBFormat || p === _SRGBAFormat) { + extension = extensions.get('EXT_sRGB'); + + if (extension !== null) { + if (p === _SRGBFormat) return extension.SRGB_EXT; + if (p === _SRGBAFormat) return extension.SRGB_ALPHA_EXT; + } else { + return null; + } + } // WebGL2 formats. + if (p === RedIntegerFormat) return gl.RED_INTEGER; if (p === RGFormat) return gl.RG; if (p === RGIntegerFormat) return gl.RG_INTEGER; if (p === RGBIntegerFormat) return gl.RGB_INTEGER; - if (p === RGBAIntegerFormat) return gl.RGBA_INTEGER; + if (p === RGBAIntegerFormat) return gl.RGBA_INTEGER; // S3TC if (p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format) { - extension = extensions.get('WEBGL_compressed_texture_s3tc'); - - if (extension !== null) { - if (p === RGB_S3TC_DXT1_Format) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT; - if (p === RGBA_S3TC_DXT1_Format) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT; - if (p === RGBA_S3TC_DXT3_Format) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT; - if (p === RGBA_S3TC_DXT5_Format) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT; + if (encoding === sRGBEncoding) { + extension = extensions.get('WEBGL_compressed_texture_s3tc_srgb'); + + if (extension !== null) { + if (p === RGB_S3TC_DXT1_Format) return extension.COMPRESSED_SRGB_S3TC_DXT1_EXT; + if (p === RGBA_S3TC_DXT1_Format) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT; + if (p === RGBA_S3TC_DXT3_Format) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT; + if (p === RGBA_S3TC_DXT5_Format) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; + } else { + return null; + } } else { - return null; + extension = extensions.get('WEBGL_compressed_texture_s3tc'); + + if (extension !== null) { + if (p === RGB_S3TC_DXT1_Format) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT; + if (p === RGBA_S3TC_DXT1_Format) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT; + if (p === RGBA_S3TC_DXT3_Format) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT; + if (p === RGBA_S3TC_DXT5_Format) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT; + } else { + return null; + } } - } + } // PVRTC + if (p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format) { extension = extensions.get('WEBGL_compressed_texture_pvrtc'); @@ -17682,7 +17631,8 @@ } else { return null; } - } + } // ETC1 + if (p === RGB_ETC1_Format) { extension = extensions.get('WEBGL_compressed_texture_etc1'); @@ -17692,38 +17642,55 @@ } else { return null; } - } + } // ETC2 + if (p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format) { extension = extensions.get('WEBGL_compressed_texture_etc'); if (extension !== null) { - if (p === RGB_ETC2_Format) return extension.COMPRESSED_RGB8_ETC2; - if (p === RGBA_ETC2_EAC_Format) return extension.COMPRESSED_RGBA8_ETC2_EAC; + if (p === RGB_ETC2_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2; + if (p === RGBA_ETC2_EAC_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC; + } else { + return null; } - } + } // ASTC - if (p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format || p === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format || p === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format || p === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format || p === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format || p === SRGB8_ALPHA8_ASTC_4x4_Format || p === SRGB8_ALPHA8_ASTC_5x4_Format || p === SRGB8_ALPHA8_ASTC_5x5_Format || p === SRGB8_ALPHA8_ASTC_6x5_Format || p === SRGB8_ALPHA8_ASTC_6x6_Format || p === SRGB8_ALPHA8_ASTC_8x5_Format || p === SRGB8_ALPHA8_ASTC_8x6_Format || p === SRGB8_ALPHA8_ASTC_8x8_Format || p === SRGB8_ALPHA8_ASTC_10x5_Format || p === SRGB8_ALPHA8_ASTC_10x6_Format || p === SRGB8_ALPHA8_ASTC_10x8_Format || p === SRGB8_ALPHA8_ASTC_10x10_Format || p === SRGB8_ALPHA8_ASTC_12x10_Format || p === SRGB8_ALPHA8_ASTC_12x12_Format) { + + if (p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format || p === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format || p === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format || p === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format || p === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format) { extension = extensions.get('WEBGL_compressed_texture_astc'); if (extension !== null) { - // TODO Complete? - return p; + if (p === RGBA_ASTC_4x4_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : extension.COMPRESSED_RGBA_ASTC_4x4_KHR; + if (p === RGBA_ASTC_5x4_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : extension.COMPRESSED_RGBA_ASTC_5x4_KHR; + if (p === RGBA_ASTC_5x5_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : extension.COMPRESSED_RGBA_ASTC_5x5_KHR; + if (p === RGBA_ASTC_6x5_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : extension.COMPRESSED_RGBA_ASTC_6x5_KHR; + if (p === RGBA_ASTC_6x6_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : extension.COMPRESSED_RGBA_ASTC_6x6_KHR; + if (p === RGBA_ASTC_8x5_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : extension.COMPRESSED_RGBA_ASTC_8x5_KHR; + if (p === RGBA_ASTC_8x6_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : extension.COMPRESSED_RGBA_ASTC_8x6_KHR; + if (p === RGBA_ASTC_8x8_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : extension.COMPRESSED_RGBA_ASTC_8x8_KHR; + if (p === RGBA_ASTC_10x5_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : extension.COMPRESSED_RGBA_ASTC_10x5_KHR; + if (p === RGBA_ASTC_10x6_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : extension.COMPRESSED_RGBA_ASTC_10x6_KHR; + if (p === RGBA_ASTC_10x8_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : extension.COMPRESSED_RGBA_ASTC_10x8_KHR; + if (p === RGBA_ASTC_10x10_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : extension.COMPRESSED_RGBA_ASTC_10x10_KHR; + if (p === RGBA_ASTC_12x10_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : extension.COMPRESSED_RGBA_ASTC_12x10_KHR; + if (p === RGBA_ASTC_12x12_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : extension.COMPRESSED_RGBA_ASTC_12x12_KHR; } else { return null; } - } + } // BPTC + if (p === RGBA_BPTC_Format) { extension = extensions.get('EXT_texture_compression_bptc'); if (extension !== null) { - // TODO Complete? - return p; + if (p === RGBA_BPTC_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT : extension.COMPRESSED_RGBA_BPTC_UNORM_EXT; } else { return null; } - } + } // + if (p === UnsignedInt248Type) { if (isWebGL2) return gl.UNSIGNED_INT_24_8; @@ -18176,7 +18143,11 @@ session.updateRenderState({ baseLayer: glBaseLayer }); - newRenderTarget = new WebGLRenderTarget(glBaseLayer.framebufferWidth, glBaseLayer.framebufferHeight); + newRenderTarget = new WebGLRenderTarget(glBaseLayer.framebufferWidth, glBaseLayer.framebufferHeight, { + format: RGBAFormat, + type: UnsignedByteType, + encoding: renderer.outputEncoding + }); } else { isMultisample = attributes.antialias; let depthFormat = null; @@ -18194,6 +18165,11 @@ depthFormat: glDepthFormat, scaleFactor: framebufferScaleFactor }; + + if (renderer.outputEncoding === sRGBEncoding) { + projectionlayerInit.colorFormat = attributes.alpha || isMultisample ? gl.SRGB8_ALPHA8 : gl.SRGB8; + } + glBinding = new XRWebGLBinding(session, gl); glProjLayer = glBinding.createProjectionLayer(projectionlayerInit); session.updateRenderState({ @@ -19057,8 +19033,6 @@ this.clippingPlanes = []; this.localClippingEnabled = false; // physically based shading - this.gammaFactor = 2.0; // for backwards compatibility - this.outputEncoding = LinearEncoding; // physical lights this.physicallyCorrectLights = false; // tone mapping @@ -19398,6 +19372,7 @@ cubeuvmaps.dispose(); objects.dispose(); bindingStates.dispose(); + programCache.dispose(); xr.dispose(); xr.removeEventListener('sessionstart', onXRSessionStart); xr.removeEventListener('sessionend', onXRSessionEnd); @@ -19453,6 +19428,10 @@ programs.forEach(function (program) { programCache.releaseProgram(program); }); + + if (material.isShaderMaterial) { + programCache.releaseShaderCache(material); + } } } // Buffer rendering @@ -19944,6 +19923,7 @@ materialProperties.numIntersection = parameters.numClipIntersection; materialProperties.vertexAlphas = parameters.vertexAlphas; materialProperties.vertexTangents = parameters.vertexTangents; + materialProperties.toneMapping = parameters.toneMapping; } function setProgram(camera, scene, geometry, material, object) { @@ -19959,6 +19939,7 @@ const morphTargets = !!geometry.morphAttributes.position; const morphNormals = !!geometry.morphAttributes.normal; const morphTargetsCount = !!geometry.morphAttributes.position ? geometry.morphAttributes.position.length : 0; + const toneMapping = material.toneMapped ? _this.toneMapping : NoToneMapping; const materialProperties = properties.get(material); const lights = currentRenderState.state.lights; @@ -20002,6 +19983,8 @@ needsProgramChange = true; } else if (materialProperties.morphNormals !== morphNormals) { needsProgramChange = true; + } else if (materialProperties.toneMapping !== toneMapping) { + needsProgramChange = true; } else if (capabilities.isWebGL2 === true && materialProperties.morphTargetsCount !== morphTargetsCount) { needsProgramChange = true; } @@ -23338,7 +23321,7 @@ /** * Bezier Curves formulas obtained from - * http://en.wikipedia.org/wiki/Bézier_curve + * https://en.wikipedia.org/wiki/B%C3%A9zier_curve */ function CatmullRom(t, p0, p1, p2, p3) { const v0 = (p2 - p0) * 0.5; @@ -25325,11 +25308,55 @@ const indices = []; const vertices = []; - const uvs = []; // helper variables + const uvs = []; + const initNormals = []; + const normals = []; // helper variables const inverseSegments = 1.0 / segments; const vertex = new Vector3(); - const uv = new Vector2(); // generate vertices and uvs + const uv = new Vector2(); + const normal = new Vector3(); + const curNormal = new Vector3(); + const prevNormal = new Vector3(); + let dx = 0; + let dy = 0; // pre-compute normals for initial "meridian" + + for (let j = 0; j <= points.length - 1; j++) { + switch (j) { + case 0: + // special handling for 1st vertex on path + dx = points[j + 1].x - points[j].x; + dy = points[j + 1].y - points[j].y; + normal.x = dy * 1.0; + normal.y = -dx; + normal.z = dy * 0.0; + prevNormal.copy(normal); + normal.normalize(); + initNormals.push(normal.x, normal.y, normal.z); + break; + + case points.length - 1: + // special handling for last Vertex on path + initNormals.push(prevNormal.x, prevNormal.y, prevNormal.z); + break; + + default: + // default handling for all vertices in between + dx = points[j + 1].x - points[j].x; + dy = points[j + 1].y - points[j].y; + normal.x = dy * 1.0; + normal.y = -dx; + normal.z = dy * 0.0; + curNormal.copy(normal); + normal.x += prevNormal.x; + normal.y += prevNormal.y; + normal.z += prevNormal.z; + normal.normalize(); + initNormals.push(normal.x, normal.y, normal.z); + prevNormal.copy(curNormal); + } + } // generate vertices, uvs and normals + for (let i = 0; i <= segments; i++) { const phi = phiStart + i * inverseSegments * phiLength; @@ -25345,7 +25372,12 @@ uv.x = i / segments; uv.y = j / (points.length - 1); - uvs.push(uv.x, uv.y); + uvs.push(uv.x, uv.y); // normal + + const x = initNormals[3 * j + 0] * sin; + const y = initNormals[3 * j + 1]; + const z = initNormals[3 * j + 0] * cos; + normals.push(x, y, z); } } // indices @@ -25366,36 +25398,8 @@ this.setIndex(indices); this.setAttribute('position', new Float32BufferAttribute(vertices, 3)); - this.setAttribute('uv', new Float32BufferAttribute(uvs, 2)); // generate normals - - this.computeVertexNormals(); // if the geometry is closed, we need to average the normals along the seam. - // because the corresponding vertices are identical (but still have different UVs). - - if (phiLength === Math.PI * 2) { - const normals = this.attributes.normal.array; - const n1 = new Vector3(); - const n2 = new Vector3(); - const n = new Vector3(); // this is the buffer offset for the last line of vertices - - const base = segments * points.length * 3; - - for (let i = 0, j = 0; i < points.length; i++, j += 3) { - // select the normal of the vertex in the first line - n1.x = normals[j + 0]; - n1.y = normals[j + 1]; - n1.z = normals[j + 2]; // select the normal of the vertex in the last line - - n2.x = normals[base + j + 0]; - n2.y = normals[base + j + 1]; - n2.z = normals[base + j + 2]; // average normals - - n.addVectors(n1, n2).normalize(); // assign the new values to both normals - - normals[j + 0] = normals[base + j + 0] = n.x; - normals[j + 1] = normals[base + j + 1] = n.y; - normals[j + 2] = normals[base + j + 2] = n.z; - } - } + this.setAttribute('uv', new Float32BufferAttribute(uvs, 2)); + this.setAttribute('normal', new Float32BufferAttribute(normals, 3)); } static fromJSON(data) { @@ -28421,6 +28425,10 @@ console.warn('THREE.FileLoader: HTTP Status 0 received.'); } + if (typeof ReadableStream === 'undefined' || response.body.getReader === undefined) { + return response; + } + const callbacks = loading[url]; const reader = response.body.getReader(); const contentLength = response.headers.get('Content-Length'); @@ -28428,7 +28436,7 @@ const lengthComputable = total !== 0; let loaded = 0; // periodically read data into the new stream tracking while download progress - return new ReadableStream({ + const stream = new ReadableStream({ start(controller) { readData(); @@ -28460,12 +28468,11 @@ } }); + return new Response(stream); } else { throw Error(`fetch for "${response.url}" responded with ${response.status}: ${response.statusText}`); } - }).then(stream => { - const response = new Response(stream); - + }).then(response => { switch (this.responseType) { case 'arraybuffer': return response.arrayBuffer(); @@ -32874,6 +32881,7 @@ let binding = bindingsByName[trackName]; if (binding !== undefined) { + ++binding.referenceCount; bindings[i] = binding; } else { binding = bindings[i]; @@ -34278,7 +34286,7 @@ * - shows frustum, line of sight and up of the camera * - suitable for fast updates * - based on frustum visualization in lightgl.js shadowmap example - * http://evanw.github.com/lightgl.js/tests/shadowmap.html + * https://github.com/evanw/lightgl.js/blob/master/tests/shadowmap.html */ @@ -35988,6 +35996,15 @@ set: function () { console.warn('THREE.WebGLRenderer: .toneMappingWhitePoint has been removed.'); } + }, + gammaFactor: { + get: function () { + console.warn('THREE.WebGLRenderer: .gammaFactor has been removed.'); + return 2; + }, + set: function () { + console.warn('THREE.WebGLRenderer: .gammaFactor has been removed.'); + } } }); Object.defineProperties(WebGLShadowMap.prototype, { @@ -36373,7 +36390,6 @@ exports.GLBufferAttribute = GLBufferAttribute; exports.GLSL1 = GLSL1; exports.GLSL3 = GLSL3; - exports.GammaEncoding = GammaEncoding; exports.GreaterDepth = GreaterDepth; exports.GreaterEqualDepth = GreaterEqualDepth; exports.GreaterEqualStencilFunc = GreaterEqualStencilFunc; @@ -36558,13 +36574,8 @@ exports.RGBA_S3TC_DXT1_Format = RGBA_S3TC_DXT1_Format; exports.RGBA_S3TC_DXT3_Format = RGBA_S3TC_DXT3_Format; exports.RGBA_S3TC_DXT5_Format = RGBA_S3TC_DXT5_Format; - exports.RGBDEncoding = RGBDEncoding; - exports.RGBEEncoding = RGBEEncoding; - exports.RGBEFormat = RGBEFormat; exports.RGBFormat = RGBFormat; exports.RGBIntegerFormat = RGBIntegerFormat; - exports.RGBM16Encoding = RGBM16Encoding; - exports.RGBM7Encoding = RGBM7Encoding; exports.RGB_ETC1_Format = RGB_ETC1_Format; exports.RGB_ETC2_Format = RGB_ETC2_Format; exports.RGB_PVRTC_2BPPV1_Format = RGB_PVRTC_2BPPV1_Format; @@ -36584,20 +36595,6 @@ exports.ReverseSubtractEquation = ReverseSubtractEquation; exports.RingBufferGeometry = RingGeometry; exports.RingGeometry = RingGeometry; - exports.SRGB8_ALPHA8_ASTC_10x10_Format = SRGB8_ALPHA8_ASTC_10x10_Format; - exports.SRGB8_ALPHA8_ASTC_10x5_Format = SRGB8_ALPHA8_ASTC_10x5_Format; - exports.SRGB8_ALPHA8_ASTC_10x6_Format = SRGB8_ALPHA8_ASTC_10x6_Format; - exports.SRGB8_ALPHA8_ASTC_10x8_Format = SRGB8_ALPHA8_ASTC_10x8_Format; - exports.SRGB8_ALPHA8_ASTC_12x10_Format = SRGB8_ALPHA8_ASTC_12x10_Format; - exports.SRGB8_ALPHA8_ASTC_12x12_Format = SRGB8_ALPHA8_ASTC_12x12_Format; - exports.SRGB8_ALPHA8_ASTC_4x4_Format = SRGB8_ALPHA8_ASTC_4x4_Format; - exports.SRGB8_ALPHA8_ASTC_5x4_Format = SRGB8_ALPHA8_ASTC_5x4_Format; - exports.SRGB8_ALPHA8_ASTC_5x5_Format = SRGB8_ALPHA8_ASTC_5x5_Format; - exports.SRGB8_ALPHA8_ASTC_6x5_Format = SRGB8_ALPHA8_ASTC_6x5_Format; - exports.SRGB8_ALPHA8_ASTC_6x6_Format = SRGB8_ALPHA8_ASTC_6x6_Format; - exports.SRGB8_ALPHA8_ASTC_8x5_Format = SRGB8_ALPHA8_ASTC_8x5_Format; - exports.SRGB8_ALPHA8_ASTC_8x6_Format = SRGB8_ALPHA8_ASTC_8x6_Format; - exports.SRGB8_ALPHA8_ASTC_8x8_Format = SRGB8_ALPHA8_ASTC_8x8_Format; exports.Scene = Scene; exports.SceneUtils = SceneUtils; exports.ShaderChunk = ShaderChunk; @@ -36697,6 +36694,8 @@ exports.ZeroFactor = ZeroFactor; exports.ZeroSlopeEnding = ZeroSlopeEnding; exports.ZeroStencilOp = ZeroStencilOp; + exports._SRGBAFormat = _SRGBAFormat; + exports._SRGBFormat = _SRGBFormat; exports.sRGBEncoding = sRGBEncoding; Object.defineProperty(exports, '__esModule', { value: true }); diff --git a/build/three.min.js b/build/three.min.js index ff57da510289d4..0026add1103fbe 100644 --- a/build/three.min.js +++ b/build/three.min.js @@ -3,4 +3,4 @@ * Copyright 2010-2021 Three.js Authors * SPDX-License-Identifier: MIT */ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).THREE={})}(this,(function(t){"use strict";const e="136dev",n=100,i=300,r=301,s=302,a=303,o=304,l=306,c=307,h=1e3,u=1001,d=1002,p=1003,m=1004,f=1005,g=1006,v=1007,y=1008,x=1009,_=1012,M=1014,b=1015,w=1016,S=1020,T=1022,E=1023,A=1026,L=1027,R=33776,C=33777,P=33778,D=33779,I=35840,N=35841,z=35842,B=35843,F=37492,O=37496,U=2300,H=2301,G=2302,k=2400,V=2401,W=2402,j=2500,q=2501,X=3e3,J=3001,Y=3007,Z=3002,Q=3004,K=3005,$=3006,tt=7680,et=35044,nt=35048,it="300 es";class rt{addEventListener(t,e){void 0===this._listeners&&(this._listeners={});const n=this._listeners;void 0===n[t]&&(n[t]=[]),-1===n[t].indexOf(e)&&n[t].push(e)}hasEventListener(t,e){if(void 0===this._listeners)return!1;const n=this._listeners;return void 0!==n[t]&&-1!==n[t].indexOf(e)}removeEventListener(t,e){if(void 0===this._listeners)return;const n=this._listeners[t];if(void 0!==n){const t=n.indexOf(e);-1!==t&&n.splice(t,1)}}dispatchEvent(t){if(void 0===this._listeners)return;const e=this._listeners[t.type];if(void 0!==e){t.target=this;const n=e.slice(0);for(let e=0,i=n.length;e>8&255]+st[t>>16&255]+st[t>>24&255]+"-"+st[255&e]+st[e>>8&255]+"-"+st[e>>16&15|64]+st[e>>24&255]+"-"+st[63&n|128]+st[n>>8&255]+"-"+st[n>>16&255]+st[n>>24&255]+st[255&i]+st[i>>8&255]+st[i>>16&255]+st[i>>24&255]).toUpperCase()}function ht(t,e,n){return Math.max(e,Math.min(n,t))}function ut(t,e){return(t%e+e)%e}function dt(t,e,n){return(1-n)*t+n*e}function pt(t){return 0==(t&t-1)&&0!==t}function mt(t){return Math.pow(2,Math.ceil(Math.log(t)/Math.LN2))}function ft(t){return Math.pow(2,Math.floor(Math.log(t)/Math.LN2))}var gt=Object.freeze({__proto__:null,DEG2RAD:ot,RAD2DEG:lt,generateUUID:ct,clamp:ht,euclideanModulo:ut,mapLinear:function(t,e,n,i,r){return i+(t-e)*(r-i)/(n-e)},inverseLerp:function(t,e,n){return t!==e?(n-t)/(e-t):0},lerp:dt,damp:function(t,e,n,i){return dt(t,e,1-Math.exp(-n*i))},pingpong:function(t,e=1){return e-Math.abs(ut(t,2*e)-e)},smoothstep:function(t,e,n){return t<=e?0:t>=n?1:(t=(t-e)/(n-e))*t*(3-2*t)},smootherstep:function(t,e,n){return t<=e?0:t>=n?1:(t=(t-e)/(n-e))*t*t*(t*(6*t-15)+10)},randInt:function(t,e){return t+Math.floor(Math.random()*(e-t+1))},randFloat:function(t,e){return t+Math.random()*(e-t)},randFloatSpread:function(t){return t*(.5-Math.random())},seededRandom:function(t){return void 0!==t&&(at=t%2147483647),at=16807*at%2147483647,(at-1)/2147483646},degToRad:function(t){return t*ot},radToDeg:function(t){return t*lt},isPowerOfTwo:pt,ceilPowerOfTwo:mt,floorPowerOfTwo:ft,setQuaternionFromProperEuler:function(t,e,n,i,r){const s=Math.cos,a=Math.sin,o=s(n/2),l=a(n/2),c=s((e+i)/2),h=a((e+i)/2),u=s((e-i)/2),d=a((e-i)/2),p=s((i-e)/2),m=a((i-e)/2);switch(r){case"XYX":t.set(o*h,l*u,l*d,o*c);break;case"YZY":t.set(l*d,o*h,l*u,o*c);break;case"ZXZ":t.set(l*u,l*d,o*h,o*c);break;case"XZX":t.set(o*h,l*m,l*p,o*c);break;case"YXY":t.set(l*p,o*h,l*m,o*c);break;case"ZYZ":t.set(l*m,l*p,o*h,o*c);break;default:console.warn("THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: "+r)}}});class vt{constructor(t=0,e=0){this.x=t,this.y=e}get width(){return this.x}set width(t){this.x=t}get height(){return this.y}set height(t){this.y=t}set(t,e){return this.x=t,this.y=e,this}setScalar(t){return this.x=t,this.y=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y)}copy(t){return this.x=t.x,this.y=t.y,this}add(t,e){return void 0!==e?(console.warn("THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(t,e)):(this.x+=t.x,this.y+=t.y,this)}addScalar(t){return this.x+=t,this.y+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this}sub(t,e){return void 0!==e?(console.warn("THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(t,e)):(this.x-=t.x,this.y-=t.y,this)}subScalar(t){return this.x-=t,this.y-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this}multiply(t){return this.x*=t.x,this.y*=t.y,this}multiplyScalar(t){return this.x*=t,this.y*=t,this}divide(t){return this.x/=t.x,this.y/=t.y,this}divideScalar(t){return this.multiplyScalar(1/t)}applyMatrix3(t){const e=this.x,n=this.y,i=t.elements;return this.x=i[0]*e+i[3]*n+i[6],this.y=i[1]*e+i[4]*n+i[7],this}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this}clamp(t,e){return this.x=Math.max(t.x,Math.min(e.x,this.x)),this.y=Math.max(t.y,Math.min(e.y,this.y)),this}clampScalar(t,e){return this.x=Math.max(t,Math.min(e,this.x)),this.y=Math.max(t,Math.min(e,this.y)),this}clampLength(t,e){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(t,Math.min(e,n)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this}roundToZero(){return 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}negate(){return this.x=-this.x,this.y=-this.y,this}dot(t){return this.x*t.x+this.y*t.y}cross(t){return this.x*t.y-this.y*t.x}lengthSq(){return this.x*this.x+this.y*this.y}length(){return Math.sqrt(this.x*this.x+this.y*this.y)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)}normalize(){return this.divideScalar(this.length()||1)}angle(){return Math.atan2(-this.y,-this.x)+Math.PI}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,n=this.y-t.y;return e*e+n*n}manhattanDistanceTo(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this}lerpVectors(t,e,n){return this.x=t.x+(e.x-t.x)*n,this.y=t.y+(e.y-t.y)*n,this}equals(t){return t.x===this.x&&t.y===this.y}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t}fromBufferAttribute(t,e,n){return void 0!==n&&console.warn("THREE.Vector2: offset has been removed from .fromBufferAttribute()."),this.x=t.getX(e),this.y=t.getY(e),this}rotateAround(t,e){const n=Math.cos(e),i=Math.sin(e),r=this.x-t.x,s=this.y-t.y;return this.x=r*n-s*i+t.x,this.y=r*i+s*n+t.y,this}random(){return this.x=Math.random(),this.y=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y}}vt.prototype.isVector2=!0;class yt{constructor(){this.elements=[1,0,0,0,1,0,0,0,1],arguments.length>0&&console.error("THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.")}set(t,e,n,i,r,s,a,o,l){const c=this.elements;return c[0]=t,c[1]=i,c[2]=a,c[3]=e,c[4]=r,c[5]=o,c[6]=n,c[7]=s,c[8]=l,this}identity(){return this.set(1,0,0,0,1,0,0,0,1),this}copy(t){const e=this.elements,n=t.elements;return e[0]=n[0],e[1]=n[1],e[2]=n[2],e[3]=n[3],e[4]=n[4],e[5]=n[5],e[6]=n[6],e[7]=n[7],e[8]=n[8],this}extractBasis(t,e,n){return t.setFromMatrix3Column(this,0),e.setFromMatrix3Column(this,1),n.setFromMatrix3Column(this,2),this}setFromMatrix4(t){const e=t.elements;return this.set(e[0],e[4],e[8],e[1],e[5],e[9],e[2],e[6],e[10]),this}multiply(t){return this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const n=t.elements,i=e.elements,r=this.elements,s=n[0],a=n[3],o=n[6],l=n[1],c=n[4],h=n[7],u=n[2],d=n[5],p=n[8],m=i[0],f=i[3],g=i[6],v=i[1],y=i[4],x=i[7],_=i[2],M=i[5],b=i[8];return r[0]=s*m+a*v+o*_,r[3]=s*f+a*y+o*M,r[6]=s*g+a*x+o*b,r[1]=l*m+c*v+h*_,r[4]=l*f+c*y+h*M,r[7]=l*g+c*x+h*b,r[2]=u*m+d*v+p*_,r[5]=u*f+d*y+p*M,r[8]=u*g+d*x+p*b,this}multiplyScalar(t){const e=this.elements;return e[0]*=t,e[3]*=t,e[6]*=t,e[1]*=t,e[4]*=t,e[7]*=t,e[2]*=t,e[5]*=t,e[8]*=t,this}determinant(){const t=this.elements,e=t[0],n=t[1],i=t[2],r=t[3],s=t[4],a=t[5],o=t[6],l=t[7],c=t[8];return e*s*c-e*a*l-n*r*c+n*a*o+i*r*l-i*s*o}invert(){const t=this.elements,e=t[0],n=t[1],i=t[2],r=t[3],s=t[4],a=t[5],o=t[6],l=t[7],c=t[8],h=c*s-a*l,u=a*o-c*r,d=l*r-s*o,p=e*h+n*u+i*d;if(0===p)return this.set(0,0,0,0,0,0,0,0,0);const m=1/p;return t[0]=h*m,t[1]=(i*l-c*n)*m,t[2]=(a*n-i*s)*m,t[3]=u*m,t[4]=(c*e-i*o)*m,t[5]=(i*r-a*e)*m,t[6]=d*m,t[7]=(n*o-l*e)*m,t[8]=(s*e-n*r)*m,this}transpose(){let t;const e=this.elements;return t=e[1],e[1]=e[3],e[3]=t,t=e[2],e[2]=e[6],e[6]=t,t=e[5],e[5]=e[7],e[7]=t,this}getNormalMatrix(t){return this.setFromMatrix4(t).invert().transpose()}transposeIntoArray(t){const e=this.elements;return t[0]=e[0],t[1]=e[3],t[2]=e[6],t[3]=e[1],t[4]=e[4],t[5]=e[7],t[6]=e[2],t[7]=e[5],t[8]=e[8],this}setUvTransform(t,e,n,i,r,s,a){const o=Math.cos(r),l=Math.sin(r);return this.set(n*o,n*l,-n*(o*s+l*a)+s+t,-i*l,i*o,-i*(-l*s+o*a)+a+e,0,0,1),this}scale(t,e){const n=this.elements;return n[0]*=t,n[3]*=t,n[6]*=t,n[1]*=e,n[4]*=e,n[7]*=e,this}rotate(t){const e=Math.cos(t),n=Math.sin(t),i=this.elements,r=i[0],s=i[3],a=i[6],o=i[1],l=i[4],c=i[7];return i[0]=e*r+n*o,i[3]=e*s+n*l,i[6]=e*a+n*c,i[1]=-n*r+e*o,i[4]=-n*s+e*l,i[7]=-n*a+e*c,this}translate(t,e){const n=this.elements;return n[0]+=t*n[2],n[3]+=t*n[5],n[6]+=t*n[8],n[1]+=e*n[2],n[4]+=e*n[5],n[7]+=e*n[8],this}equals(t){const e=this.elements,n=t.elements;for(let t=0;t<9;t++)if(e[t]!==n[t])return!1;return!0}fromArray(t,e=0){for(let n=0;n<9;n++)this.elements[n]=t[n+e];return this}toArray(t=[],e=0){const n=this.elements;return t[e]=n[0],t[e+1]=n[1],t[e+2]=n[2],t[e+3]=n[3],t[e+4]=n[4],t[e+5]=n[5],t[e+6]=n[6],t[e+7]=n[7],t[e+8]=n[8],t}clone(){return(new this.constructor).fromArray(this.elements)}}function xt(t){if(0===t.length)return-1/0;let e=t[0];for(let n=1,i=t.length;ne&&(e=t[n]);return e}yt.prototype.isMatrix3=!0;const _t={Int8Array:Int8Array,Uint8Array:Uint8Array,Uint8ClampedArray:Uint8ClampedArray,Int16Array:Int16Array,Uint16Array:Uint16Array,Int32Array:Int32Array,Uint32Array:Uint32Array,Float32Array:Float32Array,Float64Array:Float64Array};function Mt(t,e){return new _t[t](e)}function bt(t){return document.createElementNS("http://www.w3.org/1999/xhtml",t)}function wt(t,e=0){let n=3735928559^e,i=1103547991^e;for(let e,r=0;r>>16,2246822507)^Math.imul(i^i>>>13,3266489909),i=Math.imul(i^i>>>16,2246822507)^Math.imul(n^n>>>13,3266489909),4294967296*(2097151&i)+(n>>>0)}let St;class Tt{static getDataURL(t){if(/^data:/i.test(t.src))return t.src;if("undefined"==typeof HTMLCanvasElement)return t.src;let e;if(t instanceof HTMLCanvasElement)e=t;else{void 0===St&&(St=bt("canvas")),St.width=t.width,St.height=t.height;const n=St.getContext("2d");t instanceof ImageData?n.putImageData(t,0,0):n.drawImage(t,0,0,t.width,t.height),e=St}return e.width>2048||e.height>2048?(console.warn("THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons",t),e.toDataURL("image/jpeg",.6)):e.toDataURL("image/png")}}let Et=0;class At extends rt{constructor(t=At.DEFAULT_IMAGE,e=At.DEFAULT_MAPPING,n=1001,i=1001,r=1006,s=1008,a=1023,o=1009,l=1,c=3e3){super(),Object.defineProperty(this,"id",{value:Et++}),this.uuid=ct(),this.name="",this.image=t,this.mipmaps=[],this.mapping=e,this.wrapS=n,this.wrapT=i,this.magFilter=r,this.minFilter=s,this.anisotropy=l,this.format=a,this.internalFormat=null,this.type=o,this.offset=new vt(0,0),this.repeat=new vt(1,1),this.center=new vt(0,0),this.rotation=0,this.matrixAutoUpdate=!0,this.matrix=new yt,this.generateMipmaps=!0,this.premultiplyAlpha=!1,this.flipY=!0,this.unpackAlignment=4,this.encoding=c,this.userData={},this.version=0,this.onUpdate=null,this.isRenderTargetTexture=!1}updateMatrix(){this.matrix.setUvTransform(this.offset.x,this.offset.y,this.repeat.x,this.repeat.y,this.rotation,this.center.x,this.center.y)}clone(){return(new this.constructor).copy(this)}copy(t){return this.name=t.name,this.image=t.image,this.mipmaps=t.mipmaps.slice(0),this.mapping=t.mapping,this.wrapS=t.wrapS,this.wrapT=t.wrapT,this.magFilter=t.magFilter,this.minFilter=t.minFilter,this.anisotropy=t.anisotropy,this.format=t.format,this.internalFormat=t.internalFormat,this.type=t.type,this.offset.copy(t.offset),this.repeat.copy(t.repeat),this.center.copy(t.center),this.rotation=t.rotation,this.matrixAutoUpdate=t.matrixAutoUpdate,this.matrix.copy(t.matrix),this.generateMipmaps=t.generateMipmaps,this.premultiplyAlpha=t.premultiplyAlpha,this.flipY=t.flipY,this.unpackAlignment=t.unpackAlignment,this.encoding=t.encoding,this.userData=JSON.parse(JSON.stringify(t.userData)),this}toJSON(t){const e=void 0===t||"string"==typeof t;if(!e&&void 0!==t.textures[this.uuid])return t.textures[this.uuid];const n={metadata:{version:4.5,type:"Texture",generator:"Texture.toJSON"},uuid:this.uuid,name:this.name,mapping:this.mapping,repeat:[this.repeat.x,this.repeat.y],offset:[this.offset.x,this.offset.y],center:[this.center.x,this.center.y],rotation:this.rotation,wrap:[this.wrapS,this.wrapT],format:this.format,type:this.type,encoding:this.encoding,minFilter:this.minFilter,magFilter:this.magFilter,anisotropy:this.anisotropy,flipY:this.flipY,premultiplyAlpha:this.premultiplyAlpha,unpackAlignment:this.unpackAlignment};if(void 0!==this.image){const i=this.image;if(void 0===i.uuid&&(i.uuid=ct()),!e&&void 0===t.images[i.uuid]){let e;if(Array.isArray(i)){e=[];for(let t=0,n=i.length;t1)switch(this.wrapS){case h:t.x=t.x-Math.floor(t.x);break;case u:t.x=t.x<0?0:1;break;case d:1===Math.abs(Math.floor(t.x)%2)?t.x=Math.ceil(t.x)-t.x:t.x=t.x-Math.floor(t.x)}if(t.y<0||t.y>1)switch(this.wrapT){case h:t.y=t.y-Math.floor(t.y);break;case u:t.y=t.y<0?0:1;break;case d:1===Math.abs(Math.floor(t.y)%2)?t.y=Math.ceil(t.y)-t.y:t.y=t.y-Math.floor(t.y)}return this.flipY&&(t.y=1-t.y),t}set needsUpdate(t){!0===t&&this.version++}}function Lt(t){return"undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&t instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&t instanceof ImageBitmap?Tt.getDataURL(t):t.data?{data:Array.prototype.slice.call(t.data),width:t.width,height:t.height,type:t.data.constructor.name}:(console.warn("THREE.Texture: Unable to serialize Texture."),{})}At.DEFAULT_IMAGE=void 0,At.DEFAULT_MAPPING=i,At.prototype.isTexture=!0;class Rt{constructor(t=0,e=0,n=0,i=1){this.x=t,this.y=e,this.z=n,this.w=i}get width(){return this.z}set width(t){this.z=t}get height(){return this.w}set height(t){this.w=t}set(t,e,n,i){return this.x=t,this.y=e,this.z=n,this.w=i,this}setScalar(t){return this.x=t,this.y=t,this.z=t,this.w=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setZ(t){return this.z=t,this}setW(t){return this.w=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;case 3:this.w=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){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: "+t)}}clone(){return new this.constructor(this.x,this.y,this.z,this.w)}copy(t){return this.x=t.x,this.y=t.y,this.z=t.z,this.w=void 0!==t.w?t.w:1,this}add(t,e){return void 0!==e?(console.warn("THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(t,e)):(this.x+=t.x,this.y+=t.y,this.z+=t.z,this.w+=t.w,this)}addScalar(t){return this.x+=t,this.y+=t,this.z+=t,this.w+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this.w=t.w+e.w,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this.w+=t.w*e,this}sub(t,e){return void 0!==e?(console.warn("THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(t,e)):(this.x-=t.x,this.y-=t.y,this.z-=t.z,this.w-=t.w,this)}subScalar(t){return this.x-=t,this.y-=t,this.z-=t,this.w-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this.w=t.w-e.w,this}multiply(t){return this.x*=t.x,this.y*=t.y,this.z*=t.z,this.w*=t.w,this}multiplyScalar(t){return this.x*=t,this.y*=t,this.z*=t,this.w*=t,this}applyMatrix4(t){const e=this.x,n=this.y,i=this.z,r=this.w,s=t.elements;return this.x=s[0]*e+s[4]*n+s[8]*i+s[12]*r,this.y=s[1]*e+s[5]*n+s[9]*i+s[13]*r,this.z=s[2]*e+s[6]*n+s[10]*i+s[14]*r,this.w=s[3]*e+s[7]*n+s[11]*i+s[15]*r,this}divideScalar(t){return this.multiplyScalar(1/t)}setAxisAngleFromQuaternion(t){this.w=2*Math.acos(t.w);const e=Math.sqrt(1-t.w*t.w);return e<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=t.x/e,this.y=t.y/e,this.z=t.z/e),this}setAxisAngleFromRotationMatrix(t){let e,n,i,r;const s=.01,a=.1,o=t.elements,l=o[0],c=o[4],h=o[8],u=o[1],d=o[5],p=o[9],m=o[2],f=o[6],g=o[10];if(Math.abs(c-u)o&&t>v?tv?o=0?1:-1,i=1-e*e;if(i>Number.EPSILON){const r=Math.sqrt(i),s=Math.atan2(r,e*n);t=Math.sin(t*s)/r,a=Math.sin(a*s)/r}const r=a*n;if(o=o*t+u*r,l=l*t+d*r,c=c*t+p*r,h=h*t+m*r,t===1-a){const t=1/Math.sqrt(o*o+l*l+c*c+h*h);o*=t,l*=t,c*=t,h*=t}}t[e]=o,t[e+1]=l,t[e+2]=c,t[e+3]=h}static multiplyQuaternionsFlat(t,e,n,i,r,s){const a=n[i],o=n[i+1],l=n[i+2],c=n[i+3],h=r[s],u=r[s+1],d=r[s+2],p=r[s+3];return t[e]=a*p+c*h+o*d-l*u,t[e+1]=o*p+c*u+l*h-a*d,t[e+2]=l*p+c*d+a*u-o*h,t[e+3]=c*p-a*h-o*u-l*d,t}get x(){return this._x}set x(t){this._x=t,this._onChangeCallback()}get y(){return this._y}set y(t){this._y=t,this._onChangeCallback()}get z(){return this._z}set z(t){this._z=t,this._onChangeCallback()}get w(){return this._w}set w(t){this._w=t,this._onChangeCallback()}set(t,e,n,i){return this._x=t,this._y=e,this._z=n,this._w=i,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._w)}copy(t){return this._x=t.x,this._y=t.y,this._z=t.z,this._w=t.w,this._onChangeCallback(),this}setFromEuler(t,e){if(!t||!t.isEuler)throw new Error("THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.");const n=t._x,i=t._y,r=t._z,s=t._order,a=Math.cos,o=Math.sin,l=a(n/2),c=a(i/2),h=a(r/2),u=o(n/2),d=o(i/2),p=o(r/2);switch(s){case"XYZ":this._x=u*c*h+l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h-u*d*p;break;case"YXZ":this._x=u*c*h+l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h+u*d*p;break;case"ZXY":this._x=u*c*h-l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h-u*d*p;break;case"ZYX":this._x=u*c*h-l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h+u*d*p;break;case"YZX":this._x=u*c*h+l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h-u*d*p;break;case"XZY":this._x=u*c*h-l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h+u*d*p;break;default:console.warn("THREE.Quaternion: .setFromEuler() encountered an unknown order: "+s)}return!1!==e&&this._onChangeCallback(),this}setFromAxisAngle(t,e){const n=e/2,i=Math.sin(n);return this._x=t.x*i,this._y=t.y*i,this._z=t.z*i,this._w=Math.cos(n),this._onChangeCallback(),this}setFromRotationMatrix(t){const e=t.elements,n=e[0],i=e[4],r=e[8],s=e[1],a=e[5],o=e[9],l=e[2],c=e[6],h=e[10],u=n+a+h;if(u>0){const t=.5/Math.sqrt(u+1);this._w=.25/t,this._x=(c-o)*t,this._y=(r-l)*t,this._z=(s-i)*t}else if(n>a&&n>h){const t=2*Math.sqrt(1+n-a-h);this._w=(c-o)/t,this._x=.25*t,this._y=(i+s)/t,this._z=(r+l)/t}else if(a>h){const t=2*Math.sqrt(1+a-n-h);this._w=(r-l)/t,this._x=(i+s)/t,this._y=.25*t,this._z=(o+c)/t}else{const t=2*Math.sqrt(1+h-n-a);this._w=(s-i)/t,this._x=(r+l)/t,this._y=(o+c)/t,this._z=.25*t}return this._onChangeCallback(),this}setFromUnitVectors(t,e){let n=t.dot(e)+1;return nMath.abs(t.z)?(this._x=-t.y,this._y=t.x,this._z=0,this._w=n):(this._x=0,this._y=-t.z,this._z=t.y,this._w=n)):(this._x=t.y*e.z-t.z*e.y,this._y=t.z*e.x-t.x*e.z,this._z=t.x*e.y-t.y*e.x,this._w=n),this.normalize()}angleTo(t){return 2*Math.acos(Math.abs(ht(this.dot(t),-1,1)))}rotateTowards(t,e){const n=this.angleTo(t);if(0===n)return this;const i=Math.min(1,e/n);return this.slerp(t,i),this}identity(){return this.set(0,0,0,1)}invert(){return this.conjugate()}conjugate(){return this._x*=-1,this._y*=-1,this._z*=-1,this._onChangeCallback(),this}dot(t){return this._x*t._x+this._y*t._y+this._z*t._z+this._w*t._w}lengthSq(){return this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w}length(){return Math.sqrt(this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w)}normalize(){let t=this.length();return 0===t?(this._x=0,this._y=0,this._z=0,this._w=1):(t=1/t,this._x=this._x*t,this._y=this._y*t,this._z=this._z*t,this._w=this._w*t),this._onChangeCallback(),this}multiply(t,e){return void 0!==e?(console.warn("THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead."),this.multiplyQuaternions(t,e)):this.multiplyQuaternions(this,t)}premultiply(t){return this.multiplyQuaternions(t,this)}multiplyQuaternions(t,e){const n=t._x,i=t._y,r=t._z,s=t._w,a=e._x,o=e._y,l=e._z,c=e._w;return this._x=n*c+s*a+i*l-r*o,this._y=i*c+s*o+r*a-n*l,this._z=r*c+s*l+n*o-i*a,this._w=s*c-n*a-i*o-r*l,this._onChangeCallback(),this}slerp(t,e){if(0===e)return this;if(1===e)return this.copy(t);const n=this._x,i=this._y,r=this._z,s=this._w;let a=s*t._w+n*t._x+i*t._y+r*t._z;if(a<0?(this._w=-t._w,this._x=-t._x,this._y=-t._y,this._z=-t._z,a=-a):this.copy(t),a>=1)return this._w=s,this._x=n,this._y=i,this._z=r,this;const o=1-a*a;if(o<=Number.EPSILON){const t=1-e;return this._w=t*s+e*this._w,this._x=t*n+e*this._x,this._y=t*i+e*this._y,this._z=t*r+e*this._z,this.normalize(),this._onChangeCallback(),this}const l=Math.sqrt(o),c=Math.atan2(l,a),h=Math.sin((1-e)*c)/l,u=Math.sin(e*c)/l;return this._w=s*h+this._w*u,this._x=n*h+this._x*u,this._y=i*h+this._y*u,this._z=r*h+this._z*u,this._onChangeCallback(),this}slerpQuaternions(t,e,n){this.copy(t).slerp(e,n)}random(){const t=Math.random(),e=Math.sqrt(1-t),n=Math.sqrt(t),i=2*Math.PI*Math.random(),r=2*Math.PI*Math.random();return this.set(e*Math.cos(i),n*Math.sin(r),n*Math.cos(r),e*Math.sin(i))}equals(t){return t._x===this._x&&t._y===this._y&&t._z===this._z&&t._w===this._w}fromArray(t,e=0){return this._x=t[e],this._y=t[e+1],this._z=t[e+2],this._w=t[e+3],this._onChangeCallback(),this}toArray(t=[],e=0){return t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._w,t}fromBufferAttribute(t,e){return this._x=t.getX(e),this._y=t.getY(e),this._z=t.getZ(e),this._w=t.getW(e),this}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}}It.prototype.isQuaternion=!0;class Nt{constructor(t=0,e=0,n=0){this.x=t,this.y=e,this.z=n}set(t,e,n){return void 0===n&&(n=this.z),this.x=t,this.y=e,this.z=n,this}setScalar(t){return this.x=t,this.y=t,this.z=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setZ(t){return this.z=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y,this.z)}copy(t){return this.x=t.x,this.y=t.y,this.z=t.z,this}add(t,e){return void 0!==e?(console.warn("THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(t,e)):(this.x+=t.x,this.y+=t.y,this.z+=t.z,this)}addScalar(t){return this.x+=t,this.y+=t,this.z+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this}sub(t,e){return void 0!==e?(console.warn("THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(t,e)):(this.x-=t.x,this.y-=t.y,this.z-=t.z,this)}subScalar(t){return this.x-=t,this.y-=t,this.z-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this}multiply(t,e){return void 0!==e?(console.warn("THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead."),this.multiplyVectors(t,e)):(this.x*=t.x,this.y*=t.y,this.z*=t.z,this)}multiplyScalar(t){return this.x*=t,this.y*=t,this.z*=t,this}multiplyVectors(t,e){return this.x=t.x*e.x,this.y=t.y*e.y,this.z=t.z*e.z,this}applyEuler(t){return t&&t.isEuler||console.error("THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order."),this.applyQuaternion(Bt.setFromEuler(t))}applyAxisAngle(t,e){return this.applyQuaternion(Bt.setFromAxisAngle(t,e))}applyMatrix3(t){const e=this.x,n=this.y,i=this.z,r=t.elements;return this.x=r[0]*e+r[3]*n+r[6]*i,this.y=r[1]*e+r[4]*n+r[7]*i,this.z=r[2]*e+r[5]*n+r[8]*i,this}applyNormalMatrix(t){return this.applyMatrix3(t).normalize()}applyMatrix4(t){const e=this.x,n=this.y,i=this.z,r=t.elements,s=1/(r[3]*e+r[7]*n+r[11]*i+r[15]);return this.x=(r[0]*e+r[4]*n+r[8]*i+r[12])*s,this.y=(r[1]*e+r[5]*n+r[9]*i+r[13])*s,this.z=(r[2]*e+r[6]*n+r[10]*i+r[14])*s,this}applyQuaternion(t){const e=this.x,n=this.y,i=this.z,r=t.x,s=t.y,a=t.z,o=t.w,l=o*e+s*i-a*n,c=o*n+a*e-r*i,h=o*i+r*n-s*e,u=-r*e-s*n-a*i;return this.x=l*o+u*-r+c*-a-h*-s,this.y=c*o+u*-s+h*-r-l*-a,this.z=h*o+u*-a+l*-s-c*-r,this}project(t){return this.applyMatrix4(t.matrixWorldInverse).applyMatrix4(t.projectionMatrix)}unproject(t){return this.applyMatrix4(t.projectionMatrixInverse).applyMatrix4(t.matrixWorld)}transformDirection(t){const e=this.x,n=this.y,i=this.z,r=t.elements;return this.x=r[0]*e+r[4]*n+r[8]*i,this.y=r[1]*e+r[5]*n+r[9]*i,this.z=r[2]*e+r[6]*n+r[10]*i,this.normalize()}divide(t){return this.x/=t.x,this.y/=t.y,this.z/=t.z,this}divideScalar(t){return this.multiplyScalar(1/t)}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this.z=Math.min(this.z,t.z),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this.z=Math.max(this.z,t.z),this}clamp(t,e){return this.x=Math.max(t.x,Math.min(e.x,this.x)),this.y=Math.max(t.y,Math.min(e.y,this.y)),this.z=Math.max(t.z,Math.min(e.z,this.z)),this}clampScalar(t,e){return this.x=Math.max(t,Math.min(e,this.x)),this.y=Math.max(t,Math.min(e,this.y)),this.z=Math.max(t,Math.min(e,this.z)),this}clampLength(t,e){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(t,Math.min(e,n)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this}roundToZero(){return 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),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this}dot(t){return this.x*t.x+this.y*t.y+this.z*t.z}lengthSq(){return this.x*this.x+this.y*this.y+this.z*this.z}length(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)}normalize(){return this.divideScalar(this.length()||1)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this.z+=(t.z-this.z)*e,this}lerpVectors(t,e,n){return this.x=t.x+(e.x-t.x)*n,this.y=t.y+(e.y-t.y)*n,this.z=t.z+(e.z-t.z)*n,this}cross(t,e){return void 0!==e?(console.warn("THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead."),this.crossVectors(t,e)):this.crossVectors(this,t)}crossVectors(t,e){const n=t.x,i=t.y,r=t.z,s=e.x,a=e.y,o=e.z;return this.x=i*o-r*a,this.y=r*s-n*o,this.z=n*a-i*s,this}projectOnVector(t){const e=t.lengthSq();if(0===e)return this.set(0,0,0);const n=t.dot(this)/e;return this.copy(t).multiplyScalar(n)}projectOnPlane(t){return zt.copy(this).projectOnVector(t),this.sub(zt)}reflect(t){return this.sub(zt.copy(t).multiplyScalar(2*this.dot(t)))}angleTo(t){const e=Math.sqrt(this.lengthSq()*t.lengthSq());if(0===e)return Math.PI/2;const n=this.dot(t)/e;return Math.acos(ht(n,-1,1))}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,n=this.y-t.y,i=this.z-t.z;return e*e+n*n+i*i}manhattanDistanceTo(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)+Math.abs(this.z-t.z)}setFromSpherical(t){return this.setFromSphericalCoords(t.radius,t.phi,t.theta)}setFromSphericalCoords(t,e,n){const i=Math.sin(e)*t;return this.x=i*Math.sin(n),this.y=Math.cos(e)*t,this.z=i*Math.cos(n),this}setFromCylindrical(t){return this.setFromCylindricalCoords(t.radius,t.theta,t.y)}setFromCylindricalCoords(t,e,n){return this.x=t*Math.sin(e),this.y=n,this.z=t*Math.cos(e),this}setFromMatrixPosition(t){const e=t.elements;return this.x=e[12],this.y=e[13],this.z=e[14],this}setFromMatrixScale(t){const e=this.setFromMatrixColumn(t,0).length(),n=this.setFromMatrixColumn(t,1).length(),i=this.setFromMatrixColumn(t,2).length();return this.x=e,this.y=n,this.z=i,this}setFromMatrixColumn(t,e){return this.fromArray(t.elements,4*e)}setFromMatrix3Column(t,e){return this.fromArray(t.elements,3*e)}equals(t){return t.x===this.x&&t.y===this.y&&t.z===this.z}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this.z=t[e+2],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t[e+2]=this.z,t}fromBufferAttribute(t,e,n){return void 0!==n&&console.warn("THREE.Vector3: offset has been removed from .fromBufferAttribute()."),this.x=t.getX(e),this.y=t.getY(e),this.z=t.getZ(e),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this}randomDirection(){const t=2*(Math.random()-.5),e=Math.random()*Math.PI*2,n=Math.sqrt(1-t**2);return this.x=n*Math.cos(e),this.y=n*Math.sin(e),this.z=t,this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z}}Nt.prototype.isVector3=!0;const zt=new Nt,Bt=new It;class Ft{constructor(t=new Nt(1/0,1/0,1/0),e=new Nt(-1/0,-1/0,-1/0)){this.min=t,this.max=e}set(t,e){return this.min.copy(t),this.max.copy(e),this}setFromArray(t){let e=1/0,n=1/0,i=1/0,r=-1/0,s=-1/0,a=-1/0;for(let o=0,l=t.length;or&&(r=l),c>s&&(s=c),h>a&&(a=h)}return this.min.set(e,n,i),this.max.set(r,s,a),this}setFromBufferAttribute(t){let e=1/0,n=1/0,i=1/0,r=-1/0,s=-1/0,a=-1/0;for(let o=0,l=t.count;or&&(r=l),c>s&&(s=c),h>a&&(a=h)}return this.min.set(e,n,i),this.max.set(r,s,a),this}setFromPoints(t){this.makeEmpty();for(let e=0,n=t.length;ethis.max.x||t.ythis.max.y||t.zthis.max.z)}containsBox(t){return this.min.x<=t.min.x&&t.max.x<=this.max.x&&this.min.y<=t.min.y&&t.max.y<=this.max.y&&this.min.z<=t.min.z&&t.max.z<=this.max.z}getParameter(t,e){return e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y),(t.z-this.min.z)/(this.max.z-this.min.z))}intersectsBox(t){return!(t.max.xthis.max.x||t.max.ythis.max.y||t.max.zthis.max.z)}intersectsSphere(t){return this.clampPoint(t.center,Ut),Ut.distanceToSquared(t.center)<=t.radius*t.radius}intersectsPlane(t){let e,n;return t.normal.x>0?(e=t.normal.x*this.min.x,n=t.normal.x*this.max.x):(e=t.normal.x*this.max.x,n=t.normal.x*this.min.x),t.normal.y>0?(e+=t.normal.y*this.min.y,n+=t.normal.y*this.max.y):(e+=t.normal.y*this.max.y,n+=t.normal.y*this.min.y),t.normal.z>0?(e+=t.normal.z*this.min.z,n+=t.normal.z*this.max.z):(e+=t.normal.z*this.max.z,n+=t.normal.z*this.min.z),e<=-t.constant&&n>=-t.constant}intersectsTriangle(t){if(this.isEmpty())return!1;this.getCenter(Xt),Jt.subVectors(this.max,Xt),Gt.subVectors(t.a,Xt),kt.subVectors(t.b,Xt),Vt.subVectors(t.c,Xt),Wt.subVectors(kt,Gt),jt.subVectors(Vt,kt),qt.subVectors(Gt,Vt);let e=[0,-Wt.z,Wt.y,0,-jt.z,jt.y,0,-qt.z,qt.y,Wt.z,0,-Wt.x,jt.z,0,-jt.x,qt.z,0,-qt.x,-Wt.y,Wt.x,0,-jt.y,jt.x,0,-qt.y,qt.x,0];return!!Qt(e,Gt,kt,Vt,Jt)&&(e=[1,0,0,0,1,0,0,0,1],!!Qt(e,Gt,kt,Vt,Jt)&&(Yt.crossVectors(Wt,jt),e=[Yt.x,Yt.y,Yt.z],Qt(e,Gt,kt,Vt,Jt)))}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return Ut.copy(t).clamp(this.min,this.max).sub(t).length()}getBoundingSphere(t){return this.getCenter(t.center),t.radius=.5*this.getSize(Ut).length(),t}intersect(t){return this.min.max(t.min),this.max.min(t.max),this.isEmpty()&&this.makeEmpty(),this}union(t){return this.min.min(t.min),this.max.max(t.max),this}applyMatrix4(t){return this.isEmpty()||(Ot[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(t),Ot[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(t),Ot[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(t),Ot[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(t),Ot[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(t),Ot[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(t),Ot[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(t),Ot[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(t),this.setFromPoints(Ot)),this}translate(t){return this.min.add(t),this.max.add(t),this}equals(t){return t.min.equals(this.min)&&t.max.equals(this.max)}}Ft.prototype.isBox3=!0;const Ot=[new Nt,new Nt,new Nt,new Nt,new Nt,new Nt,new Nt,new Nt],Ut=new Nt,Ht=new Ft,Gt=new Nt,kt=new Nt,Vt=new Nt,Wt=new Nt,jt=new Nt,qt=new Nt,Xt=new Nt,Jt=new Nt,Yt=new Nt,Zt=new Nt;function Qt(t,e,n,i,r){for(let s=0,a=t.length-3;s<=a;s+=3){Zt.fromArray(t,s);const a=r.x*Math.abs(Zt.x)+r.y*Math.abs(Zt.y)+r.z*Math.abs(Zt.z),o=e.dot(Zt),l=n.dot(Zt),c=i.dot(Zt);if(Math.max(-Math.max(o,l,c),Math.min(o,l,c))>a)return!1}return!0}const Kt=new Ft,$t=new Nt,te=new Nt,ee=new Nt;class ne{constructor(t=new Nt,e=-1){this.center=t,this.radius=e}set(t,e){return this.center.copy(t),this.radius=e,this}setFromPoints(t,e){const n=this.center;void 0!==e?n.copy(e):Kt.setFromPoints(t).getCenter(n);let i=0;for(let e=0,r=t.length;ethis.radius*this.radius&&(e.sub(this.center).normalize(),e.multiplyScalar(this.radius).add(this.center)),e}getBoundingBox(t){return this.isEmpty()?(t.makeEmpty(),t):(t.set(this.center,this.center),t.expandByScalar(this.radius),t)}applyMatrix4(t){return this.center.applyMatrix4(t),this.radius=this.radius*t.getMaxScaleOnAxis(),this}translate(t){return this.center.add(t),this}expandByPoint(t){ee.subVectors(t,this.center);const e=ee.lengthSq();if(e>this.radius*this.radius){const t=Math.sqrt(e),n=.5*(t-this.radius);this.center.add(ee.multiplyScalar(n/t)),this.radius+=n}return this}union(t){return!0===this.center.equals(t.center)?te.set(0,0,1).multiplyScalar(t.radius):te.subVectors(t.center,this.center).normalize().multiplyScalar(t.radius),this.expandByPoint($t.copy(t.center).add(te)),this.expandByPoint($t.copy(t.center).sub(te)),this}equals(t){return t.center.equals(this.center)&&t.radius===this.radius}clone(){return(new this.constructor).copy(this)}}const ie=new Nt,re=new Nt,se=new Nt,ae=new Nt,oe=new Nt,le=new Nt,ce=new Nt;class he{constructor(t=new Nt,e=new Nt(0,0,-1)){this.origin=t,this.direction=e}set(t,e){return this.origin.copy(t),this.direction.copy(e),this}copy(t){return this.origin.copy(t.origin),this.direction.copy(t.direction),this}at(t,e){return e.copy(this.direction).multiplyScalar(t).add(this.origin)}lookAt(t){return this.direction.copy(t).sub(this.origin).normalize(),this}recast(t){return this.origin.copy(this.at(t,ie)),this}closestPointToPoint(t,e){e.subVectors(t,this.origin);const n=e.dot(this.direction);return n<0?e.copy(this.origin):e.copy(this.direction).multiplyScalar(n).add(this.origin)}distanceToPoint(t){return Math.sqrt(this.distanceSqToPoint(t))}distanceSqToPoint(t){const e=ie.subVectors(t,this.origin).dot(this.direction);return e<0?this.origin.distanceToSquared(t):(ie.copy(this.direction).multiplyScalar(e).add(this.origin),ie.distanceToSquared(t))}distanceSqToSegment(t,e,n,i){re.copy(t).add(e).multiplyScalar(.5),se.copy(e).sub(t).normalize(),ae.copy(this.origin).sub(re);const r=.5*t.distanceTo(e),s=-this.direction.dot(se),a=ae.dot(this.direction),o=-ae.dot(se),l=ae.lengthSq(),c=Math.abs(1-s*s);let h,u,d,p;if(c>0)if(h=s*o-a,u=s*a-o,p=r*c,h>=0)if(u>=-p)if(u<=p){const t=1/c;h*=t,u*=t,d=h*(h+s*u+2*a)+u*(s*h+u+2*o)+l}else u=r,h=Math.max(0,-(s*u+a)),d=-h*h+u*(u+2*o)+l;else u=-r,h=Math.max(0,-(s*u+a)),d=-h*h+u*(u+2*o)+l;else u<=-p?(h=Math.max(0,-(-s*r+a)),u=h>0?-r:Math.min(Math.max(-r,-o),r),d=-h*h+u*(u+2*o)+l):u<=p?(h=0,u=Math.min(Math.max(-r,-o),r),d=u*(u+2*o)+l):(h=Math.max(0,-(s*r+a)),u=h>0?r:Math.min(Math.max(-r,-o),r),d=-h*h+u*(u+2*o)+l);else u=s>0?-r:r,h=Math.max(0,-(s*u+a)),d=-h*h+u*(u+2*o)+l;return n&&n.copy(this.direction).multiplyScalar(h).add(this.origin),i&&i.copy(se).multiplyScalar(u).add(re),d}intersectSphere(t,e){ie.subVectors(t.center,this.origin);const n=ie.dot(this.direction),i=ie.dot(ie)-n*n,r=t.radius*t.radius;if(i>r)return null;const s=Math.sqrt(r-i),a=n-s,o=n+s;return a<0&&o<0?null:a<0?this.at(o,e):this.at(a,e)}intersectsSphere(t){return this.distanceSqToPoint(t.center)<=t.radius*t.radius}distanceToPlane(t){const e=t.normal.dot(this.direction);if(0===e)return 0===t.distanceToPoint(this.origin)?0:null;const n=-(this.origin.dot(t.normal)+t.constant)/e;return n>=0?n:null}intersectPlane(t,e){const n=this.distanceToPlane(t);return null===n?null:this.at(n,e)}intersectsPlane(t){const e=t.distanceToPoint(this.origin);if(0===e)return!0;return t.normal.dot(this.direction)*e<0}intersectBox(t,e){let n,i,r,s,a,o;const l=1/this.direction.x,c=1/this.direction.y,h=1/this.direction.z,u=this.origin;return l>=0?(n=(t.min.x-u.x)*l,i=(t.max.x-u.x)*l):(n=(t.max.x-u.x)*l,i=(t.min.x-u.x)*l),c>=0?(r=(t.min.y-u.y)*c,s=(t.max.y-u.y)*c):(r=(t.max.y-u.y)*c,s=(t.min.y-u.y)*c),n>s||r>i?null:((r>n||n!=n)&&(n=r),(s=0?(a=(t.min.z-u.z)*h,o=(t.max.z-u.z)*h):(a=(t.max.z-u.z)*h,o=(t.min.z-u.z)*h),n>o||a>i?null:((a>n||n!=n)&&(n=a),(o=0?n:i,e)))}intersectsBox(t){return null!==this.intersectBox(t,ie)}intersectTriangle(t,e,n,i,r){oe.subVectors(e,t),le.subVectors(n,t),ce.crossVectors(oe,le);let s,a=this.direction.dot(ce);if(a>0){if(i)return null;s=1}else{if(!(a<0))return null;s=-1,a=-a}ae.subVectors(this.origin,t);const o=s*this.direction.dot(le.crossVectors(ae,le));if(o<0)return null;const l=s*this.direction.dot(oe.cross(ae));if(l<0)return null;if(o+l>a)return null;const c=-s*ae.dot(ce);return c<0?null:this.at(c/a,r)}applyMatrix4(t){return this.origin.applyMatrix4(t),this.direction.transformDirection(t),this}equals(t){return t.origin.equals(this.origin)&&t.direction.equals(this.direction)}clone(){return(new this.constructor).copy(this)}}class ue{constructor(){this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],arguments.length>0&&console.error("THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.")}set(t,e,n,i,r,s,a,o,l,c,h,u,d,p,m,f){const g=this.elements;return g[0]=t,g[4]=e,g[8]=n,g[12]=i,g[1]=r,g[5]=s,g[9]=a,g[13]=o,g[2]=l,g[6]=c,g[10]=h,g[14]=u,g[3]=d,g[7]=p,g[11]=m,g[15]=f,this}identity(){return this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1),this}clone(){return(new ue).fromArray(this.elements)}copy(t){const e=this.elements,n=t.elements;return e[0]=n[0],e[1]=n[1],e[2]=n[2],e[3]=n[3],e[4]=n[4],e[5]=n[5],e[6]=n[6],e[7]=n[7],e[8]=n[8],e[9]=n[9],e[10]=n[10],e[11]=n[11],e[12]=n[12],e[13]=n[13],e[14]=n[14],e[15]=n[15],this}copyPosition(t){const e=this.elements,n=t.elements;return e[12]=n[12],e[13]=n[13],e[14]=n[14],this}setFromMatrix3(t){const e=t.elements;return this.set(e[0],e[3],e[6],0,e[1],e[4],e[7],0,e[2],e[5],e[8],0,0,0,0,1),this}extractBasis(t,e,n){return t.setFromMatrixColumn(this,0),e.setFromMatrixColumn(this,1),n.setFromMatrixColumn(this,2),this}makeBasis(t,e,n){return this.set(t.x,e.x,n.x,0,t.y,e.y,n.y,0,t.z,e.z,n.z,0,0,0,0,1),this}extractRotation(t){const e=this.elements,n=t.elements,i=1/de.setFromMatrixColumn(t,0).length(),r=1/de.setFromMatrixColumn(t,1).length(),s=1/de.setFromMatrixColumn(t,2).length();return e[0]=n[0]*i,e[1]=n[1]*i,e[2]=n[2]*i,e[3]=0,e[4]=n[4]*r,e[5]=n[5]*r,e[6]=n[6]*r,e[7]=0,e[8]=n[8]*s,e[9]=n[9]*s,e[10]=n[10]*s,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromEuler(t){t&&t.isEuler||console.error("THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.");const e=this.elements,n=t.x,i=t.y,r=t.z,s=Math.cos(n),a=Math.sin(n),o=Math.cos(i),l=Math.sin(i),c=Math.cos(r),h=Math.sin(r);if("XYZ"===t.order){const t=s*c,n=s*h,i=a*c,r=a*h;e[0]=o*c,e[4]=-o*h,e[8]=l,e[1]=n+i*l,e[5]=t-r*l,e[9]=-a*o,e[2]=r-t*l,e[6]=i+n*l,e[10]=s*o}else if("YXZ"===t.order){const t=o*c,n=o*h,i=l*c,r=l*h;e[0]=t+r*a,e[4]=i*a-n,e[8]=s*l,e[1]=s*h,e[5]=s*c,e[9]=-a,e[2]=n*a-i,e[6]=r+t*a,e[10]=s*o}else if("ZXY"===t.order){const t=o*c,n=o*h,i=l*c,r=l*h;e[0]=t-r*a,e[4]=-s*h,e[8]=i+n*a,e[1]=n+i*a,e[5]=s*c,e[9]=r-t*a,e[2]=-s*l,e[6]=a,e[10]=s*o}else if("ZYX"===t.order){const t=s*c,n=s*h,i=a*c,r=a*h;e[0]=o*c,e[4]=i*l-n,e[8]=t*l+r,e[1]=o*h,e[5]=r*l+t,e[9]=n*l-i,e[2]=-l,e[6]=a*o,e[10]=s*o}else if("YZX"===t.order){const t=s*o,n=s*l,i=a*o,r=a*l;e[0]=o*c,e[4]=r-t*h,e[8]=i*h+n,e[1]=h,e[5]=s*c,e[9]=-a*c,e[2]=-l*c,e[6]=n*h+i,e[10]=t-r*h}else if("XZY"===t.order){const t=s*o,n=s*l,i=a*o,r=a*l;e[0]=o*c,e[4]=-h,e[8]=l*c,e[1]=t*h+r,e[5]=s*c,e[9]=n*h-i,e[2]=i*h-n,e[6]=a*c,e[10]=r*h+t}return e[3]=0,e[7]=0,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromQuaternion(t){return this.compose(me,t,fe)}lookAt(t,e,n){const i=this.elements;return ye.subVectors(t,e),0===ye.lengthSq()&&(ye.z=1),ye.normalize(),ge.crossVectors(n,ye),0===ge.lengthSq()&&(1===Math.abs(n.z)?ye.x+=1e-4:ye.z+=1e-4,ye.normalize(),ge.crossVectors(n,ye)),ge.normalize(),ve.crossVectors(ye,ge),i[0]=ge.x,i[4]=ve.x,i[8]=ye.x,i[1]=ge.y,i[5]=ve.y,i[9]=ye.y,i[2]=ge.z,i[6]=ve.z,i[10]=ye.z,this}multiply(t,e){return void 0!==e?(console.warn("THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead."),this.multiplyMatrices(t,e)):this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const n=t.elements,i=e.elements,r=this.elements,s=n[0],a=n[4],o=n[8],l=n[12],c=n[1],h=n[5],u=n[9],d=n[13],p=n[2],m=n[6],f=n[10],g=n[14],v=n[3],y=n[7],x=n[11],_=n[15],M=i[0],b=i[4],w=i[8],S=i[12],T=i[1],E=i[5],A=i[9],L=i[13],R=i[2],C=i[6],P=i[10],D=i[14],I=i[3],N=i[7],z=i[11],B=i[15];return r[0]=s*M+a*T+o*R+l*I,r[4]=s*b+a*E+o*C+l*N,r[8]=s*w+a*A+o*P+l*z,r[12]=s*S+a*L+o*D+l*B,r[1]=c*M+h*T+u*R+d*I,r[5]=c*b+h*E+u*C+d*N,r[9]=c*w+h*A+u*P+d*z,r[13]=c*S+h*L+u*D+d*B,r[2]=p*M+m*T+f*R+g*I,r[6]=p*b+m*E+f*C+g*N,r[10]=p*w+m*A+f*P+g*z,r[14]=p*S+m*L+f*D+g*B,r[3]=v*M+y*T+x*R+_*I,r[7]=v*b+y*E+x*C+_*N,r[11]=v*w+y*A+x*P+_*z,r[15]=v*S+y*L+x*D+_*B,this}multiplyScalar(t){const e=this.elements;return e[0]*=t,e[4]*=t,e[8]*=t,e[12]*=t,e[1]*=t,e[5]*=t,e[9]*=t,e[13]*=t,e[2]*=t,e[6]*=t,e[10]*=t,e[14]*=t,e[3]*=t,e[7]*=t,e[11]*=t,e[15]*=t,this}determinant(){const t=this.elements,e=t[0],n=t[4],i=t[8],r=t[12],s=t[1],a=t[5],o=t[9],l=t[13],c=t[2],h=t[6],u=t[10],d=t[14];return t[3]*(+r*o*h-i*l*h-r*a*u+n*l*u+i*a*d-n*o*d)+t[7]*(+e*o*d-e*l*u+r*s*u-i*s*d+i*l*c-r*o*c)+t[11]*(+e*l*h-e*a*d-r*s*h+n*s*d+r*a*c-n*l*c)+t[15]*(-i*a*c-e*o*h+e*a*u+i*s*h-n*s*u+n*o*c)}transpose(){const t=this.elements;let e;return e=t[1],t[1]=t[4],t[4]=e,e=t[2],t[2]=t[8],t[8]=e,e=t[6],t[6]=t[9],t[9]=e,e=t[3],t[3]=t[12],t[12]=e,e=t[7],t[7]=t[13],t[13]=e,e=t[11],t[11]=t[14],t[14]=e,this}setPosition(t,e,n){const i=this.elements;return t.isVector3?(i[12]=t.x,i[13]=t.y,i[14]=t.z):(i[12]=t,i[13]=e,i[14]=n),this}invert(){const t=this.elements,e=t[0],n=t[1],i=t[2],r=t[3],s=t[4],a=t[5],o=t[6],l=t[7],c=t[8],h=t[9],u=t[10],d=t[11],p=t[12],m=t[13],f=t[14],g=t[15],v=h*f*l-m*u*l+m*o*d-a*f*d-h*o*g+a*u*g,y=p*u*l-c*f*l-p*o*d+s*f*d+c*o*g-s*u*g,x=c*m*l-p*h*l+p*a*d-s*m*d-c*a*g+s*h*g,_=p*h*o-c*m*o-p*a*u+s*m*u+c*a*f-s*h*f,M=e*v+n*y+i*x+r*_;if(0===M)return this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);const b=1/M;return t[0]=v*b,t[1]=(m*u*r-h*f*r-m*i*d+n*f*d+h*i*g-n*u*g)*b,t[2]=(a*f*r-m*o*r+m*i*l-n*f*l-a*i*g+n*o*g)*b,t[3]=(h*o*r-a*u*r-h*i*l+n*u*l+a*i*d-n*o*d)*b,t[4]=y*b,t[5]=(c*f*r-p*u*r+p*i*d-e*f*d-c*i*g+e*u*g)*b,t[6]=(p*o*r-s*f*r-p*i*l+e*f*l+s*i*g-e*o*g)*b,t[7]=(s*u*r-c*o*r+c*i*l-e*u*l-s*i*d+e*o*d)*b,t[8]=x*b,t[9]=(p*h*r-c*m*r-p*n*d+e*m*d+c*n*g-e*h*g)*b,t[10]=(s*m*r-p*a*r+p*n*l-e*m*l-s*n*g+e*a*g)*b,t[11]=(c*a*r-s*h*r-c*n*l+e*h*l+s*n*d-e*a*d)*b,t[12]=_*b,t[13]=(c*m*i-p*h*i+p*n*u-e*m*u-c*n*f+e*h*f)*b,t[14]=(p*a*i-s*m*i-p*n*o+e*m*o+s*n*f-e*a*f)*b,t[15]=(s*h*i-c*a*i+c*n*o-e*h*o-s*n*u+e*a*u)*b,this}scale(t){const e=this.elements,n=t.x,i=t.y,r=t.z;return e[0]*=n,e[4]*=i,e[8]*=r,e[1]*=n,e[5]*=i,e[9]*=r,e[2]*=n,e[6]*=i,e[10]*=r,e[3]*=n,e[7]*=i,e[11]*=r,this}getMaxScaleOnAxis(){const t=this.elements,e=t[0]*t[0]+t[1]*t[1]+t[2]*t[2],n=t[4]*t[4]+t[5]*t[5]+t[6]*t[6],i=t[8]*t[8]+t[9]*t[9]+t[10]*t[10];return Math.sqrt(Math.max(e,n,i))}makeTranslation(t,e,n){return this.set(1,0,0,t,0,1,0,e,0,0,1,n,0,0,0,1),this}makeRotationX(t){const e=Math.cos(t),n=Math.sin(t);return this.set(1,0,0,0,0,e,-n,0,0,n,e,0,0,0,0,1),this}makeRotationY(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,0,n,0,0,1,0,0,-n,0,e,0,0,0,0,1),this}makeRotationZ(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,-n,0,0,n,e,0,0,0,0,1,0,0,0,0,1),this}makeRotationAxis(t,e){const n=Math.cos(e),i=Math.sin(e),r=1-n,s=t.x,a=t.y,o=t.z,l=r*s,c=r*a;return this.set(l*s+n,l*a-i*o,l*o+i*a,0,l*a+i*o,c*a+n,c*o-i*s,0,l*o-i*a,c*o+i*s,r*o*o+n,0,0,0,0,1),this}makeScale(t,e,n){return this.set(t,0,0,0,0,e,0,0,0,0,n,0,0,0,0,1),this}makeShear(t,e,n,i,r,s){return this.set(1,n,r,0,t,1,s,0,e,i,1,0,0,0,0,1),this}compose(t,e,n){const i=this.elements,r=e._x,s=e._y,a=e._z,o=e._w,l=r+r,c=s+s,h=a+a,u=r*l,d=r*c,p=r*h,m=s*c,f=s*h,g=a*h,v=o*l,y=o*c,x=o*h,_=n.x,M=n.y,b=n.z;return i[0]=(1-(m+g))*_,i[1]=(d+x)*_,i[2]=(p-y)*_,i[3]=0,i[4]=(d-x)*M,i[5]=(1-(u+g))*M,i[6]=(f+v)*M,i[7]=0,i[8]=(p+y)*b,i[9]=(f-v)*b,i[10]=(1-(u+m))*b,i[11]=0,i[12]=t.x,i[13]=t.y,i[14]=t.z,i[15]=1,this}decompose(t,e,n){const i=this.elements;let r=de.set(i[0],i[1],i[2]).length();const s=de.set(i[4],i[5],i[6]).length(),a=de.set(i[8],i[9],i[10]).length();this.determinant()<0&&(r=-r),t.x=i[12],t.y=i[13],t.z=i[14],pe.copy(this);const o=1/r,l=1/s,c=1/a;return pe.elements[0]*=o,pe.elements[1]*=o,pe.elements[2]*=o,pe.elements[4]*=l,pe.elements[5]*=l,pe.elements[6]*=l,pe.elements[8]*=c,pe.elements[9]*=c,pe.elements[10]*=c,e.setFromRotationMatrix(pe),n.x=r,n.y=s,n.z=a,this}makePerspective(t,e,n,i,r,s){void 0===s&&console.warn("THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.");const a=this.elements,o=2*r/(e-t),l=2*r/(n-i),c=(e+t)/(e-t),h=(n+i)/(n-i),u=-(s+r)/(s-r),d=-2*s*r/(s-r);return a[0]=o,a[4]=0,a[8]=c,a[12]=0,a[1]=0,a[5]=l,a[9]=h,a[13]=0,a[2]=0,a[6]=0,a[10]=u,a[14]=d,a[3]=0,a[7]=0,a[11]=-1,a[15]=0,this}makeOrthographic(t,e,n,i,r,s){const a=this.elements,o=1/(e-t),l=1/(n-i),c=1/(s-r),h=(e+t)*o,u=(n+i)*l,d=(s+r)*c;return a[0]=2*o,a[4]=0,a[8]=0,a[12]=-h,a[1]=0,a[5]=2*l,a[9]=0,a[13]=-u,a[2]=0,a[6]=0,a[10]=-2*c,a[14]=-d,a[3]=0,a[7]=0,a[11]=0,a[15]=1,this}equals(t){const e=this.elements,n=t.elements;for(let t=0;t<16;t++)if(e[t]!==n[t])return!1;return!0}fromArray(t,e=0){for(let n=0;n<16;n++)this.elements[n]=t[n+e];return this}toArray(t=[],e=0){const n=this.elements;return t[e]=n[0],t[e+1]=n[1],t[e+2]=n[2],t[e+3]=n[3],t[e+4]=n[4],t[e+5]=n[5],t[e+6]=n[6],t[e+7]=n[7],t[e+8]=n[8],t[e+9]=n[9],t[e+10]=n[10],t[e+11]=n[11],t[e+12]=n[12],t[e+13]=n[13],t[e+14]=n[14],t[e+15]=n[15],t}}ue.prototype.isMatrix4=!0;const de=new Nt,pe=new ue,me=new Nt(0,0,0),fe=new Nt(1,1,1),ge=new Nt,ve=new Nt,ye=new Nt,xe=new ue,_e=new It;class Me{constructor(t=0,e=0,n=0,i=Me.DefaultOrder){this._x=t,this._y=e,this._z=n,this._order=i}get x(){return this._x}set x(t){this._x=t,this._onChangeCallback()}get y(){return this._y}set y(t){this._y=t,this._onChangeCallback()}get z(){return this._z}set z(t){this._z=t,this._onChangeCallback()}get order(){return this._order}set order(t){this._order=t,this._onChangeCallback()}set(t,e,n,i=this._order){return this._x=t,this._y=e,this._z=n,this._order=i,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._order)}copy(t){return this._x=t._x,this._y=t._y,this._z=t._z,this._order=t._order,this._onChangeCallback(),this}setFromRotationMatrix(t,e=this._order,n=!0){const i=t.elements,r=i[0],s=i[4],a=i[8],o=i[1],l=i[5],c=i[9],h=i[2],u=i[6],d=i[10];switch(e){case"XYZ":this._y=Math.asin(ht(a,-1,1)),Math.abs(a)<.9999999?(this._x=Math.atan2(-c,d),this._z=Math.atan2(-s,r)):(this._x=Math.atan2(u,l),this._z=0);break;case"YXZ":this._x=Math.asin(-ht(c,-1,1)),Math.abs(c)<.9999999?(this._y=Math.atan2(a,d),this._z=Math.atan2(o,l)):(this._y=Math.atan2(-h,r),this._z=0);break;case"ZXY":this._x=Math.asin(ht(u,-1,1)),Math.abs(u)<.9999999?(this._y=Math.atan2(-h,d),this._z=Math.atan2(-s,l)):(this._y=0,this._z=Math.atan2(o,r));break;case"ZYX":this._y=Math.asin(-ht(h,-1,1)),Math.abs(h)<.9999999?(this._x=Math.atan2(u,d),this._z=Math.atan2(o,r)):(this._x=0,this._z=Math.atan2(-s,l));break;case"YZX":this._z=Math.asin(ht(o,-1,1)),Math.abs(o)<.9999999?(this._x=Math.atan2(-c,l),this._y=Math.atan2(-h,r)):(this._x=0,this._y=Math.atan2(a,d));break;case"XZY":this._z=Math.asin(-ht(s,-1,1)),Math.abs(s)<.9999999?(this._x=Math.atan2(u,l),this._y=Math.atan2(a,r)):(this._x=Math.atan2(-c,d),this._y=0);break;default:console.warn("THREE.Euler: .setFromRotationMatrix() encountered an unknown order: "+e)}return this._order=e,!0===n&&this._onChangeCallback(),this}setFromQuaternion(t,e,n){return xe.makeRotationFromQuaternion(t),this.setFromRotationMatrix(xe,e,n)}setFromVector3(t,e=this._order){return this.set(t.x,t.y,t.z,e)}reorder(t){return _e.setFromEuler(this),this.setFromQuaternion(_e,t)}equals(t){return t._x===this._x&&t._y===this._y&&t._z===this._z&&t._order===this._order}fromArray(t){return this._x=t[0],this._y=t[1],this._z=t[2],void 0!==t[3]&&(this._order=t[3]),this._onChangeCallback(),this}toArray(t=[],e=0){return t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._order,t}toVector3(t){return t?t.set(this._x,this._y,this._z):new Nt(this._x,this._y,this._z)}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}}Me.prototype.isEuler=!0,Me.DefaultOrder="XYZ",Me.RotationOrders=["XYZ","YZX","ZXY","XZY","YXZ","ZYX"];class be{constructor(){this.mask=1}set(t){this.mask=(1<>>0}enable(t){this.mask|=1<1){for(let t=0;t1){for(let t=0;t0){i.children=[];for(let e=0;e0){i.animations=[];for(let e=0;e0&&(n.geometries=e),i.length>0&&(n.materials=i),r.length>0&&(n.textures=r),a.length>0&&(n.images=a),o.length>0&&(n.shapes=o),l.length>0&&(n.skeletons=l),c.length>0&&(n.animations=c)}return n.object=i,n;function s(t){const e=[];for(const n in t){const i=t[n];delete i.metadata,e.push(i)}return e}}clone(t){return(new this.constructor).copy(this,t)}copy(t,e=!0){if(this.name=t.name,this.up.copy(t.up),this.position.copy(t.position),this.rotation.order=t.rotation.order,this.quaternion.copy(t.quaternion),this.scale.copy(t.scale),this.matrix.copy(t.matrix),this.matrixWorld.copy(t.matrixWorld),this.matrixAutoUpdate=t.matrixAutoUpdate,this.matrixWorldNeedsUpdate=t.matrixWorldNeedsUpdate,this.layers.mask=t.layers.mask,this.visible=t.visible,this.castShadow=t.castShadow,this.receiveShadow=t.receiveShadow,this.frustumCulled=t.frustumCulled,this.renderOrder=t.renderOrder,this.userData=JSON.parse(JSON.stringify(t.userData)),!0===e)for(let e=0;e0?i.multiplyScalar(1/Math.sqrt(r)):i.set(0,0,0)}static getBarycoord(t,e,n,i,r){Fe.subVectors(i,e),Oe.subVectors(n,e),Ue.subVectors(t,e);const s=Fe.dot(Fe),a=Fe.dot(Oe),o=Fe.dot(Ue),l=Oe.dot(Oe),c=Oe.dot(Ue),h=s*l-a*a;if(0===h)return r.set(-2,-1,-1);const u=1/h,d=(l*o-a*c)*u,p=(s*c-a*o)*u;return r.set(1-d-p,p,d)}static containsPoint(t,e,n,i){return this.getBarycoord(t,e,n,i,He),He.x>=0&&He.y>=0&&He.x+He.y<=1}static getUV(t,e,n,i,r,s,a,o){return this.getBarycoord(t,e,n,i,He),o.set(0,0),o.addScaledVector(r,He.x),o.addScaledVector(s,He.y),o.addScaledVector(a,He.z),o}static isFrontFacing(t,e,n,i){return Fe.subVectors(n,e),Oe.subVectors(t,e),Fe.cross(Oe).dot(i)<0}set(t,e,n){return this.a.copy(t),this.b.copy(e),this.c.copy(n),this}setFromPointsAndIndices(t,e,n,i){return this.a.copy(t[e]),this.b.copy(t[n]),this.c.copy(t[i]),this}setFromAttributeAndIndices(t,e,n,i){return this.a.fromBufferAttribute(t,e),this.b.fromBufferAttribute(t,n),this.c.fromBufferAttribute(t,i),this}clone(){return(new this.constructor).copy(this)}copy(t){return this.a.copy(t.a),this.b.copy(t.b),this.c.copy(t.c),this}getArea(){return Fe.subVectors(this.c,this.b),Oe.subVectors(this.a,this.b),.5*Fe.cross(Oe).length()}getMidpoint(t){return t.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)}getNormal(t){return Xe.getNormal(this.a,this.b,this.c,t)}getPlane(t){return t.setFromCoplanarPoints(this.a,this.b,this.c)}getBarycoord(t,e){return Xe.getBarycoord(t,this.a,this.b,this.c,e)}getUV(t,e,n,i,r){return Xe.getUV(t,this.a,this.b,this.c,e,n,i,r)}containsPoint(t){return Xe.containsPoint(t,this.a,this.b,this.c)}isFrontFacing(t){return Xe.isFrontFacing(this.a,this.b,this.c,t)}intersectsBox(t){return t.intersectsTriangle(this)}closestPointToPoint(t,e){const n=this.a,i=this.b,r=this.c;let s,a;Ge.subVectors(i,n),ke.subVectors(r,n),We.subVectors(t,n);const o=Ge.dot(We),l=ke.dot(We);if(o<=0&&l<=0)return e.copy(n);je.subVectors(t,i);const c=Ge.dot(je),h=ke.dot(je);if(c>=0&&h<=c)return e.copy(i);const u=o*h-c*l;if(u<=0&&o>=0&&c<=0)return s=o/(o-c),e.copy(n).addScaledVector(Ge,s);qe.subVectors(t,r);const d=Ge.dot(qe),p=ke.dot(qe);if(p>=0&&d<=p)return e.copy(r);const m=d*l-o*p;if(m<=0&&l>=0&&p<=0)return a=l/(l-p),e.copy(n).addScaledVector(ke,a);const f=c*p-d*h;if(f<=0&&h-c>=0&&d-p>=0)return Ve.subVectors(r,i),a=(h-c)/(h-c+(d-p)),e.copy(i).addScaledVector(Ve,a);const g=1/(f+m+u);return s=m*g,a=u*g,e.copy(n).addScaledVector(Ge,s).addScaledVector(ke,a)}equals(t){return t.a.equals(this.a)&&t.b.equals(this.b)&&t.c.equals(this.c)}}let Je=0;class Ye extends rt{constructor(){super(),Object.defineProperty(this,"id",{value:Je++}),this.uuid=ct(),this.name="",this.type="Material",this.fog=!0,this.blending=1,this.side=0,this.vertexColors=!1,this.opacity=1,this.format=E,this.transparent=!1,this.blendSrc=204,this.blendDst=205,this.blendEquation=n,this.blendSrcAlpha=null,this.blendDstAlpha=null,this.blendEquationAlpha=null,this.depthFunc=3,this.depthTest=!0,this.depthWrite=!0,this.stencilWriteMask=255,this.stencilFunc=519,this.stencilRef=0,this.stencilFuncMask=255,this.stencilFail=tt,this.stencilZFail=tt,this.stencilZPass=tt,this.stencilWrite=!1,this.clippingPlanes=null,this.clipIntersection=!1,this.clipShadows=!1,this.shadowSide=null,this.colorWrite=!0,this.precision=null,this.polygonOffset=!1,this.polygonOffsetFactor=0,this.polygonOffsetUnits=0,this.dithering=!1,this.alphaToCoverage=!1,this.premultipliedAlpha=!1,this.visible=!0,this.toneMapped=!0,this.userData={},this.version=0,this._alphaTest=0}get alphaTest(){return this._alphaTest}set alphaTest(t){this._alphaTest>0!=t>0&&this.version++,this._alphaTest=t}onBuild(){}onBeforeRender(){}onBeforeCompile(){}customProgramCacheKey(){return this.onBeforeCompile.toString()}setValues(t){if(void 0!==t)for(const e in t){const n=t[e];if(void 0===n){console.warn("THREE.Material: '"+e+"' parameter is undefined.");continue}if("shading"===e){console.warn("THREE."+this.type+": .shading has been removed. Use the boolean .flatShading instead."),this.flatShading=1===n;continue}const i=this[e];void 0!==i?i&&i.isColor?i.set(n):i&&i.isVector3&&n&&n.isVector3?i.copy(n):this[e]=n:console.warn("THREE."+this.type+": '"+e+"' is not a property of this material.")}}toJSON(t){const e=void 0===t||"string"==typeof t;e&&(t={textures:{},images:{}});const n={metadata:{version:4.5,type:"Material",generator:"Material.toJSON"}};function i(t){const e=[];for(const n in t){const i=t[n];delete i.metadata,e.push(i)}return e}if(n.uuid=this.uuid,n.type=this.type,""!==this.name&&(n.name=this.name),this.color&&this.color.isColor&&(n.color=this.color.getHex()),void 0!==this.roughness&&(n.roughness=this.roughness),void 0!==this.metalness&&(n.metalness=this.metalness),void 0!==this.sheen&&(n.sheen=this.sheen),this.sheenColor&&this.sheenColor.isColor&&(n.sheenColor=this.sheenColor.getHex()),void 0!==this.sheenRoughness&&(n.sheenRoughness=this.sheenRoughness),this.emissive&&this.emissive.isColor&&(n.emissive=this.emissive.getHex()),this.emissiveIntensity&&1!==this.emissiveIntensity&&(n.emissiveIntensity=this.emissiveIntensity),this.specular&&this.specular.isColor&&(n.specular=this.specular.getHex()),void 0!==this.specularIntensity&&(n.specularIntensity=this.specularIntensity),this.specularColor&&this.specularColor.isColor&&(n.specularColor=this.specularColor.getHex()),void 0!==this.shininess&&(n.shininess=this.shininess),void 0!==this.clearcoat&&(n.clearcoat=this.clearcoat),void 0!==this.clearcoatRoughness&&(n.clearcoatRoughness=this.clearcoatRoughness),this.clearcoatMap&&this.clearcoatMap.isTexture&&(n.clearcoatMap=this.clearcoatMap.toJSON(t).uuid),this.clearcoatRoughnessMap&&this.clearcoatRoughnessMap.isTexture&&(n.clearcoatRoughnessMap=this.clearcoatRoughnessMap.toJSON(t).uuid),this.clearcoatNormalMap&&this.clearcoatNormalMap.isTexture&&(n.clearcoatNormalMap=this.clearcoatNormalMap.toJSON(t).uuid,n.clearcoatNormalScale=this.clearcoatNormalScale.toArray()),this.map&&this.map.isTexture&&(n.map=this.map.toJSON(t).uuid),this.matcap&&this.matcap.isTexture&&(n.matcap=this.matcap.toJSON(t).uuid),this.alphaMap&&this.alphaMap.isTexture&&(n.alphaMap=this.alphaMap.toJSON(t).uuid),this.lightMap&&this.lightMap.isTexture&&(n.lightMap=this.lightMap.toJSON(t).uuid,n.lightMapIntensity=this.lightMapIntensity),this.aoMap&&this.aoMap.isTexture&&(n.aoMap=this.aoMap.toJSON(t).uuid,n.aoMapIntensity=this.aoMapIntensity),this.bumpMap&&this.bumpMap.isTexture&&(n.bumpMap=this.bumpMap.toJSON(t).uuid,n.bumpScale=this.bumpScale),this.normalMap&&this.normalMap.isTexture&&(n.normalMap=this.normalMap.toJSON(t).uuid,n.normalMapType=this.normalMapType,n.normalScale=this.normalScale.toArray()),this.displacementMap&&this.displacementMap.isTexture&&(n.displacementMap=this.displacementMap.toJSON(t).uuid,n.displacementScale=this.displacementScale,n.displacementBias=this.displacementBias),this.roughnessMap&&this.roughnessMap.isTexture&&(n.roughnessMap=this.roughnessMap.toJSON(t).uuid),this.metalnessMap&&this.metalnessMap.isTexture&&(n.metalnessMap=this.metalnessMap.toJSON(t).uuid),this.emissiveMap&&this.emissiveMap.isTexture&&(n.emissiveMap=this.emissiveMap.toJSON(t).uuid),this.specularMap&&this.specularMap.isTexture&&(n.specularMap=this.specularMap.toJSON(t).uuid),this.specularIntensityMap&&this.specularIntensityMap.isTexture&&(n.specularIntensityMap=this.specularIntensityMap.toJSON(t).uuid),this.specularColorMap&&this.specularColorMap.isTexture&&(n.specularColorMap=this.specularColorMap.toJSON(t).uuid),this.envMap&&this.envMap.isTexture&&(n.envMap=this.envMap.toJSON(t).uuid,void 0!==this.combine&&(n.combine=this.combine)),void 0!==this.envMapIntensity&&(n.envMapIntensity=this.envMapIntensity),void 0!==this.reflectivity&&(n.reflectivity=this.reflectivity),void 0!==this.refractionRatio&&(n.refractionRatio=this.refractionRatio),this.gradientMap&&this.gradientMap.isTexture&&(n.gradientMap=this.gradientMap.toJSON(t).uuid),void 0!==this.transmission&&(n.transmission=this.transmission),this.transmissionMap&&this.transmissionMap.isTexture&&(n.transmissionMap=this.transmissionMap.toJSON(t).uuid),void 0!==this.thickness&&(n.thickness=this.thickness),this.thicknessMap&&this.thicknessMap.isTexture&&(n.thicknessMap=this.thicknessMap.toJSON(t).uuid),void 0!==this.attenuationDistance&&(n.attenuationDistance=this.attenuationDistance),void 0!==this.attenuationColor&&(n.attenuationColor=this.attenuationColor.getHex()),void 0!==this.size&&(n.size=this.size),null!==this.shadowSide&&(n.shadowSide=this.shadowSide),void 0!==this.sizeAttenuation&&(n.sizeAttenuation=this.sizeAttenuation),1!==this.blending&&(n.blending=this.blending),0!==this.side&&(n.side=this.side),this.vertexColors&&(n.vertexColors=!0),this.opacity<1&&(n.opacity=this.opacity),this.format!==E&&(n.format=this.format),!0===this.transparent&&(n.transparent=this.transparent),n.depthFunc=this.depthFunc,n.depthTest=this.depthTest,n.depthWrite=this.depthWrite,n.colorWrite=this.colorWrite,n.stencilWrite=this.stencilWrite,n.stencilWriteMask=this.stencilWriteMask,n.stencilFunc=this.stencilFunc,n.stencilRef=this.stencilRef,n.stencilFuncMask=this.stencilFuncMask,n.stencilFail=this.stencilFail,n.stencilZFail=this.stencilZFail,n.stencilZPass=this.stencilZPass,this.rotation&&0!==this.rotation&&(n.rotation=this.rotation),!0===this.polygonOffset&&(n.polygonOffset=!0),0!==this.polygonOffsetFactor&&(n.polygonOffsetFactor=this.polygonOffsetFactor),0!==this.polygonOffsetUnits&&(n.polygonOffsetUnits=this.polygonOffsetUnits),this.linewidth&&1!==this.linewidth&&(n.linewidth=this.linewidth),void 0!==this.dashSize&&(n.dashSize=this.dashSize),void 0!==this.gapSize&&(n.gapSize=this.gapSize),void 0!==this.scale&&(n.scale=this.scale),!0===this.dithering&&(n.dithering=!0),this.alphaTest>0&&(n.alphaTest=this.alphaTest),!0===this.alphaToCoverage&&(n.alphaToCoverage=this.alphaToCoverage),!0===this.premultipliedAlpha&&(n.premultipliedAlpha=this.premultipliedAlpha),!0===this.wireframe&&(n.wireframe=this.wireframe),this.wireframeLinewidth>1&&(n.wireframeLinewidth=this.wireframeLinewidth),"round"!==this.wireframeLinecap&&(n.wireframeLinecap=this.wireframeLinecap),"round"!==this.wireframeLinejoin&&(n.wireframeLinejoin=this.wireframeLinejoin),!0===this.flatShading&&(n.flatShading=this.flatShading),!1===this.visible&&(n.visible=!1),!1===this.toneMapped&&(n.toneMapped=!1),"{}"!==JSON.stringify(this.userData)&&(n.userData=this.userData),e){const e=i(t.textures),r=i(t.images);e.length>0&&(n.textures=e),r.length>0&&(n.images=r)}return n}clone(){return(new this.constructor).copy(this)}copy(t){this.name=t.name,this.fog=t.fog,this.blending=t.blending,this.side=t.side,this.vertexColors=t.vertexColors,this.opacity=t.opacity,this.format=t.format,this.transparent=t.transparent,this.blendSrc=t.blendSrc,this.blendDst=t.blendDst,this.blendEquation=t.blendEquation,this.blendSrcAlpha=t.blendSrcAlpha,this.blendDstAlpha=t.blendDstAlpha,this.blendEquationAlpha=t.blendEquationAlpha,this.depthFunc=t.depthFunc,this.depthTest=t.depthTest,this.depthWrite=t.depthWrite,this.stencilWriteMask=t.stencilWriteMask,this.stencilFunc=t.stencilFunc,this.stencilRef=t.stencilRef,this.stencilFuncMask=t.stencilFuncMask,this.stencilFail=t.stencilFail,this.stencilZFail=t.stencilZFail,this.stencilZPass=t.stencilZPass,this.stencilWrite=t.stencilWrite;const e=t.clippingPlanes;let n=null;if(null!==e){const t=e.length;n=new Array(t);for(let i=0;i!==t;++i)n[i]=e[i].clone()}return this.clippingPlanes=n,this.clipIntersection=t.clipIntersection,this.clipShadows=t.clipShadows,this.shadowSide=t.shadowSide,this.colorWrite=t.colorWrite,this.precision=t.precision,this.polygonOffset=t.polygonOffset,this.polygonOffsetFactor=t.polygonOffsetFactor,this.polygonOffsetUnits=t.polygonOffsetUnits,this.dithering=t.dithering,this.alphaTest=t.alphaTest,this.alphaToCoverage=t.alphaToCoverage,this.premultipliedAlpha=t.premultipliedAlpha,this.visible=t.visible,this.toneMapped=t.toneMapped,this.userData=JSON.parse(JSON.stringify(t.userData)),this}dispose(){this.dispatchEvent({type:"dispose"})}set needsUpdate(t){!0===t&&this.version++}}Ye.prototype.isMaterial=!0;const Ze={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074},Qe={h:0,s:0,l:0},Ke={h:0,s:0,l:0};function $e(t,e,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?t+6*(e-t)*n:n<.5?e:n<2/3?t+6*(e-t)*(2/3-n):t}function tn(t){return t<.04045?.0773993808*t:Math.pow(.9478672986*t+.0521327014,2.4)}function en(t){return t<.0031308?12.92*t:1.055*Math.pow(t,.41666)-.055}class nn{constructor(t,e,n){return void 0===e&&void 0===n?this.set(t):this.setRGB(t,e,n)}set(t){return t&&t.isColor?this.copy(t):"number"==typeof t?this.setHex(t):"string"==typeof t&&this.setStyle(t),this}setScalar(t){return this.r=t,this.g=t,this.b=t,this}setHex(t){return t=Math.floor(t),this.r=(t>>16&255)/255,this.g=(t>>8&255)/255,this.b=(255&t)/255,this}setRGB(t,e,n){return this.r=t,this.g=e,this.b=n,this}setHSL(t,e,n){if(t=ut(t,1),e=ht(e,0,1),n=ht(n,0,1),0===e)this.r=this.g=this.b=n;else{const i=n<=.5?n*(1+e):n+e-n*e,r=2*n-i;this.r=$e(r,i,t+1/3),this.g=$e(r,i,t),this.b=$e(r,i,t-1/3)}return this}setStyle(t){function e(e){void 0!==e&&parseFloat(e)<1&&console.warn("THREE.Color: Alpha component of "+t+" will be ignored.")}let n;if(n=/^((?:rgb|hsl)a?)\(([^\)]*)\)/.exec(t)){let t;const i=n[1],r=n[2];switch(i){case"rgb":case"rgba":if(t=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(r))return this.r=Math.min(255,parseInt(t[1],10))/255,this.g=Math.min(255,parseInt(t[2],10))/255,this.b=Math.min(255,parseInt(t[3],10))/255,e(t[4]),this;if(t=/^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(r))return this.r=Math.min(100,parseInt(t[1],10))/100,this.g=Math.min(100,parseInt(t[2],10))/100,this.b=Math.min(100,parseInt(t[3],10))/100,e(t[4]),this;break;case"hsl":case"hsla":if(t=/^\s*(\d*\.?\d+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(r)){const n=parseFloat(t[1])/360,i=parseInt(t[2],10)/100,r=parseInt(t[3],10)/100;return e(t[4]),this.setHSL(n,i,r)}}}else if(n=/^\#([A-Fa-f\d]+)$/.exec(t)){const t=n[1],e=t.length;if(3===e)return this.r=parseInt(t.charAt(0)+t.charAt(0),16)/255,this.g=parseInt(t.charAt(1)+t.charAt(1),16)/255,this.b=parseInt(t.charAt(2)+t.charAt(2),16)/255,this;if(6===e)return this.r=parseInt(t.charAt(0)+t.charAt(1),16)/255,this.g=parseInt(t.charAt(2)+t.charAt(3),16)/255,this.b=parseInt(t.charAt(4)+t.charAt(5),16)/255,this}return t&&t.length>0?this.setColorName(t):this}setColorName(t){const e=Ze[t.toLowerCase()];return void 0!==e?this.setHex(e):console.warn("THREE.Color: Unknown color "+t),this}clone(){return new this.constructor(this.r,this.g,this.b)}copy(t){return this.r=t.r,this.g=t.g,this.b=t.b,this}copyGammaToLinear(t,e=2){return this.r=Math.pow(t.r,e),this.g=Math.pow(t.g,e),this.b=Math.pow(t.b,e),this}copyLinearToGamma(t,e=2){const n=e>0?1/e:1;return this.r=Math.pow(t.r,n),this.g=Math.pow(t.g,n),this.b=Math.pow(t.b,n),this}convertGammaToLinear(t){return this.copyGammaToLinear(this,t),this}convertLinearToGamma(t){return this.copyLinearToGamma(this,t),this}copySRGBToLinear(t){return this.r=tn(t.r),this.g=tn(t.g),this.b=tn(t.b),this}copyLinearToSRGB(t){return this.r=en(t.r),this.g=en(t.g),this.b=en(t.b),this}convertSRGBToLinear(){return this.copySRGBToLinear(this),this}convertLinearToSRGB(){return this.copyLinearToSRGB(this),this}getHex(){return 255*this.r<<16^255*this.g<<8^255*this.b<<0}getHexString(){return("000000"+this.getHex().toString(16)).slice(-6)}getHSL(t){const e=this.r,n=this.g,i=this.b,r=Math.max(e,n,i),s=Math.min(e,n,i);let a,o;const l=(s+r)/2;if(s===r)a=0,o=0;else{const t=r-s;switch(o=l<=.5?t/(r+s):t/(2-r-s),r){case e:a=(n-i)/t+(n65535?mn:dn)(t,1):this.index=t,this}getAttribute(t){return this.attributes[t]}setAttribute(t,e){return this.attributes[t]=e,this}deleteAttribute(t){return delete this.attributes[t],this}hasAttribute(t){return void 0!==this.attributes[t]}addGroup(t,e,n=0){this.groups.push({start:t,count:e,materialIndex:n})}clearGroups(){this.groups=[]}setDrawRange(t,e){this.drawRange.start=t,this.drawRange.count=e}applyMatrix4(t){const e=this.attributes.position;void 0!==e&&(e.applyMatrix4(t),e.needsUpdate=!0);const n=this.attributes.normal;if(void 0!==n){const e=(new yt).getNormalMatrix(t);n.applyNormalMatrix(e),n.needsUpdate=!0}const i=this.attributes.tangent;return void 0!==i&&(i.transformDirection(t),i.needsUpdate=!0),null!==this.boundingBox&&this.computeBoundingBox(),null!==this.boundingSphere&&this.computeBoundingSphere(),this}applyQuaternion(t){return xn.makeRotationFromQuaternion(t),this.applyMatrix4(xn),this}rotateX(t){return xn.makeRotationX(t),this.applyMatrix4(xn),this}rotateY(t){return xn.makeRotationY(t),this.applyMatrix4(xn),this}rotateZ(t){return xn.makeRotationZ(t),this.applyMatrix4(xn),this}translate(t,e,n){return xn.makeTranslation(t,e,n),this.applyMatrix4(xn),this}scale(t,e,n){return xn.makeScale(t,e,n),this.applyMatrix4(xn),this}lookAt(t){return _n.lookAt(t),_n.updateMatrix(),this.applyMatrix4(_n.matrix),this}center(){return this.computeBoundingBox(),this.boundingBox.getCenter(Mn).negate(),this.translate(Mn.x,Mn.y,Mn.z),this}setFromPoints(t){const e=[];for(let n=0,i=t.length;n0&&(t.userData=this.userData),void 0!==this.parameters){const e=this.parameters;for(const n in e)void 0!==e[n]&&(t[n]=e[n]);return t}t.data={attributes:{}};const e=this.index;null!==e&&(t.data.index={type:e.array.constructor.name,array:Array.prototype.slice.call(e.array)});const n=this.attributes;for(const e in n){const i=n[e];t.data.attributes[e]=i.toJSON(t.data)}const i={};let r=!1;for(const e in this.morphAttributes){const n=this.morphAttributes[e],s=[];for(let e=0,i=n.length;e0&&(i[e]=s,r=!0)}r&&(t.data.morphAttributes=i,t.data.morphTargetsRelative=this.morphTargetsRelative);const s=this.groups;s.length>0&&(t.data.groups=JSON.parse(JSON.stringify(s)));const a=this.boundingSphere;return null!==a&&(t.data.boundingSphere={center:a.center.toArray(),radius:a.radius}),t}clone(){return(new this.constructor).copy(this)}copy(t){this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null;const e={};this.name=t.name;const n=t.index;null!==n&&this.setIndex(n.clone(e));const i=t.attributes;for(const t in i){const n=i[t];this.setAttribute(t,n.clone(e))}const r=t.morphAttributes;for(const t in r){const n=[],i=r[t];for(let t=0,r=i.length;t0){const t=e[n[0]];if(void 0!==t){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let e=0,n=t.length;e0&&console.error("THREE.Mesh.updateMorphTargets() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.")}}raycast(t,e){const n=this.geometry,i=this.material,r=this.matrixWorld;if(void 0===i)return;if(null===n.boundingSphere&&n.computeBoundingSphere(),Ln.copy(n.boundingSphere),Ln.applyMatrix4(r),!1===t.ray.intersectsSphere(Ln))return;if(En.copy(r).invert(),An.copy(t.ray).applyMatrix4(En),null!==n.boundingBox&&!1===An.intersectsBox(n.boundingBox))return;let s;if(n.isBufferGeometry){const r=n.index,a=n.attributes.position,o=n.morphAttributes.position,l=n.morphTargetsRelative,c=n.attributes.uv,h=n.attributes.uv2,u=n.groups,d=n.drawRange;if(null!==r)if(Array.isArray(i))for(let n=0,p=u.length;nn.far?null:{distance:c,point:kn.clone(),object:t}}(t,e,n,i,Rn,Cn,Pn,Gn);if(p){o&&(On.fromBufferAttribute(o,c),Un.fromBufferAttribute(o,h),Hn.fromBufferAttribute(o,u),p.uv=Xe.getUV(Gn,Rn,Cn,Pn,On,Un,Hn,new vt)),l&&(On.fromBufferAttribute(l,c),Un.fromBufferAttribute(l,h),Hn.fromBufferAttribute(l,u),p.uv2=Xe.getUV(Gn,Rn,Cn,Pn,On,Un,Hn,new vt));const t={a:c,b:h,c:u,normal:new Nt,materialIndex:0};Xe.getNormal(Rn,Cn,Pn,t.normal),p.face=t}return p}Vn.prototype.isMesh=!0;class jn extends Tn{constructor(t=1,e=1,n=1,i=1,r=1,s=1){super(),this.type="BoxGeometry",this.parameters={width:t,height:e,depth:n,widthSegments:i,heightSegments:r,depthSegments:s};const a=this;i=Math.floor(i),r=Math.floor(r),s=Math.floor(s);const o=[],l=[],c=[],h=[];let u=0,d=0;function p(t,e,n,i,r,s,p,m,f,g,v){const y=s/f,x=p/g,_=s/2,M=p/2,b=m/2,w=f+1,S=g+1;let T=0,E=0;const A=new Nt;for(let s=0;s0?1:-1,c.push(A.x,A.y,A.z),h.push(o/f),h.push(1-s/g),T+=1}}for(let t=0;t0&&(e.defines=this.defines),e.vertexShader=this.vertexShader,e.fragmentShader=this.fragmentShader;const n={};for(const t in this.extensions)!0===this.extensions[t]&&(n[t]=!0);return Object.keys(n).length>0&&(e.extensions=n),e}}Yn.prototype.isShaderMaterial=!0;class Zn extends Be{constructor(){super(),this.type="Camera",this.matrixWorldInverse=new ue,this.projectionMatrix=new ue,this.projectionMatrixInverse=new ue}copy(t,e){return super.copy(t,e),this.matrixWorldInverse.copy(t.matrixWorldInverse),this.projectionMatrix.copy(t.projectionMatrix),this.projectionMatrixInverse.copy(t.projectionMatrixInverse),this}getWorldDirection(t){this.updateWorldMatrix(!0,!1);const e=this.matrixWorld.elements;return t.set(-e[8],-e[9],-e[10]).normalize()}updateMatrixWorld(t){super.updateMatrixWorld(t),this.matrixWorldInverse.copy(this.matrixWorld).invert()}updateWorldMatrix(t,e){super.updateWorldMatrix(t,e),this.matrixWorldInverse.copy(this.matrixWorld).invert()}clone(){return(new this.constructor).copy(this)}}Zn.prototype.isCamera=!0;class Qn extends Zn{constructor(t=50,e=1,n=.1,i=2e3){super(),this.type="PerspectiveCamera",this.fov=t,this.zoom=1,this.near=n,this.far=i,this.focus=10,this.aspect=e,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}copy(t,e){return super.copy(t,e),this.fov=t.fov,this.zoom=t.zoom,this.near=t.near,this.far=t.far,this.focus=t.focus,this.aspect=t.aspect,this.view=null===t.view?null:Object.assign({},t.view),this.filmGauge=t.filmGauge,this.filmOffset=t.filmOffset,this}setFocalLength(t){const e=.5*this.getFilmHeight()/t;this.fov=2*lt*Math.atan(e),this.updateProjectionMatrix()}getFocalLength(){const t=Math.tan(.5*ot*this.fov);return.5*this.getFilmHeight()/t}getEffectiveFOV(){return 2*lt*Math.atan(Math.tan(.5*ot*this.fov)/this.zoom)}getFilmWidth(){return this.filmGauge*Math.min(this.aspect,1)}getFilmHeight(){return this.filmGauge/Math.max(this.aspect,1)}setViewOffset(t,e,n,i,r,s){this.aspect=t/e,null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=t,this.view.fullHeight=e,this.view.offsetX=n,this.view.offsetY=i,this.view.width=r,this.view.height=s,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const t=this.near;let e=t*Math.tan(.5*ot*this.fov)/this.zoom,n=2*e,i=this.aspect*n,r=-.5*i;const s=this.view;if(null!==this.view&&this.view.enabled){const t=s.fullWidth,a=s.fullHeight;r+=s.offsetX*i/t,e-=s.offsetY*n/a,i*=s.width/t,n*=s.height/a}const a=this.filmOffset;0!==a&&(r+=t*a/this.getFilmWidth()),this.projectionMatrix.makePerspective(r,r+i,e,e-n,t,this.far),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(t){const e=super.toJSON(t);return e.object.fov=this.fov,e.object.zoom=this.zoom,e.object.near=this.near,e.object.far=this.far,e.object.focus=this.focus,e.object.aspect=this.aspect,null!==this.view&&(e.object.view=Object.assign({},this.view)),e.object.filmGauge=this.filmGauge,e.object.filmOffset=this.filmOffset,e}}Qn.prototype.isPerspectiveCamera=!0;const Kn=90;class $n extends Be{constructor(t,e,n){if(super(),this.type="CubeCamera",!0!==n.isWebGLCubeRenderTarget)return void console.error("THREE.CubeCamera: The constructor now expects an instance of WebGLCubeRenderTarget as third parameter.");this.renderTarget=n;const i=new Qn(Kn,1,t,e);i.layers=this.layers,i.up.set(0,-1,0),i.lookAt(new Nt(1,0,0)),this.add(i);const r=new Qn(Kn,1,t,e);r.layers=this.layers,r.up.set(0,-1,0),r.lookAt(new Nt(-1,0,0)),this.add(r);const s=new Qn(Kn,1,t,e);s.layers=this.layers,s.up.set(0,0,1),s.lookAt(new Nt(0,1,0)),this.add(s);const a=new Qn(Kn,1,t,e);a.layers=this.layers,a.up.set(0,0,-1),a.lookAt(new Nt(0,-1,0)),this.add(a);const o=new Qn(Kn,1,t,e);o.layers=this.layers,o.up.set(0,-1,0),o.lookAt(new Nt(0,0,1)),this.add(o);const l=new Qn(Kn,1,t,e);l.layers=this.layers,l.up.set(0,-1,0),l.lookAt(new Nt(0,0,-1)),this.add(l)}update(t,e){null===this.parent&&this.updateMatrixWorld();const n=this.renderTarget,[i,r,s,a,o,l]=this.children,c=t.xr.enabled,h=t.getRenderTarget();t.xr.enabled=!1;const u=n.texture.generateMipmaps;n.texture.generateMipmaps=!1,t.setRenderTarget(n,0),t.render(e,i),t.setRenderTarget(n,1),t.render(e,r),t.setRenderTarget(n,2),t.render(e,s),t.setRenderTarget(n,3),t.render(e,a),t.setRenderTarget(n,4),t.render(e,o),n.texture.generateMipmaps=u,t.setRenderTarget(n,5),t.render(e,l),t.setRenderTarget(h),t.xr.enabled=c}}class ti extends At{constructor(t,e,n,i,s,a,o,l,c,h){super(t=void 0!==t?t:[],e=void 0!==e?e:r,n,i,s,a,o,l,c,h),this.flipY=!1}get images(){return this.image}set images(t){this.image=t}}ti.prototype.isCubeTexture=!0;class ei extends Ct{constructor(t,e,n){Number.isInteger(e)&&(console.warn("THREE.WebGLCubeRenderTarget: constructor signature is now WebGLCubeRenderTarget( size, options )"),e=n),super(t,t,e),e=e||{},this.texture=new ti(void 0,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.format,e.type,e.anisotropy,e.encoding),this.texture.isRenderTargetTexture=!0,this.texture.generateMipmaps=void 0!==e.generateMipmaps&&e.generateMipmaps,this.texture.minFilter=void 0!==e.minFilter?e.minFilter:g,this.texture._needsFlipEnvMap=!1}fromEquirectangularTexture(t,e){this.texture.type=e.type,this.texture.format=E,this.texture.encoding=e.encoding,this.texture.generateMipmaps=e.generateMipmaps,this.texture.minFilter=e.minFilter,this.texture.magFilter=e.magFilter;const n={uniforms:{tEquirect:{value:null}},vertexShader:"\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\tvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\n\t\t\t\t\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n\n\t\t\t\t}\n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvWorldDirection = transformDirection( position, modelMatrix );\n\n\t\t\t\t\t#include \n\t\t\t\t\t#include \n\n\t\t\t\t}\n\t\t\t",fragmentShader:"\n\n\t\t\t\tuniform sampler2D tEquirect;\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\t#include \n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvec3 direction = normalize( vWorldDirection );\n\n\t\t\t\t\tvec2 sampleUV = equirectUv( direction );\n\n\t\t\t\t\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\n\t\t\t\t}\n\t\t\t"},i=new jn(5,5,5),r=new Yn({name:"CubemapFromEquirect",uniforms:qn(n.uniforms),vertexShader:n.vertexShader,fragmentShader:n.fragmentShader,side:1,blending:0});r.uniforms.tEquirect.value=e;const s=new Vn(i,r),a=e.minFilter;e.minFilter===y&&(e.minFilter=g);return new $n(1,10,this).update(t,s),e.minFilter=a,s.geometry.dispose(),s.material.dispose(),this}clear(t,e,n,i){const r=t.getRenderTarget();for(let r=0;r<6;r++)t.setRenderTarget(this,r),t.clear(e,n,i);t.setRenderTarget(r)}}ei.prototype.isWebGLCubeRenderTarget=!0;const ni=new Nt,ii=new Nt,ri=new yt;class si{constructor(t=new Nt(1,0,0),e=0){this.normal=t,this.constant=e}set(t,e){return this.normal.copy(t),this.constant=e,this}setComponents(t,e,n,i){return this.normal.set(t,e,n),this.constant=i,this}setFromNormalAndCoplanarPoint(t,e){return this.normal.copy(t),this.constant=-e.dot(this.normal),this}setFromCoplanarPoints(t,e,n){const i=ni.subVectors(n,e).cross(ii.subVectors(t,e)).normalize();return this.setFromNormalAndCoplanarPoint(i,t),this}copy(t){return this.normal.copy(t.normal),this.constant=t.constant,this}normalize(){const t=1/this.normal.length();return this.normal.multiplyScalar(t),this.constant*=t,this}negate(){return this.constant*=-1,this.normal.negate(),this}distanceToPoint(t){return this.normal.dot(t)+this.constant}distanceToSphere(t){return this.distanceToPoint(t.center)-t.radius}projectPoint(t,e){return e.copy(this.normal).multiplyScalar(-this.distanceToPoint(t)).add(t)}intersectLine(t,e){const n=t.delta(ni),i=this.normal.dot(n);if(0===i)return 0===this.distanceToPoint(t.start)?e.copy(t.start):null;const r=-(t.start.dot(this.normal)+this.constant)/i;return r<0||r>1?null:e.copy(n).multiplyScalar(r).add(t.start)}intersectsLine(t){const e=this.distanceToPoint(t.start),n=this.distanceToPoint(t.end);return e<0&&n>0||n<0&&e>0}intersectsBox(t){return t.intersectsPlane(this)}intersectsSphere(t){return t.intersectsPlane(this)}coplanarPoint(t){return t.copy(this.normal).multiplyScalar(-this.constant)}applyMatrix4(t,e){const n=e||ri.getNormalMatrix(t),i=this.coplanarPoint(ni).applyMatrix4(t),r=this.normal.applyMatrix3(n).normalize();return this.constant=-i.dot(r),this}translate(t){return this.constant-=t.dot(this.normal),this}equals(t){return t.normal.equals(this.normal)&&t.constant===this.constant}clone(){return(new this.constructor).copy(this)}}si.prototype.isPlane=!0;const ai=new ne,oi=new Nt;class li{constructor(t=new si,e=new si,n=new si,i=new si,r=new si,s=new si){this.planes=[t,e,n,i,r,s]}set(t,e,n,i,r,s){const a=this.planes;return a[0].copy(t),a[1].copy(e),a[2].copy(n),a[3].copy(i),a[4].copy(r),a[5].copy(s),this}copy(t){const e=this.planes;for(let n=0;n<6;n++)e[n].copy(t.planes[n]);return this}setFromProjectionMatrix(t){const e=this.planes,n=t.elements,i=n[0],r=n[1],s=n[2],a=n[3],o=n[4],l=n[5],c=n[6],h=n[7],u=n[8],d=n[9],p=n[10],m=n[11],f=n[12],g=n[13],v=n[14],y=n[15];return e[0].setComponents(a-i,h-o,m-u,y-f).normalize(),e[1].setComponents(a+i,h+o,m+u,y+f).normalize(),e[2].setComponents(a+r,h+l,m+d,y+g).normalize(),e[3].setComponents(a-r,h-l,m-d,y-g).normalize(),e[4].setComponents(a-s,h-c,m-p,y-v).normalize(),e[5].setComponents(a+s,h+c,m+p,y+v).normalize(),this}intersectsObject(t){const e=t.geometry;return null===e.boundingSphere&&e.computeBoundingSphere(),ai.copy(e.boundingSphere).applyMatrix4(t.matrixWorld),this.intersectsSphere(ai)}intersectsSprite(t){return ai.center.set(0,0,0),ai.radius=.7071067811865476,ai.applyMatrix4(t.matrixWorld),this.intersectsSphere(ai)}intersectsSphere(t){const e=this.planes,n=t.center,i=-t.radius;for(let t=0;t<6;t++){if(e[t].distanceToPoint(n)0?t.max.x:t.min.x,oi.y=i.normal.y>0?t.max.y:t.min.y,oi.z=i.normal.z>0?t.max.z:t.min.z,i.distanceToPoint(oi)<0)return!1}return!0}containsPoint(t){const e=this.planes;for(let n=0;n<6;n++)if(e[n].distanceToPoint(t)<0)return!1;return!0}clone(){return(new this.constructor).copy(this)}}function ci(){let t=null,e=!1,n=null,i=null;function r(e,s){n(e,s),i=t.requestAnimationFrame(r)}return{start:function(){!0!==e&&null!==n&&(i=t.requestAnimationFrame(r),e=!0)},stop:function(){t.cancelAnimationFrame(i),e=!1},setAnimationLoop:function(t){n=t},setContext:function(e){t=e}}}function hi(t,e){const n=e.isWebGL2,i=new WeakMap;return{get:function(t){return t.isInterleavedBufferAttribute&&(t=t.data),i.get(t)},remove:function(e){e.isInterleavedBufferAttribute&&(e=e.data);const n=i.get(e);n&&(t.deleteBuffer(n.buffer),i.delete(e))},update:function(e,r){if(e.isGLBufferAttribute){const t=i.get(e);return void((!t||t.version 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_BlinnPhong( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, 1.0, dotVH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif",bumpmap_pars_fragment:"#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy, float faceDirection ) {\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 ) * faceDirection;\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif",clipping_planes_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#pragma unroll_loop_end\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\tif ( clipped ) discard;\n\t#endif\n#endif",clipping_planes_pars_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif",clipping_planes_pars_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif",clipping_planes_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif",color_fragment:"#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif",color_pars_fragment:"#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif",color_pars_vertex:"#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvarying vec3 vColor;\n#endif",color_vertex:"#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif",common:"#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal;\n#endif\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}",cube_uv_reflection_fragment:"#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_maxMipLevel 8.0\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_maxTileSize 256.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\tfloat texelSize = 1.0 / ( 3.0 * cubeUV_maxTileSize );\n\t\tvec2 uv = getUV( direction, face ) * ( faceSize - 1.0 );\n\t\tvec2 f = fract( uv );\n\t\tuv += 0.5 - f;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tif ( mipInt < cubeUV_maxMipLevel ) {\n\t\t\tuv.y += 2.0 * cubeUV_maxTileSize;\n\t\t}\n\t\tuv.y += filterInt * 2.0 * cubeUV_minTileSize;\n\t\tuv.x += 3.0 * max( 0.0, cubeUV_maxTileSize - 2.0 * faceSize );\n\t\tuv *= texelSize;\n\t\tvec3 tl = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb;\n\t\tuv.x += texelSize;\n\t\tvec3 tr = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb;\n\t\tuv.y += texelSize;\n\t\tvec3 br = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb;\n\t\tuv.x -= texelSize;\n\t\tvec3 bl = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb;\n\t\tvec3 tm = mix( tl, tr, f.x );\n\t\tvec3 bm = mix( bl, br, f.x );\n\t\treturn mix( tm, bm, f.y );\n\t}\n\t#define r0 1.0\n\t#define v0 0.339\n\t#define m0 - 2.0\n\t#define r1 0.8\n\t#define v1 0.276\n\t#define m1 - 1.0\n\t#define r4 0.4\n\t#define v4 0.046\n\t#define m4 2.0\n\t#define r5 0.305\n\t#define v5 0.016\n\t#define m5 3.0\n\t#define r6 0.21\n\t#define v6 0.0038\n\t#define m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= r1 ) {\n\t\t\tmip = ( r0 - roughness ) * ( m1 - m0 ) / ( r0 - r1 ) + m0;\n\t\t} else if ( roughness >= r4 ) {\n\t\t\tmip = ( r1 - roughness ) * ( m4 - m1 ) / ( r1 - r4 ) + m1;\n\t\t} else if ( roughness >= r5 ) {\n\t\t\tmip = ( r4 - roughness ) * ( m5 - m4 ) / ( r4 - r5 ) + m4;\n\t\t} else if ( roughness >= r6 ) {\n\t\t\tmip = ( r5 - roughness ) * ( m6 - m5 ) / ( r5 - r6 ) + m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), m0, cubeUV_maxMipLevel );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif",defaultnormal_vertex:"vec3 transformedNormal = objectNormal;\n#ifdef USE_INSTANCING\n\tmat3 m = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( m[ 0 ], m[ 0 ] ), dot( m[ 1 ], m[ 1 ] ), dot( m[ 2 ], m[ 2 ] ) );\n\ttransformedNormal = m * transformedNormal;\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = ( modelViewMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif",displacementmap_pars_vertex:"#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif",displacementmap_vertex:"#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias );\n#endif",emissivemap_fragment:"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif",emissivemap_pars_fragment:"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif",encodings_fragment:"gl_FragColor = linearToOutputTexel( gl_FragColor );",encodings_pars_fragment:"\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.rgb, vec3( gammaFactor ) ), value.a );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.rgb, vec3( 1.0 / gammaFactor ) ), value.a );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.a );\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * value.a * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.r, max( value.g, value.b ) );\n\tfloat M = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.r, max( value.g, value.b ) );\n\tfloat D = max( maxRange / maxRGB, 1.0 );\n\tD = clamp( floor( D ) / 255.0, 0.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}",envmap_fragment:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t\tenvColor = envMapTexelToLinear( envColor );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 envColor = textureCubeUV( envMap, reflectVec, 0.0 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif",envmap_common_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif",envmap_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float reflectivity;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif",envmap_pars_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) ||defined( PHONG )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\t\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif",envmap_physical_pars_fragment:"#if defined( USE_ENVMAP )\n\t#ifdef ENVMAP_MODE_REFRACTION\n\t\tuniform float refractionRatio;\n\t#endif\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 reflectVec;\n\t\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\t\treflectVec = reflect( - viewDir, normal );\n\t\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\t#else\n\t\t\t\treflectVec = refract( - viewDir, normal, refractionRatio );\n\t\t\t#endif\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n#endif",envmap_vertex:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif",fog_vertex:"#ifdef USE_FOG\n\tvFogDepth = - mvPosition.z;\n#endif",fog_pars_vertex:"#ifdef USE_FOG\n\tvarying float vFogDepth;\n#endif",fog_fragment:"#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, vFogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif",fog_pars_fragment:"#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float vFogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif",gradientmap_pars_fragment:"#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn vec3( texture2D( gradientMap, coord ).r );\n\t#else\n\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t#endif\n}",lightmap_fragment:"#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\tvec3 lightMapIrradiance = lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tlightMapIrradiance *= PI;\n\t#endif\n\treflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif",lightmap_pars_fragment:"#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif",lights_lambert_vertex:"vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\nvIndirectFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n\tvIndirectBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\nvIndirectFront += getAmbientLightIrradiance( ambientLightColor );\nvIndirectFront += getLightProbeIrradiance( lightProbe, geometry.normal );\n#ifdef DOUBLE_SIDED\n\tvIndirectBack += getAmbientLightIrradiance( ambientLightColor );\n\tvIndirectBack += getLightProbeIrradiance( lightProbe, backGeometry.normal );\n#endif\n#if NUM_POINT_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tgetPointLightInfo( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( - dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tgetSpotLightInfo( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( - dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if NUM_DIR_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tgetDirectionalLightInfo( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( - dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvIndirectFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry.normal );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvIndirectBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry.normal );\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif",lights_pars_begin:"uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\nuniform vec3 lightProbe[ 9 ];\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\t#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tif ( cutoffDistance > 0.0 ) {\n\t\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\t}\n\t\treturn distanceFalloff;\n\t#else\n\t\tif ( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\t\treturn pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t\t}\n\t\treturn 1.0;\n\t#endif\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif",lights_toon_fragment:"ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;",lights_toon_pars_fragment:"varying vec3 vViewPosition;\nstruct ToonMaterial {\n\tvec3 diffuseColor;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Toon\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Toon\n#define Material_LightProbeLOD( material )\t(0)",lights_phong_fragment:"BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;",lights_phong_pars_fragment:"varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )\t(0)",lights_physical_fragment:"PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\t#ifdef SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULARINTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vUv ).a;\n\t\t#endif\n\t\t#ifdef USE_SPECULARCOLORMAP\n\t\t\tspecularColorFactor *= specularColorMapTexelToLinear( texture2D( specularColorMap, vUv ) ).rgb;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( ior - 1.0 ) / ( ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tmaterial.sheenColor *= sheenColorMapTexelToLinear( texture2D( sheenColorMap, vUv ) ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vUv ).a;\n\t#endif\n#endif",lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n};\nvec3 clearcoatSpecular = vec3( 0.0 );\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\tvec3 FssEss = specularColor * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = specularColor + ( 1.0 - specularColor ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3(\t\t0, 1,\t\t0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecular += ccIrradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.clearcoatNormal, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\treflectedLight.directSpecular += irradiance * BRDF_Sheen( directLight.direction, geometry.viewDir, geometry.normal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.roughness );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecular += clearcoatRadiance * EnvironmentBRDF( geometry.clearcoatNormal, geometry.viewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\tcomputeMultiscattering( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - ( singleScattering + multiScattering ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}",lights_fragment_begin:"\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\n#ifdef USE_CLEARCOAT\n\tgeometry.clearcoatNormal = clearcoatNormal;\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\tirradiance += getLightProbeIrradiance( lightProbe, geometry.normal );\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry.normal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif",lights_fragment_maps:"#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\t\tvec3 lightMapIrradiance = lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometry.normal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getIBLRadiance( geometry.viewDir, geometry.normal, material.roughness );\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif",lights_fragment_end:"#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometry, material, reflectedLight );\n#endif",logdepthbuf_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif",logdepthbuf_pars_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif",logdepthbuf_pars_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t\tvarying float vIsPerspective;\n\t#else\n\t\tuniform float logDepthBufFC;\n\t#endif\n#endif",logdepthbuf_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n\t#else\n\t\tif ( isPerspectiveMatrix( projectionMatrix ) ) {\n\t\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\t\tgl_Position.z *= gl_Position.w;\n\t\t}\n\t#endif\n#endif",map_fragment:"#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif",map_pars_fragment:"#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif",map_particle_fragment:"#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n#endif\n#ifdef USE_MAP\n\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif",map_particle_pars_fragment:"#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tuniform mat3 uvTransform;\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif",metalnessmap_fragment:"float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif",metalnessmap_pars_fragment:"#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] > 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1, 2 ) * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n\t\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n\t\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n\t\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n\t#endif\n#endif",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n\tuniform float morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t\tuniform sampler2DArray morphTargetsTexture;\n\t\tuniform vec2 morphTargetsTextureSize;\n\t\tvec3 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset, const in int stride ) {\n\t\t\tfloat texelIndex = float( vertexIndex * stride + offset );\n\t\t\tfloat y = floor( texelIndex / morphTargetsTextureSize.x );\n\t\t\tfloat x = texelIndex - y * morphTargetsTextureSize.x;\n\t\t\tvec3 morphUV = vec3( ( x + 0.5 ) / morphTargetsTextureSize.x, y / morphTargetsTextureSize.y, morphTargetIndex );\n\t\t\treturn texture( morphTargetsTexture, morphUV ).xyz;\n\t\t}\n\t#else\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\tuniform float morphTargetInfluences[ 8 ];\n\t\t#else\n\t\t\tuniform float morphTargetInfluences[ 4 ];\n\t\t#endif\n\t#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\t#ifndef USE_MORPHNORMALS\n\t\t\t\tif ( morphTargetInfluences[ i ] > 0.0 ) transformed += getMorph( gl_VertexID, i, 0, 1 ) * morphTargetInfluences[ i ];\n\t\t\t#else\n\t\t\t\tif ( morphTargetInfluences[ i ] > 0.0 ) transformed += getMorph( gl_VertexID, i, 0, 2 ) * morphTargetInfluences[ i ];\n\t\t\t#endif\n\t\t}\n\t#else\n\t\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\t\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\t\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\t\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\t\t\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\t\t\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\t\t\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\t\t#endif\n\t#endif\n#endif",normal_fragment_begin:"float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\t#ifdef USE_TANGENT\n\t\tvec3 tangent = normalize( vTangent );\n\t\tvec3 bitangent = normalize( vBitangent );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\ttangent = tangent * faceDirection;\n\t\t\tbitangent = bitangent * faceDirection;\n\t\t#endif\n\t\t#if defined( TANGENTSPACE_NORMALMAP ) || defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tmat3 vTBN = mat3( tangent, bitangent, normal );\n\t\t#endif\n\t#endif\n#endif\nvec3 geometryNormal = normal;",normal_fragment_maps:"#ifdef OBJECTSPACE_NORMALMAP\n\tnormal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( TANGENTSPACE_NORMALMAP )\n\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\t#ifdef USE_TANGENT\n\t\tnormal = normalize( vTBN * mapN );\n\t#else\n\t\tnormal = perturbNormal2Arb( - vViewPosition, normal, mapN, faceDirection );\n\t#endif\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif",normal_pars_fragment:"#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif",normal_pars_vertex:"#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif",normal_vertex:"#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif",normalmap_pars_fragment:"#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef OBJECTSPACE_NORMALMAP\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( TANGENTSPACE_NORMALMAP ) || defined ( USE_CLEARCOAT_NORMALMAP ) )\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 mapN, float faceDirection ) {\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tvec3 N = surf_norm;\n\t\tvec3 q1perp = cross( q1, N );\n\t\tvec3 q0perp = cross( N, q0 );\n\t\tvec3 T = q1perp * st0.x + q0perp * st1.x;\n\t\tvec3 B = q1perp * st0.y + q0perp * st1.y;\n\t\tfloat det = max( dot( T, T ), dot( B, B ) );\n\t\tfloat scale = ( det == 0.0 ) ? 0.0 : faceDirection * inversesqrt( det );\n\t\treturn normalize( T * ( mapN.x * scale ) + B * ( mapN.y * scale ) + N * mapN.z );\n\t}\n#endif",clearcoat_normal_fragment_begin:"#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = geometryNormal;\n#endif",clearcoat_normal_fragment_maps:"#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\t#ifdef USE_TANGENT\n\t\tclearcoatNormal = normalize( vTBN * clearcoatMapN );\n\t#else\n\t\tclearcoatNormal = perturbNormal2Arb( - vViewPosition, clearcoatNormal, clearcoatMapN, faceDirection );\n\t#endif\n#endif",clearcoat_pars_fragment:"#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif",output_fragment:"#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= transmissionAlpha + 0.1;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );",packing:"vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nvec4 pack2HalfToRGBA( vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( vec4 v ) {\n\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}",premultiplied_alpha_fragment:"#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif",project_vertex:"vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_INSTANCING\n\tmvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;",dithering_fragment:"#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif",dithering_pars_fragment:"#ifdef DITHERING\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif",roughnessmap_fragment:"float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif",roughnessmap_pars_fragment:"#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif",shadowmap_pars_fragment:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ), \n\t\t\t\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t\tf.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ), \n\t\t\t\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t\tf.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif",shadowmap_pars_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif",shadowmap_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0 || NUM_SPOT_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0\n\t\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\tvec4 shadowWorldPosition;\n\t#endif\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias, 0 );\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n#endif",shadowmask_pars_fragment:"float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#endif\n\treturn shadow;\n}",skinbase_vertex:"#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\t#ifdef BONE_TEXTURE\n\t\tuniform highp sampler2D boneTexture;\n\t\tuniform int boneTextureSize;\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tfloat j = i * 4.0;\n\t\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\t\ty = dy * ( y + 0.5 );\n\t\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\t\treturn bone;\n\t\t}\n\t#else\n\t\tuniform mat4 boneMatrices[ MAX_BONES ];\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tmat4 bone = boneMatrices[ int(i) ];\n\t\t\treturn bone;\n\t\t}\n\t#endif\n#endif",skinning_vertex:"#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif",skinnormal_vertex:"#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif",specularmap_fragment:"float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif",specularmap_pars_fragment:"#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif",tonemapping_fragment:"#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif",tonemapping_pars_fragment:"#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3(\t1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108,\t1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605,\t1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }",transmission_fragment:"#ifdef USE_TRANSMISSION\n\tfloat transmissionAlpha = 1.0;\n\tfloat transmissionFactor = transmission;\n\tfloat thicknessFactor = thickness;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\ttransmissionFactor *= texture2D( transmissionMap, vUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tthicknessFactor *= texture2D( thicknessMap, vUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmission = getIBLVolumeRefraction(\n\t\tn, v, roughnessFactor, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, ior, thicknessFactor,\n\t\tattenuationColor, attenuationDistance );\n\ttotalDiffuse = mix( totalDiffuse, transmission.rgb, transmissionFactor );\n\ttransmissionAlpha = mix( transmissionAlpha, transmission.a, transmissionFactor );\n#endif",transmission_pars_fragment:"#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tvec3 getVolumeTransmissionRay( vec3 n, vec3 v, float thickness, float ior, mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( float roughness, float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( vec2 fragCoord, float roughness, float ior ) {\n\t\tfloat framebufferLod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\treturn texture2DLodEXT( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n\t\t#else\n\t\t\treturn texture2D( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n\t\t#endif\n\t}\n\tvec3 applyVolumeAttenuation( vec3 radiance, float transmissionDistance, vec3 attenuationColor, float attenuationDistance ) {\n\t\tif ( attenuationDistance == 0.0 ) {\n\t\t\treturn radiance;\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance * radiance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( vec3 n, vec3 v, float roughness, vec3 diffuseColor, vec3 specularColor, float specularF90,\n\t\tvec3 position, mat4 modelMatrix, mat4 viewMatrix, mat4 projMatrix, float ior, float thickness,\n\t\tvec3 attenuationColor, float attenuationDistance ) {\n\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\trefractionCoords += 1.0;\n\t\trefractionCoords /= 2.0;\n\t\tvec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\tvec3 attenuatedColor = applyVolumeAttenuation( transmittedLight.rgb, length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor * diffuseColor, transmittedLight.a );\n\t}\n#endif",uv_pars_fragment:"#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )\n\tvarying vec2 vUv;\n#endif",uv_pars_vertex:"#ifdef USE_UV\n\t#ifdef UVS_VERTEX_ONLY\n\t\tvec2 vUv;\n\t#else\n\t\tvarying vec2 vUv;\n\t#endif\n\tuniform mat3 uvTransform;\n#endif",uv_vertex:"#ifdef USE_UV\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif",uv2_pars_fragment:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif",uv2_pars_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n\tuniform mat3 uv2Transform;\n#endif",uv2_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION )\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif",background_vert:"varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}",background_frag:"uniform sampler2D t2D;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\tgl_FragColor = mapTexelToLinear( texColor );\n\t#include \n\t#include \n}",cube_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}",cube_frag:"#include \nuniform float opacity;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 vReflect = vWorldDirection;\n\t#include \n\tgl_FragColor = envColor;\n\tgl_FragColor.a *= opacity;\n\t#include \n\t#include \n}",depth_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvHighPrecisionZW = gl_Position.zw;\n}",depth_frag:"#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\t#endif\n}",distanceRGBA_vert:"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}",distanceRGBA_frag:"#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main () {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}",equirect_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}",equirect_frag:"uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tvec4 texColor = texture2D( tEquirect, sampleUV );\n\tgl_FragColor = mapTexelToLinear( texColor );\n\t#include \n\t#include \n}",linedashed_vert:"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",linedashed_frag:"uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\t\treflectedLight.indirectDiffuse += lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_vert:"#define LAMBERT\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_frag:"uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.indirectDiffuse += ( gl_FrontFacing ) ? vIndirectFront : vIndirectBack;\n\t#else\n\t\treflectedLight.indirectDiffuse += vIndirectFront;\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= BRDF_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshmatcap_vert:"#define MATCAP\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n}",meshmatcap_frag:"#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t\tmatcapColor = matcapTexelToLinear( matcapColor );\n\t#else\n\t\tvec4 matcapColor = vec4( 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshnormal_vert:"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}",meshnormal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}",meshphong_vert:"#define PHONG\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphong_frag:"#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphysical_vert:"#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}",meshphysical_frag:"#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULARINTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n\t#ifdef USE_SPECULARCOLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshtoon_vert:"#define TOON\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}",meshtoon_frag:"#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",points_vert:"uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}",points_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_vert:"#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_frag:"uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n\t#include \n\t#include \n}",sprite_vert:"uniform float rotation;\nuniform vec2 center;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}",sprite_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n}"},pi={common:{diffuse:{value:new nn(16777215)},opacity:{value:1},map:{value:null},uvTransform:{value:new yt},uv2Transform:{value:new yt},alphaMap:{value:null},alphaTest:{value:0}},specularmap:{specularMap:{value:null}},envmap:{envMap:{value:null},flipEnvMap:{value:-1},reflectivity:{value:1},ior:{value:1.5},refractionRatio:{value:.98}},aomap:{aoMap:{value:null},aoMapIntensity:{value:1}},lightmap:{lightMap:{value:null},lightMapIntensity:{value:1}},emissivemap:{emissiveMap:{value:null}},bumpmap:{bumpMap:{value:null},bumpScale:{value:1}},normalmap:{normalMap:{value:null},normalScale:{value:new vt(1,1)}},displacementmap:{displacementMap:{value:null},displacementScale:{value:1},displacementBias:{value:0}},roughnessmap:{roughnessMap:{value:null}},metalnessmap:{metalnessMap:{value:null}},gradientmap:{gradientMap:{value:null}},fog:{fogDensity:{value:25e-5},fogNear:{value:1},fogFar:{value:2e3},fogColor:{value:new nn(16777215)}},lights:{ambientLightColor:{value:[]},lightProbe:{value:[]},directionalLights:{value:[],properties:{direction:{},color:{}}},directionalLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},directionalShadowMap:{value:[]},directionalShadowMatrix:{value:[]},spotLights:{value:[],properties:{color:{},position:{},direction:{},distance:{},coneCos:{},penumbraCos:{},decay:{}}},spotLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},spotShadowMap:{value:[]},spotShadowMatrix:{value:[]},pointLights:{value:[],properties:{color:{},position:{},decay:{},distance:{}}},pointLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{},shadowCameraNear:{},shadowCameraFar:{}}},pointShadowMap:{value:[]},pointShadowMatrix:{value:[]},hemisphereLights:{value:[],properties:{direction:{},skyColor:{},groundColor:{}}},rectAreaLights:{value:[],properties:{color:{},position:{},width:{},height:{}}},ltc_1:{value:null},ltc_2:{value:null}},points:{diffuse:{value:new nn(16777215)},opacity:{value:1},size:{value:1},scale:{value:1},map:{value:null},alphaMap:{value:null},alphaTest:{value:0},uvTransform:{value:new yt}},sprite:{diffuse:{value:new nn(16777215)},opacity:{value:1},center:{value:new vt(.5,.5)},rotation:{value:0},map:{value:null},alphaMap:{value:null},alphaTest:{value:0},uvTransform:{value:new yt}}},mi={basic:{uniforms:Xn([pi.common,pi.specularmap,pi.envmap,pi.aomap,pi.lightmap,pi.fog]),vertexShader:di.meshbasic_vert,fragmentShader:di.meshbasic_frag},lambert:{uniforms:Xn([pi.common,pi.specularmap,pi.envmap,pi.aomap,pi.lightmap,pi.emissivemap,pi.fog,pi.lights,{emissive:{value:new nn(0)}}]),vertexShader:di.meshlambert_vert,fragmentShader:di.meshlambert_frag},phong:{uniforms:Xn([pi.common,pi.specularmap,pi.envmap,pi.aomap,pi.lightmap,pi.emissivemap,pi.bumpmap,pi.normalmap,pi.displacementmap,pi.fog,pi.lights,{emissive:{value:new nn(0)},specular:{value:new nn(1118481)},shininess:{value:30}}]),vertexShader:di.meshphong_vert,fragmentShader:di.meshphong_frag},standard:{uniforms:Xn([pi.common,pi.envmap,pi.aomap,pi.lightmap,pi.emissivemap,pi.bumpmap,pi.normalmap,pi.displacementmap,pi.roughnessmap,pi.metalnessmap,pi.fog,pi.lights,{emissive:{value:new nn(0)},roughness:{value:1},metalness:{value:0},envMapIntensity:{value:1}}]),vertexShader:di.meshphysical_vert,fragmentShader:di.meshphysical_frag},toon:{uniforms:Xn([pi.common,pi.aomap,pi.lightmap,pi.emissivemap,pi.bumpmap,pi.normalmap,pi.displacementmap,pi.gradientmap,pi.fog,pi.lights,{emissive:{value:new nn(0)}}]),vertexShader:di.meshtoon_vert,fragmentShader:di.meshtoon_frag},matcap:{uniforms:Xn([pi.common,pi.bumpmap,pi.normalmap,pi.displacementmap,pi.fog,{matcap:{value:null}}]),vertexShader:di.meshmatcap_vert,fragmentShader:di.meshmatcap_frag},points:{uniforms:Xn([pi.points,pi.fog]),vertexShader:di.points_vert,fragmentShader:di.points_frag},dashed:{uniforms:Xn([pi.common,pi.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:di.linedashed_vert,fragmentShader:di.linedashed_frag},depth:{uniforms:Xn([pi.common,pi.displacementmap]),vertexShader:di.depth_vert,fragmentShader:di.depth_frag},normal:{uniforms:Xn([pi.common,pi.bumpmap,pi.normalmap,pi.displacementmap,{opacity:{value:1}}]),vertexShader:di.meshnormal_vert,fragmentShader:di.meshnormal_frag},sprite:{uniforms:Xn([pi.sprite,pi.fog]),vertexShader:di.sprite_vert,fragmentShader:di.sprite_frag},background:{uniforms:{uvTransform:{value:new yt},t2D:{value:null}},vertexShader:di.background_vert,fragmentShader:di.background_frag},cube:{uniforms:Xn([pi.envmap,{opacity:{value:1}}]),vertexShader:di.cube_vert,fragmentShader:di.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:di.equirect_vert,fragmentShader:di.equirect_frag},distanceRGBA:{uniforms:Xn([pi.common,pi.displacementmap,{referencePosition:{value:new Nt},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:di.distanceRGBA_vert,fragmentShader:di.distanceRGBA_frag},shadow:{uniforms:Xn([pi.lights,pi.fog,{color:{value:new nn(0)},opacity:{value:1}}]),vertexShader:di.shadow_vert,fragmentShader:di.shadow_frag}};function fi(t,e,n,i,r){const s=new nn(0);let a,o,c=0,h=null,u=0,d=null;function p(t,e){n.buffers.color.setClear(t.r,t.g,t.b,e,r)}return{getClearColor:function(){return s},setClearColor:function(t,e=1){s.set(t),c=e,p(s,c)},getClearAlpha:function(){return c},setClearAlpha:function(t){c=t,p(s,c)},render:function(n,r){let m=!1,f=!0===r.isScene?r.background:null;f&&f.isTexture&&(f=e.get(f));const g=t.xr,v=g.getSession&&g.getSession();v&&"additive"===v.environmentBlendMode&&(f=null),null===f?p(s,c):f&&f.isColor&&(p(f,1),m=!0),(t.autoClear||m)&&t.clear(t.autoClearColor,t.autoClearDepth,t.autoClearStencil),f&&(f.isCubeTexture||f.mapping===l)?(void 0===o&&(o=new Vn(new jn(1,1,1),new Yn({name:"BackgroundCubeMaterial",uniforms:qn(mi.cube.uniforms),vertexShader:mi.cube.vertexShader,fragmentShader:mi.cube.fragmentShader,side:1,depthTest:!1,depthWrite:!1,fog:!1})),o.geometry.deleteAttribute("normal"),o.geometry.deleteAttribute("uv"),o.onBeforeRender=function(t,e,n){this.matrixWorld.copyPosition(n.matrixWorld)},Object.defineProperty(o.material,"envMap",{get:function(){return this.uniforms.envMap.value}}),i.update(o)),o.material.uniforms.envMap.value=f,o.material.uniforms.flipEnvMap.value=f.isCubeTexture&&!1===f.isRenderTargetTexture?-1:1,h===f&&u===f.version&&d===t.toneMapping||(o.material.needsUpdate=!0,h=f,u=f.version,d=t.toneMapping),n.unshift(o,o.geometry,o.material,0,0,null)):f&&f.isTexture&&(void 0===a&&(a=new Vn(new ui(2,2),new Yn({name:"BackgroundMaterial",uniforms:qn(mi.background.uniforms),vertexShader:mi.background.vertexShader,fragmentShader:mi.background.fragmentShader,side:0,depthTest:!1,depthWrite:!1,fog:!1})),a.geometry.deleteAttribute("normal"),Object.defineProperty(a.material,"map",{get:function(){return this.uniforms.t2D.value}}),i.update(a)),a.material.uniforms.t2D.value=f,!0===f.matrixAutoUpdate&&f.updateMatrix(),a.material.uniforms.uvTransform.value.copy(f.matrix),h===f&&u===f.version&&d===t.toneMapping||(a.material.needsUpdate=!0,h=f,u=f.version,d=t.toneMapping),n.unshift(a,a.geometry,a.material,0,0,null))}}}function gi(t,e,n,i){const r=t.getParameter(34921),s=i.isWebGL2?null:e.get("OES_vertex_array_object"),a=i.isWebGL2||null!==s,o={},l=d(null);let c=l;function h(e){return i.isWebGL2?t.bindVertexArray(e):s.bindVertexArrayOES(e)}function u(e){return i.isWebGL2?t.deleteVertexArray(e):s.deleteVertexArrayOES(e)}function d(t){const e=[],n=[],i=[];for(let t=0;t=0){let s=l[e];if(void 0===s&&("instanceMatrix"===e&&r.instanceMatrix&&(s=r.instanceMatrix),"instanceColor"===e&&r.instanceColor&&(s=r.instanceColor)),void 0!==s){const e=s.normalized,a=s.itemSize,l=n.get(s);if(void 0===l)continue;const c=l.buffer,h=l.type,u=l.bytesPerElement;if(s.isInterleavedBufferAttribute){const n=s.data,l=n.stride,d=s.offset;if(n&&n.isInstancedInterleavedBuffer){for(let t=0;t0&&t.getShaderPrecisionFormat(35632,36338).precision>0)return"highp";e="mediump"}return"mediump"===e&&t.getShaderPrecisionFormat(35633,36337).precision>0&&t.getShaderPrecisionFormat(35632,36337).precision>0?"mediump":"lowp"}const s="undefined"!=typeof WebGL2RenderingContext&&t instanceof WebGL2RenderingContext||"undefined"!=typeof WebGL2ComputeRenderingContext&&t instanceof WebGL2ComputeRenderingContext;let a=void 0!==n.precision?n.precision:"highp";const o=r(a);o!==a&&(console.warn("THREE.WebGLRenderer:",a,"not supported, using",o,"instead."),a=o);const l=s||e.has("WEBGL_draw_buffers"),c=!0===n.logarithmicDepthBuffer,h=t.getParameter(34930),u=t.getParameter(35660),d=t.getParameter(3379),p=t.getParameter(34076),m=t.getParameter(34921),f=t.getParameter(36347),g=t.getParameter(36348),v=t.getParameter(36349),y=u>0,x=s||e.has("OES_texture_float");return{isWebGL2:s,drawBuffers:l,getMaxAnisotropy:function(){if(void 0!==i)return i;if(!0===e.has("EXT_texture_filter_anisotropic")){const n=e.get("EXT_texture_filter_anisotropic");i=t.getParameter(n.MAX_TEXTURE_MAX_ANISOTROPY_EXT)}else i=0;return i},getMaxPrecision:r,precision:a,logarithmicDepthBuffer:c,maxTextures:h,maxVertexTextures:u,maxTextureSize:d,maxCubemapSize:p,maxAttributes:m,maxVertexUniforms:f,maxVaryings:g,maxFragmentUniforms:v,vertexTextures:y,floatFragmentTextures:x,floatVertexTextures:y&&x,maxSamples:s?t.getParameter(36183):0}}function xi(t){const e=this;let n=null,i=0,r=!1,s=!1;const a=new si,o=new yt,l={value:null,needsUpdate:!1};function c(){l.value!==n&&(l.value=n,l.needsUpdate=i>0),e.numPlanes=i,e.numIntersection=0}function h(t,n,i,r){const s=null!==t?t.length:0;let c=null;if(0!==s){if(c=l.value,!0!==r||null===c){const e=i+4*s,r=n.matrixWorldInverse;o.getNormalMatrix(r),(null===c||c.length0){const a=t.getRenderTarget(),o=new ei(s.height/2);return o.fromEquirectangularTexture(t,r),e.set(r,o),t.setRenderTarget(a),r.addEventListener("dispose",i),n(o.texture,r.mapping)}return null}}}return r},dispose:function(){e=new WeakMap}}}mi.physical={uniforms:Xn([mi.standard.uniforms,{clearcoat:{value:0},clearcoatMap:{value:null},clearcoatRoughness:{value:0},clearcoatRoughnessMap:{value:null},clearcoatNormalScale:{value:new vt(1,1)},clearcoatNormalMap:{value:null},sheen:{value:0},sheenColor:{value:new nn(0)},sheenColorMap:{value:null},sheenRoughness:{value:0},sheenRoughnessMap:{value:null},transmission:{value:0},transmissionMap:{value:null},transmissionSamplerSize:{value:new vt},transmissionSamplerMap:{value:null},thickness:{value:0},thicknessMap:{value:null},attenuationDistance:{value:0},attenuationColor:{value:new nn(0)},specularIntensity:{value:0},specularIntensityMap:{value:null},specularColor:{value:new nn(1,1,1)},specularColorMap:{value:null}}]),vertexShader:di.meshphysical_vert,fragmentShader:di.meshphysical_frag};class Mi extends Zn{constructor(t=-1,e=1,n=1,i=-1,r=.1,s=2e3){super(),this.type="OrthographicCamera",this.zoom=1,this.view=null,this.left=t,this.right=e,this.top=n,this.bottom=i,this.near=r,this.far=s,this.updateProjectionMatrix()}copy(t,e){return super.copy(t,e),this.left=t.left,this.right=t.right,this.top=t.top,this.bottom=t.bottom,this.near=t.near,this.far=t.far,this.zoom=t.zoom,this.view=null===t.view?null:Object.assign({},t.view),this}setViewOffset(t,e,n,i,r,s){null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=t,this.view.fullHeight=e,this.view.offsetX=n,this.view.offsetY=i,this.view.width=r,this.view.height=s,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const t=(this.right-this.left)/(2*this.zoom),e=(this.top-this.bottom)/(2*this.zoom),n=(this.right+this.left)/2,i=(this.top+this.bottom)/2;let r=n-t,s=n+t,a=i+e,o=i-e;if(null!==this.view&&this.view.enabled){const t=(this.right-this.left)/this.view.fullWidth/this.zoom,e=(this.top-this.bottom)/this.view.fullHeight/this.zoom;r+=t*this.view.offsetX,s=r+t*this.view.width,a-=e*this.view.offsetY,o=a-e*this.view.height}this.projectionMatrix.makeOrthographic(r,s,a,o,this.near,this.far),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(t){const e=super.toJSON(t);return e.object.zoom=this.zoom,e.object.left=this.left,e.object.right=this.right,e.object.top=this.top,e.object.bottom=this.bottom,e.object.near=this.near,e.object.far=this.far,null!==this.view&&(e.object.view=Object.assign({},this.view)),e}}Mi.prototype.isOrthographicCamera=!0;class bi extends Yn{constructor(t){super(t),this.type="RawShaderMaterial"}}bi.prototype.isRawShaderMaterial=!0;const wi=Math.pow(2,8),Si=[.125,.215,.35,.446,.526,.582],Ti=5+Si.length,Ei=20,Ai={[X]:0,[J]:1,[Z]:2,[Q]:3,[K]:4,[$]:5,[Y]:6},Li=new Mi,{_lodPlanes:Ri,_sizeLods:Ci,_sigmas:Pi}=Ui(),Di=new nn;let Ii=null;const Ni=(1+Math.sqrt(5))/2,zi=1/Ni,Bi=[new Nt(1,1,1),new Nt(-1,1,1),new Nt(1,1,-1),new Nt(-1,1,-1),new Nt(0,Ni,zi),new Nt(0,Ni,-zi),new Nt(zi,0,Ni),new Nt(-zi,0,Ni),new Nt(Ni,zi,0),new Nt(-Ni,zi,0)];class Fi{constructor(t){this._renderer=t,this._pingPongRenderTarget=null,this._blurMaterial=function(t){const e=new Float32Array(t),n=new Nt(0,1,0);return new bi({name:"SphericalGaussianBlur",defines:{n:t},uniforms:{envMap:{value:null},samples:{value:1},weights:{value:e},latitudinal:{value:!1},dTheta:{value:0},mipInt:{value:0},poleAxis:{value:n},inputEncoding:{value:Ai[3e3]},outputEncoding:{value:Ai[3e3]}},vertexShader:Wi(),fragmentShader:`\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\t\t\tuniform int samples;\n\t\t\tuniform float weights[ n ];\n\t\t\tuniform bool latitudinal;\n\t\t\tuniform float dTheta;\n\t\t\tuniform float mipInt;\n\t\t\tuniform vec3 poleAxis;\n\n\t\t\t${ji()}\n\n\t\t\t#define ENVMAP_TYPE_CUBE_UV\n\t\t\t#include \n\n\t\t\tvec3 getSample( float theta, vec3 axis ) {\n\n\t\t\t\tfloat cosTheta = cos( theta );\n\t\t\t\t// Rodrigues' axis-angle rotation\n\t\t\t\tvec3 sampleDirection = vOutputDirection * cosTheta\n\t\t\t\t\t+ cross( axis, vOutputDirection ) * sin( theta )\n\t\t\t\t\t+ axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta );\n\n\t\t\t\treturn bilinearCubeUV( envMap, sampleDirection, mipInt );\n\n\t\t\t}\n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection );\n\n\t\t\t\tif ( all( equal( axis, vec3( 0.0 ) ) ) ) {\n\n\t\t\t\t\taxis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x );\n\n\t\t\t\t}\n\n\t\t\t\taxis = normalize( axis );\n\n\t\t\t\tgl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t\t\t\tgl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis );\n\n\t\t\t\tfor ( int i = 1; i < n; i++ ) {\n\n\t\t\t\t\tif ( i >= samples ) {\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tfloat theta = dTheta * float( i );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( theta, axis );\n\n\t\t\t\t}\n\n\t\t\t\tgl_FragColor = linearToOutputTexel( gl_FragColor );\n\n\t\t\t}\n\t\t`,blending:0,depthTest:!1,depthWrite:!1})}(Ei),this._equirectShader=null,this._cubemapShader=null,this._compileMaterial(this._blurMaterial)}fromScene(t,e=0,n=.1,i=100){Ii=this._renderer.getRenderTarget();const r=this._allocateTargets();return this._sceneToCubeUV(t,n,i,r),e>0&&this._blur(r,0,0,e),this._applyPMREM(r),this._cleanup(r),r}fromEquirectangular(t){return this._fromTexture(t)}fromCubemap(t){return this._fromTexture(t)}compileCubemapShader(){null===this._cubemapShader&&(this._cubemapShader=Vi(),this._compileMaterial(this._cubemapShader))}compileEquirectangularShader(){null===this._equirectShader&&(this._equirectShader=ki(),this._compileMaterial(this._equirectShader))}dispose(){this._blurMaterial.dispose(),null!==this._cubemapShader&&this._cubemapShader.dispose(),null!==this._equirectShader&&this._equirectShader.dispose();for(let t=0;t2?wi:0,wi,wi),o.setRenderTarget(i),p&&o.render(d,r),o.render(t,r)}d.geometry.dispose(),d.material.dispose(),o.toneMapping=h,o.outputEncoding=c,o.autoClear=l,t.background=m}_setEncoding(t,e){!0===this._renderer.capabilities.isWebGL2&&e.format===E&&e.type===x&&e.encoding===J?t.value=Ai[3e3]:t.value=Ai[e.encoding]}_textureToCubeUV(t,e){const n=this._renderer,i=t.mapping===r||t.mapping===s;i?null==this._cubemapShader&&(this._cubemapShader=Vi()):null==this._equirectShader&&(this._equirectShader=ki());const a=i?this._cubemapShader:this._equirectShader,o=new Vn(Ri[0],a),l=a.uniforms;l.envMap.value=t,i||l.texelSize.value.set(1/t.image.width,1/t.image.height),this._setEncoding(l.inputEncoding,t),this._setEncoding(l.outputEncoding,e.texture),Gi(e,0,0,3*wi,2*wi),n.setRenderTarget(e),n.render(o,Li)}_applyPMREM(t){const e=this._renderer,n=e.autoClear;e.autoClear=!1;for(let e=1;eEi&&console.warn(`sigmaRadians, ${r}, is too large and will clip, as it requested ${m} samples when the maximum is set to 20`);const f=[];let g=0;for(let t=0;t4?i-8+4:0),3*v,2*v),o.setRenderTarget(e),o.render(c,Li)}}function Oi(t){return void 0!==t&&t.type===x&&(t.encoding===X||t.encoding===J||t.encoding===Y)}function Ui(){const t=[],e=[],n=[];let i=8;for(let r=0;r4?a=Si[r-8+4-1]:0==r&&(a=0),n.push(a);const o=1/(s-1),l=-o/2,c=1+o/2,h=[l,l,c,l,c,c,l,l,c,c,l,c],u=6,d=6,p=3,m=2,f=1,g=new Float32Array(p*d*u),v=new Float32Array(m*d*u),y=new Float32Array(f*d*u);for(let t=0;t2?0:-1,i=[e,n,0,e+2/3,n,0,e+2/3,n+1,0,e,n,0,e+2/3,n+1,0,e,n+1,0];g.set(i,p*d*t),v.set(h,m*d*t);const r=[t,t,t,t,t,t];y.set(r,f*d*t)}const x=new Tn;x.setAttribute("position",new on(g,p)),x.setAttribute("uv",new on(v,m)),x.setAttribute("faceIndex",new on(y,f)),t.push(x),i>4&&i--}return{_lodPlanes:t,_sizeLods:e,_sigmas:n}}function Hi(t){const e=new Ct(3*wi,3*wi,t);return e.texture.mapping=l,e.texture.name="PMREM.cubeUv",e.scissorTest=!0,e}function Gi(t,e,n,i,r){t.viewport.set(e,n,i,r),t.scissor.set(e,n,i,r)}function ki(){const t=new vt(1,1);return new bi({name:"EquirectangularToCubeUV",uniforms:{envMap:{value:null},texelSize:{value:t},inputEncoding:{value:Ai[3e3]},outputEncoding:{value:Ai[3e3]}},vertexShader:Wi(),fragmentShader:`\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\t\t\tuniform vec2 texelSize;\n\n\t\t\t${ji()}\n\n\t\t\t#include \n\n\t\t\tvoid main() {\n\n\t\t\t\tgl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\n\t\t\t\tvec3 outputDirection = normalize( vOutputDirection );\n\t\t\t\tvec2 uv = equirectUv( outputDirection );\n\n\t\t\t\tvec2 f = fract( uv / texelSize - 0.5 );\n\t\t\t\tuv -= f * texelSize;\n\t\t\t\tvec3 tl = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;\n\t\t\t\tuv.x += texelSize.x;\n\t\t\t\tvec3 tr = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;\n\t\t\t\tuv.y += texelSize.y;\n\t\t\t\tvec3 br = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;\n\t\t\t\tuv.x -= texelSize.x;\n\t\t\t\tvec3 bl = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;\n\n\t\t\t\tvec3 tm = mix( tl, tr, f.x );\n\t\t\t\tvec3 bm = mix( bl, br, f.x );\n\t\t\t\tgl_FragColor.rgb = mix( tm, bm, f.y );\n\n\t\t\t\tgl_FragColor = linearToOutputTexel( gl_FragColor );\n\n\t\t\t}\n\t\t`,blending:0,depthTest:!1,depthWrite:!1})}function Vi(){return new bi({name:"CubemapToCubeUV",uniforms:{envMap:{value:null},inputEncoding:{value:Ai[3e3]},outputEncoding:{value:Ai[3e3]}},vertexShader:Wi(),fragmentShader:`\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform samplerCube envMap;\n\n\t\t\t${ji()}\n\n\t\t\tvoid main() {\n\n\t\t\t\tgl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t\t\t\tgl_FragColor.rgb = envMapTexelToLinear( textureCube( envMap, vec3( - vOutputDirection.x, vOutputDirection.yz ) ) ).rgb;\n\t\t\t\tgl_FragColor = linearToOutputTexel( gl_FragColor );\n\n\t\t\t}\n\t\t`,blending:0,depthTest:!1,depthWrite:!1})}function Wi(){return"\n\n\t\tprecision mediump float;\n\t\tprecision mediump int;\n\n\t\tattribute vec3 position;\n\t\tattribute vec2 uv;\n\t\tattribute float faceIndex;\n\n\t\tvarying vec3 vOutputDirection;\n\n\t\t// RH coordinate system; PMREM face-indexing convention\n\t\tvec3 getDirection( vec2 uv, float face ) {\n\n\t\t\tuv = 2.0 * uv - 1.0;\n\n\t\t\tvec3 direction = vec3( uv, 1.0 );\n\n\t\t\tif ( face == 0.0 ) {\n\n\t\t\t\tdirection = direction.zyx; // ( 1, v, u ) pos x\n\n\t\t\t} else if ( face == 1.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xz *= -1.0; // ( -u, 1, -v ) pos y\n\n\t\t\t} else if ( face == 2.0 ) {\n\n\t\t\t\tdirection.x *= -1.0; // ( -u, v, 1 ) pos z\n\n\t\t\t} else if ( face == 3.0 ) {\n\n\t\t\t\tdirection = direction.zyx;\n\t\t\t\tdirection.xz *= -1.0; // ( -1, v, -u ) neg x\n\n\t\t\t} else if ( face == 4.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xy *= -1.0; // ( -u, -1, v ) neg y\n\n\t\t\t} else if ( face == 5.0 ) {\n\n\t\t\t\tdirection.z *= -1.0; // ( u, v, -1 ) neg z\n\n\t\t\t}\n\n\t\t\treturn direction;\n\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\tvOutputDirection = getDirection( uv, faceIndex );\n\t\t\tgl_Position = vec4( position, 1.0 );\n\n\t\t}\n\t"}function ji(){return"\n\n\t\tuniform int inputEncoding;\n\t\tuniform int outputEncoding;\n\n\t\t#include \n\n\t\tvec4 inputTexelToLinear( vec4 value ) {\n\n\t\t\tif ( inputEncoding == 0 ) {\n\n\t\t\t\treturn value;\n\n\t\t\t} else if ( inputEncoding == 1 ) {\n\n\t\t\t\treturn sRGBToLinear( value );\n\n\t\t\t} else if ( inputEncoding == 2 ) {\n\n\t\t\t\treturn RGBEToLinear( value );\n\n\t\t\t} else if ( inputEncoding == 3 ) {\n\n\t\t\t\treturn RGBMToLinear( value, 7.0 );\n\n\t\t\t} else if ( inputEncoding == 4 ) {\n\n\t\t\t\treturn RGBMToLinear( value, 16.0 );\n\n\t\t\t} else if ( inputEncoding == 5 ) {\n\n\t\t\t\treturn RGBDToLinear( value, 256.0 );\n\n\t\t\t} else {\n\n\t\t\t\treturn GammaToLinear( value, 2.2 );\n\n\t\t\t}\n\n\t\t}\n\n\t\tvec4 linearToOutputTexel( vec4 value ) {\n\n\t\t\tif ( outputEncoding == 0 ) {\n\n\t\t\t\treturn value;\n\n\t\t\t} else if ( outputEncoding == 1 ) {\n\n\t\t\t\treturn LinearTosRGB( value );\n\n\t\t\t} else if ( outputEncoding == 2 ) {\n\n\t\t\t\treturn LinearToRGBE( value );\n\n\t\t\t} else if ( outputEncoding == 3 ) {\n\n\t\t\t\treturn LinearToRGBM( value, 7.0 );\n\n\t\t\t} else if ( outputEncoding == 4 ) {\n\n\t\t\t\treturn LinearToRGBM( value, 16.0 );\n\n\t\t\t} else if ( outputEncoding == 5 ) {\n\n\t\t\t\treturn LinearToRGBD( value, 256.0 );\n\n\t\t\t} else {\n\n\t\t\t\treturn LinearToGamma( value, 2.2 );\n\n\t\t\t}\n\n\t\t}\n\n\t\tvec4 envMapTexelToLinear( vec4 color ) {\n\n\t\t\treturn inputTexelToLinear( color );\n\n\t\t}\n\t"}function qi(t){let e=new WeakMap,n=null;function i(t){const n=t.target;n.removeEventListener("dispose",i);const r=e.get(n);void 0!==r&&(e.delete(n),r.dispose())}return{get:function(l){if(l&&l.isTexture&&!1===l.isRenderTargetTexture){const c=l.mapping,h=c===a||c===o,u=c===r||c===s;if(h||u){if(e.has(l))return e.get(l).texture;{const r=l.image;if(h&&r&&r.height>0||u&&r&&function(t){let e=0;const n=6;for(let i=0;i65535?mn:dn)(n,1);o.version=a;const l=s.get(t);l&&e.remove(l),s.set(t,o)}return{get:function(t,e){return!0===r[e.id]||(e.addEventListener("dispose",a),r[e.id]=!0,n.memory.geometries++),e},update:function(t){const n=t.attributes;for(const t in n)e.update(n[t],34962);const i=t.morphAttributes;for(const t in i){const n=i[t];for(let t=0,i=n.length;te.maxTextureSize&&(u=Math.ceil(h/e.maxTextureSize),h=e.maxTextureSize);const d=new Float32Array(h*u*4*i),p=new Qi(d,h,u,i);p.format=E,p.type=b,p.needsUpdate=!0;const m=4*l;for(let e=0;e0)return t;const r=e*n;let s=lr[r];if(void 0===s&&(s=new Float32Array(r),lr[r]=s),0!==e){i.toArray(s,0);for(let i=1,r=0;i!==e;++i)r+=n,t[i].toArray(s,r)}return s}function mr(t,e){if(t.length!==e.length)return!1;for(let n=0,i=t.length;n/gm;function xs(t){return t.replace(ys,_s)}function _s(t,e){const n=di[e];if(void 0===n)throw new Error("Can not resolve #include <"+e+">");return xs(n)}const Ms=/#pragma unroll_loop[\s]+?for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g,bs=/#pragma unroll_loop_start\s+for\s*\(\s*int\s+i\s*=\s*(\d+)\s*;\s*i\s*<\s*(\d+)\s*;\s*i\s*\+\+\s*\)\s*{([\s\S]+?)}\s+#pragma unroll_loop_end/g;function ws(t){return t.replace(bs,Ts).replace(Ms,Ss)}function Ss(t,e,n,i){return console.warn("WebGLProgram: #pragma unroll_loop shader syntax is deprecated. Please use #pragma unroll_loop_start syntax instead."),Ts(t,e,n,i)}function Ts(t,e,n,i){let r="";for(let t=parseInt(e);t0?t.gammaFactor:1,v=n.isWebGL2?"":function(t){return[t.extensionDerivatives||t.envMapCubeUV||t.bumpMap||t.tangentSpaceNormalMap||t.clearcoatNormalMap||t.flatShading||"physical"===t.shaderID?"#extension GL_OES_standard_derivatives : enable":"",(t.extensionFragDepth||t.logarithmicDepthBuffer)&&t.rendererExtensionFragDepth?"#extension GL_EXT_frag_depth : enable":"",t.extensionDrawBuffers&&t.rendererExtensionDrawBuffers?"#extension GL_EXT_draw_buffers : require":"",(t.extensionShaderTextureLOD||t.envMap||t.transmission)&&t.rendererExtensionShaderTextureLod?"#extension GL_EXT_shader_texture_lod : enable":""].filter(fs).join("\n")}(n),y=function(t){const e=[];for(const n in t){const i=t[n];!1!==i&&e.push("#define "+n+" "+i)}return e.join("\n")}(o),x=a.createProgram();let _,M,b=n.glslVersion?"#version "+n.glslVersion+"\n":"";n.isRawShaderMaterial?(_=[y].filter(fs).join("\n"),_.length>0&&(_+="\n"),M=[v,y].filter(fs).join("\n"),M.length>0&&(M+="\n")):(_=[Es(n),"#define SHADER_NAME "+n.shaderName,y,n.instancing?"#define USE_INSTANCING":"",n.instancingColor?"#define USE_INSTANCING_COLOR":"",n.supportsVertexTextures?"#define VERTEX_TEXTURES":"","#define GAMMA_FACTOR "+g,"#define MAX_BONES "+n.maxBones,n.useFog&&n.fog?"#define USE_FOG":"",n.useFog&&n.fogExp2?"#define FOG_EXP2":"",n.map?"#define USE_MAP":"",n.envMap?"#define USE_ENVMAP":"",n.envMap?"#define "+m:"",n.lightMap?"#define USE_LIGHTMAP":"",n.aoMap?"#define USE_AOMAP":"",n.emissiveMap?"#define USE_EMISSIVEMAP":"",n.bumpMap?"#define USE_BUMPMAP":"",n.normalMap?"#define USE_NORMALMAP":"",n.normalMap&&n.objectSpaceNormalMap?"#define OBJECTSPACE_NORMALMAP":"",n.normalMap&&n.tangentSpaceNormalMap?"#define TANGENTSPACE_NORMALMAP":"",n.clearcoatMap?"#define USE_CLEARCOATMAP":"",n.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",n.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",n.displacementMap&&n.supportsVertexTextures?"#define USE_DISPLACEMENTMAP":"",n.specularMap?"#define USE_SPECULARMAP":"",n.specularIntensityMap?"#define USE_SPECULARINTENSITYMAP":"",n.specularColorMap?"#define USE_SPECULARCOLORMAP":"",n.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.transmission?"#define USE_TRANSMISSION":"",n.transmissionMap?"#define USE_TRANSMISSIONMAP":"",n.thicknessMap?"#define USE_THICKNESSMAP":"",n.sheenColorMap?"#define USE_SHEENCOLORMAP":"",n.sheenRoughnessMap?"#define USE_SHEENROUGHNESSMAP":"",n.vertexTangents?"#define USE_TANGENT":"",n.vertexColors?"#define USE_COLOR":"",n.vertexAlphas?"#define USE_COLOR_ALPHA":"",n.vertexUvs?"#define USE_UV":"",n.uvsVertexOnly?"#define UVS_VERTEX_ONLY":"",n.flatShading?"#define FLAT_SHADED":"",n.skinning?"#define USE_SKINNING":"",n.useVertexTexture?"#define BONE_TEXTURE":"",n.morphTargets?"#define USE_MORPHTARGETS":"",n.morphNormals&&!1===n.flatShading?"#define USE_MORPHNORMALS":"",n.morphTargets&&n.isWebGL2?"#define MORPHTARGETS_TEXTURE":"",n.morphTargets&&n.isWebGL2?"#define MORPHTARGETS_COUNT "+n.morphTargetsCount:"",n.doubleSided?"#define DOUBLE_SIDED":"",n.flipSided?"#define FLIP_SIDED":"",n.shadowMapEnabled?"#define USE_SHADOWMAP":"",n.shadowMapEnabled?"#define "+d:"",n.sizeAttenuation?"#define USE_SIZEATTENUATION":"",n.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",n.logarithmicDepthBuffer&&n.rendererExtensionFragDepth?"#define USE_LOGDEPTHBUF_EXT":"","uniform mat4 modelMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;","#ifdef USE_INSTANCING","\tattribute mat4 instanceMatrix;","#endif","#ifdef USE_INSTANCING_COLOR","\tattribute vec3 instanceColor;","#endif","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#ifdef USE_TANGENT","\tattribute vec4 tangent;","#endif","#if defined( USE_COLOR_ALPHA )","\tattribute vec4 color;","#elif defined( USE_COLOR )","\tattribute vec3 color;","#endif","#if ( defined( USE_MORPHTARGETS ) && ! defined( MORPHTARGETS_TEXTURE ) )","\tattribute vec3 morphTarget0;","\tattribute vec3 morphTarget1;","\tattribute vec3 morphTarget2;","\tattribute vec3 morphTarget3;","\t#ifdef USE_MORPHNORMALS","\t\tattribute vec3 morphNormal0;","\t\tattribute vec3 morphNormal1;","\t\tattribute vec3 morphNormal2;","\t\tattribute vec3 morphNormal3;","\t#else","\t\tattribute vec3 morphTarget4;","\t\tattribute vec3 morphTarget5;","\t\tattribute vec3 morphTarget6;","\t\tattribute vec3 morphTarget7;","\t#endif","#endif","#ifdef USE_SKINNING","\tattribute vec4 skinIndex;","\tattribute vec4 skinWeight;","#endif","\n"].filter(fs).join("\n"),M=[v,Es(n),"#define SHADER_NAME "+n.shaderName,y,"#define GAMMA_FACTOR "+g,n.useFog&&n.fog?"#define USE_FOG":"",n.useFog&&n.fogExp2?"#define FOG_EXP2":"",n.map?"#define USE_MAP":"",n.matcap?"#define USE_MATCAP":"",n.envMap?"#define USE_ENVMAP":"",n.envMap?"#define "+p:"",n.envMap?"#define "+m:"",n.envMap?"#define "+f:"",n.lightMap?"#define USE_LIGHTMAP":"",n.aoMap?"#define USE_AOMAP":"",n.emissiveMap?"#define USE_EMISSIVEMAP":"",n.bumpMap?"#define USE_BUMPMAP":"",n.normalMap?"#define USE_NORMALMAP":"",n.normalMap&&n.objectSpaceNormalMap?"#define OBJECTSPACE_NORMALMAP":"",n.normalMap&&n.tangentSpaceNormalMap?"#define TANGENTSPACE_NORMALMAP":"",n.clearcoat?"#define USE_CLEARCOAT":"",n.clearcoatMap?"#define USE_CLEARCOATMAP":"",n.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",n.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",n.specularMap?"#define USE_SPECULARMAP":"",n.specularIntensityMap?"#define USE_SPECULARINTENSITYMAP":"",n.specularColorMap?"#define USE_SPECULARCOLORMAP":"",n.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.alphaTest?"#define USE_ALPHATEST":"",n.sheen?"#define USE_SHEEN":"",n.sheenColorMap?"#define USE_SHEENCOLORMAP":"",n.sheenRoughnessMap?"#define USE_SHEENROUGHNESSMAP":"",n.transmission?"#define USE_TRANSMISSION":"",n.transmissionMap?"#define USE_TRANSMISSIONMAP":"",n.thicknessMap?"#define USE_THICKNESSMAP":"",n.vertexTangents?"#define USE_TANGENT":"",n.vertexColors||n.instancingColor?"#define USE_COLOR":"",n.vertexAlphas?"#define USE_COLOR_ALPHA":"",n.vertexUvs?"#define USE_UV":"",n.uvsVertexOnly?"#define UVS_VERTEX_ONLY":"",n.gradientMap?"#define USE_GRADIENTMAP":"",n.flatShading?"#define FLAT_SHADED":"",n.doubleSided?"#define DOUBLE_SIDED":"",n.flipSided?"#define FLIP_SIDED":"",n.shadowMapEnabled?"#define USE_SHADOWMAP":"",n.shadowMapEnabled?"#define "+d:"",n.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",n.physicallyCorrectLights?"#define PHYSICALLY_CORRECT_LIGHTS":"",n.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",n.logarithmicDepthBuffer&&n.rendererExtensionFragDepth?"#define USE_LOGDEPTHBUF_EXT":"",(n.extensionShaderTextureLOD||n.envMap)&&n.rendererExtensionShaderTextureLod?"#define TEXTURE_LOD_EXT":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;",0!==n.toneMapping?"#define TONE_MAPPING":"",0!==n.toneMapping?di.tonemapping_pars_fragment:"",0!==n.toneMapping?ms("toneMapping",n.toneMapping):"",n.dithering?"#define DITHERING":"",n.format===T?"#define OPAQUE":"",di.encodings_pars_fragment,n.map?ds("mapTexelToLinear",n.mapEncoding):"",n.matcap?ds("matcapTexelToLinear",n.matcapEncoding):"",n.envMap?ds("envMapTexelToLinear",n.envMapEncoding):"",n.emissiveMap?ds("emissiveMapTexelToLinear",n.emissiveMapEncoding):"",n.specularColorMap?ds("specularColorMapTexelToLinear",n.specularColorMapEncoding):"",n.sheenColorMap?ds("sheenColorMapTexelToLinear",n.sheenColorMapEncoding):"",n.lightMap?ds("lightMapTexelToLinear",n.lightMapEncoding):"",ps("linearToOutputTexel",n.outputEncoding),n.depthPacking?"#define DEPTH_PACKING "+n.depthPacking:"","\n"].filter(fs).join("\n")),h=xs(h),h=gs(h,n),h=vs(h,n),u=xs(u),u=gs(u,n),u=vs(u,n),h=ws(h),u=ws(u),n.isWebGL2&&!0!==n.isRawShaderMaterial&&(b="#version 300 es\n",_=["precision mediump sampler2DArray;","#define attribute in","#define varying out","#define texture2D texture"].join("\n")+"\n"+_,M=["#define varying in",n.glslVersion===it?"":"layout(location = 0) out highp vec4 pc_fragColor;",n.glslVersion===it?"":"#define gl_FragColor pc_fragColor","#define gl_FragDepthEXT gl_FragDepth","#define texture2D texture","#define textureCube texture","#define texture2DProj textureProj","#define texture2DLodEXT textureLod","#define texture2DProjLodEXT textureProjLod","#define textureCubeLodEXT textureLod","#define texture2DGradEXT textureGrad","#define texture2DProjGradEXT textureProjGrad","#define textureCubeGradEXT textureGrad"].join("\n")+"\n"+M);const w=b+M+u,S=ls(a,35633,b+_+h),E=ls(a,35632,w);if(a.attachShader(x,S),a.attachShader(x,E),void 0!==n.index0AttributeName?a.bindAttribLocation(x,0,n.index0AttributeName):!0===n.morphTargets&&a.bindAttribLocation(x,0,"position"),a.linkProgram(x),t.debug.checkShaderErrors){const t=a.getProgramInfoLog(x).trim(),e=a.getShaderInfoLog(S).trim(),n=a.getShaderInfoLog(E).trim();let i=!0,r=!0;if(!1===a.getProgramParameter(x,35714)){i=!1;const e=us(a,S,"vertex"),n=us(a,E,"fragment");console.error("THREE.WebGLProgram: Shader Error "+a.getError()+" - VALIDATE_STATUS "+a.getProgramParameter(x,35715)+"\n\nProgram Info Log: "+t+"\n"+e+"\n"+n)}else""!==t?console.warn("THREE.WebGLProgram: Program Info Log:",t):""!==e&&""!==n||(r=!1);r&&(this.diagnostics={runnable:i,programLog:t,vertexShader:{log:e,prefix:_},fragmentShader:{log:n,prefix:M}})}let A,L;return a.deleteShader(S),a.deleteShader(E),this.getUniforms=function(){return void 0===A&&(A=new os(a,x)),A},this.getAttributes=function(){return void 0===L&&(L=function(t,e){const n={},i=t.getProgramParameter(e,35721);for(let r=0;r0,C=s.clearcoat>0;return{isWebGL2:u,shaderID:S,shaderName:s.type,vertexShader:E,fragmentShader:A,defines:s.defines,isRawShaderMaterial:!0===s.isRawShaderMaterial,glslVersion:s.glslVersion,precision:g,instancing:!0===_.isInstancedMesh,instancingColor:!0===_.isInstancedMesh&&null!==_.instanceColor,supportsVertexTextures:f,outputEncoding:null!==L?y(L.texture):t.outputEncoding,map:!!s.map,mapEncoding:y(s.map),matcap:!!s.matcap,matcapEncoding:y(s.matcap),envMap:!!w,envMapMode:w&&w.mapping,envMapEncoding:y(w),envMapCubeUV:!!w&&(w.mapping===l||w.mapping===c),lightMap:!!s.lightMap,lightMapEncoding:y(s.lightMap),aoMap:!!s.aoMap,emissiveMap:!!s.emissiveMap,emissiveMapEncoding:y(s.emissiveMap),bumpMap:!!s.bumpMap,normalMap:!!s.normalMap,objectSpaceNormalMap:1===s.normalMapType,tangentSpaceNormalMap:0===s.normalMapType,clearcoat:C,clearcoatMap:C&&!!s.clearcoatMap,clearcoatRoughnessMap:C&&!!s.clearcoatRoughnessMap,clearcoatNormalMap:C&&!!s.clearcoatNormalMap,displacementMap:!!s.displacementMap,roughnessMap:!!s.roughnessMap,metalnessMap:!!s.metalnessMap,specularMap:!!s.specularMap,specularIntensityMap:!!s.specularIntensityMap,specularColorMap:!!s.specularColorMap,specularColorMapEncoding:y(s.specularColorMap),alphaMap:!!s.alphaMap,alphaTest:R,gradientMap:!!s.gradientMap,sheen:s.sheen>0,sheenColorMap:!!s.sheenColorMap,sheenColorMapEncoding:y(s.sheenColorMap),sheenRoughnessMap:!!s.sheenRoughnessMap,transmission:s.transmission>0,transmissionMap:!!s.transmissionMap,thicknessMap:!!s.thicknessMap,combine:s.combine,vertexTangents:!!s.normalMap&&!!_.geometry&&!!_.geometry.attributes.tangent,vertexColors:s.vertexColors,vertexAlphas:!0===s.vertexColors&&!!_.geometry&&!!_.geometry.attributes.color&&4===_.geometry.attributes.color.itemSize,vertexUvs:!!(s.map||s.bumpMap||s.normalMap||s.specularMap||s.alphaMap||s.emissiveMap||s.roughnessMap||s.metalnessMap||s.clearcoatMap||s.clearcoatRoughnessMap||s.clearcoatNormalMap||s.displacementMap||s.transmissionMap||s.thicknessMap||s.specularIntensityMap||s.specularColorMap||s.sheenColorMap||s.sheenRoughnessMap),uvsVertexOnly:!(s.map||s.bumpMap||s.normalMap||s.specularMap||s.alphaMap||s.emissiveMap||s.roughnessMap||s.metalnessMap||s.clearcoatNormalMap||s.transmission>0||s.transmissionMap||s.thicknessMap||s.specularIntensityMap||s.specularColorMap||s.sheen>0||s.sheenColorMap||s.sheenRoughnessMap||!s.displacementMap),fog:!!M,useFog:s.fog,fogExp2:M&&M.isFogExp2,flatShading:!!s.flatShading,sizeAttenuation:s.sizeAttenuation,logarithmicDepthBuffer:d,skinning:!0===_.isSkinnedMesh&&T>0,maxBones:T,useVertexTexture:p,morphTargets:!!_.geometry&&!!_.geometry.morphAttributes.position,morphNormals:!!_.geometry&&!!_.geometry.morphAttributes.normal,morphTargetsCount:_.geometry&&_.geometry.morphAttributes.position?_.geometry.morphAttributes.position.length:0,numDirLights:o.directional.length,numPointLights:o.point.length,numSpotLights:o.spot.length,numRectAreaLights:o.rectArea.length,numHemiLights:o.hemi.length,numDirLightShadows:o.directionalShadowMap.length,numPointLightShadows:o.pointShadowMap.length,numSpotLightShadows:o.spotShadowMap.length,numClippingPlanes:a.numPlanes,numClipIntersection:a.numIntersection,format:s.format,dithering:s.dithering,shadowMapEnabled:t.shadowMap.enabled&&h.length>0,shadowMapType:t.shadowMap.type,toneMapping:s.toneMapped?t.toneMapping:0,physicallyCorrectLights:t.physicallyCorrectLights,premultipliedAlpha:s.premultipliedAlpha,doubleSided:2===s.side,flipSided:1===s.side,depthPacking:void 0!==s.depthPacking&&s.depthPacking,index0AttributeName:s.index0AttributeName,extensionDerivatives:s.extensions&&s.extensions.derivatives,extensionFragDepth:s.extensions&&s.extensions.fragDepth,extensionDrawBuffers:s.extensions&&s.extensions.drawBuffers,extensionShaderTextureLOD:s.extensions&&s.extensions.shaderTextureLOD,rendererExtensionFragDepth:u||i.has("EXT_frag_depth"),rendererExtensionDrawBuffers:u||i.has("WEBGL_draw_buffers"),rendererExtensionShaderTextureLod:u||i.has("EXT_shader_texture_lod"),customProgramCacheKey:s.customProgramCacheKey()}},getProgramCacheKey:function(e){const n=[];if(e.shaderID?n.push(e.shaderID):(n.push(wt(e.fragmentShader)),n.push(wt(e.vertexShader))),void 0!==e.defines)for(const t in e.defines)n.push(t),n.push(e.defines[t]);return!1===e.isRawShaderMaterial&&(!function(t,e){t.push(e.precision),t.push(e.outputEncoding),t.push(e.mapEncoding),t.push(e.matcapEncoding),t.push(e.envMapMode),t.push(e.envMapEncoding),t.push(e.lightMapEncoding),t.push(e.emissiveMapEncoding),t.push(e.combine),t.push(e.vertexUvs),t.push(e.fogExp2),t.push(e.sizeAttenuation),t.push(e.maxBones),t.push(e.morphTargetsCount),t.push(e.numDirLights),t.push(e.numPointLights),t.push(e.numSpotLights),t.push(e.numHemiLights),t.push(e.numRectAreaLights),t.push(e.numDirLightShadows),t.push(e.numPointLightShadows),t.push(e.numSpotLightShadows),t.push(e.shadowMapType),t.push(e.toneMapping),t.push(e.numClippingPlanes),t.push(e.numClipIntersection),t.push(e.format),t.push(e.specularColorMapEncoding),t.push(e.sheenColorMapEncoding)}(n,e),function(t,e){o.disableAll(),e.isWebGL2&&o.enable(0);e.supportsVertexTextures&&o.enable(1);e.instancing&&o.enable(2);e.instancingColor&&o.enable(3);e.map&&o.enable(4);e.matcap&&o.enable(5);e.envMap&&o.enable(6);e.envMapCubeUV&&o.enable(7);e.lightMap&&o.enable(8);e.aoMap&&o.enable(9);e.emissiveMap&&o.enable(10);e.bumpMap&&o.enable(11);e.normalMap&&o.enable(12);e.objectSpaceNormalMap&&o.enable(13);e.tangentSpaceNormalMap&&o.enable(14);e.clearcoat&&o.enable(15);e.clearcoatMap&&o.enable(16);e.clearcoatRoughnessMap&&o.enable(17);e.clearcoatNormalMap&&o.enable(18);e.displacementMap&&o.enable(19);e.specularMap&&o.enable(20);e.roughnessMap&&o.enable(21);e.metalnessMap&&o.enable(22);e.gradientMap&&o.enable(23);e.alphaMap&&o.enable(24);e.alphaTest&&o.enable(25);e.vertexColors&&o.enable(26);e.vertexAlphas&&o.enable(27);e.vertexUvs&&o.enable(28);e.vertexTangents&&o.enable(29);e.uvsVertexOnly&&o.enable(30);e.fog&&o.enable(31);t.push(o.mask),o.disableAll(),e.useFog&&o.enable(0);e.flatShading&&o.enable(1);e.logarithmicDepthBuffer&&o.enable(2);e.skinning&&o.enable(3);e.useVertexTexture&&o.enable(4);e.morphTargets&&o.enable(5);e.morphNormals&&o.enable(6);e.premultipliedAlpha&&o.enable(7);e.shadowMapEnabled&&o.enable(8);e.physicallyCorrectLights&&o.enable(9);e.doubleSided&&o.enable(10);e.flipSided&&o.enable(11);e.depthPacking&&o.enable(12);e.dithering&&o.enable(13);e.specularIntensityMap&&o.enable(14);e.specularColorMap&&o.enable(15);e.transmission&&o.enable(16);e.transmissionMap&&o.enable(17);e.thicknessMap&&o.enable(18);e.sheen&&o.enable(19);e.sheenColorMap&&o.enable(20);e.sheenRoughnessMap&&o.enable(21);t.push(o.mask)}(n,e),n.push(t.outputEncoding),n.push(t.gammaFactor)),n.push(e.customProgramCacheKey),n.join()},getUniforms:function(t){const e=v[t.type];let n;if(e){const t=mi[e];n=Jn.clone(t.uniforms)}else n=t.uniforms;return n},acquireProgram:function(e,n){let i;for(let t=0,e=h.length;t0?i.push(h):!0===a.transparent?r.push(h):n.push(h)},unshift:function(t,e,a,o,l,c){const h=s(t,e,a,o,l,c);a.transmission>0?i.unshift(h):!0===a.transparent?r.unshift(h):n.unshift(h)},finish:function(){for(let n=e,i=t.length;n1&&n.sort(t||Cs),i.length>1&&i.sort(e||Ps),r.length>1&&r.sort(e||Ps)}}}function Is(){let t=new WeakMap;return{get:function(e,n){let i;return!1===t.has(e)?(i=new Ds,t.set(e,[i])):n>=t.get(e).length?(i=new Ds,t.get(e).push(i)):i=t.get(e)[n],i},dispose:function(){t=new WeakMap}}}function Ns(){const t={};return{get:function(e){if(void 0!==t[e.id])return t[e.id];let n;switch(e.type){case"DirectionalLight":n={direction:new Nt,color:new nn};break;case"SpotLight":n={position:new Nt,direction:new Nt,color:new nn,distance:0,coneCos:0,penumbraCos:0,decay:0};break;case"PointLight":n={position:new Nt,color:new nn,distance:0,decay:0};break;case"HemisphereLight":n={direction:new Nt,skyColor:new nn,groundColor:new nn};break;case"RectAreaLight":n={color:new nn,position:new Nt,halfWidth:new Nt,halfHeight:new Nt}}return t[e.id]=n,n}}}let zs=0;function Bs(t,e){return(e.castShadow?1:0)-(t.castShadow?1:0)}function Fs(t,e){const n=new Ns,i=function(){const t={};return{get:function(e){if(void 0!==t[e.id])return t[e.id];let n;switch(e.type){case"DirectionalLight":case"SpotLight":n={shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new vt};break;case"PointLight":n={shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new vt,shadowCameraNear:1,shadowCameraFar:1e3}}return t[e.id]=n,n}}}(),r={version:0,hash:{directionalLength:-1,pointLength:-1,spotLength:-1,rectAreaLength:-1,hemiLength:-1,numDirectionalShadows:-1,numPointShadows:-1,numSpotShadows:-1},ambient:[0,0,0],probe:[],directional:[],directionalShadow:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotShadow:[],spotShadowMap:[],spotShadowMatrix:[],rectArea:[],rectAreaLTC1:null,rectAreaLTC2:null,point:[],pointShadow:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[]};for(let t=0;t<9;t++)r.probe.push(new Nt);const s=new Nt,a=new ue,o=new ue;return{setup:function(s,a){let o=0,l=0,c=0;for(let t=0;t<9;t++)r.probe[t].set(0,0,0);let h=0,u=0,d=0,p=0,m=0,f=0,g=0,v=0;s.sort(Bs);const y=!0!==a?Math.PI:1;for(let t=0,e=s.length;t0&&(e.isWebGL2||!0===t.has("OES_texture_float_linear")?(r.rectAreaLTC1=pi.LTC_FLOAT_1,r.rectAreaLTC2=pi.LTC_FLOAT_2):!0===t.has("OES_texture_half_float_linear")?(r.rectAreaLTC1=pi.LTC_HALF_1,r.rectAreaLTC2=pi.LTC_HALF_2):console.error("THREE.WebGLRenderer: Unable to use RectAreaLight. Missing WebGL extensions.")),r.ambient[0]=o,r.ambient[1]=l,r.ambient[2]=c;const x=r.hash;x.directionalLength===h&&x.pointLength===u&&x.spotLength===d&&x.rectAreaLength===p&&x.hemiLength===m&&x.numDirectionalShadows===f&&x.numPointShadows===g&&x.numSpotShadows===v||(r.directional.length=h,r.spot.length=d,r.rectArea.length=p,r.point.length=u,r.hemi.length=m,r.directionalShadow.length=f,r.directionalShadowMap.length=f,r.pointShadow.length=g,r.pointShadowMap.length=g,r.spotShadow.length=v,r.spotShadowMap.length=v,r.directionalShadowMatrix.length=f,r.pointShadowMatrix.length=g,r.spotShadowMatrix.length=v,x.directionalLength=h,x.pointLength=u,x.spotLength=d,x.rectAreaLength=p,x.hemiLength=m,x.numDirectionalShadows=f,x.numPointShadows=g,x.numSpotShadows=v,r.version=zs++)},setupView:function(t,e){let n=0,i=0,l=0,c=0,h=0;const u=e.matrixWorldInverse;for(let e=0,d=t.length;e=n.get(i).length?(s=new Os(t,e),n.get(i).push(s)):s=n.get(i)[r],s},dispose:function(){n=new WeakMap}}}class Hs extends Ye{constructor(t){super(),this.type="MeshDepthMaterial",this.depthPacking=3200,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.fog=!1,this.setValues(t)}copy(t){return super.copy(t),this.depthPacking=t.depthPacking,this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this}}Hs.prototype.isMeshDepthMaterial=!0;class Gs extends Ye{constructor(t){super(),this.type="MeshDistanceMaterial",this.referencePosition=new Nt,this.nearDistance=1,this.farDistance=1e3,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.fog=!1,this.setValues(t)}copy(t){return super.copy(t),this.referencePosition.copy(t.referencePosition),this.nearDistance=t.nearDistance,this.farDistance=t.farDistance,this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this}}Gs.prototype.isMeshDistanceMaterial=!0;function ks(t,e,n){let i=new li;const r=new vt,s=new vt,a=new Rt,o=new Hs({depthPacking:3201}),l=new Gs,c={},h=n.maxTextureSize,u={0:1,1:0,2:2},d=new Yn({defines:{VSM_SAMPLES:8},uniforms:{shadow_pass:{value:null},resolution:{value:new vt},radius:{value:4}},vertexShader:"void main() {\n\tgl_Position = vec4( position, 1.0 );\n}",fragmentShader:"uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include \nvoid main() {\n\tconst float samples = float( VSM_SAMPLES );\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 );\n\tfloat uvStart = samples <= 1.0 ? 0.0 : - 1.0;\n\tfor ( float i = 0.0; i < samples; i ++ ) {\n\t\tfloat uvOffset = uvStart + i * uvStride;\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ) );\n\t\t\tmean += distribution.x;\n\t\t\tsquared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\t\t#else\n\t\t\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean / samples;\n\tsquared_mean = squared_mean / samples;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}"}),m=d.clone();m.defines.HORIZONTAL_PASS=1;const f=new Tn;f.setAttribute("position",new on(new Float32Array([-1,-1,.5,3,-1,.5,-1,3,.5]),3));const v=new Vn(f,d),y=this;function x(n,i){const r=e.update(v);d.defines.VSM_SAMPLES!==n.blurSamples&&(d.defines.VSM_SAMPLES=n.blurSamples,m.defines.VSM_SAMPLES=n.blurSamples,d.needsUpdate=!0,m.needsUpdate=!0),d.uniforms.shadow_pass.value=n.map.texture,d.uniforms.resolution.value=n.mapSize,d.uniforms.radius.value=n.radius,t.setRenderTarget(n.mapPass),t.clear(),t.renderBufferDirect(i,null,r,d,v,null),m.uniforms.shadow_pass.value=n.mapPass.texture,m.uniforms.resolution.value=n.mapSize,m.uniforms.radius.value=n.radius,t.setRenderTarget(n.map),t.clear(),t.renderBufferDirect(i,null,r,m,v,null)}function _(e,n,i,r,s,a,h){let d=null;const p=!0===r.isPointLight?e.customDistanceMaterial:e.customDepthMaterial;if(d=void 0!==p?p:!0===r.isPointLight?l:o,t.localClippingEnabled&&!0===i.clipShadows&&0!==i.clippingPlanes.length||i.displacementMap&&0!==i.displacementScale||i.alphaMap&&i.alphaTest>0){const t=d.uuid,e=i.uuid;let n=c[t];void 0===n&&(n={},c[t]=n);let r=n[e];void 0===r&&(r=d.clone(),n[e]=r),d=r}return d.visible=i.visible,d.wireframe=i.wireframe,d.side=3===h?null!==i.shadowSide?i.shadowSide:i.side:null!==i.shadowSide?i.shadowSide:u[i.side],d.alphaMap=i.alphaMap,d.alphaTest=i.alphaTest,d.clipShadows=i.clipShadows,d.clippingPlanes=i.clippingPlanes,d.clipIntersection=i.clipIntersection,d.displacementMap=i.displacementMap,d.displacementScale=i.displacementScale,d.displacementBias=i.displacementBias,d.wireframeLinewidth=i.wireframeLinewidth,d.linewidth=i.linewidth,!0===r.isPointLight&&!0===d.isMeshDistanceMaterial&&(d.referencePosition.setFromMatrixPosition(r.matrixWorld),d.nearDistance=s,d.farDistance=a),d}function M(n,r,s,a,o){if(!1===n.visible)return;if(n.layers.test(r.layers)&&(n.isMesh||n.isLine||n.isPoints)&&(n.castShadow||n.receiveShadow&&3===o)&&(!n.frustumCulled||i.intersectsObject(n))){n.modelViewMatrix.multiplyMatrices(s.matrixWorldInverse,n.matrixWorld);const i=e.update(n),r=n.material;if(Array.isArray(r)){const e=i.groups;for(let l=0,c=e.length;lh||r.y>h)&&(r.x>h&&(s.x=Math.floor(h/m.x),r.x=s.x*m.x,u.mapSize.x=s.x),r.y>h&&(s.y=Math.floor(h/m.y),r.y=s.y*m.y,u.mapSize.y=s.y)),null===u.map&&!u.isPointLightShadow&&3===this.type){const t={minFilter:g,magFilter:g,format:E};u.map=new Ct(r.x,r.y,t),u.map.texture.name=c.name+".shadowMap",u.mapPass=new Ct(r.x,r.y,t),u.camera.updateProjectionMatrix()}if(null===u.map){const t={minFilter:p,magFilter:p,format:E};u.map=new Ct(r.x,r.y,t),u.map.texture.name=c.name+".shadowMap",u.camera.updateProjectionMatrix()}t.setRenderTarget(u.map),t.clear();const f=u.getViewportCount();for(let t=0;t=1):-1!==L.indexOf("OpenGL ES")&&(A=parseFloat(/^OpenGL ES (\d)/.exec(L)[1]),E=A>=2);let R=null,C={};const P=t.getParameter(3088),D=t.getParameter(2978),I=(new Rt).fromArray(P),N=(new Rt).fromArray(D);function z(e,n,i){const r=new Uint8Array(4),s=t.createTexture();t.bindTexture(e,s),t.texParameteri(e,10241,9728),t.texParameteri(e,10240,9728);for(let e=0;ei||t.height>i)&&(r=i/Math.max(t.width,t.height)),r<1||!0===e){if("undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&t instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&t instanceof ImageBitmap){const i=e?ft:Math.floor,s=i(r*t.width),a=i(r*t.height);void 0===D&&(D=N(s,a));const o=n?N(s,a):D;o.width=s,o.height=a;return o.getContext("2d").drawImage(t,0,0,s,a),console.warn("THREE.WebGLRenderer: Texture has been resized from ("+t.width+"x"+t.height+") to ("+s+"x"+a+")."),o}return"data"in t&&console.warn("THREE.WebGLRenderer: Image in DataTexture is too big ("+t.width+"x"+t.height+")."),t}return t}function B(t){return pt(t.width)&&pt(t.height)}function F(t,e){return t.generateMipmaps&&e&&t.minFilter!==p&&t.minFilter!==g}function O(e){t.generateMipmap(e)}function U(n,i,r,s){if(!1===o)return i;if(null!==n){if(void 0!==t[n])return t[n];console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '"+n+"'")}let a=i;return 6403===i&&(5126===r&&(a=33326),5131===r&&(a=33325),5121===r&&(a=33321)),6407===i&&(5126===r&&(a=34837),5131===r&&(a=34843),5121===r&&(a=32849)),6408===i&&(5126===r&&(a=34836),5131===r&&(a=34842),5121===r&&(a=s===J?35907:32856)),33325!==a&&33326!==a&&34842!==a&&34836!==a||e.get("EXT_color_buffer_float"),a}function H(t,e,n){return!0===F(t,n)||t.isFramebufferTexture&&t.minFilter!==p&&t.minFilter!==g?Math.log2(Math.max(e.width,e.height))+1:void 0!==t.mipmaps&&t.mipmaps.length>0?t.mipmaps.length:t.isCompressedTexture&&Array.isArray(t.image)?e.mipmaps.length:1}function G(t){return t===p||t===m||t===f?9728:9729}function k(e){const n=e.target;n.removeEventListener("dispose",k),function(e){const n=i.get(e);if(void 0===n.__webglInit)return;t.deleteTexture(n.__webglTexture),i.remove(e)}(n),n.isVideoTexture&&P.delete(n),a.memory.textures--}function V(e){const n=e.target;n.removeEventListener("dispose",V),function(e){const n=e.texture,r=i.get(e),s=i.get(n);if(!e)return;void 0!==s.__webglTexture&&(t.deleteTexture(s.__webglTexture),a.memory.textures--);e.depthTexture&&e.depthTexture.dispose();if(e.isWebGLCubeRenderTarget)for(let e=0;e<6;e++)t.deleteFramebuffer(r.__webglFramebuffer[e]),r.__webglDepthbuffer&&t.deleteRenderbuffer(r.__webglDepthbuffer[e]);else t.deleteFramebuffer(r.__webglFramebuffer),r.__webglDepthbuffer&&t.deleteRenderbuffer(r.__webglDepthbuffer),r.__webglMultisampledFramebuffer&&t.deleteFramebuffer(r.__webglMultisampledFramebuffer),r.__webglColorRenderbuffer&&t.deleteRenderbuffer(r.__webglColorRenderbuffer),r.__webglDepthRenderbuffer&&t.deleteRenderbuffer(r.__webglDepthRenderbuffer);if(e.isWebGLMultipleRenderTargets)for(let e=0,r=n.length;e0&&r.__version!==t.version){const n=t.image;if(void 0===n)console.warn("THREE.WebGLRenderer: Texture marked for update but image is undefined");else{if(!1!==n.complete)return void K(r,t,e);console.warn("THREE.WebGLRenderer: Texture marked for update but image is incomplete")}}n.activeTexture(33984+e),n.bindTexture(3553,r.__webglTexture)}function q(e,r){const a=i.get(e);e.version>0&&a.__version!==e.version?function(e,i,r){if(6!==i.image.length)return;Q(e,i),n.activeTexture(33984+r),n.bindTexture(34067,e.__webglTexture),t.pixelStorei(37440,i.flipY),t.pixelStorei(37441,i.premultiplyAlpha),t.pixelStorei(3317,i.unpackAlignment),t.pixelStorei(37443,0);const a=i&&(i.isCompressedTexture||i.image[0].isCompressedTexture),l=i.image[0]&&i.image[0].isDataTexture,h=[];for(let t=0;t<6;t++)h[t]=a||l?l?i.image[t].image:i.image[t]:z(i.image[t],!1,!0,c);const u=h[0],d=B(u)||o,p=s.convert(i.format),m=s.convert(i.type),f=U(i.internalFormat,p,m,i.encoding),g=o&&!0!==i.isVideoTexture,v=void 0===e.__version;let y,x=H(i,u,d);if(Z(34067,i,d),a){g&&v&&n.texStorage2D(34067,x,f,u.width,u.height);for(let t=0;t<6;t++){y=h[t].mipmaps;for(let e=0;e0&&x++,n.texStorage2D(34067,x,f,h[0].width,h[0].height));for(let t=0;t<6;t++)if(l){g?n.texSubImage2D(34069+t,0,0,0,h[t].width,h[t].height,p,m,h[t].data):n.texImage2D(34069+t,0,f,h[t].width,h[t].height,0,p,m,h[t].data);for(let e=0;e1||i.get(s).__currentAnisotropy)&&(t.texParameterf(n,a.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(s.anisotropy,r.getMaxAnisotropy())),i.get(s).__currentAnisotropy=s.anisotropy)}}function Q(e,n){void 0===e.__webglInit&&(e.__webglInit=!0,n.addEventListener("dispose",k),e.__webglTexture=t.createTexture(),a.memory.textures++)}function K(e,i,r){let a=3553;i.isDataTexture2DArray&&(a=35866),i.isDataTexture3D&&(a=32879),Q(e,i),n.activeTexture(33984+r),n.bindTexture(a,e.__webglTexture),t.pixelStorei(37440,i.flipY),t.pixelStorei(37441,i.premultiplyAlpha),t.pixelStorei(3317,i.unpackAlignment),t.pixelStorei(37443,0);const l=function(t){return!o&&(t.wrapS!==u||t.wrapT!==u||t.minFilter!==p&&t.minFilter!==g)}(i)&&!1===B(i.image),c=z(i.image,l,!1,x),h=B(c)||o,d=s.convert(i.format);let m,f=s.convert(i.type),v=U(i.internalFormat,d,f,i.encoding);Z(a,i,h);const y=i.mipmaps,w=o&&!0!==i.isVideoTexture,R=void 0===e.__version,C=H(i,c,h);if(i.isDepthTexture)v=6402,o?v=i.type===b?36012:i.type===M?33190:i.type===S?35056:33189:i.type===b&&console.error("WebGLRenderer: Floating point depth texture requires WebGL2."),i.format===A&&6402===v&&i.type!==_&&i.type!==M&&(console.warn("THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture."),i.type=_,f=s.convert(i.type)),i.format===L&&6402===v&&(v=34041,i.type!==S&&(console.warn("THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture."),i.type=S,f=s.convert(i.type))),w&&R?n.texStorage2D(3553,1,v,c.width,c.height):n.texImage2D(3553,0,v,c.width,c.height,0,d,f,null);else if(i.isDataTexture)if(y.length>0&&h){w&&R&&n.texStorage2D(3553,C,v,y[0].width,y[0].height);for(let t=0,e=y.length;t0&&h){w&&R&&n.texStorage2D(3553,C,v,y[0].width,y[0].height);for(let t=0,e=y.length;t=l&&console.warn("THREE.WebGLTextures: Trying to use "+t+" texture units while this GPU supports only "+l),W+=1,t},this.resetTextureUnits=function(){W=0},this.setTexture2D=j,this.setTexture2DArray=function(t,e){const r=i.get(t);t.version>0&&r.__version!==t.version?K(r,t,e):(n.activeTexture(33984+e),n.bindTexture(35866,r.__webglTexture))},this.setTexture3D=function(t,e){const r=i.get(t);t.version>0&&r.__version!==t.version?K(r,t,e):(n.activeTexture(33984+e),n.bindTexture(32879,r.__webglTexture))},this.setTextureCube=q,this.rebindTextures=function(t,e,n){const r=i.get(t);void 0!==e&&$(r.__webglFramebuffer,t,t.texture,36064,3553),void 0!==n&&et(t)},this.setupRenderTarget=function(e){const l=e.texture,c=i.get(e),h=i.get(l);e.addEventListener("dispose",V),!0!==e.isWebGLMultipleRenderTargets&&(void 0===h.__webglTexture&&(h.__webglTexture=t.createTexture()),h.__version=l.version,a.memory.textures++);const u=!0===e.isWebGLCubeRenderTarget,d=!0===e.isWebGLMultipleRenderTargets,p=l.isDataTexture3D||l.isDataTexture2DArray,m=B(e)||o;if(!o||l.format!==T||l.type!==b&&l.type!==w||(l.format=E,console.warn("THREE.WebGLRenderer: Rendering to textures with RGB format is not supported. Using RGBA format instead.")),u){c.__webglFramebuffer=[];for(let e=0;e<6;e++)c.__webglFramebuffer[e]=t.createFramebuffer()}else if(c.__webglFramebuffer=t.createFramebuffer(),d)if(r.drawBuffers){const n=e.texture;for(let e=0,r=n.length;eo+c?(l.inputState.pinching=!1,this.dispatchEvent({type:"pinchend",handedness:t.handedness,target:this})):!l.inputState.pinching&&a<=o-c&&(l.inputState.pinching=!0,this.dispatchEvent({type:"pinchstart",handedness:t.handedness,target:this}))}else null!==o&&t.gripSpace&&(r=e.getPose(t.gripSpace,n),null!==r&&(o.matrix.fromArray(r.transform.matrix),o.matrix.decompose(o.position,o.rotation,o.scale),r.linearVelocity?(o.hasLinearVelocity=!0,o.linearVelocity.copy(r.linearVelocity)):o.hasLinearVelocity=!1,r.angularVelocity?(o.hasAngularVelocity=!0,o.angularVelocity.copy(r.angularVelocity)):o.hasAngularVelocity=!1));return null!==a&&(a.visible=null!==i),null!==o&&(o.visible=null!==r),null!==l&&(l.visible=null!==s),this}}class Zs extends At{constructor(t,e,n,i,r,s,a,o,l,c){if((c=void 0!==c?c:A)!==A&&c!==L)throw new Error("DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat");void 0===n&&c===A&&(n=_),void 0===n&&c===L&&(n=S),super(null,i,r,s,a,o,c,n,l),this.image={width:t,height:e},this.magFilter=void 0!==a?a:p,this.minFilter=void 0!==o?o:p,this.flipY=!1,this.generateMipmaps=!1}}Zs.prototype.isDepthTexture=!0;class Qs extends rt{constructor(t,e){super();const n=this;let i=null,r=1,s=null,a="local-floor";const o=t.extensions.has("WEBGL_multisampled_render_to_texture");let l=null,c=null,h=null,u=null,d=!1,p=null;const m=e.getContextAttributes();let f=null,g=null;const v=[],y=new Map,M=new Qn;M.layers.enable(1),M.viewport=new Rt;const b=new Qn;b.layers.enable(2),b.viewport=new Rt;const w=[M,b],R=new qs;R.layers.enable(1),R.layers.enable(2);let C=null,P=null;function D(t){const e=y.get(t.inputSource);e&&e.dispatchEvent({type:t.type,data:t.inputSource})}function I(){y.forEach((function(t,e){t.disconnect(e)})),y.clear(),C=null,P=null,t.setRenderTarget(f),u=null,h=null,c=null,i=null,g=null,U.stop(),n.isPresenting=!1,n.dispatchEvent({type:"sessionend"})}function N(t){const e=i.inputSources;for(let t=0;t0&&(e.alphaTest.value=n.alphaTest);const i=t.get(n).envMap;let r,s;i&&(e.envMap.value=i,e.flipEnvMap.value=i.isCubeTexture&&!1===i.isRenderTargetTexture?-1:1,e.reflectivity.value=n.reflectivity,e.ior.value=n.ior,e.refractionRatio.value=n.refractionRatio),n.lightMap&&(e.lightMap.value=n.lightMap,e.lightMapIntensity.value=n.lightMapIntensity),n.aoMap&&(e.aoMap.value=n.aoMap,e.aoMapIntensity.value=n.aoMapIntensity),n.map?r=n.map:n.specularMap?r=n.specularMap:n.displacementMap?r=n.displacementMap:n.normalMap?r=n.normalMap:n.bumpMap?r=n.bumpMap:n.roughnessMap?r=n.roughnessMap:n.metalnessMap?r=n.metalnessMap:n.alphaMap?r=n.alphaMap:n.emissiveMap?r=n.emissiveMap:n.clearcoatMap?r=n.clearcoatMap:n.clearcoatNormalMap?r=n.clearcoatNormalMap:n.clearcoatRoughnessMap?r=n.clearcoatRoughnessMap:n.specularIntensityMap?r=n.specularIntensityMap:n.specularColorMap?r=n.specularColorMap:n.transmissionMap?r=n.transmissionMap:n.thicknessMap?r=n.thicknessMap:n.sheenColorMap?r=n.sheenColorMap:n.sheenRoughnessMap&&(r=n.sheenRoughnessMap),void 0!==r&&(r.isWebGLRenderTarget&&(r=r.texture),!0===r.matrixAutoUpdate&&r.updateMatrix(),e.uvTransform.value.copy(r.matrix)),n.aoMap?s=n.aoMap:n.lightMap&&(s=n.lightMap),void 0!==s&&(s.isWebGLRenderTarget&&(s=s.texture),!0===s.matrixAutoUpdate&&s.updateMatrix(),e.uv2Transform.value.copy(s.matrix))}function n(e,n){e.roughness.value=n.roughness,e.metalness.value=n.metalness,n.roughnessMap&&(e.roughnessMap.value=n.roughnessMap),n.metalnessMap&&(e.metalnessMap.value=n.metalnessMap),n.emissiveMap&&(e.emissiveMap.value=n.emissiveMap),n.bumpMap&&(e.bumpMap.value=n.bumpMap,e.bumpScale.value=n.bumpScale,1===n.side&&(e.bumpScale.value*=-1)),n.normalMap&&(e.normalMap.value=n.normalMap,e.normalScale.value.copy(n.normalScale),1===n.side&&e.normalScale.value.negate()),n.displacementMap&&(e.displacementMap.value=n.displacementMap,e.displacementScale.value=n.displacementScale,e.displacementBias.value=n.displacementBias);t.get(n).envMap&&(e.envMapIntensity.value=n.envMapIntensity)}return{refreshFogUniforms:function(t,e){t.fogColor.value.copy(e.color),e.isFog?(t.fogNear.value=e.near,t.fogFar.value=e.far):e.isFogExp2&&(t.fogDensity.value=e.density)},refreshMaterialUniforms:function(t,i,r,s,a){i.isMeshBasicMaterial?e(t,i):i.isMeshLambertMaterial?(e(t,i),function(t,e){e.emissiveMap&&(t.emissiveMap.value=e.emissiveMap)}(t,i)):i.isMeshToonMaterial?(e(t,i),function(t,e){e.gradientMap&&(t.gradientMap.value=e.gradientMap);e.emissiveMap&&(t.emissiveMap.value=e.emissiveMap);e.bumpMap&&(t.bumpMap.value=e.bumpMap,t.bumpScale.value=e.bumpScale,1===e.side&&(t.bumpScale.value*=-1));e.normalMap&&(t.normalMap.value=e.normalMap,t.normalScale.value.copy(e.normalScale),1===e.side&&t.normalScale.value.negate());e.displacementMap&&(t.displacementMap.value=e.displacementMap,t.displacementScale.value=e.displacementScale,t.displacementBias.value=e.displacementBias)}(t,i)):i.isMeshPhongMaterial?(e(t,i),function(t,e){t.specular.value.copy(e.specular),t.shininess.value=Math.max(e.shininess,1e-4),e.emissiveMap&&(t.emissiveMap.value=e.emissiveMap);e.bumpMap&&(t.bumpMap.value=e.bumpMap,t.bumpScale.value=e.bumpScale,1===e.side&&(t.bumpScale.value*=-1));e.normalMap&&(t.normalMap.value=e.normalMap,t.normalScale.value.copy(e.normalScale),1===e.side&&t.normalScale.value.negate());e.displacementMap&&(t.displacementMap.value=e.displacementMap,t.displacementScale.value=e.displacementScale,t.displacementBias.value=e.displacementBias)}(t,i)):i.isMeshStandardMaterial?(e(t,i),i.isMeshPhysicalMaterial?function(t,e,i){n(t,e),t.ior.value=e.ior,e.sheen>0&&(t.sheenColor.value.copy(e.sheenColor).multiplyScalar(e.sheen),t.sheenRoughness.value=e.sheenRoughness,e.sheenColorMap&&(t.sheenColorMap.value=e.sheenColorMap),e.sheenRoughnessMap&&(t.sheenRoughnessMap.value=e.sheenRoughnessMap));e.clearcoat>0&&(t.clearcoat.value=e.clearcoat,t.clearcoatRoughness.value=e.clearcoatRoughness,e.clearcoatMap&&(t.clearcoatMap.value=e.clearcoatMap),e.clearcoatRoughnessMap&&(t.clearcoatRoughnessMap.value=e.clearcoatRoughnessMap),e.clearcoatNormalMap&&(t.clearcoatNormalScale.value.copy(e.clearcoatNormalScale),t.clearcoatNormalMap.value=e.clearcoatNormalMap,1===e.side&&t.clearcoatNormalScale.value.negate()));e.transmission>0&&(t.transmission.value=e.transmission,t.transmissionSamplerMap.value=i.texture,t.transmissionSamplerSize.value.set(i.width,i.height),e.transmissionMap&&(t.transmissionMap.value=e.transmissionMap),t.thickness.value=e.thickness,e.thicknessMap&&(t.thicknessMap.value=e.thicknessMap),t.attenuationDistance.value=e.attenuationDistance,t.attenuationColor.value.copy(e.attenuationColor));t.specularIntensity.value=e.specularIntensity,t.specularColor.value.copy(e.specularColor),e.specularIntensityMap&&(t.specularIntensityMap.value=e.specularIntensityMap);e.specularColorMap&&(t.specularColorMap.value=e.specularColorMap)}(t,i,a):n(t,i)):i.isMeshMatcapMaterial?(e(t,i),function(t,e){e.matcap&&(t.matcap.value=e.matcap);e.bumpMap&&(t.bumpMap.value=e.bumpMap,t.bumpScale.value=e.bumpScale,1===e.side&&(t.bumpScale.value*=-1));e.normalMap&&(t.normalMap.value=e.normalMap,t.normalScale.value.copy(e.normalScale),1===e.side&&t.normalScale.value.negate());e.displacementMap&&(t.displacementMap.value=e.displacementMap,t.displacementScale.value=e.displacementScale,t.displacementBias.value=e.displacementBias)}(t,i)):i.isMeshDepthMaterial?(e(t,i),function(t,e){e.displacementMap&&(t.displacementMap.value=e.displacementMap,t.displacementScale.value=e.displacementScale,t.displacementBias.value=e.displacementBias)}(t,i)):i.isMeshDistanceMaterial?(e(t,i),function(t,e){e.displacementMap&&(t.displacementMap.value=e.displacementMap,t.displacementScale.value=e.displacementScale,t.displacementBias.value=e.displacementBias);t.referencePosition.value.copy(e.referencePosition),t.nearDistance.value=e.nearDistance,t.farDistance.value=e.farDistance}(t,i)):i.isMeshNormalMaterial?(e(t,i),function(t,e){e.bumpMap&&(t.bumpMap.value=e.bumpMap,t.bumpScale.value=e.bumpScale,1===e.side&&(t.bumpScale.value*=-1));e.normalMap&&(t.normalMap.value=e.normalMap,t.normalScale.value.copy(e.normalScale),1===e.side&&t.normalScale.value.negate());e.displacementMap&&(t.displacementMap.value=e.displacementMap,t.displacementScale.value=e.displacementScale,t.displacementBias.value=e.displacementBias)}(t,i)):i.isLineBasicMaterial?(function(t,e){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity}(t,i),i.isLineDashedMaterial&&function(t,e){t.dashSize.value=e.dashSize,t.totalSize.value=e.dashSize+e.gapSize,t.scale.value=e.scale}(t,i)):i.isPointsMaterial?function(t,e,n,i){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,t.size.value=e.size*n,t.scale.value=.5*i,e.map&&(t.map.value=e.map);e.alphaMap&&(t.alphaMap.value=e.alphaMap);e.alphaTest>0&&(t.alphaTest.value=e.alphaTest);let r;e.map?r=e.map:e.alphaMap&&(r=e.alphaMap);void 0!==r&&(!0===r.matrixAutoUpdate&&r.updateMatrix(),t.uvTransform.value.copy(r.matrix))}(t,i,r,s):i.isSpriteMaterial?function(t,e){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,t.rotation.value=e.rotation,e.map&&(t.map.value=e.map);e.alphaMap&&(t.alphaMap.value=e.alphaMap);e.alphaTest>0&&(t.alphaTest.value=e.alphaTest);let n;e.map?n=e.map:e.alphaMap&&(n=e.alphaMap);void 0!==n&&(!0===n.matrixAutoUpdate&&n.updateMatrix(),t.uvTransform.value.copy(n.matrix))}(t,i):i.isShadowMaterial?(t.color.value.copy(i.color),t.opacity.value=i.opacity):i.isShaderMaterial&&(i.uniformsNeedUpdate=!1)}}}function $s(t={}){const e=void 0!==t.canvas?t.canvas:function(){const t=bt("canvas");return t.style.display="block",t}(),n=void 0!==t.context?t.context:null,i=void 0!==t.alpha&&t.alpha,r=void 0===t.depth||t.depth,s=void 0===t.stencil||t.stencil,a=void 0!==t.antialias&&t.antialias,o=void 0===t.premultipliedAlpha||t.premultipliedAlpha,l=void 0!==t.preserveDrawingBuffer&&t.preserveDrawingBuffer,c=void 0!==t.powerPreference?t.powerPreference:"default",h=void 0!==t.failIfMajorPerformanceCaveat&&t.failIfMajorPerformanceCaveat;let d=null,m=null;const f=[],g=[];this.domElement=e,this.debug={checkShaderErrors:!0},this.autoClear=!0,this.autoClearColor=!0,this.autoClearDepth=!0,this.autoClearStencil=!0,this.sortObjects=!0,this.clippingPlanes=[],this.localClippingEnabled=!1,this.gammaFactor=2,this.outputEncoding=X,this.physicallyCorrectLights=!1,this.toneMapping=0,this.toneMappingExposure=1;const v=this;let _=!1,M=0,S=0,T=null,A=-1,L=null;const R=new Rt,C=new Rt;let P=null,D=e.width,I=e.height,N=1,z=null,B=null;const F=new Rt(0,0,D,I),O=new Rt(0,0,D,I);let U=!1;const H=[],G=new li;let k=!1,V=!1,W=null;const j=new ue,q=new Nt,J={background:null,fog:null,environment:null,overrideMaterial:null,isScene:!0};function Y(){return null===T?N:1}let Z,Q,K,$,tt,et,nt,it,rt,st,at,ot,lt,ct,ht,ut,dt,pt,mt,ft,gt,vt,yt,xt=n;function _t(t,n){for(let i=0;i0&&function(t,e,n){if(null===W){const t=!0===a&&!0===Q.isWebGL2;W=new(t?Dt:Ct)(1024,1024,{generateMipmaps:!0,type:null!==vt.convert(w)?w:x,minFilter:y,magFilter:p,wrapS:u,wrapT:u,useRenderToTexture:Z.has("WEBGL_multisampled_render_to_texture")})}const i=v.getRenderTarget();v.setRenderTarget(W),v.clear();const r=v.toneMapping;v.toneMapping=0,Ft(t,e,n),v.toneMapping=r,et.updateMultisampleRenderTarget(W),et.updateRenderTargetMipmap(W),v.setRenderTarget(i)}(r,e,n),i&&K.viewport(R.copy(i)),r.length>0&&Ft(r,e,n),s.length>0&&Ft(s,e,n),o.length>0&&Ft(o,e,n)}function Ft(t,e,n){const i=!0===e.isScene?e.overrideMaterial:null;for(let r=0,s=t.length;r0?g[g.length-1]:null,f.pop(),d=f.length>0?f[f.length-1]:null},this.getActiveCubeFace=function(){return M},this.getActiveMipmapLevel=function(){return S},this.getRenderTarget=function(){return T},this.setRenderTargetTextures=function(t,e,n){tt.get(t.texture).__webglTexture=e,tt.get(t.depthTexture).__webglTexture=n;const i=tt.get(t);i.__hasExternalTextures=!0,i.__hasExternalTextures&&(i.__autoAllocateDepthBuffer=void 0===n,i.__autoAllocateDepthBuffer||t.useRenderToTexture&&(console.warn("render-to-texture extension was disabled because an external texture was provided"),t.useRenderToTexture=!1,t.useRenderbuffer=!0))},this.setRenderTargetFramebuffer=function(t,e){const n=tt.get(t);n.__webglFramebuffer=e,n.__useDefaultFramebuffer=void 0===e},this.setRenderTarget=function(t,e=0,n=0){T=t,M=e,S=n;let i=!0;if(t){const e=tt.get(t);void 0!==e.__useDefaultFramebuffer?(K.bindFramebuffer(36160,null),i=!1):void 0===e.__webglFramebuffer?et.setupRenderTarget(t):e.__hasExternalTextures&&et.rebindTextures(t,tt.get(t.texture).__webglTexture,tt.get(t.depthTexture).__webglTexture)}let r=null,s=!1,a=!1;if(t){const n=t.texture;(n.isDataTexture3D||n.isDataTexture2DArray)&&(a=!0);const i=tt.get(t).__webglFramebuffer;t.isWebGLCubeRenderTarget?(r=i[e],s=!0):r=t.useRenderbuffer?tt.get(t).__webglMultisampledFramebuffer:i,R.copy(t.viewport),C.copy(t.scissor),P=t.scissorTest}else R.copy(F).multiplyScalar(N).floor(),C.copy(O).multiplyScalar(N).floor(),P=U;if(K.bindFramebuffer(36160,r)&&Q.drawBuffers&&i){let e=!1;if(t)if(t.isWebGLMultipleRenderTargets){const n=t.texture;if(H.length!==n.length||36064!==H[0]){for(let t=0,e=n.length;t=0&&e<=t.width-i&&n>=0&&n<=t.height-r&&xt.readPixels(e,n,i,r,vt.convert(o),vt.convert(l),s):console.error("THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.")}finally{const t=null!==T?tt.get(T).__webglFramebuffer:null;K.bindFramebuffer(36160,t)}}},this.copyFramebufferToTexture=function(t,e,n=0){if(!0!==e.isFramebufferTexture)return void console.error("THREE.WebGLRenderer: copyFramebufferToTexture() can only be used with FramebufferTexture.");const i=Math.pow(2,-n),r=Math.floor(e.image.width*i),s=Math.floor(e.image.height*i);et.setTexture2D(e,0),xt.copyTexSubImage2D(3553,n,0,0,t.x,t.y,r,s),K.unbindTexture()},this.copyTextureToTexture=function(t,e,n,i=0){const r=e.image.width,s=e.image.height,a=vt.convert(n.format),o=vt.convert(n.type);et.setTexture2D(n,0),xt.pixelStorei(37440,n.flipY),xt.pixelStorei(37441,n.premultiplyAlpha),xt.pixelStorei(3317,n.unpackAlignment),e.isDataTexture?xt.texSubImage2D(3553,i,t.x,t.y,r,s,a,o,e.image.data):e.isCompressedTexture?xt.compressedTexSubImage2D(3553,i,t.x,t.y,e.mipmaps[0].width,e.mipmaps[0].height,a,e.mipmaps[0].data):xt.texSubImage2D(3553,i,t.x,t.y,a,o,e.image),0===i&&n.generateMipmaps&&xt.generateMipmap(3553),K.unbindTexture()},this.copyTextureToTexture3D=function(t,e,n,i,r=0){if(v.isWebGL1Renderer)return void console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2.");const s=t.max.x-t.min.x+1,a=t.max.y-t.min.y+1,o=t.max.z-t.min.z+1,l=vt.convert(i.format),c=vt.convert(i.type);let h;if(i.isDataTexture3D)et.setTexture3D(i,0),h=32879;else{if(!i.isDataTexture2DArray)return void console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.");et.setTexture2DArray(i,0),h=35866}xt.pixelStorei(37440,i.flipY),xt.pixelStorei(37441,i.premultiplyAlpha),xt.pixelStorei(3317,i.unpackAlignment);const u=xt.getParameter(3314),d=xt.getParameter(32878),p=xt.getParameter(3316),m=xt.getParameter(3315),f=xt.getParameter(32877),g=n.isCompressedTexture?n.mipmaps[0]:n.image;xt.pixelStorei(3314,g.width),xt.pixelStorei(32878,g.height),xt.pixelStorei(3316,t.min.x),xt.pixelStorei(3315,t.min.y),xt.pixelStorei(32877,t.min.z),n.isDataTexture||n.isDataTexture3D?xt.texSubImage3D(h,r,e.x,e.y,e.z,s,a,o,l,c,g.data):n.isCompressedTexture?(console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: untested support for compressed srcTexture."),xt.compressedTexSubImage3D(h,r,e.x,e.y,e.z,s,a,o,l,g.data)):xt.texSubImage3D(h,r,e.x,e.y,e.z,s,a,o,l,c,g),xt.pixelStorei(3314,u),xt.pixelStorei(32878,d),xt.pixelStorei(3316,p),xt.pixelStorei(3315,m),xt.pixelStorei(32877,f),0===r&&i.generateMipmaps&&xt.generateMipmap(h),K.unbindTexture()},this.initTexture=function(t){et.setTexture2D(t,0),K.unbindTexture()},this.resetState=function(){M=0,S=0,T=null,K.reset(),yt.reset()},"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}$s.prototype.isWebGLRenderer=!0;class ta extends $s{}ta.prototype.isWebGL1Renderer=!0;class ea{constructor(t,e=25e-5){this.name="",this.color=new nn(t),this.density=e}clone(){return new ea(this.color,this.density)}toJSON(){return{type:"FogExp2",color:this.color.getHex(),density:this.density}}}ea.prototype.isFogExp2=!0;class na{constructor(t,e=1,n=1e3){this.name="",this.color=new nn(t),this.near=e,this.far=n}clone(){return new na(this.color,this.near,this.far)}toJSON(){return{type:"Fog",color:this.color.getHex(),near:this.near,far:this.far}}}na.prototype.isFog=!0;class ia extends Be{constructor(){super(),this.type="Scene",this.background=null,this.environment=null,this.fog=null,this.overrideMaterial=null,this.autoUpdate=!0,"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}copy(t,e){return super.copy(t,e),null!==t.background&&(this.background=t.background.clone()),null!==t.environment&&(this.environment=t.environment.clone()),null!==t.fog&&(this.fog=t.fog.clone()),null!==t.overrideMaterial&&(this.overrideMaterial=t.overrideMaterial.clone()),this.autoUpdate=t.autoUpdate,this.matrixAutoUpdate=t.matrixAutoUpdate,this}toJSON(t){const e=super.toJSON(t);return null!==this.fog&&(e.object.fog=this.fog.toJSON()),e}}ia.prototype.isScene=!0;class ra{constructor(t,e){this.array=t,this.stride=e,this.count=void 0!==t?t.length/e:0,this.usage=et,this.updateRange={offset:0,count:-1},this.version=0,this.uuid=ct()}onUploadCallback(){}set needsUpdate(t){!0===t&&this.version++}setUsage(t){return this.usage=t,this}copy(t){return this.array=new t.array.constructor(t.array),this.count=t.count,this.stride=t.stride,this.usage=t.usage,this}copyAt(t,e,n){t*=this.stride,n*=e.stride;for(let i=0,r=this.stride;it.far||e.push({distance:o,point:ca.clone(),uv:Xe.getUV(ca,fa,ga,va,ya,xa,_a,new vt),face:null,object:this})}copy(t){return super.copy(t),void 0!==t.center&&this.center.copy(t.center),this.material=t.material,this}}function ba(t,e,n,i,r,s){da.subVectors(t,n).addScalar(.5).multiply(i),void 0!==r?(pa.x=s*da.x-r*da.y,pa.y=r*da.x+s*da.y):pa.copy(da),t.copy(e),t.x+=pa.x,t.y+=pa.y,t.applyMatrix4(ma)}Ma.prototype.isSprite=!0;const wa=new Nt,Sa=new Nt;class Ta extends Be{constructor(){super(),this._currentLevel=0,this.type="LOD",Object.defineProperties(this,{levels:{enumerable:!0,value:[]},isLOD:{value:!0}}),this.autoUpdate=!0}copy(t){super.copy(t,!1);const e=t.levels;for(let t=0,n=e.length;t0){let n,i;for(n=1,i=e.length;n0){wa.setFromMatrixPosition(this.matrixWorld);const n=t.ray.origin.distanceTo(wa);this.getObjectForDistance(n).raycast(t,e)}}update(t){const e=this.levels;if(e.length>1){wa.setFromMatrixPosition(t.matrixWorld),Sa.setFromMatrixPosition(this.matrixWorld);const n=wa.distanceTo(Sa)/t.zoom;let i,r;for(e[0].object.visible=!0,i=1,r=e.length;i=e[i].distance;i++)e[i-1].object.visible=!1,e[i].object.visible=!0;for(this._currentLevel=i-1;io)continue;u.applyMatrix4(this.matrixWorld);const d=t.ray.origin.distanceTo(u);dt.far||e.push({distance:d,point:h.clone().applyMatrix4(this.matrixWorld),index:n,face:null,faceIndex:null,object:this})}}else{for(let n=Math.max(0,s.start),i=Math.min(r.count,s.start+s.count)-1;no)continue;u.applyMatrix4(this.matrixWorld);const i=t.ray.origin.distanceTo(u);it.far||e.push({distance:i,point:h.clone().applyMatrix4(this.matrixWorld),index:n,face:null,faceIndex:null,object:this})}}}else n.isGeometry&&console.error("THREE.Line.raycast() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.")}updateMorphTargets(){const t=this.geometry;if(t.isBufferGeometry){const e=t.morphAttributes,n=Object.keys(e);if(n.length>0){const t=e[n[0]];if(void 0!==t){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let e=0,n=t.length;e0&&console.error("THREE.Line.updateMorphTargets() does not support THREE.Geometry. Use THREE.BufferGeometry instead.")}}}Ya.prototype.isLine=!0;const Za=new Nt,Qa=new Nt;class Ka extends Ya{constructor(t,e){super(t,e),this.type="LineSegments"}computeLineDistances(){const t=this.geometry;if(t.isBufferGeometry)if(null===t.index){const e=t.attributes.position,n=[];for(let t=0,i=e.count;t0){const t=e[n[0]];if(void 0!==t){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let e=0,n=t.length;e0&&console.error("THREE.Points.updateMorphTargets() does not support THREE.Geometry. Use THREE.BufferGeometry instead.")}}}function ao(t,e,n,i,r,s,a){const o=no.distanceSqToPoint(t);if(or.far)return;s.push({distance:l,distanceToRay:Math.sqrt(o),point:n,index:e,face:null,object:a})}}so.prototype.isPoints=!0;class oo extends At{constructor(t,e,n,i,r,s,a,o,l){super(t,e,n,i,r,s,a,o,l),this.format=void 0!==a?a:T,this.minFilter=void 0!==s?s:g,this.magFilter=void 0!==r?r:g,this.generateMipmaps=!1;const c=this;"requestVideoFrameCallback"in t&&t.requestVideoFrameCallback((function e(){c.needsUpdate=!0,t.requestVideoFrameCallback(e)}))}clone(){return new this.constructor(this.image).copy(this)}update(){const t=this.image;!1==="requestVideoFrameCallback"in t&&t.readyState>=t.HAVE_CURRENT_DATA&&(this.needsUpdate=!0)}}oo.prototype.isVideoTexture=!0;class lo extends At{constructor(t,e,n){super({width:t,height:e}),this.format=n,this.magFilter=p,this.minFilter=p,this.generateMipmaps=!1,this.needsUpdate=!0}}lo.prototype.isFramebufferTexture=!0;class co extends At{constructor(t,e,n,i,r,s,a,o,l,c,h,u){super(null,s,a,o,l,c,i,r,h,u),this.image={width:e,height:n},this.mipmaps=t,this.flipY=!1,this.generateMipmaps=!1}}co.prototype.isCompressedTexture=!0;class ho extends At{constructor(t,e,n,i,r,s,a,o,l){super(t,e,n,i,r,s,a,o,l),this.needsUpdate=!0}}ho.prototype.isCanvasTexture=!0;class uo extends Tn{constructor(t=1,e=8,n=0,i=2*Math.PI){super(),this.type="CircleGeometry",this.parameters={radius:t,segments:e,thetaStart:n,thetaLength:i},e=Math.max(3,e);const r=[],s=[],a=[],o=[],l=new Nt,c=new vt;s.push(0,0,0),a.push(0,0,1),o.push(.5,.5);for(let r=0,h=3;r<=e;r++,h+=3){const u=n+r/e*i;l.x=t*Math.cos(u),l.y=t*Math.sin(u),s.push(l.x,l.y,l.z),a.push(0,0,1),c.x=(s[h]/t+1)/2,c.y=(s[h+1]/t+1)/2,o.push(c.x,c.y)}for(let t=1;t<=e;t++)r.push(t,t+1,0);this.setIndex(r),this.setAttribute("position",new gn(s,3)),this.setAttribute("normal",new gn(a,3)),this.setAttribute("uv",new gn(o,2))}static fromJSON(t){return new uo(t.radius,t.segments,t.thetaStart,t.thetaLength)}}class po extends Tn{constructor(t=1,e=1,n=1,i=8,r=1,s=!1,a=0,o=2*Math.PI){super(),this.type="CylinderGeometry",this.parameters={radiusTop:t,radiusBottom:e,height:n,radialSegments:i,heightSegments:r,openEnded:s,thetaStart:a,thetaLength:o};const l=this;i=Math.floor(i),r=Math.floor(r);const c=[],h=[],u=[],d=[];let p=0;const m=[],f=n/2;let g=0;function v(n){const r=p,s=new vt,m=new Nt;let v=0;const y=!0===n?t:e,x=!0===n?1:-1;for(let t=1;t<=i;t++)h.push(0,f*x,0),u.push(0,x,0),d.push(.5,.5),p++;const _=p;for(let t=0;t<=i;t++){const e=t/i*o+a,n=Math.cos(e),r=Math.sin(e);m.x=y*r,m.y=f*x,m.z=y*n,h.push(m.x,m.y,m.z),u.push(0,x,0),s.x=.5*n+.5,s.y=.5*r*x+.5,d.push(s.x,s.y),p++}for(let t=0;t0&&v(!0),e>0&&v(!1)),this.setIndex(c),this.setAttribute("position",new gn(h,3)),this.setAttribute("normal",new gn(u,3)),this.setAttribute("uv",new gn(d,2))}static fromJSON(t){return new po(t.radiusTop,t.radiusBottom,t.height,t.radialSegments,t.heightSegments,t.openEnded,t.thetaStart,t.thetaLength)}}class mo extends po{constructor(t=1,e=1,n=8,i=1,r=!1,s=0,a=2*Math.PI){super(0,t,e,n,i,r,s,a),this.type="ConeGeometry",this.parameters={radius:t,height:e,radialSegments:n,heightSegments:i,openEnded:r,thetaStart:s,thetaLength:a}}static fromJSON(t){return new mo(t.radius,t.height,t.radialSegments,t.heightSegments,t.openEnded,t.thetaStart,t.thetaLength)}}class fo extends Tn{constructor(t=[],e=[],n=1,i=0){super(),this.type="PolyhedronGeometry",this.parameters={vertices:t,indices:e,radius:n,detail:i};const r=[],s=[];function a(t,e,n,i){const r=i+1,s=[];for(let i=0;i<=r;i++){s[i]=[];const a=t.clone().lerp(n,i/r),o=e.clone().lerp(n,i/r),l=r-i;for(let t=0;t<=l;t++)s[i][t]=0===t&&i===r?a:a.clone().lerp(o,t/l)}for(let t=0;t.9&&a<.1&&(e<.2&&(s[t+0]+=1),n<.2&&(s[t+2]+=1),i<.2&&(s[t+4]+=1))}}()}(),this.setAttribute("position",new gn(r,3)),this.setAttribute("normal",new gn(r.slice(),3)),this.setAttribute("uv",new gn(s,2)),0===i?this.computeVertexNormals():this.normalizeNormals()}static fromJSON(t){return new fo(t.vertices,t.indices,t.radius,t.details)}}class go extends fo{constructor(t=1,e=0){const n=(1+Math.sqrt(5))/2,i=1/n;super([-1,-1,-1,-1,-1,1,-1,1,-1,-1,1,1,1,-1,-1,1,-1,1,1,1,-1,1,1,1,0,-i,-n,0,-i,n,0,i,-n,0,i,n,-i,-n,0,-i,n,0,i,-n,0,i,n,0,-n,0,-i,n,0,-i,-n,0,i,n,0,i],[3,11,7,3,7,15,3,15,13,7,19,17,7,17,6,7,6,15,17,4,8,17,8,10,17,10,6,8,0,16,8,16,2,8,2,10,0,12,1,0,1,18,0,18,16,6,10,2,6,2,13,6,13,15,2,16,18,2,18,3,2,3,13,18,1,9,18,9,11,18,11,3,4,14,12,4,12,0,4,0,8,11,9,5,11,5,19,11,19,7,19,5,14,19,14,4,19,4,17,1,12,14,1,14,5,1,5,9],t,e),this.type="DodecahedronGeometry",this.parameters={radius:t,detail:e}}static fromJSON(t){return new go(t.radius,t.detail)}}const vo=new Nt,yo=new Nt,xo=new Nt,_o=new Xe;class Mo extends Tn{constructor(t=null,e=1){if(super(),this.type="EdgesGeometry",this.parameters={geometry:t,thresholdAngle:e},null!==t){const n=4,i=Math.pow(10,n),r=Math.cos(ot*e),s=t.getIndex(),a=t.getAttribute("position"),o=s?s.count:a.count,l=[0,0,0],c=["a","b","c"],h=new Array(3),u={},d=[];for(let t=0;t0)){l=i;break}l=i-1}if(i=l,n[i]===s)return i/(r-1);const c=n[i];return(i+(s-c)/(n[i+1]-c))/(r-1)}getTangent(t,e){const n=1e-4;let i=t-n,r=t+n;i<0&&(i=0),r>1&&(r=1);const s=this.getPoint(i),a=this.getPoint(r),o=e||(s.isVector2?new vt:new Nt);return o.copy(a).sub(s).normalize(),o}getTangentAt(t,e){const n=this.getUtoTmapping(t);return this.getTangent(n,e)}computeFrenetFrames(t,e){const n=new Nt,i=[],r=[],s=[],a=new Nt,o=new ue;for(let e=0;e<=t;e++){const n=e/t;i[e]=this.getTangentAt(n,new Nt)}r[0]=new Nt,s[0]=new Nt;let l=Number.MAX_VALUE;const c=Math.abs(i[0].x),h=Math.abs(i[0].y),u=Math.abs(i[0].z);c<=l&&(l=c,n.set(1,0,0)),h<=l&&(l=h,n.set(0,1,0)),u<=l&&n.set(0,0,1),a.crossVectors(i[0],n).normalize(),r[0].crossVectors(i[0],a),s[0].crossVectors(i[0],r[0]);for(let e=1;e<=t;e++){if(r[e]=r[e-1].clone(),s[e]=s[e-1].clone(),a.crossVectors(i[e-1],i[e]),a.length()>Number.EPSILON){a.normalize();const t=Math.acos(ht(i[e-1].dot(i[e]),-1,1));r[e].applyMatrix4(o.makeRotationAxis(a,t))}s[e].crossVectors(i[e],r[e])}if(!0===e){let e=Math.acos(ht(r[0].dot(r[t]),-1,1));e/=t,i[0].dot(a.crossVectors(r[0],r[t]))>0&&(e=-e);for(let n=1;n<=t;n++)r[n].applyMatrix4(o.makeRotationAxis(i[n],e*n)),s[n].crossVectors(i[n],r[n])}return{tangents:i,normals:r,binormals:s}}clone(){return(new this.constructor).copy(this)}copy(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}toJSON(){const t={metadata:{version:4.5,type:"Curve",generator:"Curve.toJSON"}};return t.arcLengthDivisions=this.arcLengthDivisions,t.type=this.type,t}fromJSON(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}}class wo extends bo{constructor(t=0,e=0,n=1,i=1,r=0,s=2*Math.PI,a=!1,o=0){super(),this.type="EllipseCurve",this.aX=t,this.aY=e,this.xRadius=n,this.yRadius=i,this.aStartAngle=r,this.aEndAngle=s,this.aClockwise=a,this.aRotation=o}getPoint(t,e){const n=e||new vt,i=2*Math.PI;let r=this.aEndAngle-this.aStartAngle;const s=Math.abs(r)i;)r-=i;r0?0:(Math.floor(Math.abs(l)/r)+1)*r:0===c&&l===r-1&&(l=r-2,c=1),this.closed||l>0?a=i[(l-1)%r]:(Eo.subVectors(i[0],i[1]).add(i[0]),a=Eo);const h=i[l%r],u=i[(l+1)%r];if(this.closed||l+2i.length-2?i.length-1:s+1],h=i[s>i.length-3?i.length-1:s+2];return n.set(Po(a,o.x,l.x,c.x,h.x),Po(a,o.y,l.y,c.y,h.y)),n}copy(t){super.copy(t),this.points=[];for(let e=0,n=t.points.length;e=n){const t=i[r]-n,s=this.curves[r],a=s.getLength(),o=0===a?0:1-t/a;return s.getPointAt(o,e)}r++}return null}getLength(){const t=this.getCurveLengths();return t[t.length-1]}updateArcLengths(){this.needsUpdate=!0,this.cacheLengths=null,this.getCurveLengths()}getCurveLengths(){if(this.cacheLengths&&this.cacheLengths.length===this.curves.length)return this.cacheLengths;const t=[];let e=0;for(let n=0,i=this.curves.length;n1&&!e[e.length-1].equals(e[0])&&e.push(e[0]),e}copy(t){super.copy(t),this.curves=[];for(let e=0,n=t.curves.length;e0){const t=l.getPoint(0);t.equals(this.currentPoint)||this.lineTo(t.x,t.y)}this.curves.push(l);const c=l.getPoint(1);return this.currentPoint.copy(c),this}copy(t){return super.copy(t),this.currentPoint.copy(t.currentPoint),this}toJSON(){const t=super.toJSON();return t.currentPoint=this.currentPoint.toArray(),t}fromJSON(t){return super.fromJSON(t),this.currentPoint.fromArray(t.currentPoint),this}}class Wo extends Vo{constructor(t){super(t),this.uuid=ct(),this.type="Shape",this.holes=[]}getPointsHoles(t){const e=[];for(let n=0,i=this.holes.length;n80*n){o=c=t[0],l=h=t[1];for(let e=n;ec&&(c=u),d>h&&(h=d);p=Math.max(c-o,h-l),p=0!==p?1/p:0}return Jo(s,a,n,o,l,p),a};function qo(t,e,n,i,r){let s,a;if(r===function(t,e,n,i){let r=0;for(let s=e,a=n-i;s0)for(s=e;s=e;s-=i)a=pl(s,t[s],t[s+1],a);return a&&ol(a,a.next)&&(ml(a),a=a.next),a}function Xo(t,e){if(!t)return t;e||(e=t);let n,i=t;do{if(n=!1,i.steiner||!ol(i,i.next)&&0!==al(i.prev,i,i.next))i=i.next;else{if(ml(i),i=e=i.prev,i===i.next)break;n=!0}}while(n||i!==e);return e}function Jo(t,e,n,i,r,s,a){if(!t)return;!a&&s&&function(t,e,n,i){let r=t;do{null===r.z&&(r.z=nl(r.x,r.y,e,n,i)),r.prevZ=r.prev,r.nextZ=r.next,r=r.next}while(r!==t);r.prevZ.nextZ=null,r.prevZ=null,function(t){let e,n,i,r,s,a,o,l,c=1;do{for(n=t,t=null,s=null,a=0;n;){for(a++,i=n,o=0,e=0;e0||l>0&&i;)0!==o&&(0===l||!i||n.z<=i.z)?(r=n,n=n.nextZ,o--):(r=i,i=i.nextZ,l--),s?s.nextZ=r:t=r,r.prevZ=s,s=r;n=i}s.nextZ=null,c*=2}while(a>1)}(r)}(t,i,r,s);let o,l,c=t;for(;t.prev!==t.next;)if(o=t.prev,l=t.next,s?Zo(t,i,r,s):Yo(t))e.push(o.i/n),e.push(t.i/n),e.push(l.i/n),ml(t),t=l.next,c=l.next;else if((t=l)===c){a?1===a?Jo(t=Qo(Xo(t),e,n),e,n,i,r,s,2):2===a&&Ko(t,e,n,i,r,s):Jo(Xo(t),e,n,i,r,s,1);break}}function Yo(t){const e=t.prev,n=t,i=t.next;if(al(e,n,i)>=0)return!1;let r=t.next.next;for(;r!==t.prev;){if(rl(e.x,e.y,n.x,n.y,i.x,i.y,r.x,r.y)&&al(r.prev,r,r.next)>=0)return!1;r=r.next}return!0}function Zo(t,e,n,i){const r=t.prev,s=t,a=t.next;if(al(r,s,a)>=0)return!1;const o=r.xs.x?r.x>a.x?r.x:a.x:s.x>a.x?s.x:a.x,h=r.y>s.y?r.y>a.y?r.y:a.y:s.y>a.y?s.y:a.y,u=nl(o,l,e,n,i),d=nl(c,h,e,n,i);let p=t.prevZ,m=t.nextZ;for(;p&&p.z>=u&&m&&m.z<=d;){if(p!==t.prev&&p!==t.next&&rl(r.x,r.y,s.x,s.y,a.x,a.y,p.x,p.y)&&al(p.prev,p,p.next)>=0)return!1;if(p=p.prevZ,m!==t.prev&&m!==t.next&&rl(r.x,r.y,s.x,s.y,a.x,a.y,m.x,m.y)&&al(m.prev,m,m.next)>=0)return!1;m=m.nextZ}for(;p&&p.z>=u;){if(p!==t.prev&&p!==t.next&&rl(r.x,r.y,s.x,s.y,a.x,a.y,p.x,p.y)&&al(p.prev,p,p.next)>=0)return!1;p=p.prevZ}for(;m&&m.z<=d;){if(m!==t.prev&&m!==t.next&&rl(r.x,r.y,s.x,s.y,a.x,a.y,m.x,m.y)&&al(m.prev,m,m.next)>=0)return!1;m=m.nextZ}return!0}function Qo(t,e,n){let i=t;do{const r=i.prev,s=i.next.next;!ol(r,s)&&ll(r,i,i.next,s)&&ul(r,s)&&ul(s,r)&&(e.push(r.i/n),e.push(i.i/n),e.push(s.i/n),ml(i),ml(i.next),i=t=s),i=i.next}while(i!==t);return Xo(i)}function Ko(t,e,n,i,r,s){let a=t;do{let t=a.next.next;for(;t!==a.prev;){if(a.i!==t.i&&sl(a,t)){let o=dl(a,t);return a=Xo(a,a.next),o=Xo(o,o.next),Jo(a,e,n,i,r,s),void Jo(o,e,n,i,r,s)}t=t.next}a=a.next}while(a!==t)}function $o(t,e){return t.x-e.x}function tl(t,e){if(e=function(t,e){let n=e;const i=t.x,r=t.y;let s,a=-1/0;do{if(r<=n.y&&r>=n.next.y&&n.next.y!==n.y){const t=n.x+(r-n.y)*(n.next.x-n.x)/(n.next.y-n.y);if(t<=i&&t>a){if(a=t,t===i){if(r===n.y)return n;if(r===n.next.y)return n.next}s=n.x=n.x&&n.x>=l&&i!==n.x&&rl(rs.x||n.x===s.x&&el(s,n)))&&(s=n,u=h)),n=n.next}while(n!==o);return s}(t,e),e){const n=dl(e,t);Xo(e,e.next),Xo(n,n.next)}}function el(t,e){return al(t.prev,t,e.prev)<0&&al(e.next,t,t.next)<0}function nl(t,e,n,i,r){return(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=32767*(t-n)*r)|t<<8))|t<<4))|t<<2))|t<<1))|(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=32767*(e-i)*r)|e<<8))|e<<4))|e<<2))|e<<1))<<1}function il(t){let e=t,n=t;do{(e.x=0&&(t-a)*(i-o)-(n-a)*(e-o)>=0&&(n-a)*(s-o)-(r-a)*(i-o)>=0}function sl(t,e){return t.next.i!==e.i&&t.prev.i!==e.i&&!function(t,e){let n=t;do{if(n.i!==t.i&&n.next.i!==t.i&&n.i!==e.i&&n.next.i!==e.i&&ll(n,n.next,t,e))return!0;n=n.next}while(n!==t);return!1}(t,e)&&(ul(t,e)&&ul(e,t)&&function(t,e){let n=t,i=!1;const r=(t.x+e.x)/2,s=(t.y+e.y)/2;do{n.y>s!=n.next.y>s&&n.next.y!==n.y&&r<(n.next.x-n.x)*(s-n.y)/(n.next.y-n.y)+n.x&&(i=!i),n=n.next}while(n!==t);return i}(t,e)&&(al(t.prev,t,e.prev)||al(t,e.prev,e))||ol(t,e)&&al(t.prev,t,t.next)>0&&al(e.prev,e,e.next)>0)}function al(t,e,n){return(e.y-t.y)*(n.x-e.x)-(e.x-t.x)*(n.y-e.y)}function ol(t,e){return t.x===e.x&&t.y===e.y}function ll(t,e,n,i){const r=hl(al(t,e,n)),s=hl(al(t,e,i)),a=hl(al(n,i,t)),o=hl(al(n,i,e));return r!==s&&a!==o||(!(0!==r||!cl(t,n,e))||(!(0!==s||!cl(t,i,e))||(!(0!==a||!cl(n,t,i))||!(0!==o||!cl(n,e,i)))))}function cl(t,e,n){return e.x<=Math.max(t.x,n.x)&&e.x>=Math.min(t.x,n.x)&&e.y<=Math.max(t.y,n.y)&&e.y>=Math.min(t.y,n.y)}function hl(t){return t>0?1:t<0?-1:0}function ul(t,e){return al(t.prev,t,t.next)<0?al(t,e,t.next)>=0&&al(t,t.prev,e)>=0:al(t,e,t.prev)<0||al(t,t.next,e)<0}function dl(t,e){const n=new fl(t.i,t.x,t.y),i=new fl(e.i,e.x,e.y),r=t.next,s=e.prev;return t.next=e,e.prev=t,n.next=r,r.prev=n,i.next=n,n.prev=i,s.next=i,i.prev=s,i}function pl(t,e,n,i){const r=new fl(t,e,n);return i?(r.next=i.next,r.prev=i,i.next.prev=r,i.next=r):(r.prev=r,r.next=r),r}function ml(t){t.next.prev=t.prev,t.prev.next=t.next,t.prevZ&&(t.prevZ.nextZ=t.nextZ),t.nextZ&&(t.nextZ.prevZ=t.prevZ)}function fl(t,e,n){this.i=t,this.x=e,this.y=n,this.prev=null,this.next=null,this.z=null,this.prevZ=null,this.nextZ=null,this.steiner=!1}class gl{static area(t){const e=t.length;let n=0;for(let i=e-1,r=0;r2&&t[e-1].equals(t[0])&&t.pop()}function yl(t,e){for(let n=0;nNumber.EPSILON){const u=Math.sqrt(h),d=Math.sqrt(l*l+c*c),p=e.x-o/u,m=e.y+a/u,f=((n.x-c/d-p)*c-(n.y+l/d-m)*l)/(a*c-o*l);i=p+a*f-t.x,r=m+o*f-t.y;const g=i*i+r*r;if(g<=2)return new vt(i,r);s=Math.sqrt(g/2)}else{let t=!1;a>Number.EPSILON?l>Number.EPSILON&&(t=!0):a<-Number.EPSILON?l<-Number.EPSILON&&(t=!0):Math.sign(o)===Math.sign(c)&&(t=!0),t?(i=-o,r=a,s=Math.sqrt(h)):(i=a,r=o,s=Math.sqrt(h/2))}return new vt(i/s,r/s)}const P=[];for(let t=0,e=E.length,n=e-1,i=t+1;t=0;t--){const e=t/p,n=h*Math.cos(e*Math.PI/2),i=u*Math.sin(e*Math.PI/2)+d;for(let t=0,e=E.length;t=0;){const i=n;let r=n-1;r<0&&(r=t.length-1);for(let t=0,n=o+2*p;t0)&&d.push(e,r,l),(t!==n-1||o0!=t>0&&this.version++,this._sheen=t}get clearcoat(){return this._clearcoat}set clearcoat(t){this._clearcoat>0!=t>0&&this.version++,this._clearcoat=t}get transmission(){return this._transmission}set transmission(t){this._transmission>0!=t>0&&this.version++,this._transmission=t}copy(t){return super.copy(t),this.defines={STANDARD:"",PHYSICAL:""},this.clearcoat=t.clearcoat,this.clearcoatMap=t.clearcoatMap,this.clearcoatRoughness=t.clearcoatRoughness,this.clearcoatRoughnessMap=t.clearcoatRoughnessMap,this.clearcoatNormalMap=t.clearcoatNormalMap,this.clearcoatNormalScale.copy(t.clearcoatNormalScale),this.ior=t.ior,this.sheen=t.sheen,this.sheenColor.copy(t.sheenColor),this.sheenColorMap=t.sheenColorMap,this.sheenRoughness=t.sheenRoughness,this.sheenRoughnessMap=t.sheenRoughnessMap,this.transmission=t.transmission,this.transmissionMap=t.transmissionMap,this.thickness=t.thickness,this.thicknessMap=t.thicknessMap,this.attenuationDistance=t.attenuationDistance,this.attenuationColor.copy(t.attenuationColor),this.specularIntensity=t.specularIntensity,this.specularIntensityMap=t.specularIntensityMap,this.specularColor.copy(t.specularColor),this.specularColorMap=t.specularColorMap,this}}Bl.prototype.isMeshPhysicalMaterial=!0;class Fl extends Ye{constructor(t){super(),this.type="MeshPhongMaterial",this.color=new nn(16777215),this.specular=new nn(1118481),this.shininess=30,this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new nn(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new vt(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.flatShading=!1,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.specular.copy(t.specular),this.shininess=t.shininess,this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.flatShading=t.flatShading,this}}Fl.prototype.isMeshPhongMaterial=!0;class Ol extends Ye{constructor(t){super(),this.defines={TOON:""},this.type="MeshToonMaterial",this.color=new nn(16777215),this.map=null,this.gradientMap=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new nn(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new vt(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.alphaMap=null,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.gradientMap=t.gradientMap,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.alphaMap=t.alphaMap,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this}}Ol.prototype.isMeshToonMaterial=!0;class Ul extends Ye{constructor(t){super(),this.type="MeshNormalMaterial",this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new vt(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.fog=!1,this.flatShading=!1,this.setValues(t)}copy(t){return super.copy(t),this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.flatShading=t.flatShading,this}}Ul.prototype.isMeshNormalMaterial=!0;class Hl extends Ye{constructor(t){super(),this.type="MeshLambertMaterial",this.color=new nn(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new nn(0),this.emissiveIntensity=1,this.emissiveMap=null,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this}}Hl.prototype.isMeshLambertMaterial=!0;class Gl extends Ye{constructor(t){super(),this.defines={MATCAP:""},this.type="MeshMatcapMaterial",this.color=new nn(16777215),this.matcap=null,this.map=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new vt(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.alphaMap=null,this.flatShading=!1,this.setValues(t)}copy(t){return super.copy(t),this.defines={MATCAP:""},this.color.copy(t.color),this.matcap=t.matcap,this.map=t.map,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.alphaMap=t.alphaMap,this.flatShading=t.flatShading,this}}Gl.prototype.isMeshMatcapMaterial=!0;class kl extends Va{constructor(t){super(),this.type="LineDashedMaterial",this.scale=1,this.dashSize=3,this.gapSize=1,this.setValues(t)}copy(t){return super.copy(t),this.scale=t.scale,this.dashSize=t.dashSize,this.gapSize=t.gapSize,this}}kl.prototype.isLineDashedMaterial=!0;var Vl=Object.freeze({__proto__:null,ShadowMaterial:Nl,SpriteMaterial:oa,RawShaderMaterial:bi,ShaderMaterial:Yn,PointsMaterial:to,MeshPhysicalMaterial:Bl,MeshStandardMaterial:zl,MeshPhongMaterial:Fl,MeshToonMaterial:Ol,MeshNormalMaterial:Ul,MeshLambertMaterial:Hl,MeshDepthMaterial:Hs,MeshDistanceMaterial:Gs,MeshBasicMaterial:rn,MeshMatcapMaterial:Gl,LineDashedMaterial:kl,LineBasicMaterial:Va,Material:Ye});const Wl={arraySlice:function(t,e,n){return Wl.isTypedArray(t)?new t.constructor(t.subarray(e,void 0!==n?n:t.length)):t.slice(e,n)},convertArray:function(t,e,n){return!t||!n&&t.constructor===e?t:"number"==typeof e.BYTES_PER_ELEMENT?new e(t):Array.prototype.slice.call(t)},isTypedArray:function(t){return ArrayBuffer.isView(t)&&!(t instanceof DataView)},getKeyframeOrder:function(t){const e=t.length,n=new Array(e);for(let t=0;t!==e;++t)n[t]=t;return n.sort((function(e,n){return t[e]-t[n]})),n},sortedArray:function(t,e,n){const i=t.length,r=new t.constructor(i);for(let s=0,a=0;a!==i;++s){const i=n[s]*e;for(let n=0;n!==e;++n)r[a++]=t[i+n]}return r},flattenJSON:function(t,e,n,i){let r=1,s=t[0];for(;void 0!==s&&void 0===s[i];)s=t[r++];if(void 0===s)return;let a=s[i];if(void 0!==a)if(Array.isArray(a))do{a=s[i],void 0!==a&&(e.push(s.time),n.push.apply(n,a)),s=t[r++]}while(void 0!==s);else if(void 0!==a.toArray)do{a=s[i],void 0!==a&&(e.push(s.time),a.toArray(n,n.length)),s=t[r++]}while(void 0!==s);else do{a=s[i],void 0!==a&&(e.push(s.time),n.push(a)),s=t[r++]}while(void 0!==s)},subclip:function(t,e,n,i,r=30){const s=t.clone();s.name=e;const a=[];for(let t=0;t=i)){l.push(e.times[t]);for(let n=0;ns.tracks[t].times[0]&&(o=s.tracks[t].times[0]);for(let t=0;t=i.times[u]){const t=u*l+o,e=t+l-o;d=Wl.arraySlice(i.values,t,e)}else{const t=i.createInterpolant(),e=o,n=l-o;t.evaluate(s),d=Wl.arraySlice(t.resultBuffer,e,n)}if("quaternion"===r){(new It).fromArray(d).normalize().conjugate().toArray(d)}const p=a.times.length;for(let t=0;t=r)break t;{const a=e[1];t=r)break e}s=n,n=0}}for(;n>>1;te;)--s;if(++s,0!==r||s!==i){r>=s&&(s=Math.max(s,1),r=s-1);const t=this.getValueSize();this.times=Wl.arraySlice(n,r,s),this.values=Wl.arraySlice(this.values,r*t,s*t)}return this}validate(){let t=!0;const e=this.getValueSize();e-Math.floor(e)!=0&&(console.error("THREE.KeyframeTrack: Invalid value size in track.",this),t=!1);const n=this.times,i=this.values,r=n.length;0===r&&(console.error("THREE.KeyframeTrack: Track is empty.",this),t=!1);let s=null;for(let e=0;e!==r;e++){const i=n[e];if("number"==typeof i&&isNaN(i)){console.error("THREE.KeyframeTrack: Time is not a valid number.",this,e,i),t=!1;break}if(null!==s&&s>i){console.error("THREE.KeyframeTrack: Out of order keys.",this,e,i,s),t=!1;break}s=i}if(void 0!==i&&Wl.isTypedArray(i))for(let e=0,n=i.length;e!==n;++e){const n=i[e];if(isNaN(n)){console.error("THREE.KeyframeTrack: Value is not a valid number.",this,e,n),t=!1;break}}return t}optimize(){const t=Wl.arraySlice(this.times),e=Wl.arraySlice(this.values),n=this.getValueSize(),i=this.getInterpolation()===G,r=t.length-1;let s=1;for(let a=1;a0){t[s]=t[r];for(let t=r*n,i=s*n,a=0;a!==n;++a)e[i+a]=e[t+a];++s}return s!==t.length?(this.times=Wl.arraySlice(t,0,s),this.values=Wl.arraySlice(e,0,s*n)):(this.times=t,this.values=e),this}clone(){const t=Wl.arraySlice(this.times,0),e=Wl.arraySlice(this.values,0),n=new(0,this.constructor)(this.name,t,e);return n.createInterpolant=this.createInterpolant,n}}Yl.prototype.TimeBufferType=Float32Array,Yl.prototype.ValueBufferType=Float32Array,Yl.prototype.DefaultInterpolation=H;class Zl extends Yl{}Zl.prototype.ValueTypeName="bool",Zl.prototype.ValueBufferType=Array,Zl.prototype.DefaultInterpolation=U,Zl.prototype.InterpolantFactoryMethodLinear=void 0,Zl.prototype.InterpolantFactoryMethodSmooth=void 0;class Ql extends Yl{}Ql.prototype.ValueTypeName="color";class Kl extends Yl{}Kl.prototype.ValueTypeName="number";class $l extends jl{constructor(t,e,n,i){super(t,e,n,i)}interpolate_(t,e,n,i){const r=this.resultBuffer,s=this.sampleValues,a=this.valueSize,o=(n-e)/(i-e);let l=t*a;for(let t=l+a;l!==t;l+=4)It.slerpFlat(r,0,s,l-a,s,l,o);return r}}class tc extends Yl{InterpolantFactoryMethodLinear(t){return new $l(this.times,this.values,this.getValueSize(),t)}}tc.prototype.ValueTypeName="quaternion",tc.prototype.DefaultInterpolation=H,tc.prototype.InterpolantFactoryMethodSmooth=void 0;class ec extends Yl{}ec.prototype.ValueTypeName="string",ec.prototype.ValueBufferType=Array,ec.prototype.DefaultInterpolation=U,ec.prototype.InterpolantFactoryMethodLinear=void 0,ec.prototype.InterpolantFactoryMethodSmooth=void 0;class nc extends Yl{}nc.prototype.ValueTypeName="vector";class ic{constructor(t,e=-1,n,i=2500){this.name=t,this.tracks=n,this.duration=e,this.blendMode=i,this.uuid=ct(),this.duration<0&&this.resetDuration()}static parse(t){const e=[],n=t.tracks,i=1/(t.fps||1);for(let t=0,r=n.length;t!==r;++t)e.push(rc(n[t]).scale(i));const r=new this(t.name,t.duration,e,t.blendMode);return r.uuid=t.uuid,r}static toJSON(t){const e=[],n=t.tracks,i={name:t.name,duration:t.duration,tracks:e,uuid:t.uuid,blendMode:t.blendMode};for(let t=0,i=n.length;t!==i;++t)e.push(Yl.toJSON(n[t]));return i}static CreateFromMorphTargetSequence(t,e,n,i){const r=e.length,s=[];for(let t=0;t1){const t=s[1];let e=i[t];e||(i[t]=e=[]),e.push(n)}}const s=[];for(const t in i)s.push(this.CreateFromMorphTargetSequence(t,i[t],e,n));return s}static parseAnimation(t,e){if(!t)return console.error("THREE.AnimationClip: No animation in JSONLoader data."),null;const n=function(t,e,n,i,r){if(0!==n.length){const s=[],a=[];Wl.flattenJSON(n,s,a,i),0!==s.length&&r.push(new t(e,s,a))}},i=[],r=t.name||"default",s=t.fps||30,a=t.blendMode;let o=t.length||-1;const l=t.hierarchy||[];for(let t=0;t{e&&e(r),this.manager.itemEnd(t)}),0),r;if(void 0!==cc[t])return void cc[t].push({onLoad:e,onProgress:n,onError:i});cc[t]=[],cc[t].push({onLoad:e,onProgress:n,onError:i});const s=new Request(t,{headers:new Headers(this.requestHeader),credentials:this.withCredentials?"include":"same-origin"});fetch(s).then((e=>{if(200===e.status||0===e.status){0===e.status&&console.warn("THREE.FileLoader: HTTP Status 0 received.");const n=cc[t],i=e.body.getReader(),r=e.headers.get("Content-Length"),s=r?parseInt(r):0,a=0!==s;let o=0;return new ReadableStream({start(t){!function e(){i.read().then((({done:i,value:r})=>{if(i)t.close();else{o+=r.byteLength;const i=new ProgressEvent("progress",{lengthComputable:a,loaded:o,total:s});for(let t=0,e=n.length;t{const e=new Response(t);switch(this.responseType){case"arraybuffer":return e.arrayBuffer();case"blob":return e.blob();case"document":return e.text().then((t=>(new DOMParser).parseFromString(t,this.mimeType)));case"json":return e.json();default:return e.text()}})).then((e=>{sc.add(t,e);const n=cc[t];delete cc[t];for(let t=0,i=n.length;t{const n=cc[t];if(void 0===n)throw this.manager.itemError(t),e;delete cc[t];for(let t=0,i=n.length;t{this.manager.itemEnd(t)})),this.manager.itemStart(t)}setResponseType(t){return this.responseType=t,this}setMimeType(t){return this.mimeType=t,this}}class uc extends lc{constructor(t){super(t)}load(t,e,n,i){void 0!==this.path&&(t=this.path+t),t=this.manager.resolveURL(t);const r=this,s=sc.get(t);if(void 0!==s)return r.manager.itemStart(t),setTimeout((function(){e&&e(s),r.manager.itemEnd(t)}),0),s;const a=bt("img");function o(){c(),sc.add(t,this),e&&e(this),r.manager.itemEnd(t)}function l(e){c(),i&&i(e),r.manager.itemError(t),r.manager.itemEnd(t)}function c(){a.removeEventListener("load",o,!1),a.removeEventListener("error",l,!1)}return a.addEventListener("load",o,!1),a.addEventListener("error",l,!1),"data:"!==t.substr(0,5)&&void 0!==this.crossOrigin&&(a.crossOrigin=this.crossOrigin),r.manager.itemStart(t),a.src=t,a}}class dc extends lc{constructor(t){super(t)}load(t,e,n,i){const r=new ti,s=new uc(this.manager);s.setCrossOrigin(this.crossOrigin),s.setPath(this.path);let a=0;function o(n){s.load(t[n],(function(t){r.images[n]=t,a++,6===a&&(r.needsUpdate=!0,e&&e(r))}),void 0,i)}for(let e=0;e0:i.vertexColors=t.vertexColors),void 0!==t.uniforms)for(const e in t.uniforms){const r=t.uniforms[e];switch(i.uniforms[e]={},r.type){case"t":i.uniforms[e].value=n(r.value);break;case"c":i.uniforms[e].value=(new nn).setHex(r.value);break;case"v2":i.uniforms[e].value=(new vt).fromArray(r.value);break;case"v3":i.uniforms[e].value=(new Nt).fromArray(r.value);break;case"v4":i.uniforms[e].value=(new Rt).fromArray(r.value);break;case"m3":i.uniforms[e].value=(new yt).fromArray(r.value);break;case"m4":i.uniforms[e].value=(new ue).fromArray(r.value);break;default:i.uniforms[e].value=r.value}}if(void 0!==t.defines&&(i.defines=t.defines),void 0!==t.vertexShader&&(i.vertexShader=t.vertexShader),void 0!==t.fragmentShader&&(i.fragmentShader=t.fragmentShader),void 0!==t.extensions)for(const e in t.extensions)i.extensions[e]=t.extensions[e];if(void 0!==t.shading&&(i.flatShading=1===t.shading),void 0!==t.size&&(i.size=t.size),void 0!==t.sizeAttenuation&&(i.sizeAttenuation=t.sizeAttenuation),void 0!==t.map&&(i.map=n(t.map)),void 0!==t.matcap&&(i.matcap=n(t.matcap)),void 0!==t.alphaMap&&(i.alphaMap=n(t.alphaMap)),void 0!==t.bumpMap&&(i.bumpMap=n(t.bumpMap)),void 0!==t.bumpScale&&(i.bumpScale=t.bumpScale),void 0!==t.normalMap&&(i.normalMap=n(t.normalMap)),void 0!==t.normalMapType&&(i.normalMapType=t.normalMapType),void 0!==t.normalScale){let e=t.normalScale;!1===Array.isArray(e)&&(e=[e,e]),i.normalScale=(new vt).fromArray(e)}return void 0!==t.displacementMap&&(i.displacementMap=n(t.displacementMap)),void 0!==t.displacementScale&&(i.displacementScale=t.displacementScale),void 0!==t.displacementBias&&(i.displacementBias=t.displacementBias),void 0!==t.roughnessMap&&(i.roughnessMap=n(t.roughnessMap)),void 0!==t.metalnessMap&&(i.metalnessMap=n(t.metalnessMap)),void 0!==t.emissiveMap&&(i.emissiveMap=n(t.emissiveMap)),void 0!==t.emissiveIntensity&&(i.emissiveIntensity=t.emissiveIntensity),void 0!==t.specularMap&&(i.specularMap=n(t.specularMap)),void 0!==t.specularIntensityMap&&(i.specularIntensityMap=n(t.specularIntensityMap)),void 0!==t.specularColorMap&&(i.specularColorMap=n(t.specularColorMap)),void 0!==t.envMap&&(i.envMap=n(t.envMap)),void 0!==t.envMapIntensity&&(i.envMapIntensity=t.envMapIntensity),void 0!==t.reflectivity&&(i.reflectivity=t.reflectivity),void 0!==t.refractionRatio&&(i.refractionRatio=t.refractionRatio),void 0!==t.lightMap&&(i.lightMap=n(t.lightMap)),void 0!==t.lightMapIntensity&&(i.lightMapIntensity=t.lightMapIntensity),void 0!==t.aoMap&&(i.aoMap=n(t.aoMap)),void 0!==t.aoMapIntensity&&(i.aoMapIntensity=t.aoMapIntensity),void 0!==t.gradientMap&&(i.gradientMap=n(t.gradientMap)),void 0!==t.clearcoatMap&&(i.clearcoatMap=n(t.clearcoatMap)),void 0!==t.clearcoatRoughnessMap&&(i.clearcoatRoughnessMap=n(t.clearcoatRoughnessMap)),void 0!==t.clearcoatNormalMap&&(i.clearcoatNormalMap=n(t.clearcoatNormalMap)),void 0!==t.clearcoatNormalScale&&(i.clearcoatNormalScale=(new vt).fromArray(t.clearcoatNormalScale)),void 0!==t.transmissionMap&&(i.transmissionMap=n(t.transmissionMap)),void 0!==t.thicknessMap&&(i.thicknessMap=n(t.thicknessMap)),void 0!==t.sheenColorMap&&(i.sheenColorMap=n(t.sheenColorMap)),void 0!==t.sheenRoughnessMap&&(i.sheenRoughnessMap=n(t.sheenRoughnessMap)),i}setTextures(t){return this.textures=t,this}}class zc{static decodeText(t){if("undefined"!=typeof TextDecoder)return(new TextDecoder).decode(t);let e="";for(let n=0,i=t.length;n0){this.source.connect(this.filters[0]);for(let t=1,e=this.filters.length;t0){this.source.disconnect(this.filters[0]);for(let t=1,e=this.filters.length;t0&&this._mixBufferRegionAdditive(n,i,this._addIndex*e,1,e);for(let t=e,r=e+e;t!==r;++t)if(n[t]!==n[t+e]){a.setValue(n,i);break}}saveOriginalState(){const t=this.binding,e=this.buffer,n=this.valueSize,i=n*this._origIndex;t.getValue(e,i);for(let t=n,r=i;t!==r;++t)e[t]=e[i+t%n];this._setIdentity(),this.cumulativeWeight=0,this.cumulativeWeightAdditive=0}restoreOriginalState(){const t=3*this.valueSize;this.binding.setValue(this.buffer,t)}_setAdditiveIdentityNumeric(){const t=this._addIndex*this.valueSize,e=t+this.valueSize;for(let n=t;n=.5)for(let i=0;i!==r;++i)t[e+i]=t[n+i]}_slerp(t,e,n,i){It.slerpFlat(t,e,t,e,t,n,i)}_slerpAdditive(t,e,n,i,r){const s=this._workIndex*r;It.multiplyQuaternionsFlat(t,s,t,e,t,n),It.slerpFlat(t,e,t,e,t,s,i)}_lerp(t,e,n,i,r){const s=1-i;for(let a=0;a!==r;++a){const r=e+a;t[r]=t[r]*s+t[n+a]*i}}_lerpAdditive(t,e,n,i,r){for(let s=0;s!==r;++s){const r=e+s;t[r]=t[r]+t[n+s]*i}}}const ch="\\[\\]\\.:\\/",hh=new RegExp("[\\[\\]\\.:\\/]","g"),uh="[^\\[\\]\\.:\\/]",dh="[^"+ch.replace("\\.","")+"]",ph=/((?:WC+[\/:])*)/.source.replace("WC",uh),mh=/(WCOD+)?/.source.replace("WCOD",dh),fh=/(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace("WC",uh),gh=/\.(WC+)(?:\[(.+)\])?/.source.replace("WC",uh),vh=new RegExp("^"+ph+mh+fh+gh+"$"),yh=["material","materials","bones"];class xh{constructor(t,e,n){this.path=e,this.parsedPath=n||xh.parseTrackName(e),this.node=xh.findNode(t,this.parsedPath.nodeName)||t,this.rootNode=t,this.getValue=this._getValue_unbound,this.setValue=this._setValue_unbound}static create(t,e,n){return t&&t.isAnimationObjectGroup?new xh.Composite(t,e,n):new xh(t,e,n)}static sanitizeNodeName(t){return t.replace(/\s/g,"_").replace(hh,"")}static parseTrackName(t){const e=vh.exec(t);if(!e)throw new Error("PropertyBinding: Cannot parse trackName: "+t);const n={nodeName:e[2],objectName:e[3],objectIndex:e[4],propertyName:e[5],propertyIndex:e[6]},i=n.nodeName&&n.nodeName.lastIndexOf(".");if(void 0!==i&&-1!==i){const t=n.nodeName.substring(i+1);-1!==yh.indexOf(t)&&(n.nodeName=n.nodeName.substring(0,i),n.objectName=t)}if(null===n.propertyName||0===n.propertyName.length)throw new Error("PropertyBinding: can not parse propertyName from trackName: "+t);return n}static findNode(t,e){if(!e||""===e||"."===e||-1===e||e===t.name||e===t.uuid)return t;if(t.skeleton){const n=t.skeleton.getBoneByName(e);if(void 0!==n)return n}if(t.children){const n=function(t){for(let i=0;i=r){const s=r++,c=t[s];e[c.uuid]=l,t[l]=c,e[o]=s,t[s]=a;for(let t=0,e=i;t!==e;++t){const e=n[t],i=e[s],r=e[l];e[l]=i,e[s]=r}}}this.nCachedObjects_=r}uncache(){const t=this._objects,e=this._indicesByUUID,n=this._bindings,i=n.length;let r=this.nCachedObjects_,s=t.length;for(let a=0,o=arguments.length;a!==o;++a){const o=arguments[a].uuid,l=e[o];if(void 0!==l)if(delete e[o],l0&&(e[a.uuid]=l),t[l]=a,t.pop();for(let t=0,e=i;t!==e;++t){const e=n[t];e[l]=e[r],e.pop()}}}this.nCachedObjects_=r}subscribe_(t,e){const n=this._bindingsIndicesByPath;let i=n[t];const r=this._bindings;if(void 0!==i)return r[i];const s=this._paths,a=this._parsedPaths,o=this._objects,l=o.length,c=this.nCachedObjects_,h=new Array(l);i=r.length,n[t]=i,s.push(t),a.push(e),r.push(h);for(let n=c,i=o.length;n!==i;++n){const i=o[n];h[n]=new xh(i,t,e)}return h}unsubscribe_(t){const e=this._bindingsIndicesByPath,n=e[t];if(void 0!==n){const i=this._paths,r=this._parsedPaths,s=this._bindings,a=s.length-1,o=s[a];e[t[a]]=n,s[n]=o,s.pop(),r[n]=r[a],r.pop(),i[n]=i[a],i.pop()}}}_h.prototype.isAnimationObjectGroup=!0;class Mh{constructor(t,e,n=null,i=e.blendMode){this._mixer=t,this._clip=e,this._localRoot=n,this.blendMode=i;const r=e.tracks,s=r.length,a=new Array(s),o={endingStart:k,endingEnd:k};for(let t=0;t!==s;++t){const e=r[t].createInterpolant(null);a[t]=e,e.settings=o}this._interpolantSettings=o,this._interpolants=a,this._propertyBindings=new Array(s),this._cacheIndex=null,this._byClipCacheIndex=null,this._timeScaleInterpolant=null,this._weightInterpolant=null,this.loop=2201,this._loopCount=-1,this._startTime=null,this.time=0,this.timeScale=1,this._effectiveTimeScale=1,this.weight=1,this._effectiveWeight=1,this.repetitions=1/0,this.paused=!1,this.enabled=!0,this.clampWhenFinished=!1,this.zeroSlopeAtStart=!0,this.zeroSlopeAtEnd=!0}play(){return this._mixer._activateAction(this),this}stop(){return this._mixer._deactivateAction(this),this.reset()}reset(){return this.paused=!1,this.enabled=!0,this.time=0,this._loopCount=-1,this._startTime=null,this.stopFading().stopWarping()}isRunning(){return this.enabled&&!this.paused&&0!==this.timeScale&&null===this._startTime&&this._mixer._isActiveAction(this)}isScheduled(){return this._mixer._isActiveAction(this)}startAt(t){return this._startTime=t,this}setLoop(t,e){return this.loop=t,this.repetitions=e,this}setEffectiveWeight(t){return this.weight=t,this._effectiveWeight=this.enabled?t:0,this.stopFading()}getEffectiveWeight(){return this._effectiveWeight}fadeIn(t){return this._scheduleFading(t,0,1)}fadeOut(t){return this._scheduleFading(t,1,0)}crossFadeFrom(t,e,n){if(t.fadeOut(e),this.fadeIn(e),n){const n=this._clip.duration,i=t._clip.duration,r=i/n,s=n/i;t.warp(1,r,e),this.warp(s,1,e)}return this}crossFadeTo(t,e,n){return t.crossFadeFrom(this,e,n)}stopFading(){const t=this._weightInterpolant;return null!==t&&(this._weightInterpolant=null,this._mixer._takeBackControlInterpolant(t)),this}setEffectiveTimeScale(t){return this.timeScale=t,this._effectiveTimeScale=this.paused?0:t,this.stopWarping()}getEffectiveTimeScale(){return this._effectiveTimeScale}setDuration(t){return this.timeScale=this._clip.duration/t,this.stopWarping()}syncWith(t){return this.time=t.time,this.timeScale=t.timeScale,this.stopWarping()}halt(t){return this.warp(this._effectiveTimeScale,0,t)}warp(t,e,n){const i=this._mixer,r=i.time,s=this.timeScale;let a=this._timeScaleInterpolant;null===a&&(a=i._lendControlInterpolant(),this._timeScaleInterpolant=a);const o=a.parameterPositions,l=a.sampleValues;return o[0]=r,o[1]=r+n,l[0]=t/s,l[1]=e/s,this}stopWarping(){const t=this._timeScaleInterpolant;return null!==t&&(this._timeScaleInterpolant=null,this._mixer._takeBackControlInterpolant(t)),this}getMixer(){return this._mixer}getClip(){return this._clip}getRoot(){return this._localRoot||this._mixer._root}_update(t,e,n,i){if(!this.enabled)return void this._updateWeight(t);const r=this._startTime;if(null!==r){const i=(t-r)*n;if(i<0||0===n)return;this._startTime=null,e=n*i}e*=this._updateTimeScale(t);const s=this._updateTime(e),a=this._updateWeight(t);if(a>0){const t=this._interpolants,e=this._propertyBindings;if(this.blendMode===q)for(let n=0,i=t.length;n!==i;++n)t[n].evaluate(s),e[n].accumulateAdditive(a);else for(let n=0,r=t.length;n!==r;++n)t[n].evaluate(s),e[n].accumulate(i,a)}}_updateWeight(t){let e=0;if(this.enabled){e=this.weight;const n=this._weightInterpolant;if(null!==n){const i=n.evaluate(t)[0];e*=i,t>n.parameterPositions[1]&&(this.stopFading(),0===i&&(this.enabled=!1))}}return this._effectiveWeight=e,e}_updateTimeScale(t){let e=0;if(!this.paused){e=this.timeScale;const n=this._timeScaleInterpolant;if(null!==n){e*=n.evaluate(t)[0],t>n.parameterPositions[1]&&(this.stopWarping(),0===e?this.paused=!0:this.timeScale=e)}}return this._effectiveTimeScale=e,e}_updateTime(t){const e=this._clip.duration,n=this.loop;let i=this.time+t,r=this._loopCount;const s=2202===n;if(0===t)return-1===r?i:s&&1==(1&r)?e-i:i;if(2200===n){-1===r&&(this._loopCount=0,this._setEndings(!0,!0,!1));t:{if(i>=e)i=e;else{if(!(i<0)){this.time=i;break t}i=0}this.clampWhenFinished?this.paused=!0:this.enabled=!1,this.time=i,this._mixer.dispatchEvent({type:"finished",action:this,direction:t<0?-1:1})}}else{if(-1===r&&(t>=0?(r=0,this._setEndings(!0,0===this.repetitions,s)):this._setEndings(0===this.repetitions,!0,s)),i>=e||i<0){const n=Math.floor(i/e);i-=e*n,r+=Math.abs(n);const a=this.repetitions-r;if(a<=0)this.clampWhenFinished?this.paused=!0:this.enabled=!1,i=t>0?e:0,this.time=i,this._mixer.dispatchEvent({type:"finished",action:this,direction:t>0?1:-1});else{if(1===a){const e=t<0;this._setEndings(e,!e,s)}else this._setEndings(!1,!1,s);this._loopCount=r,this.time=i,this._mixer.dispatchEvent({type:"loop",action:this,loopDelta:n})}}else this.time=i;if(s&&1==(1&r))return e-i}return i}_setEndings(t,e,n){const i=this._interpolantSettings;n?(i.endingStart=V,i.endingEnd=V):(i.endingStart=t?this.zeroSlopeAtStart?V:k:W,i.endingEnd=e?this.zeroSlopeAtEnd?V:k:W)}_scheduleFading(t,e,n){const i=this._mixer,r=i.time;let s=this._weightInterpolant;null===s&&(s=i._lendControlInterpolant(),this._weightInterpolant=s);const a=s.parameterPositions,o=s.sampleValues;return a[0]=r,o[0]=e,a[1]=r+t,o[1]=n,this}}class bh extends rt{constructor(t){super(),this._root=t,this._initMemoryManager(),this._accuIndex=0,this.time=0,this.timeScale=1}_bindAction(t,e){const n=t._localRoot||this._root,i=t._clip.tracks,r=i.length,s=t._propertyBindings,a=t._interpolants,o=n.uuid,l=this._bindingsByRootAndName;let c=l[o];void 0===c&&(c={},l[o]=c);for(let t=0;t!==r;++t){const r=i[t],l=r.name;let h=c[l];if(void 0!==h)s[t]=h;else{if(h=s[t],void 0!==h){null===h._cacheIndex&&(++h.referenceCount,this._addInactiveBinding(h,o,l));continue}const i=e&&e._propertyBindings[t].binding.parsedPath;h=new lh(xh.create(n,l,i),r.ValueTypeName,r.getValueSize()),++h.referenceCount,this._addInactiveBinding(h,o,l),s[t]=h}a[t].resultBuffer=h.buffer}}_activateAction(t){if(!this._isActiveAction(t)){if(null===t._cacheIndex){const e=(t._localRoot||this._root).uuid,n=t._clip.uuid,i=this._actionsByClip[n];this._bindAction(t,i&&i.knownActions[0]),this._addInactiveAction(t,n,e)}const e=t._propertyBindings;for(let t=0,n=e.length;t!==n;++t){const n=e[t];0==n.useCount++&&(this._lendBinding(n),n.saveOriginalState())}this._lendAction(t)}}_deactivateAction(t){if(this._isActiveAction(t)){const e=t._propertyBindings;for(let t=0,n=e.length;t!==n;++t){const n=e[t];0==--n.useCount&&(n.restoreOriginalState(),this._takeBackBinding(n))}this._takeBackAction(t)}}_initMemoryManager(){this._actions=[],this._nActiveActions=0,this._actionsByClip={},this._bindings=[],this._nActiveBindings=0,this._bindingsByRootAndName={},this._controlInterpolants=[],this._nActiveControlInterpolants=0;const t=this;this.stats={actions:{get total(){return t._actions.length},get inUse(){return t._nActiveActions}},bindings:{get total(){return t._bindings.length},get inUse(){return t._nActiveBindings}},controlInterpolants:{get total(){return t._controlInterpolants.length},get inUse(){return t._nActiveControlInterpolants}}}}_isActiveAction(t){const e=t._cacheIndex;return null!==e&&e=0;--e)t[e].stop();return this}update(t){t*=this.timeScale;const e=this._actions,n=this._nActiveActions,i=this.time+=t,r=Math.sign(t),s=this._accuIndex^=1;for(let a=0;a!==n;++a){e[a]._update(i,t,r,s)}const a=this._bindings,o=this._nActiveBindings;for(let t=0;t!==o;++t)a[t].apply(s);return this}setTime(t){this.time=0;for(let t=0;tthis.max.x||t.ythis.max.y)}containsBox(t){return this.min.x<=t.min.x&&t.max.x<=this.max.x&&this.min.y<=t.min.y&&t.max.y<=this.max.y}getParameter(t,e){return e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y))}intersectsBox(t){return!(t.max.xthis.max.x||t.max.ythis.max.y)}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return Lh.copy(t).clamp(this.min,this.max).sub(t).length()}intersect(t){return this.min.max(t.min),this.max.min(t.max),this}union(t){return this.min.min(t.min),this.max.max(t.max),this}translate(t){return this.min.add(t),this.max.add(t),this}equals(t){return t.min.equals(this.min)&&t.max.equals(this.max)}}Rh.prototype.isBox2=!0;const Ch=new Nt,Ph=new Nt;class Dh{constructor(t=new Nt,e=new Nt){this.start=t,this.end=e}set(t,e){return this.start.copy(t),this.end.copy(e),this}copy(t){return this.start.copy(t.start),this.end.copy(t.end),this}getCenter(t){return t.addVectors(this.start,this.end).multiplyScalar(.5)}delta(t){return t.subVectors(this.end,this.start)}distanceSq(){return this.start.distanceToSquared(this.end)}distance(){return this.start.distanceTo(this.end)}at(t,e){return this.delta(e).multiplyScalar(t).add(this.start)}closestPointToPointParameter(t,e){Ch.subVectors(t,this.start),Ph.subVectors(this.end,this.start);const n=Ph.dot(Ph);let i=Ph.dot(Ch)/n;return e&&(i=ht(i,0,1)),i}closestPointToPoint(t,e,n){const i=this.closestPointToPointParameter(t,e);return this.delta(n).multiplyScalar(i).add(this.start)}applyMatrix4(t){return this.start.applyMatrix4(t),this.end.applyMatrix4(t),this}equals(t){return t.start.equals(this.start)&&t.end.equals(this.end)}clone(){return(new this.constructor).copy(this)}}const Ih=new Nt;const Nh=new Nt,zh=new ue,Bh=new ue;class Fh extends Ka{constructor(t){const e=Oh(t),n=new Tn,i=[],r=[],s=new nn(0,0,1),a=new nn(0,1,0);for(let t=0;t.99999)this.quaternion.set(0,0,0,1);else if(t.y<-.99999)this.quaternion.set(1,0,0,0);else{Qh.set(t.z,0,-t.x).normalize();const e=Math.acos(t.y);this.quaternion.setFromAxisAngle(Qh,e)}}setLength(t,e=.2*t,n=.2*e){this.line.scale.set(1,Math.max(1e-4,t-e),1),this.line.updateMatrix(),this.cone.scale.set(n,e,n),this.cone.position.y=t,this.cone.updateMatrix()}setColor(t){this.line.material.color.set(t),this.cone.material.color.set(t)}copy(t){return super.copy(t,!1),this.line.copy(t.line),this.cone.copy(t.cone),this}},t.Audio=nh,t.AudioAnalyser=oh,t.AudioContext=Vc,t.AudioListener=class extends Be{constructor(){super(),this.type="AudioListener",this.context=Vc.getContext(),this.gain=this.context.createGain(),this.gain.connect(this.context.destination),this.filter=null,this.timeDelta=0,this._clock=new Zc}getInput(){return this.gain}removeFilter(){return null!==this.filter&&(this.gain.disconnect(this.filter),this.filter.disconnect(this.context.destination),this.gain.connect(this.context.destination),this.filter=null),this}getFilter(){return this.filter}setFilter(t){return null!==this.filter?(this.gain.disconnect(this.filter),this.filter.disconnect(this.context.destination)):this.gain.disconnect(this.context.destination),this.filter=t,this.gain.connect(this.filter),this.filter.connect(this.context.destination),this}getMasterVolume(){return this.gain.gain.value}setMasterVolume(t){return this.gain.gain.setTargetAtTime(t,this.context.currentTime,.01),this}updateMatrixWorld(t){super.updateMatrixWorld(t);const e=this.context.listener,n=this.up;if(this.timeDelta=this._clock.getDelta(),this.matrixWorld.decompose(Kc,$c,th),eh.set(0,0,-1).applyQuaternion($c),e.positionX){const t=this.context.currentTime+this.timeDelta;e.positionX.linearRampToValueAtTime(Kc.x,t),e.positionY.linearRampToValueAtTime(Kc.y,t),e.positionZ.linearRampToValueAtTime(Kc.z,t),e.forwardX.linearRampToValueAtTime(eh.x,t),e.forwardY.linearRampToValueAtTime(eh.y,t),e.forwardZ.linearRampToValueAtTime(eh.z,t),e.upX.linearRampToValueAtTime(n.x,t),e.upY.linearRampToValueAtTime(n.y,t),e.upZ.linearRampToValueAtTime(n.z,t)}else e.setPosition(Kc.x,Kc.y,Kc.z),e.setOrientation(eh.x,eh.y,eh.z,n.x,n.y,n.z)}},t.AudioLoader=Wc,t.AxesHelper=tu,t.AxisHelper=function(t){return console.warn("THREE.AxisHelper has been renamed to THREE.AxesHelper."),new tu(t)},t.BackSide=1,t.BasicDepthPacking=3200,t.BasicShadowMap=0,t.BinaryTextureLoader=function(t){return console.warn("THREE.BinaryTextureLoader has been renamed to THREE.DataTextureLoader."),new pc(t)},t.Bone=Da,t.BooleanKeyframeTrack=Zl,t.BoundingBoxHelper=function(t,e){return console.warn("THREE.BoundingBoxHelper has been deprecated. Creating a THREE.BoxHelper instead."),new Zh(t,e)},t.Box2=Rh,t.Box3=Ft,t.Box3Helper=class extends Ka{constructor(t,e=16776960){const n=new Uint16Array([0,1,1,2,2,3,3,0,4,5,5,6,6,7,7,4,0,4,1,5,2,6,3,7]),i=new Tn;i.setIndex(new on(n,1)),i.setAttribute("position",new gn([1,1,1,-1,1,1,-1,-1,1,1,-1,1,1,1,-1,-1,1,-1,-1,-1,-1,1,-1,-1],3)),super(i,new Va({color:e,toneMapped:!1})),this.box=t,this.type="Box3Helper",this.geometry.computeBoundingSphere()}updateMatrixWorld(t){const e=this.box;e.isEmpty()||(e.getCenter(this.position),e.getSize(this.scale),this.scale.multiplyScalar(.5),super.updateMatrixWorld(t))}},t.BoxBufferGeometry=jn,t.BoxGeometry=jn,t.BoxHelper=Zh,t.BufferAttribute=on,t.BufferGeometry=Tn,t.BufferGeometryLoader=Fc,t.ByteType=1010,t.Cache=sc,t.Camera=Zn,t.CameraHelper=class extends Ka{constructor(t){const e=new Tn,n=new Va({color:16777215,vertexColors:!0,toneMapped:!1}),i=[],r=[],s={},a=new nn(16755200),o=new nn(16711680),l=new nn(43775),c=new nn(16777215),h=new nn(3355443);function u(t,e,n){d(t,n),d(e,n)}function d(t,e){i.push(0,0,0),r.push(e.r,e.g,e.b),void 0===s[t]&&(s[t]=[]),s[t].push(i.length/3-1)}u("n1","n2",a),u("n2","n4",a),u("n4","n3",a),u("n3","n1",a),u("f1","f2",a),u("f2","f4",a),u("f4","f3",a),u("f3","f1",a),u("n1","f1",a),u("n2","f2",a),u("n3","f3",a),u("n4","f4",a),u("p","n1",o),u("p","n2",o),u("p","n3",o),u("p","n4",o),u("u1","u2",l),u("u2","u3",l),u("u3","u1",l),u("c","t",c),u("p","c",h),u("cn1","cn2",h),u("cn3","cn4",h),u("cf1","cf2",h),u("cf3","cf4",h),e.setAttribute("position",new gn(i,3)),e.setAttribute("color",new gn(r,3)),super(e,n),this.type="CameraHelper",this.camera=t,this.camera.updateProjectionMatrix&&this.camera.updateProjectionMatrix(),this.matrix=t.matrixWorld,this.matrixAutoUpdate=!1,this.pointMap=s,this.update()}update(){const t=this.geometry,e=this.pointMap;Xh.projectionMatrixInverse.copy(this.camera.projectionMatrixInverse),Jh("c",e,t,Xh,0,0,-1),Jh("t",e,t,Xh,0,0,1),Jh("n1",e,t,Xh,-1,-1,-1),Jh("n2",e,t,Xh,1,-1,-1),Jh("n3",e,t,Xh,-1,1,-1),Jh("n4",e,t,Xh,1,1,-1),Jh("f1",e,t,Xh,-1,-1,1),Jh("f2",e,t,Xh,1,-1,1),Jh("f3",e,t,Xh,-1,1,1),Jh("f4",e,t,Xh,1,1,1),Jh("u1",e,t,Xh,.7,1.1,-1),Jh("u2",e,t,Xh,-.7,1.1,-1),Jh("u3",e,t,Xh,0,2,-1),Jh("cf1",e,t,Xh,-1,0,1),Jh("cf2",e,t,Xh,1,0,1),Jh("cf3",e,t,Xh,0,-1,1),Jh("cf4",e,t,Xh,0,1,1),Jh("cn1",e,t,Xh,-1,0,-1),Jh("cn2",e,t,Xh,1,0,-1),Jh("cn3",e,t,Xh,0,-1,-1),Jh("cn4",e,t,Xh,0,1,-1),t.getAttribute("position").needsUpdate=!0}dispose(){this.geometry.dispose(),this.material.dispose()}},t.CanvasRenderer=function(){console.error("THREE.CanvasRenderer has been removed")},t.CanvasTexture=ho,t.CatmullRomCurve3=Co,t.CineonToneMapping=3,t.CircleBufferGeometry=uo,t.CircleGeometry=uo,t.ClampToEdgeWrapping=u,t.Clock=Zc,t.Color=nn,t.ColorKeyframeTrack=Ql,t.CompressedTexture=co,t.CompressedTextureLoader=class extends lc{constructor(t){super(t)}load(t,e,n,i){const r=this,s=[],a=new co,o=new hc(this.manager);o.setPath(this.path),o.setResponseType("arraybuffer"),o.setRequestHeader(this.requestHeader),o.setWithCredentials(r.withCredentials);let l=0;function c(c){o.load(t[c],(function(t){const n=r.parse(t,!0);s[c]={width:n.width,height:n.height,format:n.format,mipmaps:n.mipmaps},l+=1,6===l&&(1===n.mipmapCount&&(a.minFilter=g),a.image=s,a.format=n.format,a.needsUpdate=!0,e&&e(a))}),n,i)}if(Array.isArray(t))for(let e=0,n=t.length;e65504&&(console.warn("THREE.DataUtils.toHalfFloat(): value exceeds 65504."),t=65504),eu[0]=t;const e=nu[0];let n=e>>16&32768,i=e>>12&2047;const r=e>>23&255;return r<103?n:r>142?(n|=31744,n|=(255==r?0:1)&&8388607&e,n):r<113?(i|=2048,n|=(i>>114-r)+(i>>113-r&1),n):(n|=r-112<<10|i>>1,n+=1&i,n)}},t.DecrementStencilOp=7683,t.DecrementWrapStencilOp=34056,t.DefaultLoadingManager=oc,t.DepthFormat=A,t.DepthStencilFormat=L,t.DepthTexture=Zs,t.DirectionalLight=Rc,t.DirectionalLightHelper=class extends Be{constructor(t,e,n){super(),this.light=t,this.light.updateMatrixWorld(),this.matrix=t.matrixWorld,this.matrixAutoUpdate=!1,this.color=n,void 0===e&&(e=1);let i=new Tn;i.setAttribute("position",new gn([-e,e,0,e,e,0,e,-e,0,-e,-e,0,-e,e,0],3));const r=new Va({fog:!1,toneMapped:!1});this.lightPlane=new Ya(i,r),this.add(this.lightPlane),i=new Tn,i.setAttribute("position",new gn([0,0,0,0,0,1],3)),this.targetLine=new Ya(i,r),this.add(this.targetLine),this.update()}dispose(){this.lightPlane.geometry.dispose(),this.lightPlane.material.dispose(),this.targetLine.geometry.dispose(),this.targetLine.material.dispose()}update(){Vh.setFromMatrixPosition(this.light.matrixWorld),Wh.setFromMatrixPosition(this.light.target.matrixWorld),jh.subVectors(Wh,Vh),this.lightPlane.lookAt(Wh),void 0!==this.color?(this.lightPlane.material.color.set(this.color),this.targetLine.material.color.set(this.color)):(this.lightPlane.material.color.copy(this.light.color),this.targetLine.material.color.copy(this.light.color)),this.targetLine.lookAt(Wh),this.targetLine.scale.z=jh.length()}},t.DiscreteInterpolant=Jl,t.DodecahedronBufferGeometry=go,t.DodecahedronGeometry=go,t.DoubleSide=2,t.DstAlphaFactor=206,t.DstColorFactor=208,t.DynamicBufferAttribute=function(t,e){return console.warn("THREE.DynamicBufferAttribute has been removed. Use new THREE.BufferAttribute().setUsage( THREE.DynamicDrawUsage ) instead."),new on(t,e).setUsage(nt)},t.DynamicCopyUsage=35050,t.DynamicDrawUsage=nt,t.DynamicReadUsage=35049,t.EdgesGeometry=Mo,t.EdgesHelper=function(t,e){return console.warn("THREE.EdgesHelper has been removed. Use THREE.EdgesGeometry instead."),new Ka(new Mo(t.geometry),new Va({color:void 0!==e?e:16777215}))},t.EllipseCurve=wo,t.EqualDepth=4,t.EqualStencilFunc=514,t.EquirectangularReflectionMapping=a,t.EquirectangularRefractionMapping=o,t.Euler=Me,t.EventDispatcher=rt,t.ExtrudeBufferGeometry=xl,t.ExtrudeGeometry=xl,t.FaceColors=1,t.FileLoader=hc,t.FlatShading=1,t.Float16BufferAttribute=fn,t.Float32Attribute=function(t,e){return console.warn("THREE.Float32Attribute has been removed. Use new THREE.Float32BufferAttribute() instead."),new gn(t,e)},t.Float32BufferAttribute=gn,t.Float64Attribute=function(t,e){return console.warn("THREE.Float64Attribute has been removed. Use new THREE.Float64BufferAttribute() instead."),new vn(t,e)},t.Float64BufferAttribute=vn,t.FloatType=b,t.Fog=na,t.FogExp2=ea,t.Font=function(){console.error("THREE.Font has been moved to /examples/jsm/loaders/FontLoader.js")},t.FontLoader=function(){console.error("THREE.FontLoader has been moved to /examples/jsm/loaders/FontLoader.js")},t.FramebufferTexture=lo,t.FrontSide=0,t.Frustum=li,t.GLBufferAttribute=Th,t.GLSL1="100",t.GLSL3=it,t.GammaEncoding=Y,t.GreaterDepth=6,t.GreaterEqualDepth=5,t.GreaterEqualStencilFunc=518,t.GreaterStencilFunc=516,t.GridHelper=kh,t.Group=Xs,t.HalfFloatType=w,t.HemisphereLight=gc,t.HemisphereLightHelper=class extends Be{constructor(t,e,n){super(),this.light=t,this.light.updateMatrixWorld(),this.matrix=t.matrixWorld,this.matrixAutoUpdate=!1,this.color=n;const i=new wl(e);i.rotateY(.5*Math.PI),this.material=new rn({wireframe:!0,fog:!1,toneMapped:!1}),void 0===this.color&&(this.material.vertexColors=!0);const r=i.getAttribute("position"),s=new Float32Array(3*r.count);i.setAttribute("color",new on(s,3)),this.add(new Vn(i,this.material)),this.update()}dispose(){this.children[0].geometry.dispose(),this.children[0].material.dispose()}update(){const t=this.children[0];if(void 0!==this.color)this.material.color.set(this.color);else{const e=t.geometry.getAttribute("color");Hh.copy(this.light.color),Gh.copy(this.light.groundColor);for(let t=0,n=e.count;t0){const n=new ac(e);r=new uc(n),r.setCrossOrigin(this.crossOrigin);for(let e=0,n=t.length;e0){i=new uc(this.manager),i.setCrossOrigin(this.crossOrigin);for(let e=0,i=t.length;eNumber.EPSILON){if(l<0&&(n=e[s],o=-o,a=e[r],l=-l),t.ya.y)continue;if(t.y===n.y){if(t.x===n.x)return!0}else{const e=l*(t.x-n.x)-o*(t.y-n.y);if(0===e)return!0;if(e<0)continue;i=!i}}else{if(t.y!==n.y)continue;if(a.x<=t.x&&t.x<=n.x||n.x<=t.x&&t.x<=a.x)return!0}}return i}const r=gl.isClockWise,s=this.subPaths;if(0===s.length)return[];if(!0===e)return n(s);let a,o,l;const c=[];if(1===s.length)return o=s[0],l=new Wo,l.curves=o.curves,c.push(l),c;let h=!r(s[0].getPoints());h=t?!h:h;const u=[],d=[];let p,m,f=[],g=0;d[g]=void 0,f[g]=[];for(let e=0,n=s.length;e1){let t=!1;const e=[];for(let t=0,e=d.length;t0&&(t||(f=u))}for(let t=0,e=d.length;t>8&255]+vt[t>>16&255]+vt[t>>24&255]+"-"+vt[255&e]+vt[e>>8&255]+"-"+vt[e>>16&15|64]+vt[e>>24&255]+"-"+vt[63&n|128]+vt[n>>8&255]+"-"+vt[n>>16&255]+vt[n>>24&255]+vt[255&i]+vt[i>>8&255]+vt[i>>16&255]+vt[i>>24&255]).toUpperCase()}function Mt(t,e,n){return Math.max(e,Math.min(n,t))}function wt(t,e){return(t%e+e)%e}function St(t,e,n){return(1-n)*t+n*e}function Tt(t){return 0==(t&t-1)&&0!==t}function Et(t){return Math.pow(2,Math.ceil(Math.log(t)/Math.LN2))}function At(t){return Math.pow(2,Math.floor(Math.log(t)/Math.LN2))}var Rt=Object.freeze({__proto__:null,DEG2RAD:xt,RAD2DEG:_t,generateUUID:bt,clamp:Mt,euclideanModulo:wt,mapLinear:function(t,e,n,i,r){return i+(t-e)*(r-i)/(n-e)},inverseLerp:function(t,e,n){return t!==e?(n-t)/(e-t):0},lerp:St,damp:function(t,e,n,i){return St(t,e,1-Math.exp(-n*i))},pingpong:function(t,e=1){return e-Math.abs(wt(t,2*e)-e)},smoothstep:function(t,e,n){return t<=e?0:t>=n?1:(t=(t-e)/(n-e))*t*(3-2*t)},smootherstep:function(t,e,n){return t<=e?0:t>=n?1:(t=(t-e)/(n-e))*t*t*(t*(6*t-15)+10)},randInt:function(t,e){return t+Math.floor(Math.random()*(e-t+1))},randFloat:function(t,e){return t+Math.random()*(e-t)},randFloatSpread:function(t){return t*(.5-Math.random())},seededRandom:function(t){return void 0!==t&&(yt=t%2147483647),yt=16807*yt%2147483647,(yt-1)/2147483646},degToRad:function(t){return t*xt},radToDeg:function(t){return t*_t},isPowerOfTwo:Tt,ceilPowerOfTwo:Et,floorPowerOfTwo:At,setQuaternionFromProperEuler:function(t,e,n,i,r){const s=Math.cos,a=Math.sin,o=s(n/2),l=a(n/2),c=s((e+i)/2),h=a((e+i)/2),u=s((e-i)/2),d=a((e-i)/2),p=s((i-e)/2),m=a((i-e)/2);switch(r){case"XYX":t.set(o*h,l*u,l*d,o*c);break;case"YZY":t.set(l*d,o*h,l*u,o*c);break;case"ZXZ":t.set(l*u,l*d,o*h,o*c);break;case"XZX":t.set(o*h,l*m,l*p,o*c);break;case"YXY":t.set(l*p,o*h,l*m,o*c);break;case"ZYZ":t.set(l*m,l*p,o*h,o*c);break;default:console.warn("THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: "+r)}}});class Lt{constructor(t=0,e=0){this.x=t,this.y=e}get width(){return this.x}set width(t){this.x=t}get height(){return this.y}set height(t){this.y=t}set(t,e){return this.x=t,this.y=e,this}setScalar(t){return this.x=t,this.y=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y)}copy(t){return this.x=t.x,this.y=t.y,this}add(t,e){return void 0!==e?(console.warn("THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(t,e)):(this.x+=t.x,this.y+=t.y,this)}addScalar(t){return this.x+=t,this.y+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this}sub(t,e){return void 0!==e?(console.warn("THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(t,e)):(this.x-=t.x,this.y-=t.y,this)}subScalar(t){return this.x-=t,this.y-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this}multiply(t){return this.x*=t.x,this.y*=t.y,this}multiplyScalar(t){return this.x*=t,this.y*=t,this}divide(t){return this.x/=t.x,this.y/=t.y,this}divideScalar(t){return this.multiplyScalar(1/t)}applyMatrix3(t){const e=this.x,n=this.y,i=t.elements;return this.x=i[0]*e+i[3]*n+i[6],this.y=i[1]*e+i[4]*n+i[7],this}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this}clamp(t,e){return this.x=Math.max(t.x,Math.min(e.x,this.x)),this.y=Math.max(t.y,Math.min(e.y,this.y)),this}clampScalar(t,e){return this.x=Math.max(t,Math.min(e,this.x)),this.y=Math.max(t,Math.min(e,this.y)),this}clampLength(t,e){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(t,Math.min(e,n)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this}roundToZero(){return 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}negate(){return this.x=-this.x,this.y=-this.y,this}dot(t){return this.x*t.x+this.y*t.y}cross(t){return this.x*t.y-this.y*t.x}lengthSq(){return this.x*this.x+this.y*this.y}length(){return Math.sqrt(this.x*this.x+this.y*this.y)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)}normalize(){return this.divideScalar(this.length()||1)}angle(){return Math.atan2(-this.y,-this.x)+Math.PI}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,n=this.y-t.y;return e*e+n*n}manhattanDistanceTo(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this}lerpVectors(t,e,n){return this.x=t.x+(e.x-t.x)*n,this.y=t.y+(e.y-t.y)*n,this}equals(t){return t.x===this.x&&t.y===this.y}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t}fromBufferAttribute(t,e,n){return void 0!==n&&console.warn("THREE.Vector2: offset has been removed from .fromBufferAttribute()."),this.x=t.getX(e),this.y=t.getY(e),this}rotateAround(t,e){const n=Math.cos(e),i=Math.sin(e),r=this.x-t.x,s=this.y-t.y;return this.x=r*n-s*i+t.x,this.y=r*i+s*n+t.y,this}random(){return this.x=Math.random(),this.y=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y}}Lt.prototype.isVector2=!0;class Ct{constructor(){this.elements=[1,0,0,0,1,0,0,0,1],arguments.length>0&&console.error("THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.")}set(t,e,n,i,r,s,a,o,l){const c=this.elements;return c[0]=t,c[1]=i,c[2]=a,c[3]=e,c[4]=r,c[5]=o,c[6]=n,c[7]=s,c[8]=l,this}identity(){return this.set(1,0,0,0,1,0,0,0,1),this}copy(t){const e=this.elements,n=t.elements;return e[0]=n[0],e[1]=n[1],e[2]=n[2],e[3]=n[3],e[4]=n[4],e[5]=n[5],e[6]=n[6],e[7]=n[7],e[8]=n[8],this}extractBasis(t,e,n){return t.setFromMatrix3Column(this,0),e.setFromMatrix3Column(this,1),n.setFromMatrix3Column(this,2),this}setFromMatrix4(t){const e=t.elements;return this.set(e[0],e[4],e[8],e[1],e[5],e[9],e[2],e[6],e[10]),this}multiply(t){return this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const n=t.elements,i=e.elements,r=this.elements,s=n[0],a=n[3],o=n[6],l=n[1],c=n[4],h=n[7],u=n[2],d=n[5],p=n[8],m=i[0],f=i[3],g=i[6],v=i[1],y=i[4],x=i[7],_=i[2],b=i[5],M=i[8];return r[0]=s*m+a*v+o*_,r[3]=s*f+a*y+o*b,r[6]=s*g+a*x+o*M,r[1]=l*m+c*v+h*_,r[4]=l*f+c*y+h*b,r[7]=l*g+c*x+h*M,r[2]=u*m+d*v+p*_,r[5]=u*f+d*y+p*b,r[8]=u*g+d*x+p*M,this}multiplyScalar(t){const e=this.elements;return e[0]*=t,e[3]*=t,e[6]*=t,e[1]*=t,e[4]*=t,e[7]*=t,e[2]*=t,e[5]*=t,e[8]*=t,this}determinant(){const t=this.elements,e=t[0],n=t[1],i=t[2],r=t[3],s=t[4],a=t[5],o=t[6],l=t[7],c=t[8];return e*s*c-e*a*l-n*r*c+n*a*o+i*r*l-i*s*o}invert(){const t=this.elements,e=t[0],n=t[1],i=t[2],r=t[3],s=t[4],a=t[5],o=t[6],l=t[7],c=t[8],h=c*s-a*l,u=a*o-c*r,d=l*r-s*o,p=e*h+n*u+i*d;if(0===p)return this.set(0,0,0,0,0,0,0,0,0);const m=1/p;return t[0]=h*m,t[1]=(i*l-c*n)*m,t[2]=(a*n-i*s)*m,t[3]=u*m,t[4]=(c*e-i*o)*m,t[5]=(i*r-a*e)*m,t[6]=d*m,t[7]=(n*o-l*e)*m,t[8]=(s*e-n*r)*m,this}transpose(){let t;const e=this.elements;return t=e[1],e[1]=e[3],e[3]=t,t=e[2],e[2]=e[6],e[6]=t,t=e[5],e[5]=e[7],e[7]=t,this}getNormalMatrix(t){return this.setFromMatrix4(t).invert().transpose()}transposeIntoArray(t){const e=this.elements;return t[0]=e[0],t[1]=e[3],t[2]=e[6],t[3]=e[1],t[4]=e[4],t[5]=e[7],t[6]=e[2],t[7]=e[5],t[8]=e[8],this}setUvTransform(t,e,n,i,r,s,a){const o=Math.cos(r),l=Math.sin(r);return this.set(n*o,n*l,-n*(o*s+l*a)+s+t,-i*l,i*o,-i*(-l*s+o*a)+a+e,0,0,1),this}scale(t,e){const n=this.elements;return n[0]*=t,n[3]*=t,n[6]*=t,n[1]*=e,n[4]*=e,n[7]*=e,this}rotate(t){const e=Math.cos(t),n=Math.sin(t),i=this.elements,r=i[0],s=i[3],a=i[6],o=i[1],l=i[4],c=i[7];return i[0]=e*r+n*o,i[3]=e*s+n*l,i[6]=e*a+n*c,i[1]=-n*r+e*o,i[4]=-n*s+e*l,i[7]=-n*a+e*c,this}translate(t,e){const n=this.elements;return n[0]+=t*n[2],n[3]+=t*n[5],n[6]+=t*n[8],n[1]+=e*n[2],n[4]+=e*n[5],n[7]+=e*n[8],this}equals(t){const e=this.elements,n=t.elements;for(let t=0;t<9;t++)if(e[t]!==n[t])return!1;return!0}fromArray(t,e=0){for(let n=0;n<9;n++)this.elements[n]=t[n+e];return this}toArray(t=[],e=0){const n=this.elements;return t[e]=n[0],t[e+1]=n[1],t[e+2]=n[2],t[e+3]=n[3],t[e+4]=n[4],t[e+5]=n[5],t[e+6]=n[6],t[e+7]=n[7],t[e+8]=n[8],t}clone(){return(new this.constructor).fromArray(this.elements)}}function Pt(t){if(0===t.length)return-1/0;let e=t[0];for(let n=1,i=t.length;ne&&(e=t[n]);return e}Ct.prototype.isMatrix3=!0;const Dt={Int8Array:Int8Array,Uint8Array:Uint8Array,Uint8ClampedArray:Uint8ClampedArray,Int16Array:Int16Array,Uint16Array:Uint16Array,Int32Array:Int32Array,Uint32Array:Uint32Array,Float32Array:Float32Array,Float64Array:Float64Array};function It(t,e){return new Dt[t](e)}function Nt(t){return document.createElementNS("http://www.w3.org/1999/xhtml",t)}const Bt={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074},zt={h:0,s:0,l:0},Ot={h:0,s:0,l:0};function Ft(t,e,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?t+6*(e-t)*n:n<.5?e:n<2/3?t+6*(e-t)*(2/3-n):t}function Ut(t){return t<.04045?.0773993808*t:Math.pow(.9478672986*t+.0521327014,2.4)}function Ht(t){return t<.0031308?12.92*t:1.055*Math.pow(t,.41666)-.055}class Gt{constructor(t,e,n){return void 0===e&&void 0===n?this.set(t):this.setRGB(t,e,n)}set(t){return t&&t.isColor?this.copy(t):"number"==typeof t?this.setHex(t):"string"==typeof t&&this.setStyle(t),this}setScalar(t){return this.r=t,this.g=t,this.b=t,this}setHex(t){return t=Math.floor(t),this.r=(t>>16&255)/255,this.g=(t>>8&255)/255,this.b=(255&t)/255,this}setRGB(t,e,n){return this.r=t,this.g=e,this.b=n,this}setHSL(t,e,n){if(t=wt(t,1),e=Mt(e,0,1),n=Mt(n,0,1),0===e)this.r=this.g=this.b=n;else{const i=n<=.5?n*(1+e):n+e-n*e,r=2*n-i;this.r=Ft(r,i,t+1/3),this.g=Ft(r,i,t),this.b=Ft(r,i,t-1/3)}return this}setStyle(t){function e(e){void 0!==e&&parseFloat(e)<1&&console.warn("THREE.Color: Alpha component of "+t+" will be ignored.")}let n;if(n=/^((?:rgb|hsl)a?)\(([^\)]*)\)/.exec(t)){let t;const i=n[1],r=n[2];switch(i){case"rgb":case"rgba":if(t=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(r))return this.r=Math.min(255,parseInt(t[1],10))/255,this.g=Math.min(255,parseInt(t[2],10))/255,this.b=Math.min(255,parseInt(t[3],10))/255,e(t[4]),this;if(t=/^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(r))return this.r=Math.min(100,parseInt(t[1],10))/100,this.g=Math.min(100,parseInt(t[2],10))/100,this.b=Math.min(100,parseInt(t[3],10))/100,e(t[4]),this;break;case"hsl":case"hsla":if(t=/^\s*(\d*\.?\d+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(r)){const n=parseFloat(t[1])/360,i=parseInt(t[2],10)/100,r=parseInt(t[3],10)/100;return e(t[4]),this.setHSL(n,i,r)}}}else if(n=/^\#([A-Fa-f\d]+)$/.exec(t)){const t=n[1],e=t.length;if(3===e)return this.r=parseInt(t.charAt(0)+t.charAt(0),16)/255,this.g=parseInt(t.charAt(1)+t.charAt(1),16)/255,this.b=parseInt(t.charAt(2)+t.charAt(2),16)/255,this;if(6===e)return this.r=parseInt(t.charAt(0)+t.charAt(1),16)/255,this.g=parseInt(t.charAt(2)+t.charAt(3),16)/255,this.b=parseInt(t.charAt(4)+t.charAt(5),16)/255,this}return t&&t.length>0?this.setColorName(t):this}setColorName(t){const e=Bt[t.toLowerCase()];return void 0!==e?this.setHex(e):console.warn("THREE.Color: Unknown color "+t),this}clone(){return new this.constructor(this.r,this.g,this.b)}copy(t){return this.r=t.r,this.g=t.g,this.b=t.b,this}copySRGBToLinear(t){return this.r=Ut(t.r),this.g=Ut(t.g),this.b=Ut(t.b),this}copyLinearToSRGB(t){return this.r=Ht(t.r),this.g=Ht(t.g),this.b=Ht(t.b),this}convertSRGBToLinear(){return this.copySRGBToLinear(this),this}convertLinearToSRGB(){return this.copyLinearToSRGB(this),this}getHex(){return 255*this.r<<16^255*this.g<<8^255*this.b<<0}getHexString(){return("000000"+this.getHex().toString(16)).slice(-6)}getHSL(t){const e=this.r,n=this.g,i=this.b,r=Math.max(e,n,i),s=Math.min(e,n,i);let a,o;const l=(s+r)/2;if(s===r)a=0,o=0;else{const t=r-s;switch(o=l<=.5?t/(r+s):t/(2-r-s),r){case e:a=(n-i)/t+(n2048||e.height>2048?(console.warn("THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons",t),e.toDataURL("image/jpeg",.6)):e.toDataURL("image/png")}static sRGBToLinear(t){if("undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&t instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&t instanceof ImageBitmap){const e=Nt("canvas");e.width=t.width,e.height=t.height;const n=e.getContext("2d");n.drawImage(t,0,0,t.width,t.height);const i=n.getImageData(0,0,t.width,t.height),r=i.data;for(let t=0;t1)switch(this.wrapS){case h:t.x=t.x-Math.floor(t.x);break;case u:t.x=t.x<0?0:1;break;case d:1===Math.abs(Math.floor(t.x)%2)?t.x=Math.ceil(t.x)-t.x:t.x=t.x-Math.floor(t.x)}if(t.y<0||t.y>1)switch(this.wrapT){case h:t.y=t.y-Math.floor(t.y);break;case u:t.y=t.y<0?0:1;break;case d:1===Math.abs(Math.floor(t.y)%2)?t.y=Math.ceil(t.y)-t.y:t.y=t.y-Math.floor(t.y)}return this.flipY&&(t.y=1-t.y),t}set needsUpdate(t){!0===t&&this.version++}}function qt(t){return"undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&t instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&t instanceof ImageBitmap?Vt.getDataURL(t):t.data?{data:Array.prototype.slice.call(t.data),width:t.width,height:t.height,type:t.data.constructor.name}:(console.warn("THREE.Texture: Unable to serialize Texture."),{})}jt.DEFAULT_IMAGE=void 0,jt.DEFAULT_MAPPING=i,jt.prototype.isTexture=!0;class Xt{constructor(t=0,e=0,n=0,i=1){this.x=t,this.y=e,this.z=n,this.w=i}get width(){return this.z}set width(t){this.z=t}get height(){return this.w}set height(t){this.w=t}set(t,e,n,i){return this.x=t,this.y=e,this.z=n,this.w=i,this}setScalar(t){return this.x=t,this.y=t,this.z=t,this.w=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setZ(t){return this.z=t,this}setW(t){return this.w=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;case 3:this.w=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){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: "+t)}}clone(){return new this.constructor(this.x,this.y,this.z,this.w)}copy(t){return this.x=t.x,this.y=t.y,this.z=t.z,this.w=void 0!==t.w?t.w:1,this}add(t,e){return void 0!==e?(console.warn("THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(t,e)):(this.x+=t.x,this.y+=t.y,this.z+=t.z,this.w+=t.w,this)}addScalar(t){return this.x+=t,this.y+=t,this.z+=t,this.w+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this.w=t.w+e.w,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this.w+=t.w*e,this}sub(t,e){return void 0!==e?(console.warn("THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(t,e)):(this.x-=t.x,this.y-=t.y,this.z-=t.z,this.w-=t.w,this)}subScalar(t){return this.x-=t,this.y-=t,this.z-=t,this.w-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this.w=t.w-e.w,this}multiply(t){return this.x*=t.x,this.y*=t.y,this.z*=t.z,this.w*=t.w,this}multiplyScalar(t){return this.x*=t,this.y*=t,this.z*=t,this.w*=t,this}applyMatrix4(t){const e=this.x,n=this.y,i=this.z,r=this.w,s=t.elements;return this.x=s[0]*e+s[4]*n+s[8]*i+s[12]*r,this.y=s[1]*e+s[5]*n+s[9]*i+s[13]*r,this.z=s[2]*e+s[6]*n+s[10]*i+s[14]*r,this.w=s[3]*e+s[7]*n+s[11]*i+s[15]*r,this}divideScalar(t){return this.multiplyScalar(1/t)}setAxisAngleFromQuaternion(t){this.w=2*Math.acos(t.w);const e=Math.sqrt(1-t.w*t.w);return e<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=t.x/e,this.y=t.y/e,this.z=t.z/e),this}setAxisAngleFromRotationMatrix(t){let e,n,i,r;const s=.01,a=.1,o=t.elements,l=o[0],c=o[4],h=o[8],u=o[1],d=o[5],p=o[9],m=o[2],f=o[6],g=o[10];if(Math.abs(c-u)o&&t>v?tv?o=0?1:-1,i=1-e*e;if(i>Number.EPSILON){const r=Math.sqrt(i),s=Math.atan2(r,e*n);t=Math.sin(t*s)/r,a=Math.sin(a*s)/r}const r=a*n;if(o=o*t+u*r,l=l*t+d*r,c=c*t+p*r,h=h*t+m*r,t===1-a){const t=1/Math.sqrt(o*o+l*l+c*c+h*h);o*=t,l*=t,c*=t,h*=t}}t[e]=o,t[e+1]=l,t[e+2]=c,t[e+3]=h}static multiplyQuaternionsFlat(t,e,n,i,r,s){const a=n[i],o=n[i+1],l=n[i+2],c=n[i+3],h=r[s],u=r[s+1],d=r[s+2],p=r[s+3];return t[e]=a*p+c*h+o*d-l*u,t[e+1]=o*p+c*u+l*h-a*d,t[e+2]=l*p+c*d+a*u-o*h,t[e+3]=c*p-a*h-o*u-l*d,t}get x(){return this._x}set x(t){this._x=t,this._onChangeCallback()}get y(){return this._y}set y(t){this._y=t,this._onChangeCallback()}get z(){return this._z}set z(t){this._z=t,this._onChangeCallback()}get w(){return this._w}set w(t){this._w=t,this._onChangeCallback()}set(t,e,n,i){return this._x=t,this._y=e,this._z=n,this._w=i,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._w)}copy(t){return this._x=t.x,this._y=t.y,this._z=t.z,this._w=t.w,this._onChangeCallback(),this}setFromEuler(t,e){if(!t||!t.isEuler)throw new Error("THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.");const n=t._x,i=t._y,r=t._z,s=t._order,a=Math.cos,o=Math.sin,l=a(n/2),c=a(i/2),h=a(r/2),u=o(n/2),d=o(i/2),p=o(r/2);switch(s){case"XYZ":this._x=u*c*h+l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h-u*d*p;break;case"YXZ":this._x=u*c*h+l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h+u*d*p;break;case"ZXY":this._x=u*c*h-l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h-u*d*p;break;case"ZYX":this._x=u*c*h-l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h+u*d*p;break;case"YZX":this._x=u*c*h+l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h-u*d*p;break;case"XZY":this._x=u*c*h-l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h+u*d*p;break;default:console.warn("THREE.Quaternion: .setFromEuler() encountered an unknown order: "+s)}return!1!==e&&this._onChangeCallback(),this}setFromAxisAngle(t,e){const n=e/2,i=Math.sin(n);return this._x=t.x*i,this._y=t.y*i,this._z=t.z*i,this._w=Math.cos(n),this._onChangeCallback(),this}setFromRotationMatrix(t){const e=t.elements,n=e[0],i=e[4],r=e[8],s=e[1],a=e[5],o=e[9],l=e[2],c=e[6],h=e[10],u=n+a+h;if(u>0){const t=.5/Math.sqrt(u+1);this._w=.25/t,this._x=(c-o)*t,this._y=(r-l)*t,this._z=(s-i)*t}else if(n>a&&n>h){const t=2*Math.sqrt(1+n-a-h);this._w=(c-o)/t,this._x=.25*t,this._y=(i+s)/t,this._z=(r+l)/t}else if(a>h){const t=2*Math.sqrt(1+a-n-h);this._w=(r-l)/t,this._x=(i+s)/t,this._y=.25*t,this._z=(o+c)/t}else{const t=2*Math.sqrt(1+h-n-a);this._w=(s-i)/t,this._x=(r+l)/t,this._y=(o+c)/t,this._z=.25*t}return this._onChangeCallback(),this}setFromUnitVectors(t,e){let n=t.dot(e)+1;return nMath.abs(t.z)?(this._x=-t.y,this._y=t.x,this._z=0,this._w=n):(this._x=0,this._y=-t.z,this._z=t.y,this._w=n)):(this._x=t.y*e.z-t.z*e.y,this._y=t.z*e.x-t.x*e.z,this._z=t.x*e.y-t.y*e.x,this._w=n),this.normalize()}angleTo(t){return 2*Math.acos(Math.abs(Mt(this.dot(t),-1,1)))}rotateTowards(t,e){const n=this.angleTo(t);if(0===n)return this;const i=Math.min(1,e/n);return this.slerp(t,i),this}identity(){return this.set(0,0,0,1)}invert(){return this.conjugate()}conjugate(){return this._x*=-1,this._y*=-1,this._z*=-1,this._onChangeCallback(),this}dot(t){return this._x*t._x+this._y*t._y+this._z*t._z+this._w*t._w}lengthSq(){return this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w}length(){return Math.sqrt(this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w)}normalize(){let t=this.length();return 0===t?(this._x=0,this._y=0,this._z=0,this._w=1):(t=1/t,this._x=this._x*t,this._y=this._y*t,this._z=this._z*t,this._w=this._w*t),this._onChangeCallback(),this}multiply(t,e){return void 0!==e?(console.warn("THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead."),this.multiplyQuaternions(t,e)):this.multiplyQuaternions(this,t)}premultiply(t){return this.multiplyQuaternions(t,this)}multiplyQuaternions(t,e){const n=t._x,i=t._y,r=t._z,s=t._w,a=e._x,o=e._y,l=e._z,c=e._w;return this._x=n*c+s*a+i*l-r*o,this._y=i*c+s*o+r*a-n*l,this._z=r*c+s*l+n*o-i*a,this._w=s*c-n*a-i*o-r*l,this._onChangeCallback(),this}slerp(t,e){if(0===e)return this;if(1===e)return this.copy(t);const n=this._x,i=this._y,r=this._z,s=this._w;let a=s*t._w+n*t._x+i*t._y+r*t._z;if(a<0?(this._w=-t._w,this._x=-t._x,this._y=-t._y,this._z=-t._z,a=-a):this.copy(t),a>=1)return this._w=s,this._x=n,this._y=i,this._z=r,this;const o=1-a*a;if(o<=Number.EPSILON){const t=1-e;return this._w=t*s+e*this._w,this._x=t*n+e*this._x,this._y=t*i+e*this._y,this._z=t*r+e*this._z,this.normalize(),this._onChangeCallback(),this}const l=Math.sqrt(o),c=Math.atan2(l,a),h=Math.sin((1-e)*c)/l,u=Math.sin(e*c)/l;return this._w=s*h+this._w*u,this._x=n*h+this._x*u,this._y=i*h+this._y*u,this._z=r*h+this._z*u,this._onChangeCallback(),this}slerpQuaternions(t,e,n){return this.copy(t).slerp(e,n)}random(){const t=Math.random(),e=Math.sqrt(1-t),n=Math.sqrt(t),i=2*Math.PI*Math.random(),r=2*Math.PI*Math.random();return this.set(e*Math.cos(i),n*Math.sin(r),n*Math.cos(r),e*Math.sin(i))}equals(t){return t._x===this._x&&t._y===this._y&&t._z===this._z&&t._w===this._w}fromArray(t,e=0){return this._x=t[e],this._y=t[e+1],this._z=t[e+2],this._w=t[e+3],this._onChangeCallback(),this}toArray(t=[],e=0){return t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._w,t}fromBufferAttribute(t,e){return this._x=t.getX(e),this._y=t.getY(e),this._z=t.getZ(e),this._w=t.getW(e),this}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}}Kt.prototype.isQuaternion=!0;class Qt{constructor(t=0,e=0,n=0){this.x=t,this.y=e,this.z=n}set(t,e,n){return void 0===n&&(n=this.z),this.x=t,this.y=e,this.z=n,this}setScalar(t){return this.x=t,this.y=t,this.z=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setZ(t){return this.z=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y,this.z)}copy(t){return this.x=t.x,this.y=t.y,this.z=t.z,this}add(t,e){return void 0!==e?(console.warn("THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(t,e)):(this.x+=t.x,this.y+=t.y,this.z+=t.z,this)}addScalar(t){return this.x+=t,this.y+=t,this.z+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this}sub(t,e){return void 0!==e?(console.warn("THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(t,e)):(this.x-=t.x,this.y-=t.y,this.z-=t.z,this)}subScalar(t){return this.x-=t,this.y-=t,this.z-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this}multiply(t,e){return void 0!==e?(console.warn("THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead."),this.multiplyVectors(t,e)):(this.x*=t.x,this.y*=t.y,this.z*=t.z,this)}multiplyScalar(t){return this.x*=t,this.y*=t,this.z*=t,this}multiplyVectors(t,e){return this.x=t.x*e.x,this.y=t.y*e.y,this.z=t.z*e.z,this}applyEuler(t){return t&&t.isEuler||console.error("THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order."),this.applyQuaternion(te.setFromEuler(t))}applyAxisAngle(t,e){return this.applyQuaternion(te.setFromAxisAngle(t,e))}applyMatrix3(t){const e=this.x,n=this.y,i=this.z,r=t.elements;return this.x=r[0]*e+r[3]*n+r[6]*i,this.y=r[1]*e+r[4]*n+r[7]*i,this.z=r[2]*e+r[5]*n+r[8]*i,this}applyNormalMatrix(t){return this.applyMatrix3(t).normalize()}applyMatrix4(t){const e=this.x,n=this.y,i=this.z,r=t.elements,s=1/(r[3]*e+r[7]*n+r[11]*i+r[15]);return this.x=(r[0]*e+r[4]*n+r[8]*i+r[12])*s,this.y=(r[1]*e+r[5]*n+r[9]*i+r[13])*s,this.z=(r[2]*e+r[6]*n+r[10]*i+r[14])*s,this}applyQuaternion(t){const e=this.x,n=this.y,i=this.z,r=t.x,s=t.y,a=t.z,o=t.w,l=o*e+s*i-a*n,c=o*n+a*e-r*i,h=o*i+r*n-s*e,u=-r*e-s*n-a*i;return this.x=l*o+u*-r+c*-a-h*-s,this.y=c*o+u*-s+h*-r-l*-a,this.z=h*o+u*-a+l*-s-c*-r,this}project(t){return this.applyMatrix4(t.matrixWorldInverse).applyMatrix4(t.projectionMatrix)}unproject(t){return this.applyMatrix4(t.projectionMatrixInverse).applyMatrix4(t.matrixWorld)}transformDirection(t){const e=this.x,n=this.y,i=this.z,r=t.elements;return this.x=r[0]*e+r[4]*n+r[8]*i,this.y=r[1]*e+r[5]*n+r[9]*i,this.z=r[2]*e+r[6]*n+r[10]*i,this.normalize()}divide(t){return this.x/=t.x,this.y/=t.y,this.z/=t.z,this}divideScalar(t){return this.multiplyScalar(1/t)}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this.z=Math.min(this.z,t.z),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this.z=Math.max(this.z,t.z),this}clamp(t,e){return this.x=Math.max(t.x,Math.min(e.x,this.x)),this.y=Math.max(t.y,Math.min(e.y,this.y)),this.z=Math.max(t.z,Math.min(e.z,this.z)),this}clampScalar(t,e){return this.x=Math.max(t,Math.min(e,this.x)),this.y=Math.max(t,Math.min(e,this.y)),this.z=Math.max(t,Math.min(e,this.z)),this}clampLength(t,e){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(t,Math.min(e,n)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this}roundToZero(){return 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),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this}dot(t){return this.x*t.x+this.y*t.y+this.z*t.z}lengthSq(){return this.x*this.x+this.y*this.y+this.z*this.z}length(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)}normalize(){return this.divideScalar(this.length()||1)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this.z+=(t.z-this.z)*e,this}lerpVectors(t,e,n){return this.x=t.x+(e.x-t.x)*n,this.y=t.y+(e.y-t.y)*n,this.z=t.z+(e.z-t.z)*n,this}cross(t,e){return void 0!==e?(console.warn("THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead."),this.crossVectors(t,e)):this.crossVectors(this,t)}crossVectors(t,e){const n=t.x,i=t.y,r=t.z,s=e.x,a=e.y,o=e.z;return this.x=i*o-r*a,this.y=r*s-n*o,this.z=n*a-i*s,this}projectOnVector(t){const e=t.lengthSq();if(0===e)return this.set(0,0,0);const n=t.dot(this)/e;return this.copy(t).multiplyScalar(n)}projectOnPlane(t){return $t.copy(this).projectOnVector(t),this.sub($t)}reflect(t){return this.sub($t.copy(t).multiplyScalar(2*this.dot(t)))}angleTo(t){const e=Math.sqrt(this.lengthSq()*t.lengthSq());if(0===e)return Math.PI/2;const n=this.dot(t)/e;return Math.acos(Mt(n,-1,1))}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,n=this.y-t.y,i=this.z-t.z;return e*e+n*n+i*i}manhattanDistanceTo(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)+Math.abs(this.z-t.z)}setFromSpherical(t){return this.setFromSphericalCoords(t.radius,t.phi,t.theta)}setFromSphericalCoords(t,e,n){const i=Math.sin(e)*t;return this.x=i*Math.sin(n),this.y=Math.cos(e)*t,this.z=i*Math.cos(n),this}setFromCylindrical(t){return this.setFromCylindricalCoords(t.radius,t.theta,t.y)}setFromCylindricalCoords(t,e,n){return this.x=t*Math.sin(e),this.y=n,this.z=t*Math.cos(e),this}setFromMatrixPosition(t){const e=t.elements;return this.x=e[12],this.y=e[13],this.z=e[14],this}setFromMatrixScale(t){const e=this.setFromMatrixColumn(t,0).length(),n=this.setFromMatrixColumn(t,1).length(),i=this.setFromMatrixColumn(t,2).length();return this.x=e,this.y=n,this.z=i,this}setFromMatrixColumn(t,e){return this.fromArray(t.elements,4*e)}setFromMatrix3Column(t,e){return this.fromArray(t.elements,3*e)}equals(t){return t.x===this.x&&t.y===this.y&&t.z===this.z}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this.z=t[e+2],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t[e+2]=this.z,t}fromBufferAttribute(t,e,n){return void 0!==n&&console.warn("THREE.Vector3: offset has been removed from .fromBufferAttribute()."),this.x=t.getX(e),this.y=t.getY(e),this.z=t.getZ(e),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this}randomDirection(){const t=2*(Math.random()-.5),e=Math.random()*Math.PI*2,n=Math.sqrt(1-t**2);return this.x=n*Math.cos(e),this.y=n*Math.sin(e),this.z=t,this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z}}Qt.prototype.isVector3=!0;const $t=new Qt,te=new Kt;class ee{constructor(t=new Qt(1/0,1/0,1/0),e=new Qt(-1/0,-1/0,-1/0)){this.min=t,this.max=e}set(t,e){return this.min.copy(t),this.max.copy(e),this}setFromArray(t){let e=1/0,n=1/0,i=1/0,r=-1/0,s=-1/0,a=-1/0;for(let o=0,l=t.length;or&&(r=l),c>s&&(s=c),h>a&&(a=h)}return this.min.set(e,n,i),this.max.set(r,s,a),this}setFromBufferAttribute(t){let e=1/0,n=1/0,i=1/0,r=-1/0,s=-1/0,a=-1/0;for(let o=0,l=t.count;or&&(r=l),c>s&&(s=c),h>a&&(a=h)}return this.min.set(e,n,i),this.max.set(r,s,a),this}setFromPoints(t){this.makeEmpty();for(let e=0,n=t.length;ethis.max.x||t.ythis.max.y||t.zthis.max.z)}containsBox(t){return this.min.x<=t.min.x&&t.max.x<=this.max.x&&this.min.y<=t.min.y&&t.max.y<=this.max.y&&this.min.z<=t.min.z&&t.max.z<=this.max.z}getParameter(t,e){return e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y),(t.z-this.min.z)/(this.max.z-this.min.z))}intersectsBox(t){return!(t.max.xthis.max.x||t.max.ythis.max.y||t.max.zthis.max.z)}intersectsSphere(t){return this.clampPoint(t.center,ie),ie.distanceToSquared(t.center)<=t.radius*t.radius}intersectsPlane(t){let e,n;return t.normal.x>0?(e=t.normal.x*this.min.x,n=t.normal.x*this.max.x):(e=t.normal.x*this.max.x,n=t.normal.x*this.min.x),t.normal.y>0?(e+=t.normal.y*this.min.y,n+=t.normal.y*this.max.y):(e+=t.normal.y*this.max.y,n+=t.normal.y*this.min.y),t.normal.z>0?(e+=t.normal.z*this.min.z,n+=t.normal.z*this.max.z):(e+=t.normal.z*this.max.z,n+=t.normal.z*this.min.z),e<=-t.constant&&n>=-t.constant}intersectsTriangle(t){if(this.isEmpty())return!1;this.getCenter(ue),de.subVectors(this.max,ue),se.subVectors(t.a,ue),ae.subVectors(t.b,ue),oe.subVectors(t.c,ue),le.subVectors(ae,se),ce.subVectors(oe,ae),he.subVectors(se,oe);let e=[0,-le.z,le.y,0,-ce.z,ce.y,0,-he.z,he.y,le.z,0,-le.x,ce.z,0,-ce.x,he.z,0,-he.x,-le.y,le.x,0,-ce.y,ce.x,0,-he.y,he.x,0];return!!fe(e,se,ae,oe,de)&&(e=[1,0,0,0,1,0,0,0,1],!!fe(e,se,ae,oe,de)&&(pe.crossVectors(le,ce),e=[pe.x,pe.y,pe.z],fe(e,se,ae,oe,de)))}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return ie.copy(t).clamp(this.min,this.max).sub(t).length()}getBoundingSphere(t){return this.getCenter(t.center),t.radius=.5*this.getSize(ie).length(),t}intersect(t){return this.min.max(t.min),this.max.min(t.max),this.isEmpty()&&this.makeEmpty(),this}union(t){return this.min.min(t.min),this.max.max(t.max),this}applyMatrix4(t){return this.isEmpty()||(ne[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(t),ne[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(t),ne[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(t),ne[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(t),ne[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(t),ne[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(t),ne[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(t),ne[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(t),this.setFromPoints(ne)),this}translate(t){return this.min.add(t),this.max.add(t),this}equals(t){return t.min.equals(this.min)&&t.max.equals(this.max)}}ee.prototype.isBox3=!0;const ne=[new Qt,new Qt,new Qt,new Qt,new Qt,new Qt,new Qt,new Qt],ie=new Qt,re=new ee,se=new Qt,ae=new Qt,oe=new Qt,le=new Qt,ce=new Qt,he=new Qt,ue=new Qt,de=new Qt,pe=new Qt,me=new Qt;function fe(t,e,n,i,r){for(let s=0,a=t.length-3;s<=a;s+=3){me.fromArray(t,s);const a=r.x*Math.abs(me.x)+r.y*Math.abs(me.y)+r.z*Math.abs(me.z),o=e.dot(me),l=n.dot(me),c=i.dot(me);if(Math.max(-Math.max(o,l,c),Math.min(o,l,c))>a)return!1}return!0}const ge=new ee,ve=new Qt,ye=new Qt,xe=new Qt;class _e{constructor(t=new Qt,e=-1){this.center=t,this.radius=e}set(t,e){return this.center.copy(t),this.radius=e,this}setFromPoints(t,e){const n=this.center;void 0!==e?n.copy(e):ge.setFromPoints(t).getCenter(n);let i=0;for(let e=0,r=t.length;ethis.radius*this.radius&&(e.sub(this.center).normalize(),e.multiplyScalar(this.radius).add(this.center)),e}getBoundingBox(t){return this.isEmpty()?(t.makeEmpty(),t):(t.set(this.center,this.center),t.expandByScalar(this.radius),t)}applyMatrix4(t){return this.center.applyMatrix4(t),this.radius=this.radius*t.getMaxScaleOnAxis(),this}translate(t){return this.center.add(t),this}expandByPoint(t){xe.subVectors(t,this.center);const e=xe.lengthSq();if(e>this.radius*this.radius){const t=Math.sqrt(e),n=.5*(t-this.radius);this.center.add(xe.multiplyScalar(n/t)),this.radius+=n}return this}union(t){return!0===this.center.equals(t.center)?ye.set(0,0,1).multiplyScalar(t.radius):ye.subVectors(t.center,this.center).normalize().multiplyScalar(t.radius),this.expandByPoint(ve.copy(t.center).add(ye)),this.expandByPoint(ve.copy(t.center).sub(ye)),this}equals(t){return t.center.equals(this.center)&&t.radius===this.radius}clone(){return(new this.constructor).copy(this)}}const be=new Qt,Me=new Qt,we=new Qt,Se=new Qt,Te=new Qt,Ee=new Qt,Ae=new Qt;class Re{constructor(t=new Qt,e=new Qt(0,0,-1)){this.origin=t,this.direction=e}set(t,e){return this.origin.copy(t),this.direction.copy(e),this}copy(t){return this.origin.copy(t.origin),this.direction.copy(t.direction),this}at(t,e){return e.copy(this.direction).multiplyScalar(t).add(this.origin)}lookAt(t){return this.direction.copy(t).sub(this.origin).normalize(),this}recast(t){return this.origin.copy(this.at(t,be)),this}closestPointToPoint(t,e){e.subVectors(t,this.origin);const n=e.dot(this.direction);return n<0?e.copy(this.origin):e.copy(this.direction).multiplyScalar(n).add(this.origin)}distanceToPoint(t){return Math.sqrt(this.distanceSqToPoint(t))}distanceSqToPoint(t){const e=be.subVectors(t,this.origin).dot(this.direction);return e<0?this.origin.distanceToSquared(t):(be.copy(this.direction).multiplyScalar(e).add(this.origin),be.distanceToSquared(t))}distanceSqToSegment(t,e,n,i){Me.copy(t).add(e).multiplyScalar(.5),we.copy(e).sub(t).normalize(),Se.copy(this.origin).sub(Me);const r=.5*t.distanceTo(e),s=-this.direction.dot(we),a=Se.dot(this.direction),o=-Se.dot(we),l=Se.lengthSq(),c=Math.abs(1-s*s);let h,u,d,p;if(c>0)if(h=s*o-a,u=s*a-o,p=r*c,h>=0)if(u>=-p)if(u<=p){const t=1/c;h*=t,u*=t,d=h*(h+s*u+2*a)+u*(s*h+u+2*o)+l}else u=r,h=Math.max(0,-(s*u+a)),d=-h*h+u*(u+2*o)+l;else u=-r,h=Math.max(0,-(s*u+a)),d=-h*h+u*(u+2*o)+l;else u<=-p?(h=Math.max(0,-(-s*r+a)),u=h>0?-r:Math.min(Math.max(-r,-o),r),d=-h*h+u*(u+2*o)+l):u<=p?(h=0,u=Math.min(Math.max(-r,-o),r),d=u*(u+2*o)+l):(h=Math.max(0,-(s*r+a)),u=h>0?r:Math.min(Math.max(-r,-o),r),d=-h*h+u*(u+2*o)+l);else u=s>0?-r:r,h=Math.max(0,-(s*u+a)),d=-h*h+u*(u+2*o)+l;return n&&n.copy(this.direction).multiplyScalar(h).add(this.origin),i&&i.copy(we).multiplyScalar(u).add(Me),d}intersectSphere(t,e){be.subVectors(t.center,this.origin);const n=be.dot(this.direction),i=be.dot(be)-n*n,r=t.radius*t.radius;if(i>r)return null;const s=Math.sqrt(r-i),a=n-s,o=n+s;return a<0&&o<0?null:a<0?this.at(o,e):this.at(a,e)}intersectsSphere(t){return this.distanceSqToPoint(t.center)<=t.radius*t.radius}distanceToPlane(t){const e=t.normal.dot(this.direction);if(0===e)return 0===t.distanceToPoint(this.origin)?0:null;const n=-(this.origin.dot(t.normal)+t.constant)/e;return n>=0?n:null}intersectPlane(t,e){const n=this.distanceToPlane(t);return null===n?null:this.at(n,e)}intersectsPlane(t){const e=t.distanceToPoint(this.origin);if(0===e)return!0;return t.normal.dot(this.direction)*e<0}intersectBox(t,e){let n,i,r,s,a,o;const l=1/this.direction.x,c=1/this.direction.y,h=1/this.direction.z,u=this.origin;return l>=0?(n=(t.min.x-u.x)*l,i=(t.max.x-u.x)*l):(n=(t.max.x-u.x)*l,i=(t.min.x-u.x)*l),c>=0?(r=(t.min.y-u.y)*c,s=(t.max.y-u.y)*c):(r=(t.max.y-u.y)*c,s=(t.min.y-u.y)*c),n>s||r>i?null:((r>n||n!=n)&&(n=r),(s=0?(a=(t.min.z-u.z)*h,o=(t.max.z-u.z)*h):(a=(t.max.z-u.z)*h,o=(t.min.z-u.z)*h),n>o||a>i?null:((a>n||n!=n)&&(n=a),(o=0?n:i,e)))}intersectsBox(t){return null!==this.intersectBox(t,be)}intersectTriangle(t,e,n,i,r){Te.subVectors(e,t),Ee.subVectors(n,t),Ae.crossVectors(Te,Ee);let s,a=this.direction.dot(Ae);if(a>0){if(i)return null;s=1}else{if(!(a<0))return null;s=-1,a=-a}Se.subVectors(this.origin,t);const o=s*this.direction.dot(Ee.crossVectors(Se,Ee));if(o<0)return null;const l=s*this.direction.dot(Te.cross(Se));if(l<0)return null;if(o+l>a)return null;const c=-s*Se.dot(Ae);return c<0?null:this.at(c/a,r)}applyMatrix4(t){return this.origin.applyMatrix4(t),this.direction.transformDirection(t),this}equals(t){return t.origin.equals(this.origin)&&t.direction.equals(this.direction)}clone(){return(new this.constructor).copy(this)}}class Le{constructor(){this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],arguments.length>0&&console.error("THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.")}set(t,e,n,i,r,s,a,o,l,c,h,u,d,p,m,f){const g=this.elements;return g[0]=t,g[4]=e,g[8]=n,g[12]=i,g[1]=r,g[5]=s,g[9]=a,g[13]=o,g[2]=l,g[6]=c,g[10]=h,g[14]=u,g[3]=d,g[7]=p,g[11]=m,g[15]=f,this}identity(){return this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1),this}clone(){return(new Le).fromArray(this.elements)}copy(t){const e=this.elements,n=t.elements;return e[0]=n[0],e[1]=n[1],e[2]=n[2],e[3]=n[3],e[4]=n[4],e[5]=n[5],e[6]=n[6],e[7]=n[7],e[8]=n[8],e[9]=n[9],e[10]=n[10],e[11]=n[11],e[12]=n[12],e[13]=n[13],e[14]=n[14],e[15]=n[15],this}copyPosition(t){const e=this.elements,n=t.elements;return e[12]=n[12],e[13]=n[13],e[14]=n[14],this}setFromMatrix3(t){const e=t.elements;return this.set(e[0],e[3],e[6],0,e[1],e[4],e[7],0,e[2],e[5],e[8],0,0,0,0,1),this}extractBasis(t,e,n){return t.setFromMatrixColumn(this,0),e.setFromMatrixColumn(this,1),n.setFromMatrixColumn(this,2),this}makeBasis(t,e,n){return this.set(t.x,e.x,n.x,0,t.y,e.y,n.y,0,t.z,e.z,n.z,0,0,0,0,1),this}extractRotation(t){const e=this.elements,n=t.elements,i=1/Ce.setFromMatrixColumn(t,0).length(),r=1/Ce.setFromMatrixColumn(t,1).length(),s=1/Ce.setFromMatrixColumn(t,2).length();return e[0]=n[0]*i,e[1]=n[1]*i,e[2]=n[2]*i,e[3]=0,e[4]=n[4]*r,e[5]=n[5]*r,e[6]=n[6]*r,e[7]=0,e[8]=n[8]*s,e[9]=n[9]*s,e[10]=n[10]*s,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromEuler(t){t&&t.isEuler||console.error("THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.");const e=this.elements,n=t.x,i=t.y,r=t.z,s=Math.cos(n),a=Math.sin(n),o=Math.cos(i),l=Math.sin(i),c=Math.cos(r),h=Math.sin(r);if("XYZ"===t.order){const t=s*c,n=s*h,i=a*c,r=a*h;e[0]=o*c,e[4]=-o*h,e[8]=l,e[1]=n+i*l,e[5]=t-r*l,e[9]=-a*o,e[2]=r-t*l,e[6]=i+n*l,e[10]=s*o}else if("YXZ"===t.order){const t=o*c,n=o*h,i=l*c,r=l*h;e[0]=t+r*a,e[4]=i*a-n,e[8]=s*l,e[1]=s*h,e[5]=s*c,e[9]=-a,e[2]=n*a-i,e[6]=r+t*a,e[10]=s*o}else if("ZXY"===t.order){const t=o*c,n=o*h,i=l*c,r=l*h;e[0]=t-r*a,e[4]=-s*h,e[8]=i+n*a,e[1]=n+i*a,e[5]=s*c,e[9]=r-t*a,e[2]=-s*l,e[6]=a,e[10]=s*o}else if("ZYX"===t.order){const t=s*c,n=s*h,i=a*c,r=a*h;e[0]=o*c,e[4]=i*l-n,e[8]=t*l+r,e[1]=o*h,e[5]=r*l+t,e[9]=n*l-i,e[2]=-l,e[6]=a*o,e[10]=s*o}else if("YZX"===t.order){const t=s*o,n=s*l,i=a*o,r=a*l;e[0]=o*c,e[4]=r-t*h,e[8]=i*h+n,e[1]=h,e[5]=s*c,e[9]=-a*c,e[2]=-l*c,e[6]=n*h+i,e[10]=t-r*h}else if("XZY"===t.order){const t=s*o,n=s*l,i=a*o,r=a*l;e[0]=o*c,e[4]=-h,e[8]=l*c,e[1]=t*h+r,e[5]=s*c,e[9]=n*h-i,e[2]=i*h-n,e[6]=a*c,e[10]=r*h+t}return e[3]=0,e[7]=0,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromQuaternion(t){return this.compose(De,t,Ie)}lookAt(t,e,n){const i=this.elements;return ze.subVectors(t,e),0===ze.lengthSq()&&(ze.z=1),ze.normalize(),Ne.crossVectors(n,ze),0===Ne.lengthSq()&&(1===Math.abs(n.z)?ze.x+=1e-4:ze.z+=1e-4,ze.normalize(),Ne.crossVectors(n,ze)),Ne.normalize(),Be.crossVectors(ze,Ne),i[0]=Ne.x,i[4]=Be.x,i[8]=ze.x,i[1]=Ne.y,i[5]=Be.y,i[9]=ze.y,i[2]=Ne.z,i[6]=Be.z,i[10]=ze.z,this}multiply(t,e){return void 0!==e?(console.warn("THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead."),this.multiplyMatrices(t,e)):this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const n=t.elements,i=e.elements,r=this.elements,s=n[0],a=n[4],o=n[8],l=n[12],c=n[1],h=n[5],u=n[9],d=n[13],p=n[2],m=n[6],f=n[10],g=n[14],v=n[3],y=n[7],x=n[11],_=n[15],b=i[0],M=i[4],w=i[8],S=i[12],T=i[1],E=i[5],A=i[9],R=i[13],L=i[2],C=i[6],P=i[10],D=i[14],I=i[3],N=i[7],B=i[11],z=i[15];return r[0]=s*b+a*T+o*L+l*I,r[4]=s*M+a*E+o*C+l*N,r[8]=s*w+a*A+o*P+l*B,r[12]=s*S+a*R+o*D+l*z,r[1]=c*b+h*T+u*L+d*I,r[5]=c*M+h*E+u*C+d*N,r[9]=c*w+h*A+u*P+d*B,r[13]=c*S+h*R+u*D+d*z,r[2]=p*b+m*T+f*L+g*I,r[6]=p*M+m*E+f*C+g*N,r[10]=p*w+m*A+f*P+g*B,r[14]=p*S+m*R+f*D+g*z,r[3]=v*b+y*T+x*L+_*I,r[7]=v*M+y*E+x*C+_*N,r[11]=v*w+y*A+x*P+_*B,r[15]=v*S+y*R+x*D+_*z,this}multiplyScalar(t){const e=this.elements;return e[0]*=t,e[4]*=t,e[8]*=t,e[12]*=t,e[1]*=t,e[5]*=t,e[9]*=t,e[13]*=t,e[2]*=t,e[6]*=t,e[10]*=t,e[14]*=t,e[3]*=t,e[7]*=t,e[11]*=t,e[15]*=t,this}determinant(){const t=this.elements,e=t[0],n=t[4],i=t[8],r=t[12],s=t[1],a=t[5],o=t[9],l=t[13],c=t[2],h=t[6],u=t[10],d=t[14];return t[3]*(+r*o*h-i*l*h-r*a*u+n*l*u+i*a*d-n*o*d)+t[7]*(+e*o*d-e*l*u+r*s*u-i*s*d+i*l*c-r*o*c)+t[11]*(+e*l*h-e*a*d-r*s*h+n*s*d+r*a*c-n*l*c)+t[15]*(-i*a*c-e*o*h+e*a*u+i*s*h-n*s*u+n*o*c)}transpose(){const t=this.elements;let e;return e=t[1],t[1]=t[4],t[4]=e,e=t[2],t[2]=t[8],t[8]=e,e=t[6],t[6]=t[9],t[9]=e,e=t[3],t[3]=t[12],t[12]=e,e=t[7],t[7]=t[13],t[13]=e,e=t[11],t[11]=t[14],t[14]=e,this}setPosition(t,e,n){const i=this.elements;return t.isVector3?(i[12]=t.x,i[13]=t.y,i[14]=t.z):(i[12]=t,i[13]=e,i[14]=n),this}invert(){const t=this.elements,e=t[0],n=t[1],i=t[2],r=t[3],s=t[4],a=t[5],o=t[6],l=t[7],c=t[8],h=t[9],u=t[10],d=t[11],p=t[12],m=t[13],f=t[14],g=t[15],v=h*f*l-m*u*l+m*o*d-a*f*d-h*o*g+a*u*g,y=p*u*l-c*f*l-p*o*d+s*f*d+c*o*g-s*u*g,x=c*m*l-p*h*l+p*a*d-s*m*d-c*a*g+s*h*g,_=p*h*o-c*m*o-p*a*u+s*m*u+c*a*f-s*h*f,b=e*v+n*y+i*x+r*_;if(0===b)return this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);const M=1/b;return t[0]=v*M,t[1]=(m*u*r-h*f*r-m*i*d+n*f*d+h*i*g-n*u*g)*M,t[2]=(a*f*r-m*o*r+m*i*l-n*f*l-a*i*g+n*o*g)*M,t[3]=(h*o*r-a*u*r-h*i*l+n*u*l+a*i*d-n*o*d)*M,t[4]=y*M,t[5]=(c*f*r-p*u*r+p*i*d-e*f*d-c*i*g+e*u*g)*M,t[6]=(p*o*r-s*f*r-p*i*l+e*f*l+s*i*g-e*o*g)*M,t[7]=(s*u*r-c*o*r+c*i*l-e*u*l-s*i*d+e*o*d)*M,t[8]=x*M,t[9]=(p*h*r-c*m*r-p*n*d+e*m*d+c*n*g-e*h*g)*M,t[10]=(s*m*r-p*a*r+p*n*l-e*m*l-s*n*g+e*a*g)*M,t[11]=(c*a*r-s*h*r-c*n*l+e*h*l+s*n*d-e*a*d)*M,t[12]=_*M,t[13]=(c*m*i-p*h*i+p*n*u-e*m*u-c*n*f+e*h*f)*M,t[14]=(p*a*i-s*m*i-p*n*o+e*m*o+s*n*f-e*a*f)*M,t[15]=(s*h*i-c*a*i+c*n*o-e*h*o-s*n*u+e*a*u)*M,this}scale(t){const e=this.elements,n=t.x,i=t.y,r=t.z;return e[0]*=n,e[4]*=i,e[8]*=r,e[1]*=n,e[5]*=i,e[9]*=r,e[2]*=n,e[6]*=i,e[10]*=r,e[3]*=n,e[7]*=i,e[11]*=r,this}getMaxScaleOnAxis(){const t=this.elements,e=t[0]*t[0]+t[1]*t[1]+t[2]*t[2],n=t[4]*t[4]+t[5]*t[5]+t[6]*t[6],i=t[8]*t[8]+t[9]*t[9]+t[10]*t[10];return Math.sqrt(Math.max(e,n,i))}makeTranslation(t,e,n){return this.set(1,0,0,t,0,1,0,e,0,0,1,n,0,0,0,1),this}makeRotationX(t){const e=Math.cos(t),n=Math.sin(t);return this.set(1,0,0,0,0,e,-n,0,0,n,e,0,0,0,0,1),this}makeRotationY(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,0,n,0,0,1,0,0,-n,0,e,0,0,0,0,1),this}makeRotationZ(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,-n,0,0,n,e,0,0,0,0,1,0,0,0,0,1),this}makeRotationAxis(t,e){const n=Math.cos(e),i=Math.sin(e),r=1-n,s=t.x,a=t.y,o=t.z,l=r*s,c=r*a;return this.set(l*s+n,l*a-i*o,l*o+i*a,0,l*a+i*o,c*a+n,c*o-i*s,0,l*o-i*a,c*o+i*s,r*o*o+n,0,0,0,0,1),this}makeScale(t,e,n){return this.set(t,0,0,0,0,e,0,0,0,0,n,0,0,0,0,1),this}makeShear(t,e,n,i,r,s){return this.set(1,n,r,0,t,1,s,0,e,i,1,0,0,0,0,1),this}compose(t,e,n){const i=this.elements,r=e._x,s=e._y,a=e._z,o=e._w,l=r+r,c=s+s,h=a+a,u=r*l,d=r*c,p=r*h,m=s*c,f=s*h,g=a*h,v=o*l,y=o*c,x=o*h,_=n.x,b=n.y,M=n.z;return i[0]=(1-(m+g))*_,i[1]=(d+x)*_,i[2]=(p-y)*_,i[3]=0,i[4]=(d-x)*b,i[5]=(1-(u+g))*b,i[6]=(f+v)*b,i[7]=0,i[8]=(p+y)*M,i[9]=(f-v)*M,i[10]=(1-(u+m))*M,i[11]=0,i[12]=t.x,i[13]=t.y,i[14]=t.z,i[15]=1,this}decompose(t,e,n){const i=this.elements;let r=Ce.set(i[0],i[1],i[2]).length();const s=Ce.set(i[4],i[5],i[6]).length(),a=Ce.set(i[8],i[9],i[10]).length();this.determinant()<0&&(r=-r),t.x=i[12],t.y=i[13],t.z=i[14],Pe.copy(this);const o=1/r,l=1/s,c=1/a;return Pe.elements[0]*=o,Pe.elements[1]*=o,Pe.elements[2]*=o,Pe.elements[4]*=l,Pe.elements[5]*=l,Pe.elements[6]*=l,Pe.elements[8]*=c,Pe.elements[9]*=c,Pe.elements[10]*=c,e.setFromRotationMatrix(Pe),n.x=r,n.y=s,n.z=a,this}makePerspective(t,e,n,i,r,s){void 0===s&&console.warn("THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.");const a=this.elements,o=2*r/(e-t),l=2*r/(n-i),c=(e+t)/(e-t),h=(n+i)/(n-i),u=-(s+r)/(s-r),d=-2*s*r/(s-r);return a[0]=o,a[4]=0,a[8]=c,a[12]=0,a[1]=0,a[5]=l,a[9]=h,a[13]=0,a[2]=0,a[6]=0,a[10]=u,a[14]=d,a[3]=0,a[7]=0,a[11]=-1,a[15]=0,this}makeOrthographic(t,e,n,i,r,s){const a=this.elements,o=1/(e-t),l=1/(n-i),c=1/(s-r),h=(e+t)*o,u=(n+i)*l,d=(s+r)*c;return a[0]=2*o,a[4]=0,a[8]=0,a[12]=-h,a[1]=0,a[5]=2*l,a[9]=0,a[13]=-u,a[2]=0,a[6]=0,a[10]=-2*c,a[14]=-d,a[3]=0,a[7]=0,a[11]=0,a[15]=1,this}equals(t){const e=this.elements,n=t.elements;for(let t=0;t<16;t++)if(e[t]!==n[t])return!1;return!0}fromArray(t,e=0){for(let n=0;n<16;n++)this.elements[n]=t[n+e];return this}toArray(t=[],e=0){const n=this.elements;return t[e]=n[0],t[e+1]=n[1],t[e+2]=n[2],t[e+3]=n[3],t[e+4]=n[4],t[e+5]=n[5],t[e+6]=n[6],t[e+7]=n[7],t[e+8]=n[8],t[e+9]=n[9],t[e+10]=n[10],t[e+11]=n[11],t[e+12]=n[12],t[e+13]=n[13],t[e+14]=n[14],t[e+15]=n[15],t}}Le.prototype.isMatrix4=!0;const Ce=new Qt,Pe=new Le,De=new Qt(0,0,0),Ie=new Qt(1,1,1),Ne=new Qt,Be=new Qt,ze=new Qt,Oe=new Le,Fe=new Kt;class Ue{constructor(t=0,e=0,n=0,i=Ue.DefaultOrder){this._x=t,this._y=e,this._z=n,this._order=i}get x(){return this._x}set x(t){this._x=t,this._onChangeCallback()}get y(){return this._y}set y(t){this._y=t,this._onChangeCallback()}get z(){return this._z}set z(t){this._z=t,this._onChangeCallback()}get order(){return this._order}set order(t){this._order=t,this._onChangeCallback()}set(t,e,n,i=this._order){return this._x=t,this._y=e,this._z=n,this._order=i,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._order)}copy(t){return this._x=t._x,this._y=t._y,this._z=t._z,this._order=t._order,this._onChangeCallback(),this}setFromRotationMatrix(t,e=this._order,n=!0){const i=t.elements,r=i[0],s=i[4],a=i[8],o=i[1],l=i[5],c=i[9],h=i[2],u=i[6],d=i[10];switch(e){case"XYZ":this._y=Math.asin(Mt(a,-1,1)),Math.abs(a)<.9999999?(this._x=Math.atan2(-c,d),this._z=Math.atan2(-s,r)):(this._x=Math.atan2(u,l),this._z=0);break;case"YXZ":this._x=Math.asin(-Mt(c,-1,1)),Math.abs(c)<.9999999?(this._y=Math.atan2(a,d),this._z=Math.atan2(o,l)):(this._y=Math.atan2(-h,r),this._z=0);break;case"ZXY":this._x=Math.asin(Mt(u,-1,1)),Math.abs(u)<.9999999?(this._y=Math.atan2(-h,d),this._z=Math.atan2(-s,l)):(this._y=0,this._z=Math.atan2(o,r));break;case"ZYX":this._y=Math.asin(-Mt(h,-1,1)),Math.abs(h)<.9999999?(this._x=Math.atan2(u,d),this._z=Math.atan2(o,r)):(this._x=0,this._z=Math.atan2(-s,l));break;case"YZX":this._z=Math.asin(Mt(o,-1,1)),Math.abs(o)<.9999999?(this._x=Math.atan2(-c,l),this._y=Math.atan2(-h,r)):(this._x=0,this._y=Math.atan2(a,d));break;case"XZY":this._z=Math.asin(-Mt(s,-1,1)),Math.abs(s)<.9999999?(this._x=Math.atan2(u,l),this._y=Math.atan2(a,r)):(this._x=Math.atan2(-c,d),this._y=0);break;default:console.warn("THREE.Euler: .setFromRotationMatrix() encountered an unknown order: "+e)}return this._order=e,!0===n&&this._onChangeCallback(),this}setFromQuaternion(t,e,n){return Oe.makeRotationFromQuaternion(t),this.setFromRotationMatrix(Oe,e,n)}setFromVector3(t,e=this._order){return this.set(t.x,t.y,t.z,e)}reorder(t){return Fe.setFromEuler(this),this.setFromQuaternion(Fe,t)}equals(t){return t._x===this._x&&t._y===this._y&&t._z===this._z&&t._order===this._order}fromArray(t){return this._x=t[0],this._y=t[1],this._z=t[2],void 0!==t[3]&&(this._order=t[3]),this._onChangeCallback(),this}toArray(t=[],e=0){return t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._order,t}toVector3(t){return t?t.set(this._x,this._y,this._z):new Qt(this._x,this._y,this._z)}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}}Ue.prototype.isEuler=!0,Ue.DefaultOrder="XYZ",Ue.RotationOrders=["XYZ","YZX","ZXY","XZY","YXZ","ZYX"];class He{constructor(){this.mask=1}set(t){this.mask=(1<>>0}enable(t){this.mask|=1<1){for(let t=0;t1){for(let t=0;t0){i.children=[];for(let e=0;e0){i.animations=[];for(let e=0;e0&&(n.geometries=e),i.length>0&&(n.materials=i),r.length>0&&(n.textures=r),a.length>0&&(n.images=a),o.length>0&&(n.shapes=o),l.length>0&&(n.skeletons=l),c.length>0&&(n.animations=c)}return n.object=i,n;function s(t){const e=[];for(const n in t){const i=t[n];delete i.metadata,e.push(i)}return e}}clone(t){return(new this.constructor).copy(this,t)}copy(t,e=!0){if(this.name=t.name,this.up.copy(t.up),this.position.copy(t.position),this.rotation.order=t.rotation.order,this.quaternion.copy(t.quaternion),this.scale.copy(t.scale),this.matrix.copy(t.matrix),this.matrixWorld.copy(t.matrixWorld),this.matrixAutoUpdate=t.matrixAutoUpdate,this.matrixWorldNeedsUpdate=t.matrixWorldNeedsUpdate,this.layers.mask=t.layers.mask,this.visible=t.visible,this.castShadow=t.castShadow,this.receiveShadow=t.receiveShadow,this.frustumCulled=t.frustumCulled,this.renderOrder=t.renderOrder,this.userData=JSON.parse(JSON.stringify(t.userData)),!0===e)for(let e=0;e0?i.multiplyScalar(1/Math.sqrt(r)):i.set(0,0,0)}static getBarycoord(t,e,n,i,r){en.subVectors(i,e),nn.subVectors(n,e),rn.subVectors(t,e);const s=en.dot(en),a=en.dot(nn),o=en.dot(rn),l=nn.dot(nn),c=nn.dot(rn),h=s*l-a*a;if(0===h)return r.set(-2,-1,-1);const u=1/h,d=(l*o-a*c)*u,p=(s*c-a*o)*u;return r.set(1-d-p,p,d)}static containsPoint(t,e,n,i){return this.getBarycoord(t,e,n,i,sn),sn.x>=0&&sn.y>=0&&sn.x+sn.y<=1}static getUV(t,e,n,i,r,s,a,o){return this.getBarycoord(t,e,n,i,sn),o.set(0,0),o.addScaledVector(r,sn.x),o.addScaledVector(s,sn.y),o.addScaledVector(a,sn.z),o}static isFrontFacing(t,e,n,i){return en.subVectors(n,e),nn.subVectors(t,e),en.cross(nn).dot(i)<0}set(t,e,n){return this.a.copy(t),this.b.copy(e),this.c.copy(n),this}setFromPointsAndIndices(t,e,n,i){return this.a.copy(t[e]),this.b.copy(t[n]),this.c.copy(t[i]),this}setFromAttributeAndIndices(t,e,n,i){return this.a.fromBufferAttribute(t,e),this.b.fromBufferAttribute(t,n),this.c.fromBufferAttribute(t,i),this}clone(){return(new this.constructor).copy(this)}copy(t){return this.a.copy(t.a),this.b.copy(t.b),this.c.copy(t.c),this}getArea(){return en.subVectors(this.c,this.b),nn.subVectors(this.a,this.b),.5*en.cross(nn).length()}getMidpoint(t){return t.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)}getNormal(t){return dn.getNormal(this.a,this.b,this.c,t)}getPlane(t){return t.setFromCoplanarPoints(this.a,this.b,this.c)}getBarycoord(t,e){return dn.getBarycoord(t,this.a,this.b,this.c,e)}getUV(t,e,n,i,r){return dn.getUV(t,this.a,this.b,this.c,e,n,i,r)}containsPoint(t){return dn.containsPoint(t,this.a,this.b,this.c)}isFrontFacing(t){return dn.isFrontFacing(this.a,this.b,this.c,t)}intersectsBox(t){return t.intersectsTriangle(this)}closestPointToPoint(t,e){const n=this.a,i=this.b,r=this.c;let s,a;an.subVectors(i,n),on.subVectors(r,n),cn.subVectors(t,n);const o=an.dot(cn),l=on.dot(cn);if(o<=0&&l<=0)return e.copy(n);hn.subVectors(t,i);const c=an.dot(hn),h=on.dot(hn);if(c>=0&&h<=c)return e.copy(i);const u=o*h-c*l;if(u<=0&&o>=0&&c<=0)return s=o/(o-c),e.copy(n).addScaledVector(an,s);un.subVectors(t,r);const d=an.dot(un),p=on.dot(un);if(p>=0&&d<=p)return e.copy(r);const m=d*l-o*p;if(m<=0&&l>=0&&p<=0)return a=l/(l-p),e.copy(n).addScaledVector(on,a);const f=c*p-d*h;if(f<=0&&h-c>=0&&d-p>=0)return ln.subVectors(r,i),a=(h-c)/(h-c+(d-p)),e.copy(i).addScaledVector(ln,a);const g=1/(f+m+u);return s=m*g,a=u*g,e.copy(n).addScaledVector(an,s).addScaledVector(on,a)}equals(t){return t.a.equals(this.a)&&t.b.equals(this.b)&&t.c.equals(this.c)}}let pn=0;class mn extends gt{constructor(){super(),Object.defineProperty(this,"id",{value:pn++}),this.uuid=bt(),this.name="",this.type="Material",this.fog=!0,this.blending=1,this.side=0,this.vertexColors=!1,this.opacity=1,this.format=E,this.transparent=!1,this.blendSrc=204,this.blendDst=205,this.blendEquation=n,this.blendSrcAlpha=null,this.blendDstAlpha=null,this.blendEquationAlpha=null,this.depthFunc=3,this.depthTest=!0,this.depthWrite=!0,this.stencilWriteMask=255,this.stencilFunc=519,this.stencilRef=0,this.stencilFuncMask=255,this.stencilFail=ht,this.stencilZFail=ht,this.stencilZPass=ht,this.stencilWrite=!1,this.clippingPlanes=null,this.clipIntersection=!1,this.clipShadows=!1,this.shadowSide=null,this.colorWrite=!0,this.precision=null,this.polygonOffset=!1,this.polygonOffsetFactor=0,this.polygonOffsetUnits=0,this.dithering=!1,this.alphaToCoverage=!1,this.premultipliedAlpha=!1,this.visible=!0,this.toneMapped=!0,this.userData={},this.version=0,this._alphaTest=0}get alphaTest(){return this._alphaTest}set alphaTest(t){this._alphaTest>0!=t>0&&this.version++,this._alphaTest=t}onBuild(){}onBeforeRender(){}onBeforeCompile(){}customProgramCacheKey(){return this.onBeforeCompile.toString()}setValues(t){if(void 0!==t)for(const e in t){const n=t[e];if(void 0===n){console.warn("THREE.Material: '"+e+"' parameter is undefined.");continue}if("shading"===e){console.warn("THREE."+this.type+": .shading has been removed. Use the boolean .flatShading instead."),this.flatShading=1===n;continue}const i=this[e];void 0!==i?i&&i.isColor?i.set(n):i&&i.isVector3&&n&&n.isVector3?i.copy(n):this[e]=n:console.warn("THREE."+this.type+": '"+e+"' is not a property of this material.")}}toJSON(t){const e=void 0===t||"string"==typeof t;e&&(t={textures:{},images:{}});const n={metadata:{version:4.5,type:"Material",generator:"Material.toJSON"}};function i(t){const e=[];for(const n in t){const i=t[n];delete i.metadata,e.push(i)}return e}if(n.uuid=this.uuid,n.type=this.type,""!==this.name&&(n.name=this.name),this.color&&this.color.isColor&&(n.color=this.color.getHex()),void 0!==this.roughness&&(n.roughness=this.roughness),void 0!==this.metalness&&(n.metalness=this.metalness),void 0!==this.sheen&&(n.sheen=this.sheen),this.sheenColor&&this.sheenColor.isColor&&(n.sheenColor=this.sheenColor.getHex()),void 0!==this.sheenRoughness&&(n.sheenRoughness=this.sheenRoughness),this.emissive&&this.emissive.isColor&&(n.emissive=this.emissive.getHex()),this.emissiveIntensity&&1!==this.emissiveIntensity&&(n.emissiveIntensity=this.emissiveIntensity),this.specular&&this.specular.isColor&&(n.specular=this.specular.getHex()),void 0!==this.specularIntensity&&(n.specularIntensity=this.specularIntensity),this.specularColor&&this.specularColor.isColor&&(n.specularColor=this.specularColor.getHex()),void 0!==this.shininess&&(n.shininess=this.shininess),void 0!==this.clearcoat&&(n.clearcoat=this.clearcoat),void 0!==this.clearcoatRoughness&&(n.clearcoatRoughness=this.clearcoatRoughness),this.clearcoatMap&&this.clearcoatMap.isTexture&&(n.clearcoatMap=this.clearcoatMap.toJSON(t).uuid),this.clearcoatRoughnessMap&&this.clearcoatRoughnessMap.isTexture&&(n.clearcoatRoughnessMap=this.clearcoatRoughnessMap.toJSON(t).uuid),this.clearcoatNormalMap&&this.clearcoatNormalMap.isTexture&&(n.clearcoatNormalMap=this.clearcoatNormalMap.toJSON(t).uuid,n.clearcoatNormalScale=this.clearcoatNormalScale.toArray()),this.map&&this.map.isTexture&&(n.map=this.map.toJSON(t).uuid),this.matcap&&this.matcap.isTexture&&(n.matcap=this.matcap.toJSON(t).uuid),this.alphaMap&&this.alphaMap.isTexture&&(n.alphaMap=this.alphaMap.toJSON(t).uuid),this.lightMap&&this.lightMap.isTexture&&(n.lightMap=this.lightMap.toJSON(t).uuid,n.lightMapIntensity=this.lightMapIntensity),this.aoMap&&this.aoMap.isTexture&&(n.aoMap=this.aoMap.toJSON(t).uuid,n.aoMapIntensity=this.aoMapIntensity),this.bumpMap&&this.bumpMap.isTexture&&(n.bumpMap=this.bumpMap.toJSON(t).uuid,n.bumpScale=this.bumpScale),this.normalMap&&this.normalMap.isTexture&&(n.normalMap=this.normalMap.toJSON(t).uuid,n.normalMapType=this.normalMapType,n.normalScale=this.normalScale.toArray()),this.displacementMap&&this.displacementMap.isTexture&&(n.displacementMap=this.displacementMap.toJSON(t).uuid,n.displacementScale=this.displacementScale,n.displacementBias=this.displacementBias),this.roughnessMap&&this.roughnessMap.isTexture&&(n.roughnessMap=this.roughnessMap.toJSON(t).uuid),this.metalnessMap&&this.metalnessMap.isTexture&&(n.metalnessMap=this.metalnessMap.toJSON(t).uuid),this.emissiveMap&&this.emissiveMap.isTexture&&(n.emissiveMap=this.emissiveMap.toJSON(t).uuid),this.specularMap&&this.specularMap.isTexture&&(n.specularMap=this.specularMap.toJSON(t).uuid),this.specularIntensityMap&&this.specularIntensityMap.isTexture&&(n.specularIntensityMap=this.specularIntensityMap.toJSON(t).uuid),this.specularColorMap&&this.specularColorMap.isTexture&&(n.specularColorMap=this.specularColorMap.toJSON(t).uuid),this.envMap&&this.envMap.isTexture&&(n.envMap=this.envMap.toJSON(t).uuid,void 0!==this.combine&&(n.combine=this.combine)),void 0!==this.envMapIntensity&&(n.envMapIntensity=this.envMapIntensity),void 0!==this.reflectivity&&(n.reflectivity=this.reflectivity),void 0!==this.refractionRatio&&(n.refractionRatio=this.refractionRatio),this.gradientMap&&this.gradientMap.isTexture&&(n.gradientMap=this.gradientMap.toJSON(t).uuid),void 0!==this.transmission&&(n.transmission=this.transmission),this.transmissionMap&&this.transmissionMap.isTexture&&(n.transmissionMap=this.transmissionMap.toJSON(t).uuid),void 0!==this.thickness&&(n.thickness=this.thickness),this.thicknessMap&&this.thicknessMap.isTexture&&(n.thicknessMap=this.thicknessMap.toJSON(t).uuid),void 0!==this.attenuationDistance&&(n.attenuationDistance=this.attenuationDistance),void 0!==this.attenuationColor&&(n.attenuationColor=this.attenuationColor.getHex()),void 0!==this.size&&(n.size=this.size),null!==this.shadowSide&&(n.shadowSide=this.shadowSide),void 0!==this.sizeAttenuation&&(n.sizeAttenuation=this.sizeAttenuation),1!==this.blending&&(n.blending=this.blending),0!==this.side&&(n.side=this.side),this.vertexColors&&(n.vertexColors=!0),this.opacity<1&&(n.opacity=this.opacity),this.format!==E&&(n.format=this.format),!0===this.transparent&&(n.transparent=this.transparent),n.depthFunc=this.depthFunc,n.depthTest=this.depthTest,n.depthWrite=this.depthWrite,n.colorWrite=this.colorWrite,n.stencilWrite=this.stencilWrite,n.stencilWriteMask=this.stencilWriteMask,n.stencilFunc=this.stencilFunc,n.stencilRef=this.stencilRef,n.stencilFuncMask=this.stencilFuncMask,n.stencilFail=this.stencilFail,n.stencilZFail=this.stencilZFail,n.stencilZPass=this.stencilZPass,this.rotation&&0!==this.rotation&&(n.rotation=this.rotation),!0===this.polygonOffset&&(n.polygonOffset=!0),0!==this.polygonOffsetFactor&&(n.polygonOffsetFactor=this.polygonOffsetFactor),0!==this.polygonOffsetUnits&&(n.polygonOffsetUnits=this.polygonOffsetUnits),this.linewidth&&1!==this.linewidth&&(n.linewidth=this.linewidth),void 0!==this.dashSize&&(n.dashSize=this.dashSize),void 0!==this.gapSize&&(n.gapSize=this.gapSize),void 0!==this.scale&&(n.scale=this.scale),!0===this.dithering&&(n.dithering=!0),this.alphaTest>0&&(n.alphaTest=this.alphaTest),!0===this.alphaToCoverage&&(n.alphaToCoverage=this.alphaToCoverage),!0===this.premultipliedAlpha&&(n.premultipliedAlpha=this.premultipliedAlpha),!0===this.wireframe&&(n.wireframe=this.wireframe),this.wireframeLinewidth>1&&(n.wireframeLinewidth=this.wireframeLinewidth),"round"!==this.wireframeLinecap&&(n.wireframeLinecap=this.wireframeLinecap),"round"!==this.wireframeLinejoin&&(n.wireframeLinejoin=this.wireframeLinejoin),!0===this.flatShading&&(n.flatShading=this.flatShading),!1===this.visible&&(n.visible=!1),!1===this.toneMapped&&(n.toneMapped=!1),"{}"!==JSON.stringify(this.userData)&&(n.userData=this.userData),e){const e=i(t.textures),r=i(t.images);e.length>0&&(n.textures=e),r.length>0&&(n.images=r)}return n}clone(){return(new this.constructor).copy(this)}copy(t){this.name=t.name,this.fog=t.fog,this.blending=t.blending,this.side=t.side,this.vertexColors=t.vertexColors,this.opacity=t.opacity,this.format=t.format,this.transparent=t.transparent,this.blendSrc=t.blendSrc,this.blendDst=t.blendDst,this.blendEquation=t.blendEquation,this.blendSrcAlpha=t.blendSrcAlpha,this.blendDstAlpha=t.blendDstAlpha,this.blendEquationAlpha=t.blendEquationAlpha,this.depthFunc=t.depthFunc,this.depthTest=t.depthTest,this.depthWrite=t.depthWrite,this.stencilWriteMask=t.stencilWriteMask,this.stencilFunc=t.stencilFunc,this.stencilRef=t.stencilRef,this.stencilFuncMask=t.stencilFuncMask,this.stencilFail=t.stencilFail,this.stencilZFail=t.stencilZFail,this.stencilZPass=t.stencilZPass,this.stencilWrite=t.stencilWrite;const e=t.clippingPlanes;let n=null;if(null!==e){const t=e.length;n=new Array(t);for(let i=0;i!==t;++i)n[i]=e[i].clone()}return this.clippingPlanes=n,this.clipIntersection=t.clipIntersection,this.clipShadows=t.clipShadows,this.shadowSide=t.shadowSide,this.colorWrite=t.colorWrite,this.precision=t.precision,this.polygonOffset=t.polygonOffset,this.polygonOffsetFactor=t.polygonOffsetFactor,this.polygonOffsetUnits=t.polygonOffsetUnits,this.dithering=t.dithering,this.alphaTest=t.alphaTest,this.alphaToCoverage=t.alphaToCoverage,this.premultipliedAlpha=t.premultipliedAlpha,this.visible=t.visible,this.toneMapped=t.toneMapped,this.userData=JSON.parse(JSON.stringify(t.userData)),this}dispose(){this.dispatchEvent({type:"dispose"})}set needsUpdate(t){!0===t&&this.version++}}mn.prototype.isMaterial=!0;class fn extends mn{constructor(t){super(),this.type="MeshBasicMaterial",this.color=new Gt(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this}}fn.prototype.isMeshBasicMaterial=!0;const gn=new Qt,vn=new Lt;class yn{constructor(t,e,n){if(Array.isArray(t))throw new TypeError("THREE.BufferAttribute: array should be a Typed Array.");this.name="",this.array=t,this.itemSize=e,this.count=void 0!==t?t.length/e:0,this.normalized=!0===n,this.usage=ut,this.updateRange={offset:0,count:-1},this.version=0}onUploadCallback(){}set needsUpdate(t){!0===t&&this.version++}setUsage(t){return this.usage=t,this}copy(t){return this.name=t.name,this.array=new t.array.constructor(t.array),this.itemSize=t.itemSize,this.count=t.count,this.normalized=t.normalized,this.usage=t.usage,this}copyAt(t,e,n){t*=this.itemSize,n*=e.itemSize;for(let i=0,r=this.itemSize;i65535?Tn:wn)(t,1):this.index=t,this}getAttribute(t){return this.attributes[t]}setAttribute(t,e){return this.attributes[t]=e,this}deleteAttribute(t){return delete this.attributes[t],this}hasAttribute(t){return void 0!==this.attributes[t]}addGroup(t,e,n=0){this.groups.push({start:t,count:e,materialIndex:n})}clearGroups(){this.groups=[]}setDrawRange(t,e){this.drawRange.start=t,this.drawRange.count=e}applyMatrix4(t){const e=this.attributes.position;void 0!==e&&(e.applyMatrix4(t),e.needsUpdate=!0);const n=this.attributes.normal;if(void 0!==n){const e=(new Ct).getNormalMatrix(t);n.applyNormalMatrix(e),n.needsUpdate=!0}const i=this.attributes.tangent;return void 0!==i&&(i.transformDirection(t),i.needsUpdate=!0),null!==this.boundingBox&&this.computeBoundingBox(),null!==this.boundingSphere&&this.computeBoundingSphere(),this}applyQuaternion(t){return Cn.makeRotationFromQuaternion(t),this.applyMatrix4(Cn),this}rotateX(t){return Cn.makeRotationX(t),this.applyMatrix4(Cn),this}rotateY(t){return Cn.makeRotationY(t),this.applyMatrix4(Cn),this}rotateZ(t){return Cn.makeRotationZ(t),this.applyMatrix4(Cn),this}translate(t,e,n){return Cn.makeTranslation(t,e,n),this.applyMatrix4(Cn),this}scale(t,e,n){return Cn.makeScale(t,e,n),this.applyMatrix4(Cn),this}lookAt(t){return Pn.lookAt(t),Pn.updateMatrix(),this.applyMatrix4(Pn.matrix),this}center(){return this.computeBoundingBox(),this.boundingBox.getCenter(Dn).negate(),this.translate(Dn.x,Dn.y,Dn.z),this}setFromPoints(t){const e=[];for(let n=0,i=t.length;n0&&(t.userData=this.userData),void 0!==this.parameters){const e=this.parameters;for(const n in e)void 0!==e[n]&&(t[n]=e[n]);return t}t.data={attributes:{}};const e=this.index;null!==e&&(t.data.index={type:e.array.constructor.name,array:Array.prototype.slice.call(e.array)});const n=this.attributes;for(const e in n){const i=n[e];t.data.attributes[e]=i.toJSON(t.data)}const i={};let r=!1;for(const e in this.morphAttributes){const n=this.morphAttributes[e],s=[];for(let e=0,i=n.length;e0&&(i[e]=s,r=!0)}r&&(t.data.morphAttributes=i,t.data.morphTargetsRelative=this.morphTargetsRelative);const s=this.groups;s.length>0&&(t.data.groups=JSON.parse(JSON.stringify(s)));const a=this.boundingSphere;return null!==a&&(t.data.boundingSphere={center:a.center.toArray(),radius:a.radius}),t}clone(){return(new this.constructor).copy(this)}copy(t){this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null;const e={};this.name=t.name;const n=t.index;null!==n&&this.setIndex(n.clone(e));const i=t.attributes;for(const t in i){const n=i[t];this.setAttribute(t,n.clone(e))}const r=t.morphAttributes;for(const t in r){const n=[],i=r[t];for(let t=0,r=i.length;t0){const t=e[n[0]];if(void 0!==t){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let e=0,n=t.length;e0&&console.error("THREE.Mesh.updateMorphTargets() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.")}}raycast(t,e){const n=this.geometry,i=this.material,r=this.matrixWorld;if(void 0===i)return;if(null===n.boundingSphere&&n.computeBoundingSphere(),Un.copy(n.boundingSphere),Un.applyMatrix4(r),!1===t.ray.intersectsSphere(Un))return;if(On.copy(r).invert(),Fn.copy(t.ray).applyMatrix4(On),null!==n.boundingBox&&!1===Fn.intersectsBox(n.boundingBox))return;let s;if(n.isBufferGeometry){const r=n.index,a=n.attributes.position,o=n.morphAttributes.position,l=n.morphTargetsRelative,c=n.attributes.uv,h=n.attributes.uv2,u=n.groups,d=n.drawRange;if(null!==r)if(Array.isArray(i))for(let n=0,p=u.length;nn.far?null:{distance:c,point:$n.clone(),object:t}}(t,e,n,i,Hn,Gn,kn,Qn);if(p){o&&(Yn.fromBufferAttribute(o,c),Zn.fromBufferAttribute(o,h),Kn.fromBufferAttribute(o,u),p.uv=dn.getUV(Qn,Hn,Gn,kn,Yn,Zn,Kn,new Lt)),l&&(Yn.fromBufferAttribute(l,c),Zn.fromBufferAttribute(l,h),Kn.fromBufferAttribute(l,u),p.uv2=dn.getUV(Qn,Hn,Gn,kn,Yn,Zn,Kn,new Lt));const t={a:c,b:h,c:u,normal:new Qt,materialIndex:0};dn.getNormal(Hn,Gn,kn,t.normal),p.face=t}return p}ti.prototype.isMesh=!0;class ni extends zn{constructor(t=1,e=1,n=1,i=1,r=1,s=1){super(),this.type="BoxGeometry",this.parameters={width:t,height:e,depth:n,widthSegments:i,heightSegments:r,depthSegments:s};const a=this;i=Math.floor(i),r=Math.floor(r),s=Math.floor(s);const o=[],l=[],c=[],h=[];let u=0,d=0;function p(t,e,n,i,r,s,p,m,f,g,v){const y=s/f,x=p/g,_=s/2,b=p/2,M=m/2,w=f+1,S=g+1;let T=0,E=0;const A=new Qt;for(let s=0;s0?1:-1,c.push(A.x,A.y,A.z),h.push(o/f),h.push(1-s/g),T+=1}}for(let t=0;t0&&(e.defines=this.defines),e.vertexShader=this.vertexShader,e.fragmentShader=this.fragmentShader;const n={};for(const t in this.extensions)!0===this.extensions[t]&&(n[t]=!0);return Object.keys(n).length>0&&(e.extensions=n),e}}ai.prototype.isShaderMaterial=!0;class oi extends tn{constructor(){super(),this.type="Camera",this.matrixWorldInverse=new Le,this.projectionMatrix=new Le,this.projectionMatrixInverse=new Le}copy(t,e){return super.copy(t,e),this.matrixWorldInverse.copy(t.matrixWorldInverse),this.projectionMatrix.copy(t.projectionMatrix),this.projectionMatrixInverse.copy(t.projectionMatrixInverse),this}getWorldDirection(t){this.updateWorldMatrix(!0,!1);const e=this.matrixWorld.elements;return t.set(-e[8],-e[9],-e[10]).normalize()}updateMatrixWorld(t){super.updateMatrixWorld(t),this.matrixWorldInverse.copy(this.matrixWorld).invert()}updateWorldMatrix(t,e){super.updateWorldMatrix(t,e),this.matrixWorldInverse.copy(this.matrixWorld).invert()}clone(){return(new this.constructor).copy(this)}}oi.prototype.isCamera=!0;class li extends oi{constructor(t=50,e=1,n=.1,i=2e3){super(),this.type="PerspectiveCamera",this.fov=t,this.zoom=1,this.near=n,this.far=i,this.focus=10,this.aspect=e,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}copy(t,e){return super.copy(t,e),this.fov=t.fov,this.zoom=t.zoom,this.near=t.near,this.far=t.far,this.focus=t.focus,this.aspect=t.aspect,this.view=null===t.view?null:Object.assign({},t.view),this.filmGauge=t.filmGauge,this.filmOffset=t.filmOffset,this}setFocalLength(t){const e=.5*this.getFilmHeight()/t;this.fov=2*_t*Math.atan(e),this.updateProjectionMatrix()}getFocalLength(){const t=Math.tan(.5*xt*this.fov);return.5*this.getFilmHeight()/t}getEffectiveFOV(){return 2*_t*Math.atan(Math.tan(.5*xt*this.fov)/this.zoom)}getFilmWidth(){return this.filmGauge*Math.min(this.aspect,1)}getFilmHeight(){return this.filmGauge/Math.max(this.aspect,1)}setViewOffset(t,e,n,i,r,s){this.aspect=t/e,null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=t,this.view.fullHeight=e,this.view.offsetX=n,this.view.offsetY=i,this.view.width=r,this.view.height=s,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const t=this.near;let e=t*Math.tan(.5*xt*this.fov)/this.zoom,n=2*e,i=this.aspect*n,r=-.5*i;const s=this.view;if(null!==this.view&&this.view.enabled){const t=s.fullWidth,a=s.fullHeight;r+=s.offsetX*i/t,e-=s.offsetY*n/a,i*=s.width/t,n*=s.height/a}const a=this.filmOffset;0!==a&&(r+=t*a/this.getFilmWidth()),this.projectionMatrix.makePerspective(r,r+i,e,e-n,t,this.far),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(t){const e=super.toJSON(t);return e.object.fov=this.fov,e.object.zoom=this.zoom,e.object.near=this.near,e.object.far=this.far,e.object.focus=this.focus,e.object.aspect=this.aspect,null!==this.view&&(e.object.view=Object.assign({},this.view)),e.object.filmGauge=this.filmGauge,e.object.filmOffset=this.filmOffset,e}}li.prototype.isPerspectiveCamera=!0;const ci=90;class hi extends tn{constructor(t,e,n){if(super(),this.type="CubeCamera",!0!==n.isWebGLCubeRenderTarget)return void console.error("THREE.CubeCamera: The constructor now expects an instance of WebGLCubeRenderTarget as third parameter.");this.renderTarget=n;const i=new li(ci,1,t,e);i.layers=this.layers,i.up.set(0,-1,0),i.lookAt(new Qt(1,0,0)),this.add(i);const r=new li(ci,1,t,e);r.layers=this.layers,r.up.set(0,-1,0),r.lookAt(new Qt(-1,0,0)),this.add(r);const s=new li(ci,1,t,e);s.layers=this.layers,s.up.set(0,0,1),s.lookAt(new Qt(0,1,0)),this.add(s);const a=new li(ci,1,t,e);a.layers=this.layers,a.up.set(0,0,-1),a.lookAt(new Qt(0,-1,0)),this.add(a);const o=new li(ci,1,t,e);o.layers=this.layers,o.up.set(0,-1,0),o.lookAt(new Qt(0,0,1)),this.add(o);const l=new li(ci,1,t,e);l.layers=this.layers,l.up.set(0,-1,0),l.lookAt(new Qt(0,0,-1)),this.add(l)}update(t,e){null===this.parent&&this.updateMatrixWorld();const n=this.renderTarget,[i,r,s,a,o,l]=this.children,c=t.xr.enabled,h=t.getRenderTarget();t.xr.enabled=!1;const u=n.texture.generateMipmaps;n.texture.generateMipmaps=!1,t.setRenderTarget(n,0),t.render(e,i),t.setRenderTarget(n,1),t.render(e,r),t.setRenderTarget(n,2),t.render(e,s),t.setRenderTarget(n,3),t.render(e,a),t.setRenderTarget(n,4),t.render(e,o),n.texture.generateMipmaps=u,t.setRenderTarget(n,5),t.render(e,l),t.setRenderTarget(h),t.xr.enabled=c,n.texture.needsPMREMUpdate=!0}}class ui extends jt{constructor(t,e,n,i,s,a,o,l,c,h){super(t=void 0!==t?t:[],e=void 0!==e?e:r,n,i,s,a,o,l,c,h),this.flipY=!1}get images(){return this.image}set images(t){this.image=t}}ui.prototype.isCubeTexture=!0;class di extends Jt{constructor(t,e,n){Number.isInteger(e)&&(console.warn("THREE.WebGLCubeRenderTarget: constructor signature is now WebGLCubeRenderTarget( size, options )"),e=n),super(t,t,e),e=e||{},this.texture=new ui(void 0,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.format,e.type,e.anisotropy,e.encoding),this.texture.isRenderTargetTexture=!0,this.texture.generateMipmaps=void 0!==e.generateMipmaps&&e.generateMipmaps,this.texture.minFilter=void 0!==e.minFilter?e.minFilter:g,this.texture._needsFlipEnvMap=!1}fromEquirectangularTexture(t,e){this.texture.type=e.type,this.texture.format=E,this.texture.encoding=e.encoding,this.texture.generateMipmaps=e.generateMipmaps,this.texture.minFilter=e.minFilter,this.texture.magFilter=e.magFilter;const n={uniforms:{tEquirect:{value:null}},vertexShader:"\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\tvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\n\t\t\t\t\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n\n\t\t\t\t}\n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvWorldDirection = transformDirection( position, modelMatrix );\n\n\t\t\t\t\t#include \n\t\t\t\t\t#include \n\n\t\t\t\t}\n\t\t\t",fragmentShader:"\n\n\t\t\t\tuniform sampler2D tEquirect;\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\t#include \n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvec3 direction = normalize( vWorldDirection );\n\n\t\t\t\t\tvec2 sampleUV = equirectUv( direction );\n\n\t\t\t\t\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\n\t\t\t\t}\n\t\t\t"},i=new ni(5,5,5),r=new ai({name:"CubemapFromEquirect",uniforms:ii(n.uniforms),vertexShader:n.vertexShader,fragmentShader:n.fragmentShader,side:1,blending:0});r.uniforms.tEquirect.value=e;const s=new ti(i,r),a=e.minFilter;e.minFilter===y&&(e.minFilter=g);return new hi(1,10,this).update(t,s),e.minFilter=a,s.geometry.dispose(),s.material.dispose(),this}clear(t,e,n,i){const r=t.getRenderTarget();for(let r=0;r<6;r++)t.setRenderTarget(this,r),t.clear(e,n,i);t.setRenderTarget(r)}}di.prototype.isWebGLCubeRenderTarget=!0;const pi=new Qt,mi=new Qt,fi=new Ct;class gi{constructor(t=new Qt(1,0,0),e=0){this.normal=t,this.constant=e}set(t,e){return this.normal.copy(t),this.constant=e,this}setComponents(t,e,n,i){return this.normal.set(t,e,n),this.constant=i,this}setFromNormalAndCoplanarPoint(t,e){return this.normal.copy(t),this.constant=-e.dot(this.normal),this}setFromCoplanarPoints(t,e,n){const i=pi.subVectors(n,e).cross(mi.subVectors(t,e)).normalize();return this.setFromNormalAndCoplanarPoint(i,t),this}copy(t){return this.normal.copy(t.normal),this.constant=t.constant,this}normalize(){const t=1/this.normal.length();return this.normal.multiplyScalar(t),this.constant*=t,this}negate(){return this.constant*=-1,this.normal.negate(),this}distanceToPoint(t){return this.normal.dot(t)+this.constant}distanceToSphere(t){return this.distanceToPoint(t.center)-t.radius}projectPoint(t,e){return e.copy(this.normal).multiplyScalar(-this.distanceToPoint(t)).add(t)}intersectLine(t,e){const n=t.delta(pi),i=this.normal.dot(n);if(0===i)return 0===this.distanceToPoint(t.start)?e.copy(t.start):null;const r=-(t.start.dot(this.normal)+this.constant)/i;return r<0||r>1?null:e.copy(n).multiplyScalar(r).add(t.start)}intersectsLine(t){const e=this.distanceToPoint(t.start),n=this.distanceToPoint(t.end);return e<0&&n>0||n<0&&e>0}intersectsBox(t){return t.intersectsPlane(this)}intersectsSphere(t){return t.intersectsPlane(this)}coplanarPoint(t){return t.copy(this.normal).multiplyScalar(-this.constant)}applyMatrix4(t,e){const n=e||fi.getNormalMatrix(t),i=this.coplanarPoint(pi).applyMatrix4(t),r=this.normal.applyMatrix3(n).normalize();return this.constant=-i.dot(r),this}translate(t){return this.constant-=t.dot(this.normal),this}equals(t){return t.normal.equals(this.normal)&&t.constant===this.constant}clone(){return(new this.constructor).copy(this)}}gi.prototype.isPlane=!0;const vi=new _e,yi=new Qt;class xi{constructor(t=new gi,e=new gi,n=new gi,i=new gi,r=new gi,s=new gi){this.planes=[t,e,n,i,r,s]}set(t,e,n,i,r,s){const a=this.planes;return a[0].copy(t),a[1].copy(e),a[2].copy(n),a[3].copy(i),a[4].copy(r),a[5].copy(s),this}copy(t){const e=this.planes;for(let n=0;n<6;n++)e[n].copy(t.planes[n]);return this}setFromProjectionMatrix(t){const e=this.planes,n=t.elements,i=n[0],r=n[1],s=n[2],a=n[3],o=n[4],l=n[5],c=n[6],h=n[7],u=n[8],d=n[9],p=n[10],m=n[11],f=n[12],g=n[13],v=n[14],y=n[15];return e[0].setComponents(a-i,h-o,m-u,y-f).normalize(),e[1].setComponents(a+i,h+o,m+u,y+f).normalize(),e[2].setComponents(a+r,h+l,m+d,y+g).normalize(),e[3].setComponents(a-r,h-l,m-d,y-g).normalize(),e[4].setComponents(a-s,h-c,m-p,y-v).normalize(),e[5].setComponents(a+s,h+c,m+p,y+v).normalize(),this}intersectsObject(t){const e=t.geometry;return null===e.boundingSphere&&e.computeBoundingSphere(),vi.copy(e.boundingSphere).applyMatrix4(t.matrixWorld),this.intersectsSphere(vi)}intersectsSprite(t){return vi.center.set(0,0,0),vi.radius=.7071067811865476,vi.applyMatrix4(t.matrixWorld),this.intersectsSphere(vi)}intersectsSphere(t){const e=this.planes,n=t.center,i=-t.radius;for(let t=0;t<6;t++){if(e[t].distanceToPoint(n)0?t.max.x:t.min.x,yi.y=i.normal.y>0?t.max.y:t.min.y,yi.z=i.normal.z>0?t.max.z:t.min.z,i.distanceToPoint(yi)<0)return!1}return!0}containsPoint(t){const e=this.planes;for(let n=0;n<6;n++)if(e[n].distanceToPoint(t)<0)return!1;return!0}clone(){return(new this.constructor).copy(this)}}function _i(){let t=null,e=!1,n=null,i=null;function r(e,s){n(e,s),i=t.requestAnimationFrame(r)}return{start:function(){!0!==e&&null!==n&&(i=t.requestAnimationFrame(r),e=!0)},stop:function(){t.cancelAnimationFrame(i),e=!1},setAnimationLoop:function(t){n=t},setContext:function(e){t=e}}}function bi(t,e){const n=e.isWebGL2,i=new WeakMap;return{get:function(t){return t.isInterleavedBufferAttribute&&(t=t.data),i.get(t)},remove:function(e){e.isInterleavedBufferAttribute&&(e=e.data);const n=i.get(e);n&&(t.deleteBuffer(n.buffer),i.delete(e))},update:function(e,r){if(e.isGLBufferAttribute){const t=i.get(e);return void((!t||t.version 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_BlinnPhong( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, 1.0, dotVH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif",bumpmap_pars_fragment:"#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy, float faceDirection ) {\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 ) * faceDirection;\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif",clipping_planes_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#pragma unroll_loop_end\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\tif ( clipped ) discard;\n\t#endif\n#endif",clipping_planes_pars_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif",clipping_planes_pars_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif",clipping_planes_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif",color_fragment:"#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif",color_pars_fragment:"#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif",color_pars_vertex:"#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvarying vec3 vColor;\n#endif",color_vertex:"#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif",common:"#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal;\n#endif\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}",cube_uv_reflection_fragment:"#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_maxMipLevel 8.0\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_maxTileSize 256.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\tfloat texelSize = 1.0 / ( 3.0 * cubeUV_maxTileSize );\n\t\tvec2 uv = getUV( direction, face ) * ( faceSize - 1.0 ) + 0.5;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tif ( mipInt < cubeUV_maxMipLevel ) {\n\t\t\tuv.y += 2.0 * cubeUV_maxTileSize;\n\t\t}\n\t\tuv.y += filterInt * 2.0 * cubeUV_minTileSize;\n\t\tuv.x += 3.0 * max( 0.0, cubeUV_maxTileSize - 2.0 * faceSize );\n\t\tuv *= texelSize;\n\t\treturn texture2D( envMap, uv ).rgb;\n\t}\n\t#define r0 1.0\n\t#define v0 0.339\n\t#define m0 - 2.0\n\t#define r1 0.8\n\t#define v1 0.276\n\t#define m1 - 1.0\n\t#define r4 0.4\n\t#define v4 0.046\n\t#define m4 2.0\n\t#define r5 0.305\n\t#define v5 0.016\n\t#define m5 3.0\n\t#define r6 0.21\n\t#define v6 0.0038\n\t#define m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= r1 ) {\n\t\t\tmip = ( r0 - roughness ) * ( m1 - m0 ) / ( r0 - r1 ) + m0;\n\t\t} else if ( roughness >= r4 ) {\n\t\t\tmip = ( r1 - roughness ) * ( m4 - m1 ) / ( r1 - r4 ) + m1;\n\t\t} else if ( roughness >= r5 ) {\n\t\t\tmip = ( r4 - roughness ) * ( m5 - m4 ) / ( r4 - r5 ) + m4;\n\t\t} else if ( roughness >= r6 ) {\n\t\t\tmip = ( r5 - roughness ) * ( m6 - m5 ) / ( r5 - r6 ) + m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), m0, cubeUV_maxMipLevel );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif",defaultnormal_vertex:"vec3 transformedNormal = objectNormal;\n#ifdef USE_INSTANCING\n\tmat3 m = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( m[ 0 ], m[ 0 ] ), dot( m[ 1 ], m[ 1 ] ), dot( m[ 2 ], m[ 2 ] ) );\n\ttransformedNormal = m * transformedNormal;\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = ( modelViewMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif",displacementmap_pars_vertex:"#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif",displacementmap_vertex:"#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias );\n#endif",emissivemap_fragment:"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif",emissivemap_pars_fragment:"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif",encodings_fragment:"gl_FragColor = linearToOutputTexel( gl_FragColor );",encodings_pars_fragment:"vec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}",envmap_fragment:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 envColor = textureCubeUV( envMap, reflectVec, 0.0 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif",envmap_common_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif",envmap_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float reflectivity;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif",envmap_pars_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) ||defined( PHONG )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\t\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif",envmap_physical_pars_fragment:"#if defined( USE_ENVMAP )\n\t#ifdef ENVMAP_MODE_REFRACTION\n\t\tuniform float refractionRatio;\n\t#endif\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 reflectVec;\n\t\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\t\treflectVec = reflect( - viewDir, normal );\n\t\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\t#else\n\t\t\t\treflectVec = refract( - viewDir, normal, refractionRatio );\n\t\t\t#endif\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n#endif",envmap_vertex:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif",fog_vertex:"#ifdef USE_FOG\n\tvFogDepth = - mvPosition.z;\n#endif",fog_pars_vertex:"#ifdef USE_FOG\n\tvarying float vFogDepth;\n#endif",fog_fragment:"#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, vFogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif",fog_pars_fragment:"#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float vFogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif",gradientmap_pars_fragment:"#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn vec3( texture2D( gradientMap, coord ).r );\n\t#else\n\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t#endif\n}",lightmap_fragment:"#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tlightMapIrradiance *= PI;\n\t#endif\n\treflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif",lightmap_pars_fragment:"#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif",lights_lambert_vertex:"vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\nvIndirectFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n\tvIndirectBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\nvIndirectFront += getAmbientLightIrradiance( ambientLightColor );\nvIndirectFront += getLightProbeIrradiance( lightProbe, geometry.normal );\n#ifdef DOUBLE_SIDED\n\tvIndirectBack += getAmbientLightIrradiance( ambientLightColor );\n\tvIndirectBack += getLightProbeIrradiance( lightProbe, backGeometry.normal );\n#endif\n#if NUM_POINT_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tgetPointLightInfo( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( - dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tgetSpotLightInfo( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( - dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if NUM_DIR_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tgetDirectionalLightInfo( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( - dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvIndirectFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry.normal );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvIndirectBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry.normal );\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif",lights_pars_begin:"uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\nuniform vec3 lightProbe[ 9 ];\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\t#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tif ( cutoffDistance > 0.0 ) {\n\t\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\t}\n\t\treturn distanceFalloff;\n\t#else\n\t\tif ( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\t\treturn pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t\t}\n\t\treturn 1.0;\n\t#endif\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif",lights_toon_fragment:"ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;",lights_toon_pars_fragment:"varying vec3 vViewPosition;\nstruct ToonMaterial {\n\tvec3 diffuseColor;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Toon\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Toon\n#define Material_LightProbeLOD( material )\t(0)",lights_phong_fragment:"BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;",lights_phong_pars_fragment:"varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )\t(0)",lights_physical_fragment:"PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\t#ifdef SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULARINTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vUv ).a;\n\t\t#endif\n\t\t#ifdef USE_SPECULARCOLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vUv ).rgb;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( ior - 1.0 ) / ( ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vUv ).a;\n\t#endif\n#endif",lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n};\nvec3 clearcoatSpecular = vec3( 0.0 );\nvec3 sheenSpecular = vec3( 0.0 );\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\tvec3 FssEss = specularColor * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = specularColor + ( 1.0 - specularColor ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3(\t\t0, 1,\t\t0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecular += ccIrradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.clearcoatNormal, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * BRDF_Sheen( directLight.direction, geometry.viewDir, geometry.normal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.roughness );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecular += clearcoatRadiance * EnvironmentBRDF( geometry.clearcoatNormal, geometry.viewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * material.sheenColor * IBLSheenBRDF( geometry.normal, geometry.viewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\tcomputeMultiscattering( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - ( singleScattering + multiScattering ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}",lights_fragment_begin:"\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\n#ifdef USE_CLEARCOAT\n\tgeometry.clearcoatNormal = clearcoatNormal;\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\tirradiance += getLightProbeIrradiance( lightProbe, geometry.normal );\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry.normal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif",lights_fragment_maps:"#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometry.normal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getIBLRadiance( geometry.viewDir, geometry.normal, material.roughness );\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif",lights_fragment_end:"#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometry, material, reflectedLight );\n#endif",logdepthbuf_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif",logdepthbuf_pars_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif",logdepthbuf_pars_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t\tvarying float vIsPerspective;\n\t#else\n\t\tuniform float logDepthBufFC;\n\t#endif\n#endif",logdepthbuf_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n\t#else\n\t\tif ( isPerspectiveMatrix( projectionMatrix ) ) {\n\t\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\t\tgl_Position.z *= gl_Position.w;\n\t\t}\n\t#endif\n#endif",map_fragment:"#ifdef USE_MAP\n\tvec4 sampledDiffuseColor = texture2D( map, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\tsampledDiffuseColor = vec4( mix( pow( sampledDiffuseColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), sampledDiffuseColor.rgb * 0.0773993808, vec3( lessThanEqual( sampledDiffuseColor.rgb, vec3( 0.04045 ) ) ) ), sampledDiffuseColor.w );\n\t#endif\n\tdiffuseColor *= sampledDiffuseColor;\n#endif",map_pars_fragment:"#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif",map_particle_fragment:"#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n#endif\n#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif",map_particle_pars_fragment:"#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tuniform mat3 uvTransform;\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif",metalnessmap_fragment:"float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif",metalnessmap_pars_fragment:"#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] > 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1, 2 ) * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n\t\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n\t\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n\t\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n\t#endif\n#endif",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n\tuniform float morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t\tuniform sampler2DArray morphTargetsTexture;\n\t\tuniform vec2 morphTargetsTextureSize;\n\t\tvec3 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset, const in int stride ) {\n\t\t\tfloat texelIndex = float( vertexIndex * stride + offset );\n\t\t\tfloat y = floor( texelIndex / morphTargetsTextureSize.x );\n\t\t\tfloat x = texelIndex - y * morphTargetsTextureSize.x;\n\t\t\tvec3 morphUV = vec3( ( x + 0.5 ) / morphTargetsTextureSize.x, y / morphTargetsTextureSize.y, morphTargetIndex );\n\t\t\treturn texture( morphTargetsTexture, morphUV ).xyz;\n\t\t}\n\t#else\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\tuniform float morphTargetInfluences[ 8 ];\n\t\t#else\n\t\t\tuniform float morphTargetInfluences[ 4 ];\n\t\t#endif\n\t#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\t#ifndef USE_MORPHNORMALS\n\t\t\t\tif ( morphTargetInfluences[ i ] > 0.0 ) transformed += getMorph( gl_VertexID, i, 0, 1 ) * morphTargetInfluences[ i ];\n\t\t\t#else\n\t\t\t\tif ( morphTargetInfluences[ i ] > 0.0 ) transformed += getMorph( gl_VertexID, i, 0, 2 ) * morphTargetInfluences[ i ];\n\t\t\t#endif\n\t\t}\n\t#else\n\t\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\t\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\t\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\t\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\t\t\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\t\t\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\t\t\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\t\t#endif\n\t#endif\n#endif",normal_fragment_begin:"float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\t#ifdef USE_TANGENT\n\t\tvec3 tangent = normalize( vTangent );\n\t\tvec3 bitangent = normalize( vBitangent );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\ttangent = tangent * faceDirection;\n\t\t\tbitangent = bitangent * faceDirection;\n\t\t#endif\n\t\t#if defined( TANGENTSPACE_NORMALMAP ) || defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tmat3 vTBN = mat3( tangent, bitangent, normal );\n\t\t#endif\n\t#endif\n#endif\nvec3 geometryNormal = normal;",normal_fragment_maps:"#ifdef OBJECTSPACE_NORMALMAP\n\tnormal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( TANGENTSPACE_NORMALMAP )\n\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\t#ifdef USE_TANGENT\n\t\tnormal = normalize( vTBN * mapN );\n\t#else\n\t\tnormal = perturbNormal2Arb( - vViewPosition, normal, mapN, faceDirection );\n\t#endif\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif",normal_pars_fragment:"#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif",normal_pars_vertex:"#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif",normal_vertex:"#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif",normalmap_pars_fragment:"#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef OBJECTSPACE_NORMALMAP\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( TANGENTSPACE_NORMALMAP ) || defined ( USE_CLEARCOAT_NORMALMAP ) )\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 mapN, float faceDirection ) {\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tvec3 N = surf_norm;\n\t\tvec3 q1perp = cross( q1, N );\n\t\tvec3 q0perp = cross( N, q0 );\n\t\tvec3 T = q1perp * st0.x + q0perp * st1.x;\n\t\tvec3 B = q1perp * st0.y + q0perp * st1.y;\n\t\tfloat det = max( dot( T, T ), dot( B, B ) );\n\t\tfloat scale = ( det == 0.0 ) ? 0.0 : faceDirection * inversesqrt( det );\n\t\treturn normalize( T * ( mapN.x * scale ) + B * ( mapN.y * scale ) + N * mapN.z );\n\t}\n#endif",clearcoat_normal_fragment_begin:"#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = geometryNormal;\n#endif",clearcoat_normal_fragment_maps:"#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\t#ifdef USE_TANGENT\n\t\tclearcoatNormal = normalize( vTBN * clearcoatMapN );\n\t#else\n\t\tclearcoatNormal = perturbNormal2Arb( - vViewPosition, clearcoatNormal, clearcoatMapN, faceDirection );\n\t#endif\n#endif",clearcoat_pars_fragment:"#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif",output_fragment:"#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= transmissionAlpha + 0.1;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );",packing:"vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nvec4 pack2HalfToRGBA( vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( vec4 v ) {\n\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}",premultiplied_alpha_fragment:"#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif",project_vertex:"vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_INSTANCING\n\tmvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;",dithering_fragment:"#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif",dithering_pars_fragment:"#ifdef DITHERING\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif",roughnessmap_fragment:"float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif",roughnessmap_pars_fragment:"#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif",shadowmap_pars_fragment:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ), \n\t\t\t\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t\tf.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ), \n\t\t\t\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t\tf.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif",shadowmap_pars_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif",shadowmap_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0 || NUM_SPOT_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0\n\t\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\tvec4 shadowWorldPosition;\n\t#endif\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias, 0 );\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n#endif",shadowmask_pars_fragment:"float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#endif\n\treturn shadow;\n}",skinbase_vertex:"#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\t#ifdef BONE_TEXTURE\n\t\tuniform highp sampler2D boneTexture;\n\t\tuniform int boneTextureSize;\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tfloat j = i * 4.0;\n\t\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\t\ty = dy * ( y + 0.5 );\n\t\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\t\treturn bone;\n\t\t}\n\t#else\n\t\tuniform mat4 boneMatrices[ MAX_BONES ];\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tmat4 bone = boneMatrices[ int(i) ];\n\t\t\treturn bone;\n\t\t}\n\t#endif\n#endif",skinning_vertex:"#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif",skinnormal_vertex:"#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif",specularmap_fragment:"float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif",specularmap_pars_fragment:"#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif",tonemapping_fragment:"#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif",tonemapping_pars_fragment:"#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3(\t1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108,\t1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605,\t1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }",transmission_fragment:"#ifdef USE_TRANSMISSION\n\tfloat transmissionAlpha = 1.0;\n\tfloat transmissionFactor = transmission;\n\tfloat thicknessFactor = thickness;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\ttransmissionFactor *= texture2D( transmissionMap, vUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tthicknessFactor *= texture2D( thicknessMap, vUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmission = getIBLVolumeRefraction(\n\t\tn, v, roughnessFactor, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, ior, thicknessFactor,\n\t\tattenuationColor, attenuationDistance );\n\ttotalDiffuse = mix( totalDiffuse, transmission.rgb, transmissionFactor );\n\ttransmissionAlpha = mix( transmissionAlpha, transmission.a, transmissionFactor );\n#endif",transmission_pars_fragment:"#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat framebufferLod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\treturn texture2DLodEXT( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n\t\t#else\n\t\t\treturn texture2D( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n\t\t#endif\n\t}\n\tvec3 applyVolumeAttenuation( const in vec3 radiance, const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( attenuationDistance == 0.0 ) {\n\t\t\treturn radiance;\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance * radiance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\trefractionCoords += 1.0;\n\t\trefractionCoords /= 2.0;\n\t\tvec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\tvec3 attenuatedColor = applyVolumeAttenuation( transmittedLight.rgb, length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor * diffuseColor, transmittedLight.a );\n\t}\n#endif",uv_pars_fragment:"#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )\n\tvarying vec2 vUv;\n#endif",uv_pars_vertex:"#ifdef USE_UV\n\t#ifdef UVS_VERTEX_ONLY\n\t\tvec2 vUv;\n\t#else\n\t\tvarying vec2 vUv;\n\t#endif\n\tuniform mat3 uvTransform;\n#endif",uv_vertex:"#ifdef USE_UV\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif",uv2_pars_fragment:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif",uv2_pars_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n\tuniform mat3 uv2Transform;\n#endif",uv2_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION )\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif",background_vert:"varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}",background_frag:"uniform sampler2D t2D;\nvarying vec2 vUv;\nvoid main() {\n\tgl_FragColor = texture2D( t2D, vUv );\n\t#include \n\t#include \n}",cube_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}",cube_frag:"#include \nuniform float opacity;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 vReflect = vWorldDirection;\n\t#include \n\tgl_FragColor = envColor;\n\tgl_FragColor.a *= opacity;\n\t#include \n\t#include \n}",depth_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvHighPrecisionZW = gl_Position.zw;\n}",depth_frag:"#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\t#endif\n}",distanceRGBA_vert:"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}",distanceRGBA_frag:"#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main () {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}",equirect_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}",equirect_frag:"uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\t#include \n\t#include \n}",linedashed_vert:"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",linedashed_frag:"uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_vert:"#define LAMBERT\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_frag:"uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.indirectDiffuse += ( gl_FrontFacing ) ? vIndirectFront : vIndirectBack;\n\t#else\n\t\treflectedLight.indirectDiffuse += vIndirectFront;\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= BRDF_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshmatcap_vert:"#define MATCAP\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n}",meshmatcap_frag:"#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t#else\n\t\tvec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshnormal_vert:"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}",meshnormal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}",meshphong_vert:"#define PHONG\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphong_frag:"#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphysical_vert:"#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}",meshphysical_frag:"#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULARINTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n\t#ifdef USE_SPECULARCOLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecular;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshtoon_vert:"#define TOON\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}",meshtoon_frag:"#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",points_vert:"uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}",points_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_vert:"#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_frag:"uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n\t#include \n\t#include \n}",sprite_vert:"uniform float rotation;\nuniform vec2 center;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}",sprite_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n}"},Si={common:{diffuse:{value:new Gt(16777215)},opacity:{value:1},map:{value:null},uvTransform:{value:new Ct},uv2Transform:{value:new Ct},alphaMap:{value:null},alphaTest:{value:0}},specularmap:{specularMap:{value:null}},envmap:{envMap:{value:null},flipEnvMap:{value:-1},reflectivity:{value:1},ior:{value:1.5},refractionRatio:{value:.98}},aomap:{aoMap:{value:null},aoMapIntensity:{value:1}},lightmap:{lightMap:{value:null},lightMapIntensity:{value:1}},emissivemap:{emissiveMap:{value:null}},bumpmap:{bumpMap:{value:null},bumpScale:{value:1}},normalmap:{normalMap:{value:null},normalScale:{value:new Lt(1,1)}},displacementmap:{displacementMap:{value:null},displacementScale:{value:1},displacementBias:{value:0}},roughnessmap:{roughnessMap:{value:null}},metalnessmap:{metalnessMap:{value:null}},gradientmap:{gradientMap:{value:null}},fog:{fogDensity:{value:25e-5},fogNear:{value:1},fogFar:{value:2e3},fogColor:{value:new Gt(16777215)}},lights:{ambientLightColor:{value:[]},lightProbe:{value:[]},directionalLights:{value:[],properties:{direction:{},color:{}}},directionalLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},directionalShadowMap:{value:[]},directionalShadowMatrix:{value:[]},spotLights:{value:[],properties:{color:{},position:{},direction:{},distance:{},coneCos:{},penumbraCos:{},decay:{}}},spotLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},spotShadowMap:{value:[]},spotShadowMatrix:{value:[]},pointLights:{value:[],properties:{color:{},position:{},decay:{},distance:{}}},pointLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{},shadowCameraNear:{},shadowCameraFar:{}}},pointShadowMap:{value:[]},pointShadowMatrix:{value:[]},hemisphereLights:{value:[],properties:{direction:{},skyColor:{},groundColor:{}}},rectAreaLights:{value:[],properties:{color:{},position:{},width:{},height:{}}},ltc_1:{value:null},ltc_2:{value:null}},points:{diffuse:{value:new Gt(16777215)},opacity:{value:1},size:{value:1},scale:{value:1},map:{value:null},alphaMap:{value:null},alphaTest:{value:0},uvTransform:{value:new Ct}},sprite:{diffuse:{value:new Gt(16777215)},opacity:{value:1},center:{value:new Lt(.5,.5)},rotation:{value:0},map:{value:null},alphaMap:{value:null},alphaTest:{value:0},uvTransform:{value:new Ct}}},Ti={basic:{uniforms:ri([Si.common,Si.specularmap,Si.envmap,Si.aomap,Si.lightmap,Si.fog]),vertexShader:wi.meshbasic_vert,fragmentShader:wi.meshbasic_frag},lambert:{uniforms:ri([Si.common,Si.specularmap,Si.envmap,Si.aomap,Si.lightmap,Si.emissivemap,Si.fog,Si.lights,{emissive:{value:new Gt(0)}}]),vertexShader:wi.meshlambert_vert,fragmentShader:wi.meshlambert_frag},phong:{uniforms:ri([Si.common,Si.specularmap,Si.envmap,Si.aomap,Si.lightmap,Si.emissivemap,Si.bumpmap,Si.normalmap,Si.displacementmap,Si.fog,Si.lights,{emissive:{value:new Gt(0)},specular:{value:new Gt(1118481)},shininess:{value:30}}]),vertexShader:wi.meshphong_vert,fragmentShader:wi.meshphong_frag},standard:{uniforms:ri([Si.common,Si.envmap,Si.aomap,Si.lightmap,Si.emissivemap,Si.bumpmap,Si.normalmap,Si.displacementmap,Si.roughnessmap,Si.metalnessmap,Si.fog,Si.lights,{emissive:{value:new Gt(0)},roughness:{value:1},metalness:{value:0},envMapIntensity:{value:1}}]),vertexShader:wi.meshphysical_vert,fragmentShader:wi.meshphysical_frag},toon:{uniforms:ri([Si.common,Si.aomap,Si.lightmap,Si.emissivemap,Si.bumpmap,Si.normalmap,Si.displacementmap,Si.gradientmap,Si.fog,Si.lights,{emissive:{value:new Gt(0)}}]),vertexShader:wi.meshtoon_vert,fragmentShader:wi.meshtoon_frag},matcap:{uniforms:ri([Si.common,Si.bumpmap,Si.normalmap,Si.displacementmap,Si.fog,{matcap:{value:null}}]),vertexShader:wi.meshmatcap_vert,fragmentShader:wi.meshmatcap_frag},points:{uniforms:ri([Si.points,Si.fog]),vertexShader:wi.points_vert,fragmentShader:wi.points_frag},dashed:{uniforms:ri([Si.common,Si.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:wi.linedashed_vert,fragmentShader:wi.linedashed_frag},depth:{uniforms:ri([Si.common,Si.displacementmap]),vertexShader:wi.depth_vert,fragmentShader:wi.depth_frag},normal:{uniforms:ri([Si.common,Si.bumpmap,Si.normalmap,Si.displacementmap,{opacity:{value:1}}]),vertexShader:wi.meshnormal_vert,fragmentShader:wi.meshnormal_frag},sprite:{uniforms:ri([Si.sprite,Si.fog]),vertexShader:wi.sprite_vert,fragmentShader:wi.sprite_frag},background:{uniforms:{uvTransform:{value:new Ct},t2D:{value:null}},vertexShader:wi.background_vert,fragmentShader:wi.background_frag},cube:{uniforms:ri([Si.envmap,{opacity:{value:1}}]),vertexShader:wi.cube_vert,fragmentShader:wi.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:wi.equirect_vert,fragmentShader:wi.equirect_frag},distanceRGBA:{uniforms:ri([Si.common,Si.displacementmap,{referencePosition:{value:new Qt},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:wi.distanceRGBA_vert,fragmentShader:wi.distanceRGBA_frag},shadow:{uniforms:ri([Si.lights,Si.fog,{color:{value:new Gt(0)},opacity:{value:1}}]),vertexShader:wi.shadow_vert,fragmentShader:wi.shadow_frag}};function Ei(t,e,n,i,r){const s=new Gt(0);let a,o,c=0,h=null,u=0,d=null;function p(t,e){n.buffers.color.setClear(t.r,t.g,t.b,e,r)}return{getClearColor:function(){return s},setClearColor:function(t,e=1){s.set(t),c=e,p(s,c)},getClearAlpha:function(){return c},setClearAlpha:function(t){c=t,p(s,c)},render:function(n,r){let m=!1,f=!0===r.isScene?r.background:null;f&&f.isTexture&&(f=e.get(f));const g=t.xr,v=g.getSession&&g.getSession();v&&"additive"===v.environmentBlendMode&&(f=null),null===f?p(s,c):f&&f.isColor&&(p(f,1),m=!0),(t.autoClear||m)&&t.clear(t.autoClearColor,t.autoClearDepth,t.autoClearStencil),f&&(f.isCubeTexture||f.mapping===l)?(void 0===o&&(o=new ti(new ni(1,1,1),new ai({name:"BackgroundCubeMaterial",uniforms:ii(Ti.cube.uniforms),vertexShader:Ti.cube.vertexShader,fragmentShader:Ti.cube.fragmentShader,side:1,depthTest:!1,depthWrite:!1,fog:!1})),o.geometry.deleteAttribute("normal"),o.geometry.deleteAttribute("uv"),o.onBeforeRender=function(t,e,n){this.matrixWorld.copyPosition(n.matrixWorld)},Object.defineProperty(o.material,"envMap",{get:function(){return this.uniforms.envMap.value}}),i.update(o)),o.material.uniforms.envMap.value=f,o.material.uniforms.flipEnvMap.value=f.isCubeTexture&&!1===f.isRenderTargetTexture?-1:1,h===f&&u===f.version&&d===t.toneMapping||(o.material.needsUpdate=!0,h=f,u=f.version,d=t.toneMapping),n.unshift(o,o.geometry,o.material,0,0,null)):f&&f.isTexture&&(void 0===a&&(a=new ti(new Mi(2,2),new ai({name:"BackgroundMaterial",uniforms:ii(Ti.background.uniforms),vertexShader:Ti.background.vertexShader,fragmentShader:Ti.background.fragmentShader,side:0,depthTest:!1,depthWrite:!1,fog:!1})),a.geometry.deleteAttribute("normal"),Object.defineProperty(a.material,"map",{get:function(){return this.uniforms.t2D.value}}),i.update(a)),a.material.uniforms.t2D.value=f,!0===f.matrixAutoUpdate&&f.updateMatrix(),a.material.uniforms.uvTransform.value.copy(f.matrix),h===f&&u===f.version&&d===t.toneMapping||(a.material.needsUpdate=!0,h=f,u=f.version,d=t.toneMapping),n.unshift(a,a.geometry,a.material,0,0,null))}}}function Ai(t,e,n,i){const r=t.getParameter(34921),s=i.isWebGL2?null:e.get("OES_vertex_array_object"),a=i.isWebGL2||null!==s,o={},l=d(null);let c=l;function h(e){return i.isWebGL2?t.bindVertexArray(e):s.bindVertexArrayOES(e)}function u(e){return i.isWebGL2?t.deleteVertexArray(e):s.deleteVertexArrayOES(e)}function d(t){const e=[],n=[],i=[];for(let t=0;t=0){let s=l[e];if(void 0===s&&("instanceMatrix"===e&&r.instanceMatrix&&(s=r.instanceMatrix),"instanceColor"===e&&r.instanceColor&&(s=r.instanceColor)),void 0!==s){const e=s.normalized,a=s.itemSize,l=n.get(s);if(void 0===l)continue;const c=l.buffer,h=l.type,u=l.bytesPerElement;if(s.isInterleavedBufferAttribute){const n=s.data,l=n.stride,d=s.offset;if(n&&n.isInstancedInterleavedBuffer){for(let t=0;t0&&t.getShaderPrecisionFormat(35632,36338).precision>0)return"highp";e="mediump"}return"mediump"===e&&t.getShaderPrecisionFormat(35633,36337).precision>0&&t.getShaderPrecisionFormat(35632,36337).precision>0?"mediump":"lowp"}const s="undefined"!=typeof WebGL2RenderingContext&&t instanceof WebGL2RenderingContext||"undefined"!=typeof WebGL2ComputeRenderingContext&&t instanceof WebGL2ComputeRenderingContext;let a=void 0!==n.precision?n.precision:"highp";const o=r(a);o!==a&&(console.warn("THREE.WebGLRenderer:",a,"not supported, using",o,"instead."),a=o);const l=s||e.has("WEBGL_draw_buffers"),c=!0===n.logarithmicDepthBuffer,h=t.getParameter(34930),u=t.getParameter(35660),d=t.getParameter(3379),p=t.getParameter(34076),m=t.getParameter(34921),f=t.getParameter(36347),g=t.getParameter(36348),v=t.getParameter(36349),y=u>0,x=s||e.has("OES_texture_float");return{isWebGL2:s,drawBuffers:l,getMaxAnisotropy:function(){if(void 0!==i)return i;if(!0===e.has("EXT_texture_filter_anisotropic")){const n=e.get("EXT_texture_filter_anisotropic");i=t.getParameter(n.MAX_TEXTURE_MAX_ANISOTROPY_EXT)}else i=0;return i},getMaxPrecision:r,precision:a,logarithmicDepthBuffer:c,maxTextures:h,maxVertexTextures:u,maxTextureSize:d,maxCubemapSize:p,maxAttributes:m,maxVertexUniforms:f,maxVaryings:g,maxFragmentUniforms:v,vertexTextures:y,floatFragmentTextures:x,floatVertexTextures:y&&x,maxSamples:s?t.getParameter(36183):0}}function Ci(t){const e=this;let n=null,i=0,r=!1,s=!1;const a=new gi,o=new Ct,l={value:null,needsUpdate:!1};function c(){l.value!==n&&(l.value=n,l.needsUpdate=i>0),e.numPlanes=i,e.numIntersection=0}function h(t,n,i,r){const s=null!==t?t.length:0;let c=null;if(0!==s){if(c=l.value,!0!==r||null===c){const e=i+4*s,r=n.matrixWorldInverse;o.getNormalMatrix(r),(null===c||c.length0){const a=new di(s.height/2);return a.fromEquirectangularTexture(t,r),e.set(r,a),r.addEventListener("dispose",i),n(a.texture,r.mapping)}return null}}}return r},dispose:function(){e=new WeakMap}}}Ti.physical={uniforms:ri([Ti.standard.uniforms,{clearcoat:{value:0},clearcoatMap:{value:null},clearcoatRoughness:{value:0},clearcoatRoughnessMap:{value:null},clearcoatNormalScale:{value:new Lt(1,1)},clearcoatNormalMap:{value:null},sheen:{value:0},sheenColor:{value:new Gt(0)},sheenColorMap:{value:null},sheenRoughness:{value:1},sheenRoughnessMap:{value:null},transmission:{value:0},transmissionMap:{value:null},transmissionSamplerSize:{value:new Lt},transmissionSamplerMap:{value:null},thickness:{value:0},thicknessMap:{value:null},attenuationDistance:{value:0},attenuationColor:{value:new Gt(0)},specularIntensity:{value:1},specularIntensityMap:{value:null},specularColor:{value:new Gt(1,1,1)},specularColorMap:{value:null}}]),vertexShader:wi.meshphysical_vert,fragmentShader:wi.meshphysical_frag};class Di extends oi{constructor(t=-1,e=1,n=1,i=-1,r=.1,s=2e3){super(),this.type="OrthographicCamera",this.zoom=1,this.view=null,this.left=t,this.right=e,this.top=n,this.bottom=i,this.near=r,this.far=s,this.updateProjectionMatrix()}copy(t,e){return super.copy(t,e),this.left=t.left,this.right=t.right,this.top=t.top,this.bottom=t.bottom,this.near=t.near,this.far=t.far,this.zoom=t.zoom,this.view=null===t.view?null:Object.assign({},t.view),this}setViewOffset(t,e,n,i,r,s){null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=t,this.view.fullHeight=e,this.view.offsetX=n,this.view.offsetY=i,this.view.width=r,this.view.height=s,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const t=(this.right-this.left)/(2*this.zoom),e=(this.top-this.bottom)/(2*this.zoom),n=(this.right+this.left)/2,i=(this.top+this.bottom)/2;let r=n-t,s=n+t,a=i+e,o=i-e;if(null!==this.view&&this.view.enabled){const t=(this.right-this.left)/this.view.fullWidth/this.zoom,e=(this.top-this.bottom)/this.view.fullHeight/this.zoom;r+=t*this.view.offsetX,s=r+t*this.view.width,a-=e*this.view.offsetY,o=a-e*this.view.height}this.projectionMatrix.makeOrthographic(r,s,a,o,this.near,this.far),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(t){const e=super.toJSON(t);return e.object.zoom=this.zoom,e.object.left=this.left,e.object.right=this.right,e.object.top=this.top,e.object.bottom=this.bottom,e.object.near=this.near,e.object.far=this.far,null!==this.view&&(e.object.view=Object.assign({},this.view)),e}}Di.prototype.isOrthographicCamera=!0;class Ii extends ai{constructor(t){super(t),this.type="RawShaderMaterial"}}Ii.prototype.isRawShaderMaterial=!0;const Ni=Math.pow(2,8),Bi=[.125,.215,.35,.446,.526,.582],zi=5+Bi.length,Oi=20,Fi=new Di,{_lodPlanes:Ui,_sizeLods:Hi,_sigmas:Gi}=Ji(),ki=new Gt;let Vi=null;const Wi=(1+Math.sqrt(5))/2,ji=1/Wi,qi=[new Qt(1,1,1),new Qt(-1,1,1),new Qt(1,1,-1),new Qt(-1,1,-1),new Qt(0,Wi,ji),new Qt(0,Wi,-ji),new Qt(ji,0,Wi),new Qt(-ji,0,Wi),new Qt(Wi,ji,0),new Qt(-Wi,ji,0)];class Xi{constructor(t){this._renderer=t,this._pingPongRenderTarget=null,this._blurMaterial=function(t){const e=new Float32Array(t),n=new Qt(0,1,0);return new Ii({name:"SphericalGaussianBlur",defines:{n:t},uniforms:{envMap:{value:null},samples:{value:1},weights:{value:e},latitudinal:{value:!1},dTheta:{value:0},mipInt:{value:0},poleAxis:{value:n}},vertexShader:$i(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\t\t\tuniform int samples;\n\t\t\tuniform float weights[ n ];\n\t\t\tuniform bool latitudinal;\n\t\t\tuniform float dTheta;\n\t\t\tuniform float mipInt;\n\t\t\tuniform vec3 poleAxis;\n\n\t\t\t#define ENVMAP_TYPE_CUBE_UV\n\t\t\t#include \n\n\t\t\tvec3 getSample( float theta, vec3 axis ) {\n\n\t\t\t\tfloat cosTheta = cos( theta );\n\t\t\t\t// Rodrigues' axis-angle rotation\n\t\t\t\tvec3 sampleDirection = vOutputDirection * cosTheta\n\t\t\t\t\t+ cross( axis, vOutputDirection ) * sin( theta )\n\t\t\t\t\t+ axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta );\n\n\t\t\t\treturn bilinearCubeUV( envMap, sampleDirection, mipInt );\n\n\t\t\t}\n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection );\n\n\t\t\t\tif ( all( equal( axis, vec3( 0.0 ) ) ) ) {\n\n\t\t\t\t\taxis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x );\n\n\t\t\t\t}\n\n\t\t\t\taxis = normalize( axis );\n\n\t\t\t\tgl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t\t\t\tgl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis );\n\n\t\t\t\tfor ( int i = 1; i < n; i++ ) {\n\n\t\t\t\t\tif ( i >= samples ) {\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tfloat theta = dTheta * float( i );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( theta, axis );\n\n\t\t\t\t}\n\n\t\t\t}\n\t\t",blending:0,depthTest:!1,depthWrite:!1})}(Oi),this._equirectShader=null,this._cubemapShader=null,this._compileMaterial(this._blurMaterial)}fromScene(t,e=0,n=.1,i=100){Vi=this._renderer.getRenderTarget();const r=this._allocateTargets();return this._sceneToCubeUV(t,n,i,r),e>0&&this._blur(r,0,0,e),this._applyPMREM(r),this._cleanup(r),r}fromEquirectangular(t,e=null){return this._fromTexture(t,e)}fromCubemap(t,e=null){return this._fromTexture(t,e)}compileCubemapShader(){null===this._cubemapShader&&(this._cubemapShader=Qi(),this._compileMaterial(this._cubemapShader))}compileEquirectangularShader(){null===this._equirectShader&&(this._equirectShader=Ki(),this._compileMaterial(this._equirectShader))}dispose(){this._blurMaterial.dispose(),null!==this._cubemapShader&&this._cubemapShader.dispose(),null!==this._equirectShader&&this._equirectShader.dispose();for(let t=0;t2?Ni:0,Ni,Ni),o.setRenderTarget(i),d&&o.render(u,r),o.render(t,r)}u.geometry.dispose(),u.material.dispose(),o.toneMapping=c,o.autoClear=l,t.background=p}_textureToCubeUV(t,e){const n=this._renderer,i=t.mapping===r||t.mapping===s;i?null==this._cubemapShader&&(this._cubemapShader=Qi()):null==this._equirectShader&&(this._equirectShader=Ki());const a=i?this._cubemapShader:this._equirectShader,o=new ti(Ui[0],a),l=a.uniforms;l.envMap.value=t,i||l.texelSize.value.set(1/t.image.width,1/t.image.height),Zi(e,0,0,3*Ni,2*Ni),n.setRenderTarget(e),n.render(o,Fi)}_applyPMREM(t){const e=this._renderer,n=e.autoClear;e.autoClear=!1;for(let e=1;eOi&&console.warn(`sigmaRadians, ${r}, is too large and will clip, as it requested ${m} samples when the maximum is set to 20`);const f=[];let g=0;for(let t=0;t4?i-8+4:0),3*v,2*v),o.setRenderTarget(e),o.render(c,Fi)}}function Ji(){const t=[],e=[],n=[];let i=8;for(let r=0;r4?a=Bi[r-8+4-1]:0==r&&(a=0),n.push(a);const o=1/(s-1),l=-o/2,c=1+o/2,h=[l,l,c,l,c,c,l,l,c,c,l,c],u=6,d=6,p=3,m=2,f=1,g=new Float32Array(p*d*u),v=new Float32Array(m*d*u),y=new Float32Array(f*d*u);for(let t=0;t2?0:-1,i=[e,n,0,e+2/3,n,0,e+2/3,n+1,0,e,n,0,e+2/3,n+1,0,e,n+1,0];g.set(i,p*d*t),v.set(h,m*d*t);const r=[t,t,t,t,t,t];y.set(r,f*d*t)}const x=new zn;x.setAttribute("position",new yn(g,p)),x.setAttribute("uv",new yn(v,m)),x.setAttribute("faceIndex",new yn(y,f)),t.push(x),i>4&&i--}return{_lodPlanes:t,_sizeLods:e,_sigmas:n}}function Yi(t){const e=new Jt(3*Ni,3*Ni,t);return e.texture.mapping=l,e.texture.name="PMREM.cubeUv",e.scissorTest=!0,e}function Zi(t,e,n,i,r){t.viewport.set(e,n,i,r),t.scissor.set(e,n,i,r)}function Ki(){const t=new Lt(1,1);return new Ii({name:"EquirectangularToCubeUV",uniforms:{envMap:{value:null},texelSize:{value:t}},vertexShader:$i(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\t\t\tuniform vec2 texelSize;\n\n\t\t\t#include \n\n\t\t\tvoid main() {\n\n\t\t\t\tgl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\n\t\t\t\tvec3 outputDirection = normalize( vOutputDirection );\n\t\t\t\tvec2 uv = equirectUv( outputDirection );\n\n\t\t\t\tvec2 f = fract( uv / texelSize - 0.5 );\n\t\t\t\tuv -= f * texelSize;\n\t\t\t\tvec3 tl = texture2D ( envMap, uv ).rgb;\n\t\t\t\tuv.x += texelSize.x;\n\t\t\t\tvec3 tr = texture2D ( envMap, uv ).rgb;\n\t\t\t\tuv.y += texelSize.y;\n\t\t\t\tvec3 br = texture2D ( envMap, uv ).rgb;\n\t\t\t\tuv.x -= texelSize.x;\n\t\t\t\tvec3 bl = texture2D ( envMap, uv ).rgb;\n\n\t\t\t\tvec3 tm = mix( tl, tr, f.x );\n\t\t\t\tvec3 bm = mix( bl, br, f.x );\n\t\t\t\tgl_FragColor.rgb = mix( tm, bm, f.y );\n\n\t\t\t}\n\t\t",blending:0,depthTest:!1,depthWrite:!1})}function Qi(){return new Ii({name:"CubemapToCubeUV",uniforms:{envMap:{value:null}},vertexShader:$i(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform samplerCube envMap;\n\n\t\t\tvoid main() {\n\n\t\t\t\tgl_FragColor = textureCube( envMap, vec3( - vOutputDirection.x, vOutputDirection.yz ) );\n\n\t\t\t}\n\t\t",blending:0,depthTest:!1,depthWrite:!1})}function $i(){return"\n\n\t\tprecision mediump float;\n\t\tprecision mediump int;\n\n\t\tattribute vec3 position;\n\t\tattribute vec2 uv;\n\t\tattribute float faceIndex;\n\n\t\tvarying vec3 vOutputDirection;\n\n\t\t// RH coordinate system; PMREM face-indexing convention\n\t\tvec3 getDirection( vec2 uv, float face ) {\n\n\t\t\tuv = 2.0 * uv - 1.0;\n\n\t\t\tvec3 direction = vec3( uv, 1.0 );\n\n\t\t\tif ( face == 0.0 ) {\n\n\t\t\t\tdirection = direction.zyx; // ( 1, v, u ) pos x\n\n\t\t\t} else if ( face == 1.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xz *= -1.0; // ( -u, 1, -v ) pos y\n\n\t\t\t} else if ( face == 2.0 ) {\n\n\t\t\t\tdirection.x *= -1.0; // ( -u, v, 1 ) pos z\n\n\t\t\t} else if ( face == 3.0 ) {\n\n\t\t\t\tdirection = direction.zyx;\n\t\t\t\tdirection.xz *= -1.0; // ( -1, v, -u ) neg x\n\n\t\t\t} else if ( face == 4.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xy *= -1.0; // ( -u, -1, v ) neg y\n\n\t\t\t} else if ( face == 5.0 ) {\n\n\t\t\t\tdirection.z *= -1.0; // ( u, v, -1 ) neg z\n\n\t\t\t}\n\n\t\t\treturn direction;\n\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\tvOutputDirection = getDirection( uv, faceIndex );\n\t\t\tgl_Position = vec4( position, 1.0 );\n\n\t\t}\n\t"}function tr(t){let e=new WeakMap,n=null;function i(t){const n=t.target;n.removeEventListener("dispose",i);const r=e.get(n);void 0!==r&&(e.delete(n),r.dispose())}return{get:function(l){if(l&&l.isTexture){const c=l.mapping,h=c===a||c===o,u=c===r||c===s;if(h||u){if(l.isRenderTargetTexture&&!0===l.needsPMREMUpdate){l.needsPMREMUpdate=!1;let i=e.get(l);return null===n&&(n=new Xi(t)),i=h?n.fromEquirectangular(l,i):n.fromCubemap(l,i),e.set(l,i),i.texture}if(e.has(l))return e.get(l).texture;{const r=l.image;if(h&&r&&r.height>0||u&&r&&function(t){let e=0;const n=6;for(let i=0;i65535?Tn:wn)(n,1);o.version=a;const l=s.get(t);l&&e.remove(l),s.set(t,o)}return{get:function(t,e){return!0===r[e.id]||(e.addEventListener("dispose",a),r[e.id]=!0,n.memory.geometries++),e},update:function(t){const n=t.attributes;for(const t in n)e.update(n[t],34962);const i=t.morphAttributes;for(const t in i){const n=i[t];for(let t=0,i=n.length;te.maxTextureSize&&(u=Math.ceil(h/e.maxTextureSize),h=e.maxTextureSize);const d=new Float32Array(h*u*4*i),p=new sr(d,h,u,i);p.format=E,p.type=M,p.needsUpdate=!0;const m=4*l;for(let e=0;e0)return t;const r=e*n;let s=gr[r];if(void 0===s&&(s=new Float32Array(r),gr[r]=s),0!==e){i.toArray(s,0);for(let i=1,r=0;i!==e;++i)r+=n,t[i].toArray(s,r)}return s}function Mr(t,e){if(t.length!==e.length)return!1;for(let n=0,i=t.length;n/gm;function Ts(t){return t.replace(Ss,Es)}function Es(t,e){const n=wi[e];if(void 0===n)throw new Error("Can not resolve #include <"+e+">");return Ts(n)}const As=/#pragma unroll_loop[\s]+?for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g,Rs=/#pragma unroll_loop_start\s+for\s*\(\s*int\s+i\s*=\s*(\d+)\s*;\s*i\s*<\s*(\d+)\s*;\s*i\s*\+\+\s*\)\s*{([\s\S]+?)}\s+#pragma unroll_loop_end/g;function Ls(t){return t.replace(Rs,Ps).replace(As,Cs)}function Cs(t,e,n,i){return console.warn("WebGLProgram: #pragma unroll_loop shader syntax is deprecated. Please use #pragma unroll_loop_start syntax instead."),Ps(t,e,n,i)}function Ps(t,e,n,i){let r="";for(let t=parseInt(e);t0&&(x+="\n"),_=[g,v].filter(bs).join("\n"),_.length>0&&(_+="\n")):(x=[Ds(n),"#define SHADER_NAME "+n.shaderName,v,n.instancing?"#define USE_INSTANCING":"",n.instancingColor?"#define USE_INSTANCING_COLOR":"",n.supportsVertexTextures?"#define VERTEX_TEXTURES":"","#define MAX_BONES "+n.maxBones,n.useFog&&n.fog?"#define USE_FOG":"",n.useFog&&n.fogExp2?"#define FOG_EXP2":"",n.map?"#define USE_MAP":"",n.envMap?"#define USE_ENVMAP":"",n.envMap?"#define "+m:"",n.lightMap?"#define USE_LIGHTMAP":"",n.aoMap?"#define USE_AOMAP":"",n.emissiveMap?"#define USE_EMISSIVEMAP":"",n.bumpMap?"#define USE_BUMPMAP":"",n.normalMap?"#define USE_NORMALMAP":"",n.normalMap&&n.objectSpaceNormalMap?"#define OBJECTSPACE_NORMALMAP":"",n.normalMap&&n.tangentSpaceNormalMap?"#define TANGENTSPACE_NORMALMAP":"",n.clearcoatMap?"#define USE_CLEARCOATMAP":"",n.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",n.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",n.displacementMap&&n.supportsVertexTextures?"#define USE_DISPLACEMENTMAP":"",n.specularMap?"#define USE_SPECULARMAP":"",n.specularIntensityMap?"#define USE_SPECULARINTENSITYMAP":"",n.specularColorMap?"#define USE_SPECULARCOLORMAP":"",n.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.transmission?"#define USE_TRANSMISSION":"",n.transmissionMap?"#define USE_TRANSMISSIONMAP":"",n.thicknessMap?"#define USE_THICKNESSMAP":"",n.sheenColorMap?"#define USE_SHEENCOLORMAP":"",n.sheenRoughnessMap?"#define USE_SHEENROUGHNESSMAP":"",n.vertexTangents?"#define USE_TANGENT":"",n.vertexColors?"#define USE_COLOR":"",n.vertexAlphas?"#define USE_COLOR_ALPHA":"",n.vertexUvs?"#define USE_UV":"",n.uvsVertexOnly?"#define UVS_VERTEX_ONLY":"",n.flatShading?"#define FLAT_SHADED":"",n.skinning?"#define USE_SKINNING":"",n.useVertexTexture?"#define BONE_TEXTURE":"",n.morphTargets?"#define USE_MORPHTARGETS":"",n.morphNormals&&!1===n.flatShading?"#define USE_MORPHNORMALS":"",n.morphTargets&&n.isWebGL2?"#define MORPHTARGETS_TEXTURE":"",n.morphTargets&&n.isWebGL2?"#define MORPHTARGETS_COUNT "+n.morphTargetsCount:"",n.doubleSided?"#define DOUBLE_SIDED":"",n.flipSided?"#define FLIP_SIDED":"",n.shadowMapEnabled?"#define USE_SHADOWMAP":"",n.shadowMapEnabled?"#define "+d:"",n.sizeAttenuation?"#define USE_SIZEATTENUATION":"",n.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",n.logarithmicDepthBuffer&&n.rendererExtensionFragDepth?"#define USE_LOGDEPTHBUF_EXT":"","uniform mat4 modelMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;","#ifdef USE_INSTANCING","\tattribute mat4 instanceMatrix;","#endif","#ifdef USE_INSTANCING_COLOR","\tattribute vec3 instanceColor;","#endif","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#ifdef USE_TANGENT","\tattribute vec4 tangent;","#endif","#if defined( USE_COLOR_ALPHA )","\tattribute vec4 color;","#elif defined( USE_COLOR )","\tattribute vec3 color;","#endif","#if ( defined( USE_MORPHTARGETS ) && ! defined( MORPHTARGETS_TEXTURE ) )","\tattribute vec3 morphTarget0;","\tattribute vec3 morphTarget1;","\tattribute vec3 morphTarget2;","\tattribute vec3 morphTarget3;","\t#ifdef USE_MORPHNORMALS","\t\tattribute vec3 morphNormal0;","\t\tattribute vec3 morphNormal1;","\t\tattribute vec3 morphNormal2;","\t\tattribute vec3 morphNormal3;","\t#else","\t\tattribute vec3 morphTarget4;","\t\tattribute vec3 morphTarget5;","\t\tattribute vec3 morphTarget6;","\t\tattribute vec3 morphTarget7;","\t#endif","#endif","#ifdef USE_SKINNING","\tattribute vec4 skinIndex;","\tattribute vec4 skinWeight;","#endif","\n"].filter(bs).join("\n"),_=[g,Ds(n),"#define SHADER_NAME "+n.shaderName,v,n.useFog&&n.fog?"#define USE_FOG":"",n.useFog&&n.fogExp2?"#define FOG_EXP2":"",n.map?"#define USE_MAP":"",n.matcap?"#define USE_MATCAP":"",n.envMap?"#define USE_ENVMAP":"",n.envMap?"#define "+p:"",n.envMap?"#define "+m:"",n.envMap?"#define "+f:"",n.lightMap?"#define USE_LIGHTMAP":"",n.aoMap?"#define USE_AOMAP":"",n.emissiveMap?"#define USE_EMISSIVEMAP":"",n.bumpMap?"#define USE_BUMPMAP":"",n.normalMap?"#define USE_NORMALMAP":"",n.normalMap&&n.objectSpaceNormalMap?"#define OBJECTSPACE_NORMALMAP":"",n.normalMap&&n.tangentSpaceNormalMap?"#define TANGENTSPACE_NORMALMAP":"",n.clearcoat?"#define USE_CLEARCOAT":"",n.clearcoatMap?"#define USE_CLEARCOATMAP":"",n.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",n.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",n.specularMap?"#define USE_SPECULARMAP":"",n.specularIntensityMap?"#define USE_SPECULARINTENSITYMAP":"",n.specularColorMap?"#define USE_SPECULARCOLORMAP":"",n.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.alphaTest?"#define USE_ALPHATEST":"",n.sheen?"#define USE_SHEEN":"",n.sheenColorMap?"#define USE_SHEENCOLORMAP":"",n.sheenRoughnessMap?"#define USE_SHEENROUGHNESSMAP":"",n.transmission?"#define USE_TRANSMISSION":"",n.transmissionMap?"#define USE_TRANSMISSIONMAP":"",n.thicknessMap?"#define USE_THICKNESSMAP":"",n.decodeVideoTexture?"#define DECODE_VIDEO_TEXTURE":"",n.vertexTangents?"#define USE_TANGENT":"",n.vertexColors||n.instancingColor?"#define USE_COLOR":"",n.vertexAlphas?"#define USE_COLOR_ALPHA":"",n.vertexUvs?"#define USE_UV":"",n.uvsVertexOnly?"#define UVS_VERTEX_ONLY":"",n.gradientMap?"#define USE_GRADIENTMAP":"",n.flatShading?"#define FLAT_SHADED":"",n.doubleSided?"#define DOUBLE_SIDED":"",n.flipSided?"#define FLIP_SIDED":"",n.shadowMapEnabled?"#define USE_SHADOWMAP":"",n.shadowMapEnabled?"#define "+d:"",n.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",n.physicallyCorrectLights?"#define PHYSICALLY_CORRECT_LIGHTS":"",n.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",n.logarithmicDepthBuffer&&n.rendererExtensionFragDepth?"#define USE_LOGDEPTHBUF_EXT":"",(n.extensionShaderTextureLOD||n.envMap)&&n.rendererExtensionShaderTextureLod?"#define TEXTURE_LOD_EXT":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;",0!==n.toneMapping?"#define TONE_MAPPING":"",0!==n.toneMapping?wi.tonemapping_pars_fragment:"",0!==n.toneMapping?_s("toneMapping",n.toneMapping):"",n.dithering?"#define DITHERING":"",n.format===T?"#define OPAQUE":"",wi.encodings_pars_fragment,xs("linearToOutputTexel",n.outputEncoding),n.depthPacking?"#define DEPTH_PACKING "+n.depthPacking:"","\n"].filter(bs).join("\n")),h=Ts(h),h=Ms(h,n),h=ws(h,n),u=Ts(u),u=Ms(u,n),u=ws(u,n),h=Ls(h),u=Ls(u),n.isWebGL2&&!0!==n.isRawShaderMaterial&&(b="#version 300 es\n",x=["precision mediump sampler2DArray;","#define attribute in","#define varying out","#define texture2D texture"].join("\n")+"\n"+x,_=["#define varying in",n.glslVersion===pt?"":"layout(location = 0) out highp vec4 pc_fragColor;",n.glslVersion===pt?"":"#define gl_FragColor pc_fragColor","#define gl_FragDepthEXT gl_FragDepth","#define texture2D texture","#define textureCube texture","#define texture2DProj textureProj","#define texture2DLodEXT textureLod","#define texture2DProjLodEXT textureProjLod","#define textureCubeLodEXT textureLod","#define texture2DGradEXT textureGrad","#define texture2DProjGradEXT textureProjGrad","#define textureCubeGradEXT textureGrad"].join("\n")+"\n"+_);const M=b+_+u,w=gs(a,35633,b+x+h),S=gs(a,35632,M);if(a.attachShader(y,w),a.attachShader(y,S),void 0!==n.index0AttributeName?a.bindAttribLocation(y,0,n.index0AttributeName):!0===n.morphTargets&&a.bindAttribLocation(y,0,"position"),a.linkProgram(y),t.debug.checkShaderErrors){const t=a.getProgramInfoLog(y).trim(),e=a.getShaderInfoLog(w).trim(),n=a.getShaderInfoLog(S).trim();let i=!0,r=!0;if(!1===a.getProgramParameter(y,35714)){i=!1;const e=ys(a,w,"vertex"),n=ys(a,S,"fragment");console.error("THREE.WebGLProgram: Shader Error "+a.getError()+" - VALIDATE_STATUS "+a.getProgramParameter(y,35715)+"\n\nProgram Info Log: "+t+"\n"+e+"\n"+n)}else""!==t?console.warn("THREE.WebGLProgram: Program Info Log:",t):""!==e&&""!==n||(r=!1);r&&(this.diagnostics={runnable:i,programLog:t,vertexShader:{log:e,prefix:x},fragmentShader:{log:n,prefix:_}})}let E,A;return a.deleteShader(w),a.deleteShader(S),this.getUniforms=function(){return void 0===E&&(E=new fs(a,y)),E},this.getAttributes=function(){return void 0===A&&(A=function(t,e){const n={},i=t.getProgramParameter(e,35721);for(let r=0;r0,D=s.clearcoat>0;return{isWebGL2:d,shaderID:S,shaderName:s.type,vertexShader:E,fragmentShader:A,defines:s.defines,customVertexShaderID:R,customFragmentShaderID:L,isRawShaderMaterial:!0===s.isRawShaderMaterial,glslVersion:s.glslVersion,precision:v,instancing:!0===_.isInstancedMesh,instancingColor:!0===_.isInstancedMesh&&null!==_.instanceColor,supportsVertexTextures:g,outputEncoding:null!==C?C.texture.encoding:t.outputEncoding,map:!!s.map,matcap:!!s.matcap,envMap:!!w,envMapMode:w&&w.mapping,envMapCubeUV:!!w&&(w.mapping===l||w.mapping===c),lightMap:!!s.lightMap,aoMap:!!s.aoMap,emissiveMap:!!s.emissiveMap,bumpMap:!!s.bumpMap,normalMap:!!s.normalMap,objectSpaceNormalMap:1===s.normalMapType,tangentSpaceNormalMap:0===s.normalMapType,decodeVideoTexture:!!s.map&&!0===s.map.isVideoTexture&&s.map.encoding===ct,clearcoat:D,clearcoatMap:D&&!!s.clearcoatMap,clearcoatRoughnessMap:D&&!!s.clearcoatRoughnessMap,clearcoatNormalMap:D&&!!s.clearcoatNormalMap,displacementMap:!!s.displacementMap,roughnessMap:!!s.roughnessMap,metalnessMap:!!s.metalnessMap,specularMap:!!s.specularMap,specularIntensityMap:!!s.specularIntensityMap,specularColorMap:!!s.specularColorMap,alphaMap:!!s.alphaMap,alphaTest:P,gradientMap:!!s.gradientMap,sheen:s.sheen>0,sheenColorMap:!!s.sheenColorMap,sheenRoughnessMap:!!s.sheenRoughnessMap,transmission:s.transmission>0,transmissionMap:!!s.transmissionMap,thicknessMap:!!s.thicknessMap,combine:s.combine,vertexTangents:!!s.normalMap&&!!_.geometry&&!!_.geometry.attributes.tangent,vertexColors:s.vertexColors,vertexAlphas:!0===s.vertexColors&&!!_.geometry&&!!_.geometry.attributes.color&&4===_.geometry.attributes.color.itemSize,vertexUvs:!!(s.map||s.bumpMap||s.normalMap||s.specularMap||s.alphaMap||s.emissiveMap||s.roughnessMap||s.metalnessMap||s.clearcoatMap||s.clearcoatRoughnessMap||s.clearcoatNormalMap||s.displacementMap||s.transmissionMap||s.thicknessMap||s.specularIntensityMap||s.specularColorMap||s.sheenColorMap||s.sheenRoughnessMap),uvsVertexOnly:!(s.map||s.bumpMap||s.normalMap||s.specularMap||s.alphaMap||s.emissiveMap||s.roughnessMap||s.metalnessMap||s.clearcoatNormalMap||s.transmission>0||s.transmissionMap||s.thicknessMap||s.specularIntensityMap||s.specularColorMap||s.sheen>0||s.sheenColorMap||s.sheenRoughnessMap||!s.displacementMap),fog:!!b,useFog:s.fog,fogExp2:b&&b.isFogExp2,flatShading:!!s.flatShading,sizeAttenuation:s.sizeAttenuation,logarithmicDepthBuffer:p,skinning:!0===_.isSkinnedMesh&&T>0,maxBones:T,useVertexTexture:m,morphTargets:!!_.geometry&&!!_.geometry.morphAttributes.position,morphNormals:!!_.geometry&&!!_.geometry.morphAttributes.normal,morphTargetsCount:_.geometry&&_.geometry.morphAttributes.position?_.geometry.morphAttributes.position.length:0,numDirLights:o.directional.length,numPointLights:o.point.length,numSpotLights:o.spot.length,numRectAreaLights:o.rectArea.length,numHemiLights:o.hemi.length,numDirLightShadows:o.directionalShadowMap.length,numPointLightShadows:o.pointShadowMap.length,numSpotLightShadows:o.spotShadowMap.length,numClippingPlanes:a.numPlanes,numClipIntersection:a.numIntersection,format:s.format,dithering:s.dithering,shadowMapEnabled:t.shadowMap.enabled&&u.length>0,shadowMapType:t.shadowMap.type,toneMapping:s.toneMapped?t.toneMapping:0,physicallyCorrectLights:t.physicallyCorrectLights,premultipliedAlpha:s.premultipliedAlpha,doubleSided:2===s.side,flipSided:1===s.side,depthPacking:void 0!==s.depthPacking&&s.depthPacking,index0AttributeName:s.index0AttributeName,extensionDerivatives:s.extensions&&s.extensions.derivatives,extensionFragDepth:s.extensions&&s.extensions.fragDepth,extensionDrawBuffers:s.extensions&&s.extensions.drawBuffers,extensionShaderTextureLOD:s.extensions&&s.extensions.shaderTextureLOD,rendererExtensionFragDepth:d||i.has("EXT_frag_depth"),rendererExtensionDrawBuffers:d||i.has("WEBGL_draw_buffers"),rendererExtensionShaderTextureLod:d||i.has("EXT_shader_texture_lod"),customProgramCacheKey:s.customProgramCacheKey()}},getProgramCacheKey:function(e){const n=[];if(e.shaderID?n.push(e.shaderID):(n.push(e.customVertexShaderID),n.push(e.customFragmentShaderID)),void 0!==e.defines)for(const t in e.defines)n.push(t),n.push(e.defines[t]);return!1===e.isRawShaderMaterial&&(!function(t,e){t.push(e.precision),t.push(e.outputEncoding),t.push(e.envMapMode),t.push(e.combine),t.push(e.vertexUvs),t.push(e.fogExp2),t.push(e.sizeAttenuation),t.push(e.maxBones),t.push(e.morphTargetsCount),t.push(e.numDirLights),t.push(e.numPointLights),t.push(e.numSpotLights),t.push(e.numHemiLights),t.push(e.numRectAreaLights),t.push(e.numDirLightShadows),t.push(e.numPointLightShadows),t.push(e.numSpotLightShadows),t.push(e.shadowMapType),t.push(e.toneMapping),t.push(e.numClippingPlanes),t.push(e.numClipIntersection),t.push(e.format)}(n,e),function(t,e){o.disableAll(),e.isWebGL2&&o.enable(0);e.supportsVertexTextures&&o.enable(1);e.instancing&&o.enable(2);e.instancingColor&&o.enable(3);e.map&&o.enable(4);e.matcap&&o.enable(5);e.envMap&&o.enable(6);e.envMapCubeUV&&o.enable(7);e.lightMap&&o.enable(8);e.aoMap&&o.enable(9);e.emissiveMap&&o.enable(10);e.bumpMap&&o.enable(11);e.normalMap&&o.enable(12);e.objectSpaceNormalMap&&o.enable(13);e.tangentSpaceNormalMap&&o.enable(14);e.clearcoat&&o.enable(15);e.clearcoatMap&&o.enable(16);e.clearcoatRoughnessMap&&o.enable(17);e.clearcoatNormalMap&&o.enable(18);e.displacementMap&&o.enable(19);e.specularMap&&o.enable(20);e.roughnessMap&&o.enable(21);e.metalnessMap&&o.enable(22);e.gradientMap&&o.enable(23);e.alphaMap&&o.enable(24);e.alphaTest&&o.enable(25);e.vertexColors&&o.enable(26);e.vertexAlphas&&o.enable(27);e.vertexUvs&&o.enable(28);e.vertexTangents&&o.enable(29);e.uvsVertexOnly&&o.enable(30);e.fog&&o.enable(31);t.push(o.mask),o.disableAll(),e.useFog&&o.enable(0);e.flatShading&&o.enable(1);e.logarithmicDepthBuffer&&o.enable(2);e.skinning&&o.enable(3);e.useVertexTexture&&o.enable(4);e.morphTargets&&o.enable(5);e.morphNormals&&o.enable(6);e.premultipliedAlpha&&o.enable(7);e.shadowMapEnabled&&o.enable(8);e.physicallyCorrectLights&&o.enable(9);e.doubleSided&&o.enable(10);e.flipSided&&o.enable(11);e.depthPacking&&o.enable(12);e.dithering&&o.enable(13);e.specularIntensityMap&&o.enable(14);e.specularColorMap&&o.enable(15);e.transmission&&o.enable(16);e.transmissionMap&&o.enable(17);e.thicknessMap&&o.enable(18);e.sheen&&o.enable(19);e.sheenColorMap&&o.enable(20);e.sheenRoughnessMap&&o.enable(21);e.decodeVideoTexture&&o.enable(22);t.push(o.mask)}(n,e),n.push(t.outputEncoding)),n.push(e.customProgramCacheKey),n.join()},getUniforms:function(t){const e=y[t.type];let n;if(e){const t=Ti[e];n=si.clone(t.uniforms)}else n=t.uniforms;return n},acquireProgram:function(e,n){let i;for(let t=0,e=u.length;t0?i.push(h):!0===a.transparent?r.push(h):n.push(h)},unshift:function(t,e,a,o,l,c){const h=s(t,e,a,o,l,c);a.transmission>0?i.unshift(h):!0===a.transparent?r.unshift(h):n.unshift(h)},finish:function(){for(let n=e,i=t.length;n1&&n.sort(t||Us),i.length>1&&i.sort(e||Hs),r.length>1&&r.sort(e||Hs)}}}function ks(){let t=new WeakMap;return{get:function(e,n){let i;return!1===t.has(e)?(i=new Gs,t.set(e,[i])):n>=t.get(e).length?(i=new Gs,t.get(e).push(i)):i=t.get(e)[n],i},dispose:function(){t=new WeakMap}}}function Vs(){const t={};return{get:function(e){if(void 0!==t[e.id])return t[e.id];let n;switch(e.type){case"DirectionalLight":n={direction:new Qt,color:new Gt};break;case"SpotLight":n={position:new Qt,direction:new Qt,color:new Gt,distance:0,coneCos:0,penumbraCos:0,decay:0};break;case"PointLight":n={position:new Qt,color:new Gt,distance:0,decay:0};break;case"HemisphereLight":n={direction:new Qt,skyColor:new Gt,groundColor:new Gt};break;case"RectAreaLight":n={color:new Gt,position:new Qt,halfWidth:new Qt,halfHeight:new Qt}}return t[e.id]=n,n}}}let Ws=0;function js(t,e){return(e.castShadow?1:0)-(t.castShadow?1:0)}function qs(t,e){const n=new Vs,i=function(){const t={};return{get:function(e){if(void 0!==t[e.id])return t[e.id];let n;switch(e.type){case"DirectionalLight":case"SpotLight":n={shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new Lt};break;case"PointLight":n={shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new Lt,shadowCameraNear:1,shadowCameraFar:1e3}}return t[e.id]=n,n}}}(),r={version:0,hash:{directionalLength:-1,pointLength:-1,spotLength:-1,rectAreaLength:-1,hemiLength:-1,numDirectionalShadows:-1,numPointShadows:-1,numSpotShadows:-1},ambient:[0,0,0],probe:[],directional:[],directionalShadow:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotShadow:[],spotShadowMap:[],spotShadowMatrix:[],rectArea:[],rectAreaLTC1:null,rectAreaLTC2:null,point:[],pointShadow:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[]};for(let t=0;t<9;t++)r.probe.push(new Qt);const s=new Qt,a=new Le,o=new Le;return{setup:function(s,a){let o=0,l=0,c=0;for(let t=0;t<9;t++)r.probe[t].set(0,0,0);let h=0,u=0,d=0,p=0,m=0,f=0,g=0,v=0;s.sort(js);const y=!0!==a?Math.PI:1;for(let t=0,e=s.length;t0&&(e.isWebGL2||!0===t.has("OES_texture_float_linear")?(r.rectAreaLTC1=Si.LTC_FLOAT_1,r.rectAreaLTC2=Si.LTC_FLOAT_2):!0===t.has("OES_texture_half_float_linear")?(r.rectAreaLTC1=Si.LTC_HALF_1,r.rectAreaLTC2=Si.LTC_HALF_2):console.error("THREE.WebGLRenderer: Unable to use RectAreaLight. Missing WebGL extensions.")),r.ambient[0]=o,r.ambient[1]=l,r.ambient[2]=c;const x=r.hash;x.directionalLength===h&&x.pointLength===u&&x.spotLength===d&&x.rectAreaLength===p&&x.hemiLength===m&&x.numDirectionalShadows===f&&x.numPointShadows===g&&x.numSpotShadows===v||(r.directional.length=h,r.spot.length=d,r.rectArea.length=p,r.point.length=u,r.hemi.length=m,r.directionalShadow.length=f,r.directionalShadowMap.length=f,r.pointShadow.length=g,r.pointShadowMap.length=g,r.spotShadow.length=v,r.spotShadowMap.length=v,r.directionalShadowMatrix.length=f,r.pointShadowMatrix.length=g,r.spotShadowMatrix.length=v,x.directionalLength=h,x.pointLength=u,x.spotLength=d,x.rectAreaLength=p,x.hemiLength=m,x.numDirectionalShadows=f,x.numPointShadows=g,x.numSpotShadows=v,r.version=Ws++)},setupView:function(t,e){let n=0,i=0,l=0,c=0,h=0;const u=e.matrixWorldInverse;for(let e=0,d=t.length;e=n.get(i).length?(s=new Xs(t,e),n.get(i).push(s)):s=n.get(i)[r],s},dispose:function(){n=new WeakMap}}}class Ys extends mn{constructor(t){super(),this.type="MeshDepthMaterial",this.depthPacking=3200,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.fog=!1,this.setValues(t)}copy(t){return super.copy(t),this.depthPacking=t.depthPacking,this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this}}Ys.prototype.isMeshDepthMaterial=!0;class Zs extends mn{constructor(t){super(),this.type="MeshDistanceMaterial",this.referencePosition=new Qt,this.nearDistance=1,this.farDistance=1e3,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.fog=!1,this.setValues(t)}copy(t){return super.copy(t),this.referencePosition.copy(t.referencePosition),this.nearDistance=t.nearDistance,this.farDistance=t.farDistance,this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this}}Zs.prototype.isMeshDistanceMaterial=!0;function Ks(t,e,n){let i=new xi;const r=new Lt,s=new Lt,a=new Xt,o=new Ys({depthPacking:3201}),l=new Zs,c={},h=n.maxTextureSize,u={0:1,1:0,2:2},d=new ai({defines:{VSM_SAMPLES:8},uniforms:{shadow_pass:{value:null},resolution:{value:new Lt},radius:{value:4}},vertexShader:"void main() {\n\tgl_Position = vec4( position, 1.0 );\n}",fragmentShader:"uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include \nvoid main() {\n\tconst float samples = float( VSM_SAMPLES );\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 );\n\tfloat uvStart = samples <= 1.0 ? 0.0 : - 1.0;\n\tfor ( float i = 0.0; i < samples; i ++ ) {\n\t\tfloat uvOffset = uvStart + i * uvStride;\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ) );\n\t\t\tmean += distribution.x;\n\t\t\tsquared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\t\t#else\n\t\t\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean / samples;\n\tsquared_mean = squared_mean / samples;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}"}),m=d.clone();m.defines.HORIZONTAL_PASS=1;const f=new zn;f.setAttribute("position",new yn(new Float32Array([-1,-1,.5,3,-1,.5,-1,3,.5]),3));const v=new ti(f,d),y=this;function x(n,i){const r=e.update(v);d.defines.VSM_SAMPLES!==n.blurSamples&&(d.defines.VSM_SAMPLES=n.blurSamples,m.defines.VSM_SAMPLES=n.blurSamples,d.needsUpdate=!0,m.needsUpdate=!0),d.uniforms.shadow_pass.value=n.map.texture,d.uniforms.resolution.value=n.mapSize,d.uniforms.radius.value=n.radius,t.setRenderTarget(n.mapPass),t.clear(),t.renderBufferDirect(i,null,r,d,v,null),m.uniforms.shadow_pass.value=n.mapPass.texture,m.uniforms.resolution.value=n.mapSize,m.uniforms.radius.value=n.radius,t.setRenderTarget(n.map),t.clear(),t.renderBufferDirect(i,null,r,m,v,null)}function _(e,n,i,r,s,a,h){let d=null;const p=!0===r.isPointLight?e.customDistanceMaterial:e.customDepthMaterial;if(d=void 0!==p?p:!0===r.isPointLight?l:o,t.localClippingEnabled&&!0===i.clipShadows&&0!==i.clippingPlanes.length||i.displacementMap&&0!==i.displacementScale||i.alphaMap&&i.alphaTest>0){const t=d.uuid,e=i.uuid;let n=c[t];void 0===n&&(n={},c[t]=n);let r=n[e];void 0===r&&(r=d.clone(),n[e]=r),d=r}return d.visible=i.visible,d.wireframe=i.wireframe,d.side=3===h?null!==i.shadowSide?i.shadowSide:i.side:null!==i.shadowSide?i.shadowSide:u[i.side],d.alphaMap=i.alphaMap,d.alphaTest=i.alphaTest,d.clipShadows=i.clipShadows,d.clippingPlanes=i.clippingPlanes,d.clipIntersection=i.clipIntersection,d.displacementMap=i.displacementMap,d.displacementScale=i.displacementScale,d.displacementBias=i.displacementBias,d.wireframeLinewidth=i.wireframeLinewidth,d.linewidth=i.linewidth,!0===r.isPointLight&&!0===d.isMeshDistanceMaterial&&(d.referencePosition.setFromMatrixPosition(r.matrixWorld),d.nearDistance=s,d.farDistance=a),d}function b(n,r,s,a,o){if(!1===n.visible)return;if(n.layers.test(r.layers)&&(n.isMesh||n.isLine||n.isPoints)&&(n.castShadow||n.receiveShadow&&3===o)&&(!n.frustumCulled||i.intersectsObject(n))){n.modelViewMatrix.multiplyMatrices(s.matrixWorldInverse,n.matrixWorld);const i=e.update(n),r=n.material;if(Array.isArray(r)){const e=i.groups;for(let l=0,c=e.length;lh||r.y>h)&&(r.x>h&&(s.x=Math.floor(h/m.x),r.x=s.x*m.x,u.mapSize.x=s.x),r.y>h&&(s.y=Math.floor(h/m.y),r.y=s.y*m.y,u.mapSize.y=s.y)),null===u.map&&!u.isPointLightShadow&&3===this.type){const t={minFilter:g,magFilter:g,format:E};u.map=new Jt(r.x,r.y,t),u.map.texture.name=c.name+".shadowMap",u.mapPass=new Jt(r.x,r.y,t),u.camera.updateProjectionMatrix()}if(null===u.map){const t={minFilter:p,magFilter:p,format:E};u.map=new Jt(r.x,r.y,t),u.map.texture.name=c.name+".shadowMap",u.camera.updateProjectionMatrix()}t.setRenderTarget(u.map),t.clear();const f=u.getViewportCount();for(let t=0;t=1):-1!==R.indexOf("OpenGL ES")&&(A=parseFloat(/^OpenGL ES (\d)/.exec(R)[1]),E=A>=2);let L=null,C={};const P=t.getParameter(3088),D=t.getParameter(2978),I=(new Xt).fromArray(P),N=(new Xt).fromArray(D);function B(e,n,i){const r=new Uint8Array(4),s=t.createTexture();t.bindTexture(e,s),t.texParameteri(e,10241,9728),t.texParameteri(e,10240,9728);for(let e=0;ei||t.height>i)&&(r=i/Math.max(t.width,t.height)),r<1||!0===e){if("undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&t instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&t instanceof ImageBitmap){const i=e?At:Math.floor,s=i(r*t.width),a=i(r*t.height);void 0===I&&(I=B(s,a));const o=n?B(s,a):I;o.width=s,o.height=a;return o.getContext("2d").drawImage(t,0,0,s,a),console.warn("THREE.WebGLRenderer: Texture has been resized from ("+t.width+"x"+t.height+") to ("+s+"x"+a+")."),o}return"data"in t&&console.warn("THREE.WebGLRenderer: Image in DataTexture is too big ("+t.width+"x"+t.height+")."),t}return t}function O(t){return Tt(t.width)&&Tt(t.height)}function F(t,e){return t.generateMipmaps&&e&&t.minFilter!==p&&t.minFilter!==g}function U(e){t.generateMipmap(e)}function H(n,i,r,s,a=!1){if(!1===o)return i;if(null!==n){if(void 0!==t[n])return t[n];console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '"+n+"'")}let l=i;return 6403===i&&(5126===r&&(l=33326),5131===r&&(l=33325),5121===r&&(l=33321)),6407===i&&(5126===r&&(l=34837),5131===r&&(l=34843),5121===r&&(l=32849)),6408===i&&(5126===r&&(l=34836),5131===r&&(l=34842),5121===r&&(l=s===ct&&!1===a?35907:32856)),33325!==l&&33326!==l&&34842!==l&&34836!==l||e.get("EXT_color_buffer_float"),l}function G(t,e,n){return!0===F(t,n)||t.isFramebufferTexture&&t.minFilter!==p&&t.minFilter!==g?Math.log2(Math.max(e.width,e.height))+1:void 0!==t.mipmaps&&t.mipmaps.length>0?t.mipmaps.length:t.isCompressedTexture&&Array.isArray(t.image)?e.mipmaps.length:1}function k(t){return t===p||t===m||t===f?9728:9729}function V(e){const n=e.target;n.removeEventListener("dispose",V),function(e){const n=i.get(e);if(void 0===n.__webglInit)return;t.deleteTexture(n.__webglTexture),i.remove(e)}(n),n.isVideoTexture&&D.delete(n),a.memory.textures--}function W(e){const n=e.target;n.removeEventListener("dispose",W),function(e){const n=e.texture,r=i.get(e),s=i.get(n);if(!e)return;void 0!==s.__webglTexture&&(t.deleteTexture(s.__webglTexture),a.memory.textures--);e.depthTexture&&e.depthTexture.dispose();if(e.isWebGLCubeRenderTarget)for(let e=0;e<6;e++)t.deleteFramebuffer(r.__webglFramebuffer[e]),r.__webglDepthbuffer&&t.deleteRenderbuffer(r.__webglDepthbuffer[e]);else t.deleteFramebuffer(r.__webglFramebuffer),r.__webglDepthbuffer&&t.deleteRenderbuffer(r.__webglDepthbuffer),r.__webglMultisampledFramebuffer&&t.deleteFramebuffer(r.__webglMultisampledFramebuffer),r.__webglColorRenderbuffer&&t.deleteRenderbuffer(r.__webglColorRenderbuffer),r.__webglDepthRenderbuffer&&t.deleteRenderbuffer(r.__webglDepthRenderbuffer);if(e.isWebGLMultipleRenderTargets)for(let e=0,r=n.length;e0&&r.__version!==t.version){const n=t.image;if(void 0===n)console.warn("THREE.WebGLRenderer: Texture marked for update but image is undefined");else{if(!1!==n.complete)return void Q(r,t,e);console.warn("THREE.WebGLRenderer: Texture marked for update but image is incomplete")}}n.activeTexture(33984+e),n.bindTexture(3553,r.__webglTexture)}function X(e,r){const a=i.get(e);e.version>0&&a.__version!==e.version?function(e,i,r){if(6!==i.image.length)return;K(e,i),n.activeTexture(33984+r),n.bindTexture(34067,e.__webglTexture),t.pixelStorei(37440,i.flipY),t.pixelStorei(37441,i.premultiplyAlpha),t.pixelStorei(3317,i.unpackAlignment),t.pixelStorei(37443,0);const a=i&&(i.isCompressedTexture||i.image[0].isCompressedTexture),l=i.image[0]&&i.image[0].isDataTexture,h=[];for(let t=0;t<6;t++)h[t]=a||l?l?i.image[t].image:i.image[t]:z(i.image[t],!1,!0,c),h[t]=it(i,h[t]);const u=h[0],d=O(u)||o,p=s.convert(i.format,i.encoding),m=s.convert(i.type),f=H(i.internalFormat,p,m,i.encoding),g=o&&!0!==i.isVideoTexture,v=void 0===e.__version;let y,x=G(i,u,d);if(Z(34067,i,d),a){g&&v&&n.texStorage2D(34067,x,f,u.width,u.height);for(let t=0;t<6;t++){y=h[t].mipmaps;for(let e=0;e0&&x++,n.texStorage2D(34067,x,f,h[0].width,h[0].height));for(let t=0;t<6;t++)if(l){g?n.texSubImage2D(34069+t,0,0,0,h[t].width,h[t].height,p,m,h[t].data):n.texImage2D(34069+t,0,f,h[t].width,h[t].height,0,p,m,h[t].data);for(let e=0;e1||i.get(s).__currentAnisotropy)&&(t.texParameterf(n,a.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(s.anisotropy,r.getMaxAnisotropy())),i.get(s).__currentAnisotropy=s.anisotropy)}}function K(e,n){void 0===e.__webglInit&&(e.__webglInit=!0,n.addEventListener("dispose",V),e.__webglTexture=t.createTexture(),a.memory.textures++)}function Q(e,i,r){let a=3553;i.isDataTexture2DArray&&(a=35866),i.isDataTexture3D&&(a=32879),K(e,i),n.activeTexture(33984+r),n.bindTexture(a,e.__webglTexture),t.pixelStorei(37440,i.flipY),t.pixelStorei(37441,i.premultiplyAlpha),t.pixelStorei(3317,i.unpackAlignment),t.pixelStorei(37443,0);const l=function(t){return!o&&(t.wrapS!==u||t.wrapT!==u||t.minFilter!==p&&t.minFilter!==g)}(i)&&!1===O(i.image);let c=z(i.image,l,!1,L);c=it(i,c);const h=O(c)||o,d=s.convert(i.format,i.encoding);let m,f=s.convert(i.type),v=H(i.internalFormat,d,f,i.encoding,i.isVideoTexture);Z(a,i,h);const y=i.mipmaps,x=o&&!0!==i.isVideoTexture,w=void 0===e.__version,C=G(i,c,h);if(i.isDepthTexture)v=6402,o?v=i.type===M?36012:i.type===b?33190:i.type===S?35056:33189:i.type===M&&console.error("WebGLRenderer: Floating point depth texture requires WebGL2."),i.format===A&&6402===v&&i.type!==_&&i.type!==b&&(console.warn("THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture."),i.type=_,f=s.convert(i.type)),i.format===R&&6402===v&&(v=34041,i.type!==S&&(console.warn("THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture."),i.type=S,f=s.convert(i.type))),x&&w?n.texStorage2D(3553,1,v,c.width,c.height):n.texImage2D(3553,0,v,c.width,c.height,0,d,f,null);else if(i.isDataTexture)if(y.length>0&&h){x&&w&&n.texStorage2D(3553,C,v,y[0].width,y[0].height);for(let t=0,e=y.length;t0&&h){x&&w&&n.texStorage2D(3553,C,v,y[0].width,y[0].height);for(let t=0,e=y.length;t=l&&console.warn("THREE.WebGLTextures: Trying to use "+t+" texture units while this GPU supports only "+l),j+=1,t},this.resetTextureUnits=function(){j=0},this.setTexture2D=q,this.setTexture2DArray=function(t,e){const r=i.get(t);t.version>0&&r.__version!==t.version?Q(r,t,e):(n.activeTexture(33984+e),n.bindTexture(35866,r.__webglTexture))},this.setTexture3D=function(t,e){const r=i.get(t);t.version>0&&r.__version!==t.version?Q(r,t,e):(n.activeTexture(33984+e),n.bindTexture(32879,r.__webglTexture))},this.setTextureCube=X,this.rebindTextures=function(t,e,n){const r=i.get(t);void 0!==e&&$(r.__webglFramebuffer,t,t.texture,36064,3553),void 0!==n&&et(t)},this.setupRenderTarget=function(e){const l=e.texture,c=i.get(e),h=i.get(l);e.addEventListener("dispose",W),!0!==e.isWebGLMultipleRenderTargets&&(void 0===h.__webglTexture&&(h.__webglTexture=t.createTexture()),h.__version=l.version,a.memory.textures++);const u=!0===e.isWebGLCubeRenderTarget,d=!0===e.isWebGLMultipleRenderTargets,p=l.isDataTexture3D||l.isDataTexture2DArray,m=O(e)||o;if(!o||l.format!==T||l.type!==M&&l.type!==w||(l.format=E,console.warn("THREE.WebGLRenderer: Rendering to textures with RGB format is not supported. Using RGBA format instead.")),u){c.__webglFramebuffer=[];for(let e=0;e<6;e++)c.__webglFramebuffer[e]=t.createFramebuffer()}else if(c.__webglFramebuffer=t.createFramebuffer(),d)if(r.drawBuffers){const n=e.texture;for(let e=0,r=n.length;eo+c?(l.inputState.pinching=!1,this.dispatchEvent({type:"pinchend",handedness:t.handedness,target:this})):!l.inputState.pinching&&a<=o-c&&(l.inputState.pinching=!0,this.dispatchEvent({type:"pinchstart",handedness:t.handedness,target:this}))}else null!==o&&t.gripSpace&&(r=e.getPose(t.gripSpace,n),null!==r&&(o.matrix.fromArray(r.transform.matrix),o.matrix.decompose(o.position,o.rotation,o.scale),r.linearVelocity?(o.hasLinearVelocity=!0,o.linearVelocity.copy(r.linearVelocity)):o.hasLinearVelocity=!1,r.angularVelocity?(o.hasAngularVelocity=!0,o.angularVelocity.copy(r.angularVelocity)):o.hasAngularVelocity=!1));return null!==a&&(a.visible=null!==i),null!==o&&(o.visible=null!==r),null!==l&&(l.visible=null!==s),this}}class sa extends jt{constructor(t,e,n,i,r,s,a,o,l,c){if((c=void 0!==c?c:A)!==A&&c!==R)throw new Error("DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat");void 0===n&&c===A&&(n=_),void 0===n&&c===R&&(n=S),super(null,i,r,s,a,o,c,n,l),this.image={width:t,height:e},this.magFilter=void 0!==a?a:p,this.minFilter=void 0!==o?o:p,this.flipY=!1,this.generateMipmaps=!1}}sa.prototype.isDepthTexture=!0;class aa extends gt{constructor(t,e){super();const n=this;let i=null,r=1,s=null,a="local-floor";const o=t.extensions.has("WEBGL_multisampled_render_to_texture");let l=null,c=null,h=null,u=null,d=!1,p=null;const m=e.getContextAttributes();let f=null,g=null;const v=[],y=new Map,b=new li;b.layers.enable(1),b.viewport=new Xt;const M=new li;M.layers.enable(2),M.viewport=new Xt;const w=[b,M],L=new ea;L.layers.enable(1),L.layers.enable(2);let C=null,P=null;function D(t){const e=y.get(t.inputSource);e&&e.dispatchEvent({type:t.type,data:t.inputSource})}function I(){y.forEach((function(t,e){t.disconnect(e)})),y.clear(),C=null,P=null,t.setRenderTarget(f),u=null,h=null,c=null,i=null,g=null,U.stop(),n.isPresenting=!1,n.dispatchEvent({type:"sessionend"})}function N(t){const e=i.inputSources;for(let t=0;t0&&(e.alphaTest.value=n.alphaTest);const i=t.get(n).envMap;let r,s;i&&(e.envMap.value=i,e.flipEnvMap.value=i.isCubeTexture&&!1===i.isRenderTargetTexture?-1:1,e.reflectivity.value=n.reflectivity,e.ior.value=n.ior,e.refractionRatio.value=n.refractionRatio),n.lightMap&&(e.lightMap.value=n.lightMap,e.lightMapIntensity.value=n.lightMapIntensity),n.aoMap&&(e.aoMap.value=n.aoMap,e.aoMapIntensity.value=n.aoMapIntensity),n.map?r=n.map:n.specularMap?r=n.specularMap:n.displacementMap?r=n.displacementMap:n.normalMap?r=n.normalMap:n.bumpMap?r=n.bumpMap:n.roughnessMap?r=n.roughnessMap:n.metalnessMap?r=n.metalnessMap:n.alphaMap?r=n.alphaMap:n.emissiveMap?r=n.emissiveMap:n.clearcoatMap?r=n.clearcoatMap:n.clearcoatNormalMap?r=n.clearcoatNormalMap:n.clearcoatRoughnessMap?r=n.clearcoatRoughnessMap:n.specularIntensityMap?r=n.specularIntensityMap:n.specularColorMap?r=n.specularColorMap:n.transmissionMap?r=n.transmissionMap:n.thicknessMap?r=n.thicknessMap:n.sheenColorMap?r=n.sheenColorMap:n.sheenRoughnessMap&&(r=n.sheenRoughnessMap),void 0!==r&&(r.isWebGLRenderTarget&&(r=r.texture),!0===r.matrixAutoUpdate&&r.updateMatrix(),e.uvTransform.value.copy(r.matrix)),n.aoMap?s=n.aoMap:n.lightMap&&(s=n.lightMap),void 0!==s&&(s.isWebGLRenderTarget&&(s=s.texture),!0===s.matrixAutoUpdate&&s.updateMatrix(),e.uv2Transform.value.copy(s.matrix))}function n(e,n){e.roughness.value=n.roughness,e.metalness.value=n.metalness,n.roughnessMap&&(e.roughnessMap.value=n.roughnessMap),n.metalnessMap&&(e.metalnessMap.value=n.metalnessMap),n.emissiveMap&&(e.emissiveMap.value=n.emissiveMap),n.bumpMap&&(e.bumpMap.value=n.bumpMap,e.bumpScale.value=n.bumpScale,1===n.side&&(e.bumpScale.value*=-1)),n.normalMap&&(e.normalMap.value=n.normalMap,e.normalScale.value.copy(n.normalScale),1===n.side&&e.normalScale.value.negate()),n.displacementMap&&(e.displacementMap.value=n.displacementMap,e.displacementScale.value=n.displacementScale,e.displacementBias.value=n.displacementBias);t.get(n).envMap&&(e.envMapIntensity.value=n.envMapIntensity)}return{refreshFogUniforms:function(t,e){t.fogColor.value.copy(e.color),e.isFog?(t.fogNear.value=e.near,t.fogFar.value=e.far):e.isFogExp2&&(t.fogDensity.value=e.density)},refreshMaterialUniforms:function(t,i,r,s,a){i.isMeshBasicMaterial?e(t,i):i.isMeshLambertMaterial?(e(t,i),function(t,e){e.emissiveMap&&(t.emissiveMap.value=e.emissiveMap)}(t,i)):i.isMeshToonMaterial?(e(t,i),function(t,e){e.gradientMap&&(t.gradientMap.value=e.gradientMap);e.emissiveMap&&(t.emissiveMap.value=e.emissiveMap);e.bumpMap&&(t.bumpMap.value=e.bumpMap,t.bumpScale.value=e.bumpScale,1===e.side&&(t.bumpScale.value*=-1));e.normalMap&&(t.normalMap.value=e.normalMap,t.normalScale.value.copy(e.normalScale),1===e.side&&t.normalScale.value.negate());e.displacementMap&&(t.displacementMap.value=e.displacementMap,t.displacementScale.value=e.displacementScale,t.displacementBias.value=e.displacementBias)}(t,i)):i.isMeshPhongMaterial?(e(t,i),function(t,e){t.specular.value.copy(e.specular),t.shininess.value=Math.max(e.shininess,1e-4),e.emissiveMap&&(t.emissiveMap.value=e.emissiveMap);e.bumpMap&&(t.bumpMap.value=e.bumpMap,t.bumpScale.value=e.bumpScale,1===e.side&&(t.bumpScale.value*=-1));e.normalMap&&(t.normalMap.value=e.normalMap,t.normalScale.value.copy(e.normalScale),1===e.side&&t.normalScale.value.negate());e.displacementMap&&(t.displacementMap.value=e.displacementMap,t.displacementScale.value=e.displacementScale,t.displacementBias.value=e.displacementBias)}(t,i)):i.isMeshStandardMaterial?(e(t,i),i.isMeshPhysicalMaterial?function(t,e,i){n(t,e),t.ior.value=e.ior,e.sheen>0&&(t.sheenColor.value.copy(e.sheenColor).multiplyScalar(e.sheen),t.sheenRoughness.value=e.sheenRoughness,e.sheenColorMap&&(t.sheenColorMap.value=e.sheenColorMap),e.sheenRoughnessMap&&(t.sheenRoughnessMap.value=e.sheenRoughnessMap));e.clearcoat>0&&(t.clearcoat.value=e.clearcoat,t.clearcoatRoughness.value=e.clearcoatRoughness,e.clearcoatMap&&(t.clearcoatMap.value=e.clearcoatMap),e.clearcoatRoughnessMap&&(t.clearcoatRoughnessMap.value=e.clearcoatRoughnessMap),e.clearcoatNormalMap&&(t.clearcoatNormalScale.value.copy(e.clearcoatNormalScale),t.clearcoatNormalMap.value=e.clearcoatNormalMap,1===e.side&&t.clearcoatNormalScale.value.negate()));e.transmission>0&&(t.transmission.value=e.transmission,t.transmissionSamplerMap.value=i.texture,t.transmissionSamplerSize.value.set(i.width,i.height),e.transmissionMap&&(t.transmissionMap.value=e.transmissionMap),t.thickness.value=e.thickness,e.thicknessMap&&(t.thicknessMap.value=e.thicknessMap),t.attenuationDistance.value=e.attenuationDistance,t.attenuationColor.value.copy(e.attenuationColor));t.specularIntensity.value=e.specularIntensity,t.specularColor.value.copy(e.specularColor),e.specularIntensityMap&&(t.specularIntensityMap.value=e.specularIntensityMap);e.specularColorMap&&(t.specularColorMap.value=e.specularColorMap)}(t,i,a):n(t,i)):i.isMeshMatcapMaterial?(e(t,i),function(t,e){e.matcap&&(t.matcap.value=e.matcap);e.bumpMap&&(t.bumpMap.value=e.bumpMap,t.bumpScale.value=e.bumpScale,1===e.side&&(t.bumpScale.value*=-1));e.normalMap&&(t.normalMap.value=e.normalMap,t.normalScale.value.copy(e.normalScale),1===e.side&&t.normalScale.value.negate());e.displacementMap&&(t.displacementMap.value=e.displacementMap,t.displacementScale.value=e.displacementScale,t.displacementBias.value=e.displacementBias)}(t,i)):i.isMeshDepthMaterial?(e(t,i),function(t,e){e.displacementMap&&(t.displacementMap.value=e.displacementMap,t.displacementScale.value=e.displacementScale,t.displacementBias.value=e.displacementBias)}(t,i)):i.isMeshDistanceMaterial?(e(t,i),function(t,e){e.displacementMap&&(t.displacementMap.value=e.displacementMap,t.displacementScale.value=e.displacementScale,t.displacementBias.value=e.displacementBias);t.referencePosition.value.copy(e.referencePosition),t.nearDistance.value=e.nearDistance,t.farDistance.value=e.farDistance}(t,i)):i.isMeshNormalMaterial?(e(t,i),function(t,e){e.bumpMap&&(t.bumpMap.value=e.bumpMap,t.bumpScale.value=e.bumpScale,1===e.side&&(t.bumpScale.value*=-1));e.normalMap&&(t.normalMap.value=e.normalMap,t.normalScale.value.copy(e.normalScale),1===e.side&&t.normalScale.value.negate());e.displacementMap&&(t.displacementMap.value=e.displacementMap,t.displacementScale.value=e.displacementScale,t.displacementBias.value=e.displacementBias)}(t,i)):i.isLineBasicMaterial?(function(t,e){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity}(t,i),i.isLineDashedMaterial&&function(t,e){t.dashSize.value=e.dashSize,t.totalSize.value=e.dashSize+e.gapSize,t.scale.value=e.scale}(t,i)):i.isPointsMaterial?function(t,e,n,i){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,t.size.value=e.size*n,t.scale.value=.5*i,e.map&&(t.map.value=e.map);e.alphaMap&&(t.alphaMap.value=e.alphaMap);e.alphaTest>0&&(t.alphaTest.value=e.alphaTest);let r;e.map?r=e.map:e.alphaMap&&(r=e.alphaMap);void 0!==r&&(!0===r.matrixAutoUpdate&&r.updateMatrix(),t.uvTransform.value.copy(r.matrix))}(t,i,r,s):i.isSpriteMaterial?function(t,e){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,t.rotation.value=e.rotation,e.map&&(t.map.value=e.map);e.alphaMap&&(t.alphaMap.value=e.alphaMap);e.alphaTest>0&&(t.alphaTest.value=e.alphaTest);let n;e.map?n=e.map:e.alphaMap&&(n=e.alphaMap);void 0!==n&&(!0===n.matrixAutoUpdate&&n.updateMatrix(),t.uvTransform.value.copy(n.matrix))}(t,i):i.isShadowMaterial?(t.color.value.copy(i.color),t.opacity.value=i.opacity):i.isShaderMaterial&&(i.uniformsNeedUpdate=!1)}}}function la(t={}){const e=void 0!==t.canvas?t.canvas:function(){const t=Nt("canvas");return t.style.display="block",t}(),n=void 0!==t.context?t.context:null,i=void 0!==t.alpha&&t.alpha,r=void 0===t.depth||t.depth,s=void 0===t.stencil||t.stencil,a=void 0!==t.antialias&&t.antialias,o=void 0===t.premultipliedAlpha||t.premultipliedAlpha,l=void 0!==t.preserveDrawingBuffer&&t.preserveDrawingBuffer,c=void 0!==t.powerPreference?t.powerPreference:"default",h=void 0!==t.failIfMajorPerformanceCaveat&&t.failIfMajorPerformanceCaveat;let d=null,m=null;const f=[],g=[];this.domElement=e,this.debug={checkShaderErrors:!0},this.autoClear=!0,this.autoClearColor=!0,this.autoClearDepth=!0,this.autoClearStencil=!0,this.sortObjects=!0,this.clippingPlanes=[],this.localClippingEnabled=!1,this.outputEncoding=lt,this.physicallyCorrectLights=!1,this.toneMapping=0,this.toneMappingExposure=1;const v=this;let _=!1,b=0,S=0,T=null,A=-1,R=null;const L=new Xt,C=new Xt;let P=null,D=e.width,I=e.height,N=1,B=null,z=null;const O=new Xt(0,0,D,I),F=new Xt(0,0,D,I);let U=!1;const H=[],G=new xi;let k=!1,V=!1,W=null;const j=new Le,q=new Qt,X={background:null,fog:null,environment:null,overrideMaterial:null,isScene:!0};function J(){return null===T?N:1}let Y,Z,K,Q,$,tt,et,nt,it,rt,st,at,ot,ct,ht,ut,dt,pt,mt,ft,gt,vt,yt,xt=n;function _t(t,n){for(let i=0;i0&&function(t,e,n){if(null===W){const t=!0===a&&!0===Z.isWebGL2;W=new(t?Zt:Jt)(1024,1024,{generateMipmaps:!0,type:null!==vt.convert(w)?w:x,minFilter:y,magFilter:p,wrapS:u,wrapT:u,useRenderToTexture:Y.has("WEBGL_multisampled_render_to_texture")})}const i=v.getRenderTarget();v.setRenderTarget(W),v.clear();const r=v.toneMapping;v.toneMapping=0,Dt(t,e,n),v.toneMapping=r,tt.updateMultisampleRenderTarget(W),tt.updateRenderTargetMipmap(W),v.setRenderTarget(i)}(r,e,n),i&&K.viewport(L.copy(i)),r.length>0&&Dt(r,e,n),s.length>0&&Dt(s,e,n),o.length>0&&Dt(o,e,n)}function Dt(t,e,n){const i=!0===e.isScene?e.overrideMaterial:null;for(let r=0,s=t.length;r0?g[g.length-1]:null,f.pop(),d=f.length>0?f[f.length-1]:null},this.getActiveCubeFace=function(){return b},this.getActiveMipmapLevel=function(){return S},this.getRenderTarget=function(){return T},this.setRenderTargetTextures=function(t,e,n){$.get(t.texture).__webglTexture=e,$.get(t.depthTexture).__webglTexture=n;const i=$.get(t);i.__hasExternalTextures=!0,i.__hasExternalTextures&&(i.__autoAllocateDepthBuffer=void 0===n,i.__autoAllocateDepthBuffer||t.useRenderToTexture&&(console.warn("render-to-texture extension was disabled because an external texture was provided"),t.useRenderToTexture=!1,t.useRenderbuffer=!0))},this.setRenderTargetFramebuffer=function(t,e){const n=$.get(t);n.__webglFramebuffer=e,n.__useDefaultFramebuffer=void 0===e},this.setRenderTarget=function(t,e=0,n=0){T=t,b=e,S=n;let i=!0;if(t){const e=$.get(t);void 0!==e.__useDefaultFramebuffer?(K.bindFramebuffer(36160,null),i=!1):void 0===e.__webglFramebuffer?tt.setupRenderTarget(t):e.__hasExternalTextures&&tt.rebindTextures(t,$.get(t.texture).__webglTexture,$.get(t.depthTexture).__webglTexture)}let r=null,s=!1,a=!1;if(t){const n=t.texture;(n.isDataTexture3D||n.isDataTexture2DArray)&&(a=!0);const i=$.get(t).__webglFramebuffer;t.isWebGLCubeRenderTarget?(r=i[e],s=!0):r=t.useRenderbuffer?$.get(t).__webglMultisampledFramebuffer:i,L.copy(t.viewport),C.copy(t.scissor),P=t.scissorTest}else L.copy(O).multiplyScalar(N).floor(),C.copy(F).multiplyScalar(N).floor(),P=U;if(K.bindFramebuffer(36160,r)&&Z.drawBuffers&&i){let e=!1;if(t)if(t.isWebGLMultipleRenderTargets){const n=t.texture;if(H.length!==n.length||36064!==H[0]){for(let t=0,e=n.length;t=0&&e<=t.width-i&&n>=0&&n<=t.height-r&&xt.readPixels(e,n,i,r,vt.convert(o),vt.convert(l),s):console.error("THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.")}finally{const t=null!==T?$.get(T).__webglFramebuffer:null;K.bindFramebuffer(36160,t)}}},this.copyFramebufferToTexture=function(t,e,n=0){if(!0!==e.isFramebufferTexture)return void console.error("THREE.WebGLRenderer: copyFramebufferToTexture() can only be used with FramebufferTexture.");const i=Math.pow(2,-n),r=Math.floor(e.image.width*i),s=Math.floor(e.image.height*i);tt.setTexture2D(e,0),xt.copyTexSubImage2D(3553,n,0,0,t.x,t.y,r,s),K.unbindTexture()},this.copyTextureToTexture=function(t,e,n,i=0){const r=e.image.width,s=e.image.height,a=vt.convert(n.format),o=vt.convert(n.type);tt.setTexture2D(n,0),xt.pixelStorei(37440,n.flipY),xt.pixelStorei(37441,n.premultiplyAlpha),xt.pixelStorei(3317,n.unpackAlignment),e.isDataTexture?xt.texSubImage2D(3553,i,t.x,t.y,r,s,a,o,e.image.data):e.isCompressedTexture?xt.compressedTexSubImage2D(3553,i,t.x,t.y,e.mipmaps[0].width,e.mipmaps[0].height,a,e.mipmaps[0].data):xt.texSubImage2D(3553,i,t.x,t.y,a,o,e.image),0===i&&n.generateMipmaps&&xt.generateMipmap(3553),K.unbindTexture()},this.copyTextureToTexture3D=function(t,e,n,i,r=0){if(v.isWebGL1Renderer)return void console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2.");const s=t.max.x-t.min.x+1,a=t.max.y-t.min.y+1,o=t.max.z-t.min.z+1,l=vt.convert(i.format),c=vt.convert(i.type);let h;if(i.isDataTexture3D)tt.setTexture3D(i,0),h=32879;else{if(!i.isDataTexture2DArray)return void console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.");tt.setTexture2DArray(i,0),h=35866}xt.pixelStorei(37440,i.flipY),xt.pixelStorei(37441,i.premultiplyAlpha),xt.pixelStorei(3317,i.unpackAlignment);const u=xt.getParameter(3314),d=xt.getParameter(32878),p=xt.getParameter(3316),m=xt.getParameter(3315),f=xt.getParameter(32877),g=n.isCompressedTexture?n.mipmaps[0]:n.image;xt.pixelStorei(3314,g.width),xt.pixelStorei(32878,g.height),xt.pixelStorei(3316,t.min.x),xt.pixelStorei(3315,t.min.y),xt.pixelStorei(32877,t.min.z),n.isDataTexture||n.isDataTexture3D?xt.texSubImage3D(h,r,e.x,e.y,e.z,s,a,o,l,c,g.data):n.isCompressedTexture?(console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: untested support for compressed srcTexture."),xt.compressedTexSubImage3D(h,r,e.x,e.y,e.z,s,a,o,l,g.data)):xt.texSubImage3D(h,r,e.x,e.y,e.z,s,a,o,l,c,g),xt.pixelStorei(3314,u),xt.pixelStorei(32878,d),xt.pixelStorei(3316,p),xt.pixelStorei(3315,m),xt.pixelStorei(32877,f),0===r&&i.generateMipmaps&&xt.generateMipmap(h),K.unbindTexture()},this.initTexture=function(t){tt.setTexture2D(t,0),K.unbindTexture()},this.resetState=function(){b=0,S=0,T=null,K.reset(),yt.reset()},"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}la.prototype.isWebGLRenderer=!0;class ca extends la{}ca.prototype.isWebGL1Renderer=!0;class ha{constructor(t,e=25e-5){this.name="",this.color=new Gt(t),this.density=e}clone(){return new ha(this.color,this.density)}toJSON(){return{type:"FogExp2",color:this.color.getHex(),density:this.density}}}ha.prototype.isFogExp2=!0;class ua{constructor(t,e=1,n=1e3){this.name="",this.color=new Gt(t),this.near=e,this.far=n}clone(){return new ua(this.color,this.near,this.far)}toJSON(){return{type:"Fog",color:this.color.getHex(),near:this.near,far:this.far}}}ua.prototype.isFog=!0;class da extends tn{constructor(){super(),this.type="Scene",this.background=null,this.environment=null,this.fog=null,this.overrideMaterial=null,this.autoUpdate=!0,"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}copy(t,e){return super.copy(t,e),null!==t.background&&(this.background=t.background.clone()),null!==t.environment&&(this.environment=t.environment.clone()),null!==t.fog&&(this.fog=t.fog.clone()),null!==t.overrideMaterial&&(this.overrideMaterial=t.overrideMaterial.clone()),this.autoUpdate=t.autoUpdate,this.matrixAutoUpdate=t.matrixAutoUpdate,this}toJSON(t){const e=super.toJSON(t);return null!==this.fog&&(e.object.fog=this.fog.toJSON()),e}}da.prototype.isScene=!0;class pa{constructor(t,e){this.array=t,this.stride=e,this.count=void 0!==t?t.length/e:0,this.usage=ut,this.updateRange={offset:0,count:-1},this.version=0,this.uuid=bt()}onUploadCallback(){}set needsUpdate(t){!0===t&&this.version++}setUsage(t){return this.usage=t,this}copy(t){return this.array=new t.array.constructor(t.array),this.count=t.count,this.stride=t.stride,this.usage=t.usage,this}copyAt(t,e,n){t*=this.stride,n*=e.stride;for(let i=0,r=this.stride;it.far||e.push({distance:o,point:ya.clone(),uv:dn.getUV(ya,Sa,Ta,Ea,Aa,Ra,La,new Lt),face:null,object:this})}copy(t){return super.copy(t),void 0!==t.center&&this.center.copy(t.center),this.material=t.material,this}}function Pa(t,e,n,i,r,s){ba.subVectors(t,n).addScalar(.5).multiply(i),void 0!==r?(Ma.x=s*ba.x-r*ba.y,Ma.y=r*ba.x+s*ba.y):Ma.copy(ba),t.copy(e),t.x+=Ma.x,t.y+=Ma.y,t.applyMatrix4(wa)}Ca.prototype.isSprite=!0;const Da=new Qt,Ia=new Qt;class Na extends tn{constructor(){super(),this._currentLevel=0,this.type="LOD",Object.defineProperties(this,{levels:{enumerable:!0,value:[]},isLOD:{value:!0}}),this.autoUpdate=!0}copy(t){super.copy(t,!1);const e=t.levels;for(let t=0,n=e.length;t0){let n,i;for(n=1,i=e.length;n0){Da.setFromMatrixPosition(this.matrixWorld);const n=t.ray.origin.distanceTo(Da);this.getObjectForDistance(n).raycast(t,e)}}update(t){const e=this.levels;if(e.length>1){Da.setFromMatrixPosition(t.matrixWorld),Ia.setFromMatrixPosition(this.matrixWorld);const n=Da.distanceTo(Ia)/t.zoom;let i,r;for(e[0].object.visible=!0,i=1,r=e.length;i=e[i].distance;i++)e[i-1].object.visible=!1,e[i].object.visible=!0;for(this._currentLevel=i-1;io)continue;u.applyMatrix4(this.matrixWorld);const d=t.ray.origin.distanceTo(u);dt.far||e.push({distance:d,point:h.clone().applyMatrix4(this.matrixWorld),index:n,face:null,faceIndex:null,object:this})}}else{for(let n=Math.max(0,s.start),i=Math.min(r.count,s.start+s.count)-1;no)continue;u.applyMatrix4(this.matrixWorld);const i=t.ray.origin.distanceTo(u);it.far||e.push({distance:i,point:h.clone().applyMatrix4(this.matrixWorld),index:n,face:null,faceIndex:null,object:this})}}}else n.isGeometry&&console.error("THREE.Line.raycast() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.")}updateMorphTargets(){const t=this.geometry;if(t.isBufferGeometry){const e=t.morphAttributes,n=Object.keys(e);if(n.length>0){const t=e[n[0]];if(void 0!==t){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let e=0,n=t.length;e0&&console.error("THREE.Line.updateMorphTargets() does not support THREE.Geometry. Use THREE.BufferGeometry instead.")}}}ro.prototype.isLine=!0;const so=new Qt,ao=new Qt;class oo extends ro{constructor(t,e){super(t,e),this.type="LineSegments"}computeLineDistances(){const t=this.geometry;if(t.isBufferGeometry)if(null===t.index){const e=t.attributes.position,n=[];for(let t=0,i=e.count;t0){const t=e[n[0]];if(void 0!==t){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let e=0,n=t.length;e0&&console.error("THREE.Points.updateMorphTargets() does not support THREE.Geometry. Use THREE.BufferGeometry instead.")}}}function go(t,e,n,i,r,s,a){const o=uo.distanceSqToPoint(t);if(or.far)return;s.push({distance:l,distanceToRay:Math.sqrt(o),point:n,index:e,face:null,object:a})}}fo.prototype.isPoints=!0;class vo extends jt{constructor(t,e,n,i,r,s,a,o,l){super(t,e,n,i,r,s,a,o,l),this.format=void 0!==a?a:T,this.minFilter=void 0!==s?s:g,this.magFilter=void 0!==r?r:g,this.generateMipmaps=!1;const c=this;"requestVideoFrameCallback"in t&&t.requestVideoFrameCallback((function e(){c.needsUpdate=!0,t.requestVideoFrameCallback(e)}))}clone(){return new this.constructor(this.image).copy(this)}update(){const t=this.image;!1==="requestVideoFrameCallback"in t&&t.readyState>=t.HAVE_CURRENT_DATA&&(this.needsUpdate=!0)}}vo.prototype.isVideoTexture=!0;class yo extends jt{constructor(t,e,n){super({width:t,height:e}),this.format=n,this.magFilter=p,this.minFilter=p,this.generateMipmaps=!1,this.needsUpdate=!0}}yo.prototype.isFramebufferTexture=!0;class xo extends jt{constructor(t,e,n,i,r,s,a,o,l,c,h,u){super(null,s,a,o,l,c,i,r,h,u),this.image={width:e,height:n},this.mipmaps=t,this.flipY=!1,this.generateMipmaps=!1}}xo.prototype.isCompressedTexture=!0;class _o extends jt{constructor(t,e,n,i,r,s,a,o,l){super(t,e,n,i,r,s,a,o,l),this.needsUpdate=!0}}_o.prototype.isCanvasTexture=!0;class bo extends zn{constructor(t=1,e=8,n=0,i=2*Math.PI){super(),this.type="CircleGeometry",this.parameters={radius:t,segments:e,thetaStart:n,thetaLength:i},e=Math.max(3,e);const r=[],s=[],a=[],o=[],l=new Qt,c=new Lt;s.push(0,0,0),a.push(0,0,1),o.push(.5,.5);for(let r=0,h=3;r<=e;r++,h+=3){const u=n+r/e*i;l.x=t*Math.cos(u),l.y=t*Math.sin(u),s.push(l.x,l.y,l.z),a.push(0,0,1),c.x=(s[h]/t+1)/2,c.y=(s[h+1]/t+1)/2,o.push(c.x,c.y)}for(let t=1;t<=e;t++)r.push(t,t+1,0);this.setIndex(r),this.setAttribute("position",new An(s,3)),this.setAttribute("normal",new An(a,3)),this.setAttribute("uv",new An(o,2))}static fromJSON(t){return new bo(t.radius,t.segments,t.thetaStart,t.thetaLength)}}class Mo extends zn{constructor(t=1,e=1,n=1,i=8,r=1,s=!1,a=0,o=2*Math.PI){super(),this.type="CylinderGeometry",this.parameters={radiusTop:t,radiusBottom:e,height:n,radialSegments:i,heightSegments:r,openEnded:s,thetaStart:a,thetaLength:o};const l=this;i=Math.floor(i),r=Math.floor(r);const c=[],h=[],u=[],d=[];let p=0;const m=[],f=n/2;let g=0;function v(n){const r=p,s=new Lt,m=new Qt;let v=0;const y=!0===n?t:e,x=!0===n?1:-1;for(let t=1;t<=i;t++)h.push(0,f*x,0),u.push(0,x,0),d.push(.5,.5),p++;const _=p;for(let t=0;t<=i;t++){const e=t/i*o+a,n=Math.cos(e),r=Math.sin(e);m.x=y*r,m.y=f*x,m.z=y*n,h.push(m.x,m.y,m.z),u.push(0,x,0),s.x=.5*n+.5,s.y=.5*r*x+.5,d.push(s.x,s.y),p++}for(let t=0;t0&&v(!0),e>0&&v(!1)),this.setIndex(c),this.setAttribute("position",new An(h,3)),this.setAttribute("normal",new An(u,3)),this.setAttribute("uv",new An(d,2))}static fromJSON(t){return new Mo(t.radiusTop,t.radiusBottom,t.height,t.radialSegments,t.heightSegments,t.openEnded,t.thetaStart,t.thetaLength)}}class wo extends Mo{constructor(t=1,e=1,n=8,i=1,r=!1,s=0,a=2*Math.PI){super(0,t,e,n,i,r,s,a),this.type="ConeGeometry",this.parameters={radius:t,height:e,radialSegments:n,heightSegments:i,openEnded:r,thetaStart:s,thetaLength:a}}static fromJSON(t){return new wo(t.radius,t.height,t.radialSegments,t.heightSegments,t.openEnded,t.thetaStart,t.thetaLength)}}class So extends zn{constructor(t=[],e=[],n=1,i=0){super(),this.type="PolyhedronGeometry",this.parameters={vertices:t,indices:e,radius:n,detail:i};const r=[],s=[];function a(t,e,n,i){const r=i+1,s=[];for(let i=0;i<=r;i++){s[i]=[];const a=t.clone().lerp(n,i/r),o=e.clone().lerp(n,i/r),l=r-i;for(let t=0;t<=l;t++)s[i][t]=0===t&&i===r?a:a.clone().lerp(o,t/l)}for(let t=0;t.9&&a<.1&&(e<.2&&(s[t+0]+=1),n<.2&&(s[t+2]+=1),i<.2&&(s[t+4]+=1))}}()}(),this.setAttribute("position",new An(r,3)),this.setAttribute("normal",new An(r.slice(),3)),this.setAttribute("uv",new An(s,2)),0===i?this.computeVertexNormals():this.normalizeNormals()}static fromJSON(t){return new So(t.vertices,t.indices,t.radius,t.details)}}class To extends So{constructor(t=1,e=0){const n=(1+Math.sqrt(5))/2,i=1/n;super([-1,-1,-1,-1,-1,1,-1,1,-1,-1,1,1,1,-1,-1,1,-1,1,1,1,-1,1,1,1,0,-i,-n,0,-i,n,0,i,-n,0,i,n,-i,-n,0,-i,n,0,i,-n,0,i,n,0,-n,0,-i,n,0,-i,-n,0,i,n,0,i],[3,11,7,3,7,15,3,15,13,7,19,17,7,17,6,7,6,15,17,4,8,17,8,10,17,10,6,8,0,16,8,16,2,8,2,10,0,12,1,0,1,18,0,18,16,6,10,2,6,2,13,6,13,15,2,16,18,2,18,3,2,3,13,18,1,9,18,9,11,18,11,3,4,14,12,4,12,0,4,0,8,11,9,5,11,5,19,11,19,7,19,5,14,19,14,4,19,4,17,1,12,14,1,14,5,1,5,9],t,e),this.type="DodecahedronGeometry",this.parameters={radius:t,detail:e}}static fromJSON(t){return new To(t.radius,t.detail)}}const Eo=new Qt,Ao=new Qt,Ro=new Qt,Lo=new dn;class Co extends zn{constructor(t=null,e=1){if(super(),this.type="EdgesGeometry",this.parameters={geometry:t,thresholdAngle:e},null!==t){const n=4,i=Math.pow(10,n),r=Math.cos(xt*e),s=t.getIndex(),a=t.getAttribute("position"),o=s?s.count:a.count,l=[0,0,0],c=["a","b","c"],h=new Array(3),u={},d=[];for(let t=0;t0)){l=i;break}l=i-1}if(i=l,n[i]===s)return i/(r-1);const c=n[i];return(i+(s-c)/(n[i+1]-c))/(r-1)}getTangent(t,e){const n=1e-4;let i=t-n,r=t+n;i<0&&(i=0),r>1&&(r=1);const s=this.getPoint(i),a=this.getPoint(r),o=e||(s.isVector2?new Lt:new Qt);return o.copy(a).sub(s).normalize(),o}getTangentAt(t,e){const n=this.getUtoTmapping(t);return this.getTangent(n,e)}computeFrenetFrames(t,e){const n=new Qt,i=[],r=[],s=[],a=new Qt,o=new Le;for(let e=0;e<=t;e++){const n=e/t;i[e]=this.getTangentAt(n,new Qt)}r[0]=new Qt,s[0]=new Qt;let l=Number.MAX_VALUE;const c=Math.abs(i[0].x),h=Math.abs(i[0].y),u=Math.abs(i[0].z);c<=l&&(l=c,n.set(1,0,0)),h<=l&&(l=h,n.set(0,1,0)),u<=l&&n.set(0,0,1),a.crossVectors(i[0],n).normalize(),r[0].crossVectors(i[0],a),s[0].crossVectors(i[0],r[0]);for(let e=1;e<=t;e++){if(r[e]=r[e-1].clone(),s[e]=s[e-1].clone(),a.crossVectors(i[e-1],i[e]),a.length()>Number.EPSILON){a.normalize();const t=Math.acos(Mt(i[e-1].dot(i[e]),-1,1));r[e].applyMatrix4(o.makeRotationAxis(a,t))}s[e].crossVectors(i[e],r[e])}if(!0===e){let e=Math.acos(Mt(r[0].dot(r[t]),-1,1));e/=t,i[0].dot(a.crossVectors(r[0],r[t]))>0&&(e=-e);for(let n=1;n<=t;n++)r[n].applyMatrix4(o.makeRotationAxis(i[n],e*n)),s[n].crossVectors(i[n],r[n])}return{tangents:i,normals:r,binormals:s}}clone(){return(new this.constructor).copy(this)}copy(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}toJSON(){const t={metadata:{version:4.5,type:"Curve",generator:"Curve.toJSON"}};return t.arcLengthDivisions=this.arcLengthDivisions,t.type=this.type,t}fromJSON(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}}class Do extends Po{constructor(t=0,e=0,n=1,i=1,r=0,s=2*Math.PI,a=!1,o=0){super(),this.type="EllipseCurve",this.aX=t,this.aY=e,this.xRadius=n,this.yRadius=i,this.aStartAngle=r,this.aEndAngle=s,this.aClockwise=a,this.aRotation=o}getPoint(t,e){const n=e||new Lt,i=2*Math.PI;let r=this.aEndAngle-this.aStartAngle;const s=Math.abs(r)i;)r-=i;r0?0:(Math.floor(Math.abs(l)/r)+1)*r:0===c&&l===r-1&&(l=r-2,c=1),this.closed||l>0?a=i[(l-1)%r]:(Bo.subVectors(i[0],i[1]).add(i[0]),a=Bo);const h=i[l%r],u=i[(l+1)%r];if(this.closed||l+2i.length-2?i.length-1:s+1],h=i[s>i.length-3?i.length-1:s+2];return n.set(Ho(a,o.x,l.x,c.x,h.x),Ho(a,o.y,l.y,c.y,h.y)),n}copy(t){super.copy(t),this.points=[];for(let e=0,n=t.points.length;e=n){const t=i[r]-n,s=this.curves[r],a=s.getLength(),o=0===a?0:1-t/a;return s.getPointAt(o,e)}r++}return null}getLength(){const t=this.getCurveLengths();return t[t.length-1]}updateArcLengths(){this.needsUpdate=!0,this.cacheLengths=null,this.getCurveLengths()}getCurveLengths(){if(this.cacheLengths&&this.cacheLengths.length===this.curves.length)return this.cacheLengths;const t=[];let e=0;for(let n=0,i=this.curves.length;n1&&!e[e.length-1].equals(e[0])&&e.push(e[0]),e}copy(t){super.copy(t),this.curves=[];for(let e=0,n=t.curves.length;e0){const t=l.getPoint(0);t.equals(this.currentPoint)||this.lineTo(t.x,t.y)}this.curves.push(l);const c=l.getPoint(1);return this.currentPoint.copy(c),this}copy(t){return super.copy(t),this.currentPoint.copy(t.currentPoint),this}toJSON(){const t=super.toJSON();return t.currentPoint=this.currentPoint.toArray(),t}fromJSON(t){return super.fromJSON(t),this.currentPoint.fromArray(t.currentPoint),this}}class $o extends Qo{constructor(t){super(t),this.uuid=bt(),this.type="Shape",this.holes=[]}getPointsHoles(t){const e=[];for(let n=0,i=this.holes.length;n80*n){o=c=t[0],l=h=t[1];for(let e=n;ec&&(c=u),d>h&&(h=d);p=Math.max(c-o,h-l),p=0!==p?1/p:0}return il(s,a,n,o,l,p),a};function el(t,e,n,i,r){let s,a;if(r===function(t,e,n,i){let r=0;for(let s=e,a=n-i;s0)for(s=e;s=e;s-=i)a=Ml(s,t[s],t[s+1],a);return a&&gl(a,a.next)&&(wl(a),a=a.next),a}function nl(t,e){if(!t)return t;e||(e=t);let n,i=t;do{if(n=!1,i.steiner||!gl(i,i.next)&&0!==fl(i.prev,i,i.next))i=i.next;else{if(wl(i),i=e=i.prev,i===i.next)break;n=!0}}while(n||i!==e);return e}function il(t,e,n,i,r,s,a){if(!t)return;!a&&s&&function(t,e,n,i){let r=t;do{null===r.z&&(r.z=ul(r.x,r.y,e,n,i)),r.prevZ=r.prev,r.nextZ=r.next,r=r.next}while(r!==t);r.prevZ.nextZ=null,r.prevZ=null,function(t){let e,n,i,r,s,a,o,l,c=1;do{for(n=t,t=null,s=null,a=0;n;){for(a++,i=n,o=0,e=0;e0||l>0&&i;)0!==o&&(0===l||!i||n.z<=i.z)?(r=n,n=n.nextZ,o--):(r=i,i=i.nextZ,l--),s?s.nextZ=r:t=r,r.prevZ=s,s=r;n=i}s.nextZ=null,c*=2}while(a>1)}(r)}(t,i,r,s);let o,l,c=t;for(;t.prev!==t.next;)if(o=t.prev,l=t.next,s?sl(t,i,r,s):rl(t))e.push(o.i/n),e.push(t.i/n),e.push(l.i/n),wl(t),t=l.next,c=l.next;else if((t=l)===c){a?1===a?il(t=al(nl(t),e,n),e,n,i,r,s,2):2===a&&ol(t,e,n,i,r,s):il(nl(t),e,n,i,r,s,1);break}}function rl(t){const e=t.prev,n=t,i=t.next;if(fl(e,n,i)>=0)return!1;let r=t.next.next;for(;r!==t.prev;){if(pl(e.x,e.y,n.x,n.y,i.x,i.y,r.x,r.y)&&fl(r.prev,r,r.next)>=0)return!1;r=r.next}return!0}function sl(t,e,n,i){const r=t.prev,s=t,a=t.next;if(fl(r,s,a)>=0)return!1;const o=r.xs.x?r.x>a.x?r.x:a.x:s.x>a.x?s.x:a.x,h=r.y>s.y?r.y>a.y?r.y:a.y:s.y>a.y?s.y:a.y,u=ul(o,l,e,n,i),d=ul(c,h,e,n,i);let p=t.prevZ,m=t.nextZ;for(;p&&p.z>=u&&m&&m.z<=d;){if(p!==t.prev&&p!==t.next&&pl(r.x,r.y,s.x,s.y,a.x,a.y,p.x,p.y)&&fl(p.prev,p,p.next)>=0)return!1;if(p=p.prevZ,m!==t.prev&&m!==t.next&&pl(r.x,r.y,s.x,s.y,a.x,a.y,m.x,m.y)&&fl(m.prev,m,m.next)>=0)return!1;m=m.nextZ}for(;p&&p.z>=u;){if(p!==t.prev&&p!==t.next&&pl(r.x,r.y,s.x,s.y,a.x,a.y,p.x,p.y)&&fl(p.prev,p,p.next)>=0)return!1;p=p.prevZ}for(;m&&m.z<=d;){if(m!==t.prev&&m!==t.next&&pl(r.x,r.y,s.x,s.y,a.x,a.y,m.x,m.y)&&fl(m.prev,m,m.next)>=0)return!1;m=m.nextZ}return!0}function al(t,e,n){let i=t;do{const r=i.prev,s=i.next.next;!gl(r,s)&&vl(r,i,i.next,s)&&_l(r,s)&&_l(s,r)&&(e.push(r.i/n),e.push(i.i/n),e.push(s.i/n),wl(i),wl(i.next),i=t=s),i=i.next}while(i!==t);return nl(i)}function ol(t,e,n,i,r,s){let a=t;do{let t=a.next.next;for(;t!==a.prev;){if(a.i!==t.i&&ml(a,t)){let o=bl(a,t);return a=nl(a,a.next),o=nl(o,o.next),il(a,e,n,i,r,s),void il(o,e,n,i,r,s)}t=t.next}a=a.next}while(a!==t)}function ll(t,e){return t.x-e.x}function cl(t,e){if(e=function(t,e){let n=e;const i=t.x,r=t.y;let s,a=-1/0;do{if(r<=n.y&&r>=n.next.y&&n.next.y!==n.y){const t=n.x+(r-n.y)*(n.next.x-n.x)/(n.next.y-n.y);if(t<=i&&t>a){if(a=t,t===i){if(r===n.y)return n;if(r===n.next.y)return n.next}s=n.x=n.x&&n.x>=l&&i!==n.x&&pl(rs.x||n.x===s.x&&hl(s,n)))&&(s=n,u=h)),n=n.next}while(n!==o);return s}(t,e),e){const n=bl(e,t);nl(e,e.next),nl(n,n.next)}}function hl(t,e){return fl(t.prev,t,e.prev)<0&&fl(e.next,t,t.next)<0}function ul(t,e,n,i,r){return(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=32767*(t-n)*r)|t<<8))|t<<4))|t<<2))|t<<1))|(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=32767*(e-i)*r)|e<<8))|e<<4))|e<<2))|e<<1))<<1}function dl(t){let e=t,n=t;do{(e.x=0&&(t-a)*(i-o)-(n-a)*(e-o)>=0&&(n-a)*(s-o)-(r-a)*(i-o)>=0}function ml(t,e){return t.next.i!==e.i&&t.prev.i!==e.i&&!function(t,e){let n=t;do{if(n.i!==t.i&&n.next.i!==t.i&&n.i!==e.i&&n.next.i!==e.i&&vl(n,n.next,t,e))return!0;n=n.next}while(n!==t);return!1}(t,e)&&(_l(t,e)&&_l(e,t)&&function(t,e){let n=t,i=!1;const r=(t.x+e.x)/2,s=(t.y+e.y)/2;do{n.y>s!=n.next.y>s&&n.next.y!==n.y&&r<(n.next.x-n.x)*(s-n.y)/(n.next.y-n.y)+n.x&&(i=!i),n=n.next}while(n!==t);return i}(t,e)&&(fl(t.prev,t,e.prev)||fl(t,e.prev,e))||gl(t,e)&&fl(t.prev,t,t.next)>0&&fl(e.prev,e,e.next)>0)}function fl(t,e,n){return(e.y-t.y)*(n.x-e.x)-(e.x-t.x)*(n.y-e.y)}function gl(t,e){return t.x===e.x&&t.y===e.y}function vl(t,e,n,i){const r=xl(fl(t,e,n)),s=xl(fl(t,e,i)),a=xl(fl(n,i,t)),o=xl(fl(n,i,e));return r!==s&&a!==o||(!(0!==r||!yl(t,n,e))||(!(0!==s||!yl(t,i,e))||(!(0!==a||!yl(n,t,i))||!(0!==o||!yl(n,e,i)))))}function yl(t,e,n){return e.x<=Math.max(t.x,n.x)&&e.x>=Math.min(t.x,n.x)&&e.y<=Math.max(t.y,n.y)&&e.y>=Math.min(t.y,n.y)}function xl(t){return t>0?1:t<0?-1:0}function _l(t,e){return fl(t.prev,t,t.next)<0?fl(t,e,t.next)>=0&&fl(t,t.prev,e)>=0:fl(t,e,t.prev)<0||fl(t,t.next,e)<0}function bl(t,e){const n=new Sl(t.i,t.x,t.y),i=new Sl(e.i,e.x,e.y),r=t.next,s=e.prev;return t.next=e,e.prev=t,n.next=r,r.prev=n,i.next=n,n.prev=i,s.next=i,i.prev=s,i}function Ml(t,e,n,i){const r=new Sl(t,e,n);return i?(r.next=i.next,r.prev=i,i.next.prev=r,i.next=r):(r.prev=r,r.next=r),r}function wl(t){t.next.prev=t.prev,t.prev.next=t.next,t.prevZ&&(t.prevZ.nextZ=t.nextZ),t.nextZ&&(t.nextZ.prevZ=t.prevZ)}function Sl(t,e,n){this.i=t,this.x=e,this.y=n,this.prev=null,this.next=null,this.z=null,this.prevZ=null,this.nextZ=null,this.steiner=!1}class Tl{static area(t){const e=t.length;let n=0;for(let i=e-1,r=0;r2&&t[e-1].equals(t[0])&&t.pop()}function Al(t,e){for(let n=0;nNumber.EPSILON){const u=Math.sqrt(h),d=Math.sqrt(l*l+c*c),p=e.x-o/u,m=e.y+a/u,f=((n.x-c/d-p)*c-(n.y+l/d-m)*l)/(a*c-o*l);i=p+a*f-t.x,r=m+o*f-t.y;const g=i*i+r*r;if(g<=2)return new Lt(i,r);s=Math.sqrt(g/2)}else{let t=!1;a>Number.EPSILON?l>Number.EPSILON&&(t=!0):a<-Number.EPSILON?l<-Number.EPSILON&&(t=!0):Math.sign(o)===Math.sign(c)&&(t=!0),t?(i=-o,r=a,s=Math.sqrt(h)):(i=a,r=o,s=Math.sqrt(h/2))}return new Lt(i/s,r/s)}const P=[];for(let t=0,e=E.length,n=e-1,i=t+1;t=0;t--){const e=t/p,n=h*Math.cos(e*Math.PI/2),i=u*Math.sin(e*Math.PI/2)+d;for(let t=0,e=E.length;t=0;){const i=n;let r=n-1;r<0&&(r=t.length-1);for(let t=0,n=o+2*p;t0)&&d.push(e,r,l),(t!==n-1||o0!=t>0&&this.version++,this._sheen=t}get clearcoat(){return this._clearcoat}set clearcoat(t){this._clearcoat>0!=t>0&&this.version++,this._clearcoat=t}get transmission(){return this._transmission}set transmission(t){this._transmission>0!=t>0&&this.version++,this._transmission=t}copy(t){return super.copy(t),this.defines={STANDARD:"",PHYSICAL:""},this.clearcoat=t.clearcoat,this.clearcoatMap=t.clearcoatMap,this.clearcoatRoughness=t.clearcoatRoughness,this.clearcoatRoughnessMap=t.clearcoatRoughnessMap,this.clearcoatNormalMap=t.clearcoatNormalMap,this.clearcoatNormalScale.copy(t.clearcoatNormalScale),this.ior=t.ior,this.sheen=t.sheen,this.sheenColor.copy(t.sheenColor),this.sheenColorMap=t.sheenColorMap,this.sheenRoughness=t.sheenRoughness,this.sheenRoughnessMap=t.sheenRoughnessMap,this.transmission=t.transmission,this.transmissionMap=t.transmissionMap,this.thickness=t.thickness,this.thicknessMap=t.thicknessMap,this.attenuationDistance=t.attenuationDistance,this.attenuationColor.copy(t.attenuationColor),this.specularIntensity=t.specularIntensity,this.specularIntensityMap=t.specularIntensityMap,this.specularColor.copy(t.specularColor),this.specularColorMap=t.specularColorMap,this}}jl.prototype.isMeshPhysicalMaterial=!0;class ql extends mn{constructor(t){super(),this.type="MeshPhongMaterial",this.color=new Gt(16777215),this.specular=new Gt(1118481),this.shininess=30,this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Gt(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Lt(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.flatShading=!1,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.specular.copy(t.specular),this.shininess=t.shininess,this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.flatShading=t.flatShading,this}}ql.prototype.isMeshPhongMaterial=!0;class Xl extends mn{constructor(t){super(),this.defines={TOON:""},this.type="MeshToonMaterial",this.color=new Gt(16777215),this.map=null,this.gradientMap=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Gt(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Lt(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.alphaMap=null,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.gradientMap=t.gradientMap,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.alphaMap=t.alphaMap,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this}}Xl.prototype.isMeshToonMaterial=!0;class Jl extends mn{constructor(t){super(),this.type="MeshNormalMaterial",this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Lt(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.fog=!1,this.flatShading=!1,this.setValues(t)}copy(t){return super.copy(t),this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.flatShading=t.flatShading,this}}Jl.prototype.isMeshNormalMaterial=!0;class Yl extends mn{constructor(t){super(),this.type="MeshLambertMaterial",this.color=new Gt(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Gt(0),this.emissiveIntensity=1,this.emissiveMap=null,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this}}Yl.prototype.isMeshLambertMaterial=!0;class Zl extends mn{constructor(t){super(),this.defines={MATCAP:""},this.type="MeshMatcapMaterial",this.color=new Gt(16777215),this.matcap=null,this.map=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Lt(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.alphaMap=null,this.flatShading=!1,this.setValues(t)}copy(t){return super.copy(t),this.defines={MATCAP:""},this.color.copy(t.color),this.matcap=t.matcap,this.map=t.map,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.alphaMap=t.alphaMap,this.flatShading=t.flatShading,this}}Zl.prototype.isMeshMatcapMaterial=!0;class Kl extends Qa{constructor(t){super(),this.type="LineDashedMaterial",this.scale=1,this.dashSize=3,this.gapSize=1,this.setValues(t)}copy(t){return super.copy(t),this.scale=t.scale,this.dashSize=t.dashSize,this.gapSize=t.gapSize,this}}Kl.prototype.isLineDashedMaterial=!0;var Ql=Object.freeze({__proto__:null,ShadowMaterial:Vl,SpriteMaterial:ga,RawShaderMaterial:Ii,ShaderMaterial:ai,PointsMaterial:co,MeshPhysicalMaterial:jl,MeshStandardMaterial:Wl,MeshPhongMaterial:ql,MeshToonMaterial:Xl,MeshNormalMaterial:Jl,MeshLambertMaterial:Yl,MeshDepthMaterial:Ys,MeshDistanceMaterial:Zs,MeshBasicMaterial:fn,MeshMatcapMaterial:Zl,LineDashedMaterial:Kl,LineBasicMaterial:Qa,Material:mn});const $l={arraySlice:function(t,e,n){return $l.isTypedArray(t)?new t.constructor(t.subarray(e,void 0!==n?n:t.length)):t.slice(e,n)},convertArray:function(t,e,n){return!t||!n&&t.constructor===e?t:"number"==typeof e.BYTES_PER_ELEMENT?new e(t):Array.prototype.slice.call(t)},isTypedArray:function(t){return ArrayBuffer.isView(t)&&!(t instanceof DataView)},getKeyframeOrder:function(t){const e=t.length,n=new Array(e);for(let t=0;t!==e;++t)n[t]=t;return n.sort((function(e,n){return t[e]-t[n]})),n},sortedArray:function(t,e,n){const i=t.length,r=new t.constructor(i);for(let s=0,a=0;a!==i;++s){const i=n[s]*e;for(let n=0;n!==e;++n)r[a++]=t[i+n]}return r},flattenJSON:function(t,e,n,i){let r=1,s=t[0];for(;void 0!==s&&void 0===s[i];)s=t[r++];if(void 0===s)return;let a=s[i];if(void 0!==a)if(Array.isArray(a))do{a=s[i],void 0!==a&&(e.push(s.time),n.push.apply(n,a)),s=t[r++]}while(void 0!==s);else if(void 0!==a.toArray)do{a=s[i],void 0!==a&&(e.push(s.time),a.toArray(n,n.length)),s=t[r++]}while(void 0!==s);else do{a=s[i],void 0!==a&&(e.push(s.time),n.push(a)),s=t[r++]}while(void 0!==s)},subclip:function(t,e,n,i,r=30){const s=t.clone();s.name=e;const a=[];for(let t=0;t=i)){l.push(e.times[t]);for(let n=0;ns.tracks[t].times[0]&&(o=s.tracks[t].times[0]);for(let t=0;t=i.times[u]){const t=u*l+o,e=t+l-o;d=$l.arraySlice(i.values,t,e)}else{const t=i.createInterpolant(),e=o,n=l-o;t.evaluate(s),d=$l.arraySlice(t.resultBuffer,e,n)}if("quaternion"===r){(new Kt).fromArray(d).normalize().conjugate().toArray(d)}const p=a.times.length;for(let t=0;t=r)break t;{const a=e[1];t=r)break e}s=n,n=0}}for(;n>>1;te;)--s;if(++s,0!==r||s!==i){r>=s&&(s=Math.max(s,1),r=s-1);const t=this.getValueSize();this.times=$l.arraySlice(n,r,s),this.values=$l.arraySlice(this.values,r*t,s*t)}return this}validate(){let t=!0;const e=this.getValueSize();e-Math.floor(e)!=0&&(console.error("THREE.KeyframeTrack: Invalid value size in track.",this),t=!1);const n=this.times,i=this.values,r=n.length;0===r&&(console.error("THREE.KeyframeTrack: Track is empty.",this),t=!1);let s=null;for(let e=0;e!==r;e++){const i=n[e];if("number"==typeof i&&isNaN(i)){console.error("THREE.KeyframeTrack: Time is not a valid number.",this,e,i),t=!1;break}if(null!==s&&s>i){console.error("THREE.KeyframeTrack: Out of order keys.",this,e,i,s),t=!1;break}s=i}if(void 0!==i&&$l.isTypedArray(i))for(let e=0,n=i.length;e!==n;++e){const n=i[e];if(isNaN(n)){console.error("THREE.KeyframeTrack: Value is not a valid number.",this,e,n),t=!1;break}}return t}optimize(){const t=$l.arraySlice(this.times),e=$l.arraySlice(this.values),n=this.getValueSize(),i=this.getInterpolation()===nt,r=t.length-1;let s=1;for(let a=1;a0){t[s]=t[r];for(let t=r*n,i=s*n,a=0;a!==n;++a)e[i+a]=e[t+a];++s}return s!==t.length?(this.times=$l.arraySlice(t,0,s),this.values=$l.arraySlice(e,0,s*n)):(this.times=t,this.values=e),this}clone(){const t=$l.arraySlice(this.times,0),e=$l.arraySlice(this.values,0),n=new(0,this.constructor)(this.name,t,e);return n.createInterpolant=this.createInterpolant,n}}rc.prototype.TimeBufferType=Float32Array,rc.prototype.ValueBufferType=Float32Array,rc.prototype.DefaultInterpolation=et;class sc extends rc{}sc.prototype.ValueTypeName="bool",sc.prototype.ValueBufferType=Array,sc.prototype.DefaultInterpolation=tt,sc.prototype.InterpolantFactoryMethodLinear=void 0,sc.prototype.InterpolantFactoryMethodSmooth=void 0;class ac extends rc{}ac.prototype.ValueTypeName="color";class oc extends rc{}oc.prototype.ValueTypeName="number";class lc extends tc{constructor(t,e,n,i){super(t,e,n,i)}interpolate_(t,e,n,i){const r=this.resultBuffer,s=this.sampleValues,a=this.valueSize,o=(n-e)/(i-e);let l=t*a;for(let t=l+a;l!==t;l+=4)Kt.slerpFlat(r,0,s,l-a,s,l,o);return r}}class cc extends rc{InterpolantFactoryMethodLinear(t){return new lc(this.times,this.values,this.getValueSize(),t)}}cc.prototype.ValueTypeName="quaternion",cc.prototype.DefaultInterpolation=et,cc.prototype.InterpolantFactoryMethodSmooth=void 0;class hc extends rc{}hc.prototype.ValueTypeName="string",hc.prototype.ValueBufferType=Array,hc.prototype.DefaultInterpolation=tt,hc.prototype.InterpolantFactoryMethodLinear=void 0,hc.prototype.InterpolantFactoryMethodSmooth=void 0;class uc extends rc{}uc.prototype.ValueTypeName="vector";class dc{constructor(t,e=-1,n,i=2500){this.name=t,this.tracks=n,this.duration=e,this.blendMode=i,this.uuid=bt(),this.duration<0&&this.resetDuration()}static parse(t){const e=[],n=t.tracks,i=1/(t.fps||1);for(let t=0,r=n.length;t!==r;++t)e.push(pc(n[t]).scale(i));const r=new this(t.name,t.duration,e,t.blendMode);return r.uuid=t.uuid,r}static toJSON(t){const e=[],n=t.tracks,i={name:t.name,duration:t.duration,tracks:e,uuid:t.uuid,blendMode:t.blendMode};for(let t=0,i=n.length;t!==i;++t)e.push(rc.toJSON(n[t]));return i}static CreateFromMorphTargetSequence(t,e,n,i){const r=e.length,s=[];for(let t=0;t1){const t=s[1];let e=i[t];e||(i[t]=e=[]),e.push(n)}}const s=[];for(const t in i)s.push(this.CreateFromMorphTargetSequence(t,i[t],e,n));return s}static parseAnimation(t,e){if(!t)return console.error("THREE.AnimationClip: No animation in JSONLoader data."),null;const n=function(t,e,n,i,r){if(0!==n.length){const s=[],a=[];$l.flattenJSON(n,s,a,i),0!==s.length&&r.push(new t(e,s,a))}},i=[],r=t.name||"default",s=t.fps||30,a=t.blendMode;let o=t.length||-1;const l=t.hierarchy||[];for(let t=0;t{e&&e(r),this.manager.itemEnd(t)}),0),r;if(void 0!==yc[t])return void yc[t].push({onLoad:e,onProgress:n,onError:i});yc[t]=[],yc[t].push({onLoad:e,onProgress:n,onError:i});const s=new Request(t,{headers:new Headers(this.requestHeader),credentials:this.withCredentials?"include":"same-origin"});fetch(s).then((e=>{if(200===e.status||0===e.status){if(0===e.status&&console.warn("THREE.FileLoader: HTTP Status 0 received."),"undefined"==typeof ReadableStream||void 0===e.body.getReader)return e;const n=yc[t],i=e.body.getReader(),r=e.headers.get("Content-Length"),s=r?parseInt(r):0,a=0!==s;let o=0;const l=new ReadableStream({start(t){!function e(){i.read().then((({done:i,value:r})=>{if(i)t.close();else{o+=r.byteLength;const i=new ProgressEvent("progress",{lengthComputable:a,loaded:o,total:s});for(let t=0,e=n.length;t{switch(this.responseType){case"arraybuffer":return t.arrayBuffer();case"blob":return t.blob();case"document":return t.text().then((t=>(new DOMParser).parseFromString(t,this.mimeType)));case"json":return t.json();default:return t.text()}})).then((e=>{mc.add(t,e);const n=yc[t];delete yc[t];for(let t=0,i=n.length;t{const n=yc[t];if(void 0===n)throw this.manager.itemError(t),e;delete yc[t];for(let t=0,i=n.length;t{this.manager.itemEnd(t)})),this.manager.itemStart(t)}setResponseType(t){return this.responseType=t,this}setMimeType(t){return this.mimeType=t,this}}class _c extends vc{constructor(t){super(t)}load(t,e,n,i){void 0!==this.path&&(t=this.path+t),t=this.manager.resolveURL(t);const r=this,s=mc.get(t);if(void 0!==s)return r.manager.itemStart(t),setTimeout((function(){e&&e(s),r.manager.itemEnd(t)}),0),s;const a=Nt("img");function o(){c(),mc.add(t,this),e&&e(this),r.manager.itemEnd(t)}function l(e){c(),i&&i(e),r.manager.itemError(t),r.manager.itemEnd(t)}function c(){a.removeEventListener("load",o,!1),a.removeEventListener("error",l,!1)}return a.addEventListener("load",o,!1),a.addEventListener("error",l,!1),"data:"!==t.substr(0,5)&&void 0!==this.crossOrigin&&(a.crossOrigin=this.crossOrigin),r.manager.itemStart(t),a.src=t,a}}class bc extends vc{constructor(t){super(t)}load(t,e,n,i){const r=new ui,s=new _c(this.manager);s.setCrossOrigin(this.crossOrigin),s.setPath(this.path);let a=0;function o(n){s.load(t[n],(function(t){r.images[n]=t,a++,6===a&&(r.needsUpdate=!0,e&&e(r))}),void 0,i)}for(let e=0;e0:i.vertexColors=t.vertexColors),void 0!==t.uniforms)for(const e in t.uniforms){const r=t.uniforms[e];switch(i.uniforms[e]={},r.type){case"t":i.uniforms[e].value=n(r.value);break;case"c":i.uniforms[e].value=(new Gt).setHex(r.value);break;case"v2":i.uniforms[e].value=(new Lt).fromArray(r.value);break;case"v3":i.uniforms[e].value=(new Qt).fromArray(r.value);break;case"v4":i.uniforms[e].value=(new Xt).fromArray(r.value);break;case"m3":i.uniforms[e].value=(new Ct).fromArray(r.value);break;case"m4":i.uniforms[e].value=(new Le).fromArray(r.value);break;default:i.uniforms[e].value=r.value}}if(void 0!==t.defines&&(i.defines=t.defines),void 0!==t.vertexShader&&(i.vertexShader=t.vertexShader),void 0!==t.fragmentShader&&(i.fragmentShader=t.fragmentShader),void 0!==t.extensions)for(const e in t.extensions)i.extensions[e]=t.extensions[e];if(void 0!==t.shading&&(i.flatShading=1===t.shading),void 0!==t.size&&(i.size=t.size),void 0!==t.sizeAttenuation&&(i.sizeAttenuation=t.sizeAttenuation),void 0!==t.map&&(i.map=n(t.map)),void 0!==t.matcap&&(i.matcap=n(t.matcap)),void 0!==t.alphaMap&&(i.alphaMap=n(t.alphaMap)),void 0!==t.bumpMap&&(i.bumpMap=n(t.bumpMap)),void 0!==t.bumpScale&&(i.bumpScale=t.bumpScale),void 0!==t.normalMap&&(i.normalMap=n(t.normalMap)),void 0!==t.normalMapType&&(i.normalMapType=t.normalMapType),void 0!==t.normalScale){let e=t.normalScale;!1===Array.isArray(e)&&(e=[e,e]),i.normalScale=(new Lt).fromArray(e)}return void 0!==t.displacementMap&&(i.displacementMap=n(t.displacementMap)),void 0!==t.displacementScale&&(i.displacementScale=t.displacementScale),void 0!==t.displacementBias&&(i.displacementBias=t.displacementBias),void 0!==t.roughnessMap&&(i.roughnessMap=n(t.roughnessMap)),void 0!==t.metalnessMap&&(i.metalnessMap=n(t.metalnessMap)),void 0!==t.emissiveMap&&(i.emissiveMap=n(t.emissiveMap)),void 0!==t.emissiveIntensity&&(i.emissiveIntensity=t.emissiveIntensity),void 0!==t.specularMap&&(i.specularMap=n(t.specularMap)),void 0!==t.specularIntensityMap&&(i.specularIntensityMap=n(t.specularIntensityMap)),void 0!==t.specularColorMap&&(i.specularColorMap=n(t.specularColorMap)),void 0!==t.envMap&&(i.envMap=n(t.envMap)),void 0!==t.envMapIntensity&&(i.envMapIntensity=t.envMapIntensity),void 0!==t.reflectivity&&(i.reflectivity=t.reflectivity),void 0!==t.refractionRatio&&(i.refractionRatio=t.refractionRatio),void 0!==t.lightMap&&(i.lightMap=n(t.lightMap)),void 0!==t.lightMapIntensity&&(i.lightMapIntensity=t.lightMapIntensity),void 0!==t.aoMap&&(i.aoMap=n(t.aoMap)),void 0!==t.aoMapIntensity&&(i.aoMapIntensity=t.aoMapIntensity),void 0!==t.gradientMap&&(i.gradientMap=n(t.gradientMap)),void 0!==t.clearcoatMap&&(i.clearcoatMap=n(t.clearcoatMap)),void 0!==t.clearcoatRoughnessMap&&(i.clearcoatRoughnessMap=n(t.clearcoatRoughnessMap)),void 0!==t.clearcoatNormalMap&&(i.clearcoatNormalMap=n(t.clearcoatNormalMap)),void 0!==t.clearcoatNormalScale&&(i.clearcoatNormalScale=(new Lt).fromArray(t.clearcoatNormalScale)),void 0!==t.transmissionMap&&(i.transmissionMap=n(t.transmissionMap)),void 0!==t.thicknessMap&&(i.thicknessMap=n(t.thicknessMap)),void 0!==t.sheenColorMap&&(i.sheenColorMap=n(t.sheenColorMap)),void 0!==t.sheenRoughnessMap&&(i.sheenRoughnessMap=n(t.sheenRoughnessMap)),i}setTextures(t){return this.textures=t,this}}class Wc{static decodeText(t){if("undefined"!=typeof TextDecoder)return(new TextDecoder).decode(t);let e="";for(let n=0,i=t.length;n0){this.source.connect(this.filters[0]);for(let t=1,e=this.filters.length;t0){this.source.disconnect(this.filters[0]);for(let t=1,e=this.filters.length;t0&&this._mixBufferRegionAdditive(n,i,this._addIndex*e,1,e);for(let t=e,r=e+e;t!==r;++t)if(n[t]!==n[t+e]){a.setValue(n,i);break}}saveOriginalState(){const t=this.binding,e=this.buffer,n=this.valueSize,i=n*this._origIndex;t.getValue(e,i);for(let t=n,r=i;t!==r;++t)e[t]=e[i+t%n];this._setIdentity(),this.cumulativeWeight=0,this.cumulativeWeightAdditive=0}restoreOriginalState(){const t=3*this.valueSize;this.binding.setValue(this.buffer,t)}_setAdditiveIdentityNumeric(){const t=this._addIndex*this.valueSize,e=t+this.valueSize;for(let n=t;n=.5)for(let i=0;i!==r;++i)t[e+i]=t[n+i]}_slerp(t,e,n,i){Kt.slerpFlat(t,e,t,e,t,n,i)}_slerpAdditive(t,e,n,i,r){const s=this._workIndex*r;Kt.multiplyQuaternionsFlat(t,s,t,e,t,n),Kt.slerpFlat(t,e,t,e,t,s,i)}_lerp(t,e,n,i,r){const s=1-i;for(let a=0;a!==r;++a){const r=e+a;t[r]=t[r]*s+t[n+a]*i}}_lerpAdditive(t,e,n,i,r){for(let s=0;s!==r;++s){const r=e+s;t[r]=t[r]+t[n+s]*i}}}const yh="\\[\\]\\.:\\/",xh=new RegExp("[\\[\\]\\.:\\/]","g"),_h="[^\\[\\]\\.:\\/]",bh="[^"+yh.replace("\\.","")+"]",Mh=/((?:WC+[\/:])*)/.source.replace("WC",_h),wh=/(WCOD+)?/.source.replace("WCOD",bh),Sh=/(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace("WC",_h),Th=/\.(WC+)(?:\[(.+)\])?/.source.replace("WC",_h),Eh=new RegExp("^"+Mh+wh+Sh+Th+"$"),Ah=["material","materials","bones"];class Rh{constructor(t,e,n){this.path=e,this.parsedPath=n||Rh.parseTrackName(e),this.node=Rh.findNode(t,this.parsedPath.nodeName)||t,this.rootNode=t,this.getValue=this._getValue_unbound,this.setValue=this._setValue_unbound}static create(t,e,n){return t&&t.isAnimationObjectGroup?new Rh.Composite(t,e,n):new Rh(t,e,n)}static sanitizeNodeName(t){return t.replace(/\s/g,"_").replace(xh,"")}static parseTrackName(t){const e=Eh.exec(t);if(!e)throw new Error("PropertyBinding: Cannot parse trackName: "+t);const n={nodeName:e[2],objectName:e[3],objectIndex:e[4],propertyName:e[5],propertyIndex:e[6]},i=n.nodeName&&n.nodeName.lastIndexOf(".");if(void 0!==i&&-1!==i){const t=n.nodeName.substring(i+1);-1!==Ah.indexOf(t)&&(n.nodeName=n.nodeName.substring(0,i),n.objectName=t)}if(null===n.propertyName||0===n.propertyName.length)throw new Error("PropertyBinding: can not parse propertyName from trackName: "+t);return n}static findNode(t,e){if(!e||""===e||"."===e||-1===e||e===t.name||e===t.uuid)return t;if(t.skeleton){const n=t.skeleton.getBoneByName(e);if(void 0!==n)return n}if(t.children){const n=function(t){for(let i=0;i=r){const s=r++,c=t[s];e[c.uuid]=l,t[l]=c,e[o]=s,t[s]=a;for(let t=0,e=i;t!==e;++t){const e=n[t],i=e[s],r=e[l];e[l]=i,e[s]=r}}}this.nCachedObjects_=r}uncache(){const t=this._objects,e=this._indicesByUUID,n=this._bindings,i=n.length;let r=this.nCachedObjects_,s=t.length;for(let a=0,o=arguments.length;a!==o;++a){const o=arguments[a].uuid,l=e[o];if(void 0!==l)if(delete e[o],l0&&(e[a.uuid]=l),t[l]=a,t.pop();for(let t=0,e=i;t!==e;++t){const e=n[t];e[l]=e[r],e.pop()}}}this.nCachedObjects_=r}subscribe_(t,e){const n=this._bindingsIndicesByPath;let i=n[t];const r=this._bindings;if(void 0!==i)return r[i];const s=this._paths,a=this._parsedPaths,o=this._objects,l=o.length,c=this.nCachedObjects_,h=new Array(l);i=r.length,n[t]=i,s.push(t),a.push(e),r.push(h);for(let n=c,i=o.length;n!==i;++n){const i=o[n];h[n]=new Rh(i,t,e)}return h}unsubscribe_(t){const e=this._bindingsIndicesByPath,n=e[t];if(void 0!==n){const i=this._paths,r=this._parsedPaths,s=this._bindings,a=s.length-1,o=s[a];e[t[a]]=n,s[n]=o,s.pop(),r[n]=r[a],r.pop(),i[n]=i[a],i.pop()}}}Lh.prototype.isAnimationObjectGroup=!0;class Ch{constructor(t,e,n=null,i=e.blendMode){this._mixer=t,this._clip=e,this._localRoot=n,this.blendMode=i;const r=e.tracks,s=r.length,a=new Array(s),o={endingStart:it,endingEnd:it};for(let t=0;t!==s;++t){const e=r[t].createInterpolant(null);a[t]=e,e.settings=o}this._interpolantSettings=o,this._interpolants=a,this._propertyBindings=new Array(s),this._cacheIndex=null,this._byClipCacheIndex=null,this._timeScaleInterpolant=null,this._weightInterpolant=null,this.loop=2201,this._loopCount=-1,this._startTime=null,this.time=0,this.timeScale=1,this._effectiveTimeScale=1,this.weight=1,this._effectiveWeight=1,this.repetitions=1/0,this.paused=!1,this.enabled=!0,this.clampWhenFinished=!1,this.zeroSlopeAtStart=!0,this.zeroSlopeAtEnd=!0}play(){return this._mixer._activateAction(this),this}stop(){return this._mixer._deactivateAction(this),this.reset()}reset(){return this.paused=!1,this.enabled=!0,this.time=0,this._loopCount=-1,this._startTime=null,this.stopFading().stopWarping()}isRunning(){return this.enabled&&!this.paused&&0!==this.timeScale&&null===this._startTime&&this._mixer._isActiveAction(this)}isScheduled(){return this._mixer._isActiveAction(this)}startAt(t){return this._startTime=t,this}setLoop(t,e){return this.loop=t,this.repetitions=e,this}setEffectiveWeight(t){return this.weight=t,this._effectiveWeight=this.enabled?t:0,this.stopFading()}getEffectiveWeight(){return this._effectiveWeight}fadeIn(t){return this._scheduleFading(t,0,1)}fadeOut(t){return this._scheduleFading(t,1,0)}crossFadeFrom(t,e,n){if(t.fadeOut(e),this.fadeIn(e),n){const n=this._clip.duration,i=t._clip.duration,r=i/n,s=n/i;t.warp(1,r,e),this.warp(s,1,e)}return this}crossFadeTo(t,e,n){return t.crossFadeFrom(this,e,n)}stopFading(){const t=this._weightInterpolant;return null!==t&&(this._weightInterpolant=null,this._mixer._takeBackControlInterpolant(t)),this}setEffectiveTimeScale(t){return this.timeScale=t,this._effectiveTimeScale=this.paused?0:t,this.stopWarping()}getEffectiveTimeScale(){return this._effectiveTimeScale}setDuration(t){return this.timeScale=this._clip.duration/t,this.stopWarping()}syncWith(t){return this.time=t.time,this.timeScale=t.timeScale,this.stopWarping()}halt(t){return this.warp(this._effectiveTimeScale,0,t)}warp(t,e,n){const i=this._mixer,r=i.time,s=this.timeScale;let a=this._timeScaleInterpolant;null===a&&(a=i._lendControlInterpolant(),this._timeScaleInterpolant=a);const o=a.parameterPositions,l=a.sampleValues;return o[0]=r,o[1]=r+n,l[0]=t/s,l[1]=e/s,this}stopWarping(){const t=this._timeScaleInterpolant;return null!==t&&(this._timeScaleInterpolant=null,this._mixer._takeBackControlInterpolant(t)),this}getMixer(){return this._mixer}getClip(){return this._clip}getRoot(){return this._localRoot||this._mixer._root}_update(t,e,n,i){if(!this.enabled)return void this._updateWeight(t);const r=this._startTime;if(null!==r){const i=(t-r)*n;if(i<0||0===n)return;this._startTime=null,e=n*i}e*=this._updateTimeScale(t);const s=this._updateTime(e),a=this._updateWeight(t);if(a>0){const t=this._interpolants,e=this._propertyBindings;if(this.blendMode===ot)for(let n=0,i=t.length;n!==i;++n)t[n].evaluate(s),e[n].accumulateAdditive(a);else for(let n=0,r=t.length;n!==r;++n)t[n].evaluate(s),e[n].accumulate(i,a)}}_updateWeight(t){let e=0;if(this.enabled){e=this.weight;const n=this._weightInterpolant;if(null!==n){const i=n.evaluate(t)[0];e*=i,t>n.parameterPositions[1]&&(this.stopFading(),0===i&&(this.enabled=!1))}}return this._effectiveWeight=e,e}_updateTimeScale(t){let e=0;if(!this.paused){e=this.timeScale;const n=this._timeScaleInterpolant;if(null!==n){e*=n.evaluate(t)[0],t>n.parameterPositions[1]&&(this.stopWarping(),0===e?this.paused=!0:this.timeScale=e)}}return this._effectiveTimeScale=e,e}_updateTime(t){const e=this._clip.duration,n=this.loop;let i=this.time+t,r=this._loopCount;const s=2202===n;if(0===t)return-1===r?i:s&&1==(1&r)?e-i:i;if(2200===n){-1===r&&(this._loopCount=0,this._setEndings(!0,!0,!1));t:{if(i>=e)i=e;else{if(!(i<0)){this.time=i;break t}i=0}this.clampWhenFinished?this.paused=!0:this.enabled=!1,this.time=i,this._mixer.dispatchEvent({type:"finished",action:this,direction:t<0?-1:1})}}else{if(-1===r&&(t>=0?(r=0,this._setEndings(!0,0===this.repetitions,s)):this._setEndings(0===this.repetitions,!0,s)),i>=e||i<0){const n=Math.floor(i/e);i-=e*n,r+=Math.abs(n);const a=this.repetitions-r;if(a<=0)this.clampWhenFinished?this.paused=!0:this.enabled=!1,i=t>0?e:0,this.time=i,this._mixer.dispatchEvent({type:"finished",action:this,direction:t>0?1:-1});else{if(1===a){const e=t<0;this._setEndings(e,!e,s)}else this._setEndings(!1,!1,s);this._loopCount=r,this.time=i,this._mixer.dispatchEvent({type:"loop",action:this,loopDelta:n})}}else this.time=i;if(s&&1==(1&r))return e-i}return i}_setEndings(t,e,n){const i=this._interpolantSettings;n?(i.endingStart=rt,i.endingEnd=rt):(i.endingStart=t?this.zeroSlopeAtStart?rt:it:st,i.endingEnd=e?this.zeroSlopeAtEnd?rt:it:st)}_scheduleFading(t,e,n){const i=this._mixer,r=i.time;let s=this._weightInterpolant;null===s&&(s=i._lendControlInterpolant(),this._weightInterpolant=s);const a=s.parameterPositions,o=s.sampleValues;return a[0]=r,o[0]=e,a[1]=r+t,o[1]=n,this}}class Ph extends gt{constructor(t){super(),this._root=t,this._initMemoryManager(),this._accuIndex=0,this.time=0,this.timeScale=1}_bindAction(t,e){const n=t._localRoot||this._root,i=t._clip.tracks,r=i.length,s=t._propertyBindings,a=t._interpolants,o=n.uuid,l=this._bindingsByRootAndName;let c=l[o];void 0===c&&(c={},l[o]=c);for(let t=0;t!==r;++t){const r=i[t],l=r.name;let h=c[l];if(void 0!==h)++h.referenceCount,s[t]=h;else{if(h=s[t],void 0!==h){null===h._cacheIndex&&(++h.referenceCount,this._addInactiveBinding(h,o,l));continue}const i=e&&e._propertyBindings[t].binding.parsedPath;h=new vh(Rh.create(n,l,i),r.ValueTypeName,r.getValueSize()),++h.referenceCount,this._addInactiveBinding(h,o,l),s[t]=h}a[t].resultBuffer=h.buffer}}_activateAction(t){if(!this._isActiveAction(t)){if(null===t._cacheIndex){const e=(t._localRoot||this._root).uuid,n=t._clip.uuid,i=this._actionsByClip[n];this._bindAction(t,i&&i.knownActions[0]),this._addInactiveAction(t,n,e)}const e=t._propertyBindings;for(let t=0,n=e.length;t!==n;++t){const n=e[t];0==n.useCount++&&(this._lendBinding(n),n.saveOriginalState())}this._lendAction(t)}}_deactivateAction(t){if(this._isActiveAction(t)){const e=t._propertyBindings;for(let t=0,n=e.length;t!==n;++t){const n=e[t];0==--n.useCount&&(n.restoreOriginalState(),this._takeBackBinding(n))}this._takeBackAction(t)}}_initMemoryManager(){this._actions=[],this._nActiveActions=0,this._actionsByClip={},this._bindings=[],this._nActiveBindings=0,this._bindingsByRootAndName={},this._controlInterpolants=[],this._nActiveControlInterpolants=0;const t=this;this.stats={actions:{get total(){return t._actions.length},get inUse(){return t._nActiveActions}},bindings:{get total(){return t._bindings.length},get inUse(){return t._nActiveBindings}},controlInterpolants:{get total(){return t._controlInterpolants.length},get inUse(){return t._nActiveControlInterpolants}}}}_isActiveAction(t){const e=t._cacheIndex;return null!==e&&e=0;--e)t[e].stop();return this}update(t){t*=this.timeScale;const e=this._actions,n=this._nActiveActions,i=this.time+=t,r=Math.sign(t),s=this._accuIndex^=1;for(let a=0;a!==n;++a){e[a]._update(i,t,r,s)}const a=this._bindings,o=this._nActiveBindings;for(let t=0;t!==o;++t)a[t].apply(s);return this}setTime(t){this.time=0;for(let t=0;tthis.max.x||t.ythis.max.y)}containsBox(t){return this.min.x<=t.min.x&&t.max.x<=this.max.x&&this.min.y<=t.min.y&&t.max.y<=this.max.y}getParameter(t,e){return e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y))}intersectsBox(t){return!(t.max.xthis.max.x||t.max.ythis.max.y)}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return Oh.copy(t).clamp(this.min,this.max).sub(t).length()}intersect(t){return this.min.max(t.min),this.max.min(t.max),this}union(t){return this.min.min(t.min),this.max.max(t.max),this}translate(t){return this.min.add(t),this.max.add(t),this}equals(t){return t.min.equals(this.min)&&t.max.equals(this.max)}}Fh.prototype.isBox2=!0;const Uh=new Qt,Hh=new Qt;class Gh{constructor(t=new Qt,e=new Qt){this.start=t,this.end=e}set(t,e){return this.start.copy(t),this.end.copy(e),this}copy(t){return this.start.copy(t.start),this.end.copy(t.end),this}getCenter(t){return t.addVectors(this.start,this.end).multiplyScalar(.5)}delta(t){return t.subVectors(this.end,this.start)}distanceSq(){return this.start.distanceToSquared(this.end)}distance(){return this.start.distanceTo(this.end)}at(t,e){return this.delta(e).multiplyScalar(t).add(this.start)}closestPointToPointParameter(t,e){Uh.subVectors(t,this.start),Hh.subVectors(this.end,this.start);const n=Hh.dot(Hh);let i=Hh.dot(Uh)/n;return e&&(i=Mt(i,0,1)),i}closestPointToPoint(t,e,n){const i=this.closestPointToPointParameter(t,e);return this.delta(n).multiplyScalar(i).add(this.start)}applyMatrix4(t){return this.start.applyMatrix4(t),this.end.applyMatrix4(t),this}equals(t){return t.start.equals(this.start)&&t.end.equals(this.end)}clone(){return(new this.constructor).copy(this)}}const kh=new Qt;const Vh=new Qt,Wh=new Le,jh=new Le;class qh extends oo{constructor(t){const e=Xh(t),n=new zn,i=[],r=[],s=new Gt(0,0,1),a=new Gt(0,1,0);for(let t=0;t.99999)this.quaternion.set(0,0,0,1);else if(t.y<-.99999)this.quaternion.set(1,0,0,0);else{au.set(t.z,0,-t.x).normalize();const e=Math.acos(t.y);this.quaternion.setFromAxisAngle(au,e)}}setLength(t,e=.2*t,n=.2*e){this.line.scale.set(1,Math.max(1e-4,t-e),1),this.line.updateMatrix(),this.cone.scale.set(n,e,n),this.cone.position.y=t,this.cone.updateMatrix()}setColor(t){this.line.material.color.set(t),this.cone.material.color.set(t)}copy(t){return super.copy(t,!1),this.line.copy(t.line),this.cone.copy(t.cone),this}},t.Audio=uh,t.AudioAnalyser=gh,t.AudioContext=Qc,t.AudioListener=class extends tn{constructor(){super(),this.type="AudioListener",this.context=Qc.getContext(),this.gain=this.context.createGain(),this.gain.connect(this.context.destination),this.filter=null,this.timeDelta=0,this._clock=new sh}getInput(){return this.gain}removeFilter(){return null!==this.filter&&(this.gain.disconnect(this.filter),this.filter.disconnect(this.context.destination),this.gain.connect(this.context.destination),this.filter=null),this}getFilter(){return this.filter}setFilter(t){return null!==this.filter?(this.gain.disconnect(this.filter),this.filter.disconnect(this.context.destination)):this.gain.disconnect(this.context.destination),this.filter=t,this.gain.connect(this.filter),this.filter.connect(this.context.destination),this}getMasterVolume(){return this.gain.gain.value}setMasterVolume(t){return this.gain.gain.setTargetAtTime(t,this.context.currentTime,.01),this}updateMatrixWorld(t){super.updateMatrixWorld(t);const e=this.context.listener,n=this.up;if(this.timeDelta=this._clock.getDelta(),this.matrixWorld.decompose(oh,lh,ch),hh.set(0,0,-1).applyQuaternion(lh),e.positionX){const t=this.context.currentTime+this.timeDelta;e.positionX.linearRampToValueAtTime(oh.x,t),e.positionY.linearRampToValueAtTime(oh.y,t),e.positionZ.linearRampToValueAtTime(oh.z,t),e.forwardX.linearRampToValueAtTime(hh.x,t),e.forwardY.linearRampToValueAtTime(hh.y,t),e.forwardZ.linearRampToValueAtTime(hh.z,t),e.upX.linearRampToValueAtTime(n.x,t),e.upY.linearRampToValueAtTime(n.y,t),e.upZ.linearRampToValueAtTime(n.z,t)}else e.setPosition(oh.x,oh.y,oh.z),e.setOrientation(hh.x,hh.y,hh.z,n.x,n.y,n.z)}},t.AudioLoader=$c,t.AxesHelper=cu,t.AxisHelper=function(t){return console.warn("THREE.AxisHelper has been renamed to THREE.AxesHelper."),new cu(t)},t.BackSide=1,t.BasicDepthPacking=3200,t.BasicShadowMap=0,t.BinaryTextureLoader=function(t){return console.warn("THREE.BinaryTextureLoader has been renamed to THREE.DataTextureLoader."),new Mc(t)},t.Bone=Ga,t.BooleanKeyframeTrack=sc,t.BoundingBoxHelper=function(t,e){return console.warn("THREE.BoundingBoxHelper has been deprecated. Creating a THREE.BoxHelper instead."),new su(t,e)},t.Box2=Fh,t.Box3=ee,t.Box3Helper=class extends oo{constructor(t,e=16776960){const n=new Uint16Array([0,1,1,2,2,3,3,0,4,5,5,6,6,7,7,4,0,4,1,5,2,6,3,7]),i=new zn;i.setIndex(new yn(n,1)),i.setAttribute("position",new An([1,1,1,-1,1,1,-1,-1,1,1,-1,1,1,1,-1,-1,1,-1,-1,-1,-1,1,-1,-1],3)),super(i,new Qa({color:e,toneMapped:!1})),this.box=t,this.type="Box3Helper",this.geometry.computeBoundingSphere()}updateMatrixWorld(t){const e=this.box;e.isEmpty()||(e.getCenter(this.position),e.getSize(this.scale),this.scale.multiplyScalar(.5),super.updateMatrixWorld(t))}},t.BoxBufferGeometry=ni,t.BoxGeometry=ni,t.BoxHelper=su,t.BufferAttribute=yn,t.BufferGeometry=zn,t.BufferGeometryLoader=qc,t.ByteType=1010,t.Cache=mc,t.Camera=oi,t.CameraHelper=class extends oo{constructor(t){const e=new zn,n=new Qa({color:16777215,vertexColors:!0,toneMapped:!1}),i=[],r=[],s={},a=new Gt(16755200),o=new Gt(16711680),l=new Gt(43775),c=new Gt(16777215),h=new Gt(3355443);function u(t,e,n){d(t,n),d(e,n)}function d(t,e){i.push(0,0,0),r.push(e.r,e.g,e.b),void 0===s[t]&&(s[t]=[]),s[t].push(i.length/3-1)}u("n1","n2",a),u("n2","n4",a),u("n4","n3",a),u("n3","n1",a),u("f1","f2",a),u("f2","f4",a),u("f4","f3",a),u("f3","f1",a),u("n1","f1",a),u("n2","f2",a),u("n3","f3",a),u("n4","f4",a),u("p","n1",o),u("p","n2",o),u("p","n3",o),u("p","n4",o),u("u1","u2",l),u("u2","u3",l),u("u3","u1",l),u("c","t",c),u("p","c",h),u("cn1","cn2",h),u("cn3","cn4",h),u("cf1","cf2",h),u("cf3","cf4",h),e.setAttribute("position",new An(i,3)),e.setAttribute("color",new An(r,3)),super(e,n),this.type="CameraHelper",this.camera=t,this.camera.updateProjectionMatrix&&this.camera.updateProjectionMatrix(),this.matrix=t.matrixWorld,this.matrixAutoUpdate=!1,this.pointMap=s,this.update()}update(){const t=this.geometry,e=this.pointMap;nu.projectionMatrixInverse.copy(this.camera.projectionMatrixInverse),iu("c",e,t,nu,0,0,-1),iu("t",e,t,nu,0,0,1),iu("n1",e,t,nu,-1,-1,-1),iu("n2",e,t,nu,1,-1,-1),iu("n3",e,t,nu,-1,1,-1),iu("n4",e,t,nu,1,1,-1),iu("f1",e,t,nu,-1,-1,1),iu("f2",e,t,nu,1,-1,1),iu("f3",e,t,nu,-1,1,1),iu("f4",e,t,nu,1,1,1),iu("u1",e,t,nu,.7,1.1,-1),iu("u2",e,t,nu,-.7,1.1,-1),iu("u3",e,t,nu,0,2,-1),iu("cf1",e,t,nu,-1,0,1),iu("cf2",e,t,nu,1,0,1),iu("cf3",e,t,nu,0,-1,1),iu("cf4",e,t,nu,0,1,1),iu("cn1",e,t,nu,-1,0,-1),iu("cn2",e,t,nu,1,0,-1),iu("cn3",e,t,nu,0,-1,-1),iu("cn4",e,t,nu,0,1,-1),t.getAttribute("position").needsUpdate=!0}dispose(){this.geometry.dispose(),this.material.dispose()}},t.CanvasRenderer=function(){console.error("THREE.CanvasRenderer has been removed")},t.CanvasTexture=_o,t.CatmullRomCurve3=Uo,t.CineonToneMapping=3,t.CircleBufferGeometry=bo,t.CircleGeometry=bo,t.ClampToEdgeWrapping=u,t.Clock=sh,t.Color=Gt,t.ColorKeyframeTrack=ac,t.CompressedTexture=xo,t.CompressedTextureLoader=class extends vc{constructor(t){super(t)}load(t,e,n,i){const r=this,s=[],a=new xo,o=new xc(this.manager);o.setPath(this.path),o.setResponseType("arraybuffer"),o.setRequestHeader(this.requestHeader),o.setWithCredentials(r.withCredentials);let l=0;function c(c){o.load(t[c],(function(t){const n=r.parse(t,!0);s[c]={width:n.width,height:n.height,format:n.format,mipmaps:n.mipmaps},l+=1,6===l&&(1===n.mipmapCount&&(a.minFilter=g),a.image=s,a.format=n.format,a.needsUpdate=!0,e&&e(a))}),n,i)}if(Array.isArray(t))for(let e=0,n=t.length;e65504&&(console.warn("THREE.DataUtils.toHalfFloat(): value exceeds 65504."),t=65504),hu[0]=t;const e=uu[0];let n=e>>16&32768,i=e>>12&2047;const r=e>>23&255;return r<103?n:r>142?(n|=31744,n|=(255==r?0:1)&&8388607&e,n):r<113?(i|=2048,n|=(i>>114-r)+(i>>113-r&1),n):(n|=r-112<<10|i>>1,n+=1&i,n)}},t.DecrementStencilOp=7683,t.DecrementWrapStencilOp=34056,t.DefaultLoadingManager=gc,t.DepthFormat=A,t.DepthStencilFormat=R,t.DepthTexture=sa,t.DirectionalLight=Fc,t.DirectionalLightHelper=class extends tn{constructor(t,e,n){super(),this.light=t,this.light.updateMatrixWorld(),this.matrix=t.matrixWorld,this.matrixAutoUpdate=!1,this.color=n,void 0===e&&(e=1);let i=new zn;i.setAttribute("position",new An([-e,e,0,e,e,0,e,-e,0,-e,-e,0,-e,e,0],3));const r=new Qa({fog:!1,toneMapped:!1});this.lightPlane=new ro(i,r),this.add(this.lightPlane),i=new zn,i.setAttribute("position",new An([0,0,0,0,0,1],3)),this.targetLine=new ro(i,r),this.add(this.targetLine),this.update()}dispose(){this.lightPlane.geometry.dispose(),this.lightPlane.material.dispose(),this.targetLine.geometry.dispose(),this.targetLine.material.dispose()}update(){Qh.setFromMatrixPosition(this.light.matrixWorld),$h.setFromMatrixPosition(this.light.target.matrixWorld),tu.subVectors($h,Qh),this.lightPlane.lookAt($h),void 0!==this.color?(this.lightPlane.material.color.set(this.color),this.targetLine.material.color.set(this.color)):(this.lightPlane.material.color.copy(this.light.color),this.targetLine.material.color.copy(this.light.color)),this.targetLine.lookAt($h),this.targetLine.scale.z=tu.length()}},t.DiscreteInterpolant=ic,t.DodecahedronBufferGeometry=To,t.DodecahedronGeometry=To,t.DoubleSide=2,t.DstAlphaFactor=206,t.DstColorFactor=208,t.DynamicBufferAttribute=function(t,e){return console.warn("THREE.DynamicBufferAttribute has been removed. Use new THREE.BufferAttribute().setUsage( THREE.DynamicDrawUsage ) instead."),new yn(t,e).setUsage(dt)},t.DynamicCopyUsage=35050,t.DynamicDrawUsage=dt,t.DynamicReadUsage=35049,t.EdgesGeometry=Co,t.EdgesHelper=function(t,e){return console.warn("THREE.EdgesHelper has been removed. Use THREE.EdgesGeometry instead."),new oo(new Co(t.geometry),new Qa({color:void 0!==e?e:16777215}))},t.EllipseCurve=Do,t.EqualDepth=4,t.EqualStencilFunc=514,t.EquirectangularReflectionMapping=a,t.EquirectangularRefractionMapping=o,t.Euler=Ue,t.EventDispatcher=gt,t.ExtrudeBufferGeometry=Rl,t.ExtrudeGeometry=Rl,t.FaceColors=1,t.FileLoader=xc,t.FlatShading=1,t.Float16BufferAttribute=En,t.Float32Attribute=function(t,e){return console.warn("THREE.Float32Attribute has been removed. Use new THREE.Float32BufferAttribute() instead."),new An(t,e)},t.Float32BufferAttribute=An,t.Float64Attribute=function(t,e){return console.warn("THREE.Float64Attribute has been removed. Use new THREE.Float64BufferAttribute() instead."),new Rn(t,e)},t.Float64BufferAttribute=Rn,t.FloatType=M,t.Fog=ua,t.FogExp2=ha,t.Font=function(){console.error("THREE.Font has been moved to /examples/jsm/loaders/FontLoader.js")},t.FontLoader=function(){console.error("THREE.FontLoader has been moved to /examples/jsm/loaders/FontLoader.js")},t.FramebufferTexture=yo,t.FrontSide=0,t.Frustum=xi,t.GLBufferAttribute=Nh,t.GLSL1="100",t.GLSL3=pt,t.GreaterDepth=6,t.GreaterEqualDepth=5,t.GreaterEqualStencilFunc=518,t.GreaterStencilFunc=516,t.GridHelper=Kh,t.Group=na,t.HalfFloatType=w,t.HemisphereLight=Tc,t.HemisphereLightHelper=class extends tn{constructor(t,e,n){super(),this.light=t,this.light.updateMatrixWorld(),this.matrix=t.matrixWorld,this.matrixAutoUpdate=!1,this.color=n;const i=new Dl(e);i.rotateY(.5*Math.PI),this.material=new fn({wireframe:!0,fog:!1,toneMapped:!1}),void 0===this.color&&(this.material.vertexColors=!0);const r=i.getAttribute("position"),s=new Float32Array(3*r.count);i.setAttribute("color",new yn(s,3)),this.add(new ti(i,this.material)),this.update()}dispose(){this.children[0].geometry.dispose(),this.children[0].material.dispose()}update(){const t=this.children[0];if(void 0!==this.color)this.material.color.set(this.color);else{const e=t.geometry.getAttribute("color");Yh.copy(this.light.color),Zh.copy(this.light.groundColor);for(let t=0,n=e.count;t0){const n=new fc(e);r=new _c(n),r.setCrossOrigin(this.crossOrigin);for(let e=0,n=t.length;e0){i=new _c(this.manager),i.setCrossOrigin(this.crossOrigin);for(let e=0,i=t.length;eNumber.EPSILON){if(l<0&&(n=e[s],o=-o,a=e[r],l=-l),t.ya.y)continue;if(t.y===n.y){if(t.x===n.x)return!0}else{const e=l*(t.x-n.x)-o*(t.y-n.y);if(0===e)return!0;if(e<0)continue;i=!i}}else{if(t.y!==n.y)continue;if(a.x<=t.x&&t.x<=n.x||n.x<=t.x&&t.x<=a.x)return!0}}return i}const r=Tl.isClockWise,s=this.subPaths;if(0===s.length)return[];if(!0===e)return n(s);let a,o,l;const c=[];if(1===s.length)return o=s[0],l=new $o,l.curves=o.curves,c.push(l),c;let h=!r(s[0].getPoints());h=t?!h:h;const u=[],d=[];let p,m,f=[],g=0;d[g]=void 0,f[g]=[];for(let e=0,n=s.length;e1){let t=!1;const e=[];for(let t=0,e=d.length;t0&&(t||(f=u))}for(let t=0,e=d.length;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; - h1 = Math.imul( h1 ^ ch, 2654435761 ); +} - h2 = Math.imul( h2 ^ ch, 1597334677 ); +function SRGBToLinear( c ) { - } + return ( c < 0.04045 ) ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 ); - h1 = Math.imul( h1 ^ ( h1 >>> 16 ), 2246822507 ) ^ Math.imul( h2 ^ ( h2 >>> 13 ), 3266489909 ); +} - h2 = Math.imul( h2 ^ ( h2 >>> 16 ), 2246822507 ) ^ Math.imul( h1 ^ ( h1 >>> 13 ), 3266489909 ); +function LinearToSRGB( c ) { - return 4294967296 * ( 2097151 & h2 ) + ( h1 >>> 0 ); + return ( c < 0.0031308 ) ? c * 12.92 : 1.055 * ( Math.pow( c, 0.41666 ) ) - 0.055; } -let _canvas; - -class ImageUtils { +class Color { - static getDataURL( image ) { + constructor( r, g, b ) { - if ( /^data:/i.test( image.src ) ) { + if ( g === undefined && b === undefined ) { - return image.src; + // r is THREE.Color, hex or string + return this.set( r ); } - if ( typeof HTMLCanvasElement == 'undefined' ) { + return this.setRGB( r, g, b ); - return image.src; + } - } + set( value ) { - let canvas; + if ( value && value.isColor ) { - if ( image instanceof HTMLCanvasElement ) { + this.copy( value ); - canvas = image; + } else if ( typeof value === 'number' ) { - } else { + this.setHex( value ); - if ( _canvas === undefined ) _canvas = createElementNS( 'canvas' ); + } else if ( typeof value === 'string' ) { - _canvas.width = image.width; - _canvas.height = image.height; + this.setStyle( value ); - const context = _canvas.getContext( '2d' ); + } - if ( image instanceof ImageData ) { + return this; - context.putImageData( image, 0, 0 ); + } - } else { + setScalar( scalar ) { - context.drawImage( image, 0, 0, image.width, image.height ); + this.r = scalar; + this.g = scalar; + this.b = scalar; - } + return this; - canvas = _canvas; + } - } + setHex( hex ) { - if ( canvas.width > 2048 || canvas.height > 2048 ) { + hex = Math.floor( hex ); - console.warn( 'THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons', image ); + this.r = ( hex >> 16 & 255 ) / 255; + this.g = ( hex >> 8 & 255 ) / 255; + this.b = ( hex & 255 ) / 255; - return canvas.toDataURL( 'image/jpeg', 0.6 ); + return this; - } else { + } - return canvas.toDataURL( 'image/png' ); + setRGB( r, g, b ) { - } + this.r = r; + this.g = g; + this.b = b; + + return this; } -} + setHSL( h, s, l ) { -let textureId = 0; + // h,s,l ranges are in 0.0 - 1.0 + h = euclideanModulo( h, 1 ); + s = clamp( s, 0, 1 ); + l = clamp( l, 0, 1 ); -class Texture extends EventDispatcher { + if ( s === 0 ) { - constructor( image = Texture.DEFAULT_IMAGE, mapping = Texture.DEFAULT_MAPPING, wrapS = ClampToEdgeWrapping, wrapT = ClampToEdgeWrapping, magFilter = LinearFilter, minFilter = LinearMipmapLinearFilter, format = RGBAFormat, type = UnsignedByteType, anisotropy = 1, encoding = LinearEncoding ) { + this.r = this.g = this.b = l; - super(); + } else { - Object.defineProperty( this, 'id', { value: textureId ++ } ); + const p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s ); + const q = ( 2 * l ) - p; - this.uuid = generateUUID(); + this.r = hue2rgb( q, p, h + 1 / 3 ); + this.g = hue2rgb( q, p, h ); + this.b = hue2rgb( q, p, h - 1 / 3 ); - this.name = ''; + } - this.image = image; - this.mipmaps = []; + return this; - this.mapping = mapping; + } - this.wrapS = wrapS; - this.wrapT = wrapT; + setStyle( style ) { - this.magFilter = magFilter; - this.minFilter = minFilter; + function handleAlpha( string ) { - this.anisotropy = anisotropy; + if ( string === undefined ) return; - this.format = format; - this.internalFormat = null; - this.type = type; + if ( parseFloat( string ) < 1 ) { - this.offset = new Vector2( 0, 0 ); - this.repeat = new Vector2( 1, 1 ); - this.center = new Vector2( 0, 0 ); - this.rotation = 0; + console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' ); - this.matrixAutoUpdate = true; - this.matrix = new Matrix3(); + } - this.generateMipmaps = true; - this.premultiplyAlpha = false; - this.flipY = true; - this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml) + } - // Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap. - // - // Also changing the encoding after already used by a Material will not automatically make the Material - // update. You need to explicitly call Material.needsUpdate to trigger it to recompile. - this.encoding = encoding; - this.userData = {}; + let m; - this.version = 0; - this.onUpdate = null; + if ( m = /^((?:rgb|hsl)a?)\(([^\)]*)\)/.exec( style ) ) { - this.isRenderTargetTexture = false; + // rgb / hsl - } + let color; + const name = m[ 1 ]; + const components = m[ 2 ]; - updateMatrix() { + switch ( name ) { - this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y ); + case 'rgb': + case 'rgba': - } + if ( color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { - clone() { + // 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; - return new this.constructor().copy( this ); + handleAlpha( color[ 4 ] ); - } + return this; - copy( source ) { + } - this.name = source.name; + if ( color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { - this.image = source.image; - this.mipmaps = source.mipmaps.slice( 0 ); + // 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; - this.mapping = source.mapping; + handleAlpha( color[ 4 ] ); - this.wrapS = source.wrapS; - this.wrapT = source.wrapT; + return this; - this.magFilter = source.magFilter; - this.minFilter = source.minFilter; + } - this.anisotropy = source.anisotropy; + break; - this.format = source.format; - this.internalFormat = source.internalFormat; - this.type = source.type; + case 'hsl': + case 'hsla': - this.offset.copy( source.offset ); - this.repeat.copy( source.repeat ); - this.center.copy( source.center ); - this.rotation = source.rotation; + if ( color = /^\s*(\d*\.?\d+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { - this.matrixAutoUpdate = source.matrixAutoUpdate; - this.matrix.copy( source.matrix ); + // hsl(120,50%,50%) hsla(120,50%,50%,0.5) + const h = parseFloat( color[ 1 ] ) / 360; + const s = parseInt( color[ 2 ], 10 ) / 100; + const l = parseInt( color[ 3 ], 10 ) / 100; - this.generateMipmaps = source.generateMipmaps; - this.premultiplyAlpha = source.premultiplyAlpha; - this.flipY = source.flipY; - this.unpackAlignment = source.unpackAlignment; - this.encoding = source.encoding; + handleAlpha( color[ 4 ] ); - this.userData = JSON.parse( JSON.stringify( source.userData ) ); + return this.setHSL( h, s, l ); - return this; + } - } + break; - toJSON( meta ) { + } - const isRootObject = ( meta === undefined || typeof meta === 'string' ); + } else if ( m = /^\#([A-Fa-f\d]+)$/.exec( style ) ) { - if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) { + // hex color - return meta.textures[ this.uuid ]; + const hex = m[ 1 ]; + const size = hex.length; - } + if ( size === 3 ) { - const output = { + // #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; - metadata: { - version: 4.5, - type: 'Texture', - generator: 'Texture.toJSON' - }, + return this; - uuid: this.uuid, - name: this.name, + } else if ( size === 6 ) { - mapping: this.mapping, + // #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; - repeat: [ this.repeat.x, this.repeat.y ], - offset: [ this.offset.x, this.offset.y ], - center: [ this.center.x, this.center.y ], - rotation: this.rotation, + return this; - wrap: [ this.wrapS, this.wrapT ], + } - format: this.format, - type: this.type, - encoding: this.encoding, + } - minFilter: this.minFilter, - magFilter: this.magFilter, - anisotropy: this.anisotropy, + if ( style && style.length > 0 ) { - flipY: this.flipY, + return this.setColorName( style ); - premultiplyAlpha: this.premultiplyAlpha, - unpackAlignment: this.unpackAlignment + } - }; + return this; - if ( this.image !== undefined ) { + } - // TODO: Move to THREE.Image + setColorName( style ) { - const image = this.image; + // color keywords + const hex = _colorKeywords[ style.toLowerCase() ]; - if ( image.uuid === undefined ) { + if ( hex !== undefined ) { - image.uuid = generateUUID(); // UGH + // red + this.setHex( hex ); - } + } else { - if ( ! isRootObject && meta.images[ image.uuid ] === undefined ) { + // unknown color + console.warn( 'THREE.Color: Unknown color ' + style ); - let url; + } - if ( Array.isArray( image ) ) { + return this; - // process array of images e.g. CubeTexture + } - url = []; + clone() { - for ( let i = 0, l = image.length; i < l; i ++ ) { + return new this.constructor( this.r, this.g, this.b ); - // check cube texture with data textures + } - if ( image[ i ].isDataTexture ) { + copy( color ) { - url.push( serializeImage( image[ i ].image ) ); + this.r = color.r; + this.g = color.g; + this.b = color.b; - } else { + return this; - url.push( serializeImage( image[ i ] ) ); + } - } + copySRGBToLinear( color ) { - } + this.r = SRGBToLinear( color.r ); + this.g = SRGBToLinear( color.g ); + this.b = SRGBToLinear( color.b ); - } else { + return this; - // process single image + } - url = serializeImage( image ); + copyLinearToSRGB( color ) { - } + this.r = LinearToSRGB( color.r ); + this.g = LinearToSRGB( color.g ); + this.b = LinearToSRGB( color.b ); - meta.images[ image.uuid ] = { - uuid: image.uuid, - url: url - }; + return this; - } + } - output.image = image.uuid; + convertSRGBToLinear() { - } + this.copySRGBToLinear( this ); - if ( JSON.stringify( this.userData ) !== '{}' ) output.userData = this.userData; + return this; - if ( ! isRootObject ) { + } - meta.textures[ this.uuid ] = output; + convertLinearToSRGB() { - } + this.copyLinearToSRGB( this ); - return output; + return this; } - dispose() { + getHex() { - this.dispatchEvent( { type: 'dispose' } ); + return ( this.r * 255 ) << 16 ^ ( this.g * 255 ) << 8 ^ ( this.b * 255 ) << 0; } - transformUv( uv ) { - - if ( this.mapping !== UVMapping ) return uv; + getHexString() { - uv.applyMatrix3( this.matrix ); + return ( '000000' + this.getHex().toString( 16 ) ).slice( - 6 ); - if ( uv.x < 0 || uv.x > 1 ) { + } - switch ( this.wrapS ) { + getHSL( target ) { - case RepeatWrapping: + // h,s,l ranges are in 0.0 - 1.0 - uv.x = uv.x - Math.floor( uv.x ); - break; + const r = this.r, g = this.g, b = this.b; - case ClampToEdgeWrapping: + const max = Math.max( r, g, b ); + const min = Math.min( r, g, b ); - uv.x = uv.x < 0 ? 0 : 1; - break; + let hue, saturation; + const lightness = ( min + max ) / 2.0; - case MirroredRepeatWrapping: + if ( min === max ) { - if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) { + hue = 0; + saturation = 0; - uv.x = Math.ceil( uv.x ) - uv.x; + } else { - } else { + const delta = max - min; - uv.x = uv.x - Math.floor( uv.x ); + saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min ); - } + switch ( max ) { - break; + 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; + } - if ( uv.y < 0 || uv.y > 1 ) { + target.h = hue; + target.s = saturation; + target.l = lightness; - switch ( this.wrapT ) { + return target; - case RepeatWrapping: + } - uv.y = uv.y - Math.floor( uv.y ); - break; + getStyle() { - case ClampToEdgeWrapping: + return 'rgb(' + ( ( this.r * 255 ) | 0 ) + ',' + ( ( this.g * 255 ) | 0 ) + ',' + ( ( this.b * 255 ) | 0 ) + ')'; - uv.y = uv.y < 0 ? 0 : 1; - break; + } - case MirroredRepeatWrapping: + offsetHSL( h, s, l ) { - if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) { + this.getHSL( _hslA ); - uv.y = Math.ceil( uv.y ) - uv.y; + _hslA.h += h; _hslA.s += s; _hslA.l += l; - } else { + this.setHSL( _hslA.h, _hslA.s, _hslA.l ); - uv.y = uv.y - Math.floor( uv.y ); + return this; - } + } - break; + add( color ) { - } + this.r += color.r; + this.g += color.g; + this.b += color.b; - } + return this; - if ( this.flipY ) { + } - uv.y = 1 - uv.y; + addColors( color1, color2 ) { - } + this.r = color1.r + color2.r; + this.g = color1.g + color2.g; + this.b = color1.b + color2.b; - return uv; + return this; } - set needsUpdate( value ) { - - if ( value === true ) this.version ++; - - } + addScalar( s ) { -} + this.r += s; + this.g += s; + this.b += s; -Texture.DEFAULT_IMAGE = undefined; -Texture.DEFAULT_MAPPING = UVMapping; + return this; -Texture.prototype.isTexture = true; + } -function serializeImage( image ) { + sub( color ) { - if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || - ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || - ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { + this.r = Math.max( 0, this.r - color.r ); + this.g = Math.max( 0, this.g - color.g ); + this.b = Math.max( 0, this.b - color.b ); - // default images + return this; - return ImageUtils.getDataURL( image ); + } - } else { + multiply( color ) { - if ( image.data ) { + this.r *= color.r; + this.g *= color.g; + this.b *= color.b; - // images of DataTexture + return this; - return { - data: Array.prototype.slice.call( image.data ), - width: image.width, - height: image.height, - type: image.data.constructor.name - }; + } - } else { + multiplyScalar( s ) { - console.warn( 'THREE.Texture: Unable to serialize Texture.' ); - return {}; + this.r *= s; + this.g *= s; + this.b *= s; - } + return this; } -} + lerp( color, alpha ) { -class Vector4 { - - constructor( x = 0, y = 0, z = 0, w = 1 ) { + this.r += ( color.r - this.r ) * alpha; + this.g += ( color.g - this.g ) * alpha; + this.b += ( color.b - this.b ) * alpha; - this.x = x; - this.y = y; - this.z = z; - this.w = w; + return this; } - get width() { + lerpColors( color1, color2, alpha ) { - return this.z; + this.r = color1.r + ( color2.r - color1.r ) * alpha; + this.g = color1.g + ( color2.g - color1.g ) * alpha; + this.b = color1.b + ( color2.b - color1.b ) * alpha; + + return this; } - set width( value ) { + lerpHSL( color, alpha ) { - this.z = value; + this.getHSL( _hslA ); + color.getHSL( _hslB ); - } + const h = lerp( _hslA.h, _hslB.h, alpha ); + const s = lerp( _hslA.s, _hslB.s, alpha ); + const l = lerp( _hslA.l, _hslB.l, alpha ); - get height() { + this.setHSL( h, s, l ); - return this.w; + return this; } - set height( value ) { + equals( c ) { - this.w = value; + return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b ); } - set( x, y, z, w ) { + fromArray( array, offset = 0 ) { - this.x = x; - this.y = y; - this.z = z; - this.w = w; + this.r = array[ offset ]; + this.g = array[ offset + 1 ]; + this.b = array[ offset + 2 ]; return this; } - setScalar( scalar ) { + toArray( array = [], offset = 0 ) { - this.x = scalar; - this.y = scalar; - this.z = scalar; - this.w = scalar; + array[ offset ] = this.r; + array[ offset + 1 ] = this.g; + array[ offset + 2 ] = this.b; - return this; + return array; } - setX( x ) { + fromBufferAttribute( attribute, index ) { - this.x = x; + this.r = attribute.getX( index ); + this.g = attribute.getY( index ); + this.b = attribute.getZ( index ); - return this; + if ( attribute.normalized === true ) { - } + // assuming Uint8Array - setY( y ) { + this.r /= 255; + this.g /= 255; + this.b /= 255; - this.y = y; + } return this; } - setZ( z ) { - - this.z = z; + toJSON() { - return this; + return this.getHex(); } - setW( w ) { +} - this.w = w; +Color.NAMES = _colorKeywords; - return this; +Color.prototype.isColor = true; +Color.prototype.r = 1; +Color.prototype.g = 1; +Color.prototype.b = 1; - } +let _canvas; - setComponent( index, value ) { +class ImageUtils { - switch ( index ) { + static getDataURL( image ) { - 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 ); + if ( /^data:/i.test( image.src ) ) { - } + return image.src; - return this; + } - } + if ( typeof HTMLCanvasElement == 'undefined' ) { - getComponent( index ) { + return image.src; - 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 ); + let canvas; - } + if ( image instanceof HTMLCanvasElement ) { - } + canvas = image; - clone() { + } else { - return new this.constructor( this.x, this.y, this.z, this.w ); + if ( _canvas === undefined ) _canvas = createElementNS( 'canvas' ); - } + _canvas.width = image.width; + _canvas.height = image.height; - copy( v ) { + const context = _canvas.getContext( '2d' ); - this.x = v.x; - this.y = v.y; - this.z = v.z; - this.w = ( v.w !== undefined ) ? v.w : 1; + if ( image instanceof ImageData ) { - return this; + context.putImageData( image, 0, 0 ); - } + } else { - add( v, w ) { + context.drawImage( image, 0, 0, image.width, image.height ); - if ( w !== undefined ) { + } - console.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' ); - return this.addVectors( v, w ); + canvas = _canvas; } - this.x += v.x; - this.y += v.y; - this.z += v.z; - this.w += v.w; + if ( canvas.width > 2048 || canvas.height > 2048 ) { - return this; + console.warn( 'THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons', image ); - } + return canvas.toDataURL( 'image/jpeg', 0.6 ); - addScalar( s ) { + } else { - this.x += s; - this.y += s; - this.z += s; - this.w += s; + return canvas.toDataURL( 'image/png' ); - return this; + } } - addVectors( 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; + static sRGBToLinear( image ) { - return this; + if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || + ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || + ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { - } + const canvas = createElementNS( 'canvas' ); - addScaledVector( v, s ) { + canvas.width = image.width; + canvas.height = image.height; - this.x += v.x * s; - this.y += v.y * s; - this.z += v.z * s; - this.w += v.w * s; + const context = canvas.getContext( '2d' ); + context.drawImage( image, 0, 0, image.width, image.height ); - return this; + const imageData = context.getImageData( 0, 0, image.width, image.height ); + const data = imageData.data; - } + for ( let i = 0; i < data.length; i ++ ) { - sub( v, w ) { + data[ i ] = SRGBToLinear( data[ i ] / 255 ) * 255; - if ( w !== undefined ) { + } - console.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' ); - return this.subVectors( v, w ); + context.putImageData( imageData, 0, 0 ); - } + return canvas; - this.x -= v.x; - this.y -= v.y; - this.z -= v.z; - this.w -= v.w; + } else if ( image.data ) { - return this; + const data = image.data.slice( 0 ); - } + for ( let i = 0; i < data.length; i ++ ) { - subScalar( s ) { + if ( data instanceof Uint8Array || data instanceof Uint8ClampedArray ) { - this.x -= s; - this.y -= s; - this.z -= s; - this.w -= s; + data[ i ] = Math.floor( SRGBToLinear( data[ i ] / 255 ) * 255 ); - return this; + } else { - } + // assuming float - subVectors( a, b ) { + data[ i ] = SRGBToLinear( data[ i ] ); - 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; + } - } + return { + data: data, + width: image.width, + height: image.height + }; - multiply( v ) { + } else { - this.x *= v.x; - this.y *= v.y; - this.z *= v.z; - this.w *= v.w; + console.warn( 'THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.' ); + return image; - return this; + } } - multiplyScalar( scalar ) { +} - this.x *= scalar; - this.y *= scalar; - this.z *= scalar; - this.w *= scalar; +let textureId = 0; - return this; +class Texture extends EventDispatcher { - } + constructor( image = Texture.DEFAULT_IMAGE, mapping = Texture.DEFAULT_MAPPING, wrapS = ClampToEdgeWrapping, wrapT = ClampToEdgeWrapping, magFilter = LinearFilter, minFilter = LinearMipmapLinearFilter, format = RGBAFormat, type = UnsignedByteType, anisotropy = 1, encoding = LinearEncoding ) { - applyMatrix4( m ) { + super(); - const x = this.x, y = this.y, z = this.z, w = this.w; - const e = m.elements; + Object.defineProperty( this, 'id', { value: textureId ++ } ); - 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; + this.uuid = generateUUID(); - return this; + this.name = ''; - } + this.image = image; + this.mipmaps = []; - divideScalar( scalar ) { + this.mapping = mapping; - return this.multiplyScalar( 1 / scalar ); + this.wrapS = wrapS; + this.wrapT = wrapT; - } + this.magFilter = magFilter; + this.minFilter = minFilter; - setAxisAngleFromQuaternion( q ) { + this.anisotropy = anisotropy; - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm + this.format = format; + this.internalFormat = null; + this.type = type; - // q is assumed to be normalized + this.offset = new Vector2( 0, 0 ); + this.repeat = new Vector2( 1, 1 ); + this.center = new Vector2( 0, 0 ); + this.rotation = 0; - this.w = 2 * Math.acos( q.w ); + this.matrixAutoUpdate = true; + this.matrix = new Matrix3(); - const s = Math.sqrt( 1 - q.w * q.w ); + this.generateMipmaps = true; + this.premultiplyAlpha = false; + this.flipY = true; + this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml) - if ( s < 0.0001 ) { + // Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap. + // + // Also changing the encoding after already used by a Material will not automatically make the Material + // update. You need to explicitly call Material.needsUpdate to trigger it to recompile. + this.encoding = encoding; - this.x = 1; - this.y = 0; - this.z = 0; + this.userData = {}; - } else { + this.version = 0; + this.onUpdate = null; - this.x = q.x / s; - this.y = q.y / s; - this.z = q.z / s; + this.isRenderTargetTexture = false; // indicates whether a texture belongs to a render target or not + this.needsPMREMUpdate = false; // indicates whether this texture should be processed by PMREMGenerator or not (only relevant for render target textures) - } + } - return this; + updateMatrix() { + + this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y ); } - setAxisAngleFromRotationMatrix( m ) { + clone() { - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm + return new this.constructor().copy( this ); - // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) + } - let angle, x, y, z; // variables for result - const epsilon = 0.01, // margin to allow for rounding errors - epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees + copy( source ) { - te = m.elements, + this.name = source.name; - 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 ]; + this.image = source.image; + this.mipmaps = source.mipmaps.slice( 0 ); - if ( ( Math.abs( m12 - m21 ) < epsilon ) && - ( Math.abs( m13 - m31 ) < epsilon ) && - ( Math.abs( m23 - m32 ) < epsilon ) ) { + this.mapping = source.mapping; - // singularity found - // first check for identity matrix which must have +1 for all terms - // in leading diagonal and zero in other terms + this.wrapS = source.wrapS; + this.wrapT = source.wrapT; - if ( ( Math.abs( m12 + m21 ) < epsilon2 ) && - ( Math.abs( m13 + m31 ) < epsilon2 ) && - ( Math.abs( m23 + m32 ) < epsilon2 ) && - ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) { + this.magFilter = source.magFilter; + this.minFilter = source.minFilter; - // this singularity is identity matrix so angle = 0 + this.anisotropy = source.anisotropy; - this.set( 1, 0, 0, 0 ); + this.format = source.format; + this.internalFormat = source.internalFormat; + this.type = source.type; - return this; // zero angle, arbitrary axis + this.offset.copy( source.offset ); + this.repeat.copy( source.repeat ); + this.center.copy( source.center ); + this.rotation = source.rotation; - } + this.matrixAutoUpdate = source.matrixAutoUpdate; + this.matrix.copy( source.matrix ); - // otherwise this singularity is angle = 180 + this.generateMipmaps = source.generateMipmaps; + this.premultiplyAlpha = source.premultiplyAlpha; + this.flipY = source.flipY; + this.unpackAlignment = source.unpackAlignment; + this.encoding = source.encoding; - angle = Math.PI; + this.userData = JSON.parse( JSON.stringify( source.userData ) ); - const xx = ( m11 + 1 ) / 2; - const yy = ( m22 + 1 ) / 2; - const zz = ( m33 + 1 ) / 2; - const xy = ( m12 + m21 ) / 4; - const xz = ( m13 + m31 ) / 4; - const yz = ( m23 + m32 ) / 4; + return this; - if ( ( xx > yy ) && ( xx > zz ) ) { + } - // m11 is the largest diagonal term + toJSON( meta ) { - if ( xx < epsilon ) { + const isRootObject = ( meta === undefined || typeof meta === 'string' ); - x = 0; - y = 0.707106781; - z = 0.707106781; + if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) { - } else { + return meta.textures[ this.uuid ]; - x = Math.sqrt( xx ); - y = xy / x; - z = xz / x; + } - } + const output = { - } else if ( yy > zz ) { + metadata: { + version: 4.5, + type: 'Texture', + generator: 'Texture.toJSON' + }, - // m22 is the largest diagonal term + uuid: this.uuid, + name: this.name, - if ( yy < epsilon ) { + mapping: this.mapping, - x = 0.707106781; - y = 0; - z = 0.707106781; + repeat: [ this.repeat.x, this.repeat.y ], + offset: [ this.offset.x, this.offset.y ], + center: [ this.center.x, this.center.y ], + rotation: this.rotation, - } else { + wrap: [ this.wrapS, this.wrapT ], - y = Math.sqrt( yy ); - x = xy / y; - z = yz / y; + format: this.format, + type: this.type, + encoding: this.encoding, - } + minFilter: this.minFilter, + magFilter: this.magFilter, + anisotropy: this.anisotropy, - } else { + flipY: this.flipY, - // m33 is the largest diagonal term so base result on this + premultiplyAlpha: this.premultiplyAlpha, + unpackAlignment: this.unpackAlignment - if ( zz < epsilon ) { + }; - x = 0.707106781; - y = 0.707106781; - z = 0; + if ( this.image !== undefined ) { - } else { + // TODO: Move to THREE.Image - z = Math.sqrt( zz ); - x = xz / z; - y = yz / z; + const image = this.image; - } + if ( image.uuid === undefined ) { + + image.uuid = generateUUID(); // UGH } - this.set( x, y, z, angle ); + if ( ! isRootObject && meta.images[ image.uuid ] === undefined ) { - return this; // return 180 deg rotation + let url; - } + if ( Array.isArray( image ) ) { - // as we have reached here there are no singularities so we can handle normally + // process array of images e.g. CubeTexture - let s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) + - ( m13 - m31 ) * ( m13 - m31 ) + - ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize + url = []; - if ( Math.abs( s ) < 0.001 ) s = 1; + for ( let i = 0, l = image.length; i < l; i ++ ) { - // prevent divide by zero, should not happen if matrix is orthogonal and should be - // caught by singularity test above, but I've left it in just in case + // check cube texture with data textures - this.x = ( m32 - m23 ) / s; - this.y = ( m13 - m31 ) / s; - this.z = ( m21 - m12 ) / s; - this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 ); + if ( image[ i ].isDataTexture ) { - return this; + url.push( serializeImage( image[ i ].image ) ); - } + } else { - min( v ) { + url.push( serializeImage( image[ i ] ) ); - this.x = Math.min( this.x, v.x ); - this.y = Math.min( this.y, v.y ); - this.z = Math.min( this.z, v.z ); - this.w = Math.min( this.w, v.w ); + } - return this; + } - } + } else { - max( v ) { + // process single image - this.x = Math.max( this.x, v.x ); - this.y = Math.max( this.y, v.y ); - this.z = Math.max( this.z, v.z ); - this.w = Math.max( this.w, v.w ); + url = serializeImage( image ); - return this; + } - } + meta.images[ image.uuid ] = { + uuid: image.uuid, + url: url + }; - clamp( min, max ) { + } - // assumes min < max, componentwise + output.image = image.uuid; - 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 ) ); - this.w = Math.max( min.w, Math.min( max.w, this.w ) ); + } - return this; + if ( JSON.stringify( this.userData ) !== '{}' ) output.userData = this.userData; - } + if ( ! isRootObject ) { - clampScalar( minVal, maxVal ) { + meta.textures[ this.uuid ] = output; - this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); - this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); - this.z = Math.max( minVal, Math.min( maxVal, this.z ) ); - this.w = Math.max( minVal, Math.min( maxVal, this.w ) ); + } - return this; + return output; } - clampLength( min, max ) { - - const length = this.length(); + dispose() { - return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); + this.dispatchEvent( { type: 'dispose' } ); } - floor() { + transformUv( uv ) { - this.x = Math.floor( this.x ); - this.y = Math.floor( this.y ); - this.z = Math.floor( this.z ); - this.w = Math.floor( this.w ); + if ( this.mapping !== UVMapping ) return uv; - return this; + uv.applyMatrix3( this.matrix ); - } + if ( uv.x < 0 || uv.x > 1 ) { - ceil() { + switch ( this.wrapS ) { - this.x = Math.ceil( this.x ); - this.y = Math.ceil( this.y ); - this.z = Math.ceil( this.z ); - this.w = Math.ceil( this.w ); + case RepeatWrapping: - return this; + uv.x = uv.x - Math.floor( uv.x ); + break; - } + case ClampToEdgeWrapping: - round() { + uv.x = uv.x < 0 ? 0 : 1; + break; - this.x = Math.round( this.x ); - this.y = Math.round( this.y ); - this.z = Math.round( this.z ); - this.w = Math.round( this.w ); + case MirroredRepeatWrapping: - return this; + if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) { - } + uv.x = Math.ceil( uv.x ) - uv.x; - roundToZero() { + } else { - 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 ); - this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w ); + uv.x = uv.x - Math.floor( uv.x ); - return this; + } - } + break; - negate() { + } - this.x = - this.x; - this.y = - this.y; - this.z = - this.z; - this.w = - this.w; + } - return this; + if ( uv.y < 0 || uv.y > 1 ) { - } + switch ( this.wrapT ) { - dot( v ) { + case RepeatWrapping: - return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w; + uv.y = uv.y - Math.floor( uv.y ); + break; - } + case ClampToEdgeWrapping: - lengthSq() { + uv.y = uv.y < 0 ? 0 : 1; + break; - return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; + case MirroredRepeatWrapping: - } + if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) { - length() { + uv.y = Math.ceil( uv.y ) - uv.y; - return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w ); + } else { - } + uv.y = uv.y - Math.floor( uv.y ); - manhattanLength() { + } - return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w ); + break; - } + } - normalize() { + } - return this.divideScalar( this.length() || 1 ); + if ( this.flipY ) { - } + uv.y = 1 - uv.y; - setLength( length ) { + } - return this.normalize().multiplyScalar( length ); + return uv; } - lerp( v, alpha ) { - - this.x += ( v.x - this.x ) * alpha; - this.y += ( v.y - this.y ) * alpha; - this.z += ( v.z - this.z ) * alpha; - this.w += ( v.w - this.w ) * alpha; + set needsUpdate( value ) { - return this; + if ( value === true ) this.version ++; } - lerpVectors( v1, v2, alpha ) { +} - this.x = v1.x + ( v2.x - v1.x ) * alpha; - this.y = v1.y + ( v2.y - v1.y ) * alpha; - this.z = v1.z + ( v2.z - v1.z ) * alpha; - this.w = v1.w + ( v2.w - v1.w ) * alpha; +Texture.DEFAULT_IMAGE = undefined; +Texture.DEFAULT_MAPPING = UVMapping; - return this; +Texture.prototype.isTexture = true; - } +function serializeImage( image ) { - equals( v ) { + if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || + ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || + ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { - return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) ); + // default images - } + return ImageUtils.getDataURL( image ); - fromArray( array, offset = 0 ) { + } else { - this.x = array[ offset ]; - this.y = array[ offset + 1 ]; - this.z = array[ offset + 2 ]; - this.w = array[ offset + 3 ]; + if ( image.data ) { - return this; + // images of DataTexture - } + return { + data: Array.prototype.slice.call( image.data ), + width: image.width, + height: image.height, + type: image.data.constructor.name + }; - toArray( array = [], offset = 0 ) { + } else { - array[ offset ] = this.x; - array[ offset + 1 ] = this.y; - array[ offset + 2 ] = this.z; - array[ offset + 3 ] = this.w; + console.warn( 'THREE.Texture: Unable to serialize Texture.' ); + return {}; - return array; + } } - fromBufferAttribute( attribute, index, offset ) { - - if ( offset !== undefined ) { - - console.warn( 'THREE.Vector4: offset has been removed from .fromBufferAttribute().' ); +} - } +class Vector4 { - this.x = attribute.getX( index ); - this.y = attribute.getY( index ); - this.z = attribute.getZ( index ); - this.w = attribute.getW( index ); + constructor( x = 0, y = 0, z = 0, w = 1 ) { - return this; + this.x = x; + this.y = y; + this.z = z; + this.w = w; } - random() { - - this.x = Math.random(); - this.y = Math.random(); - this.z = Math.random(); - this.w = Math.random(); + get width() { - return this; + return this.z; } - *[ Symbol.iterator ]() { + set width( value ) { - yield this.x; - yield this.y; - yield this.z; - yield this.w; + this.z = value; } -} + get height() { -Vector4.prototype.isVector4 = true; + return this.w; -/* - In options, we can specify: - * Texture parameters for an auto-generated target texture - * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers -*/ -class WebGLRenderTarget extends EventDispatcher { + } - constructor( width, height, options = {} ) { + set height( value ) { - super(); + this.w = value; - this.width = width; - this.height = height; - this.depth = 1; + } - this.scissor = new Vector4( 0, 0, width, height ); - this.scissorTest = false; + set( x, y, z, w ) { - this.viewport = new Vector4( 0, 0, width, height ); + this.x = x; + this.y = y; + this.z = z; + this.w = w; - this.texture = new Texture( undefined, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding ); - this.texture.isRenderTargetTexture = true; + return this; - this.texture.image = { width: width, height: height, depth: 1 }; + } - this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false; - this.texture.internalFormat = options.internalFormat !== undefined ? options.internalFormat : null; - this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter; + setScalar( scalar ) { - this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true; - this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : false; - this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null; + this.x = scalar; + this.y = scalar; + this.z = scalar; + this.w = scalar; + + return this; } - setTexture( texture ) { + setX( x ) { - texture.image = { - width: this.width, - height: this.height, - depth: this.depth - }; + this.x = x; - this.texture = texture; + return this; } - setSize( width, height, depth = 1 ) { + setY( y ) { - if ( this.width !== width || this.height !== height || this.depth !== depth ) { + this.y = y; - this.width = width; - this.height = height; - this.depth = depth; + return this; - this.texture.image.width = width; - this.texture.image.height = height; - this.texture.image.depth = depth; + } - this.dispose(); + setZ( z ) { - } + this.z = z; - this.viewport.set( 0, 0, width, height ); - this.scissor.set( 0, 0, width, height ); + return this; } - clone() { + setW( w ) { - return new this.constructor().copy( this ); + this.w = w; - } + return this; - copy( source ) { + } - this.width = source.width; - this.height = source.height; - this.depth = source.depth; + setComponent( index, value ) { - this.viewport.copy( source.viewport ); + switch ( index ) { - this.texture = source.texture.clone(); - this.texture.image = { ...this.texture.image }; // See #20328. + 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 ); - this.depthBuffer = source.depthBuffer; - this.stencilBuffer = source.stencilBuffer; - this.depthTexture = source.depthTexture; + } return this; } - dispose() { + getComponent( index ) { - this.dispatchEvent( { type: 'dispose' } ); + 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() { -WebGLRenderTarget.prototype.isWebGLRenderTarget = true; + return new this.constructor( this.x, this.y, this.z, this.w ); -class WebGLMultipleRenderTargets extends WebGLRenderTarget { + } - constructor( width, height, count ) { + copy( v ) { - super( width, height ); + this.x = v.x; + this.y = v.y; + this.z = v.z; + this.w = ( v.w !== undefined ) ? v.w : 1; - const texture = this.texture; + return this; - this.texture = []; + } - for ( let i = 0; i < count; i ++ ) { + add( v, w ) { - this.texture[ i ] = texture.clone(); + if ( w !== undefined ) { + + console.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' ); + return this.addVectors( v, w ); } + this.x += v.x; + this.y += v.y; + this.z += v.z; + this.w += v.w; + + return this; + } - setSize( width, height, depth = 1 ) { + addScalar( s ) { - if ( this.width !== width || this.height !== height || this.depth !== depth ) { + this.x += s; + this.y += s; + this.z += s; + this.w += s; - this.width = width; - this.height = height; - this.depth = depth; + return this; - for ( let i = 0, il = this.texture.length; i < il; i ++ ) { + } - this.texture[ i ].image.width = width; - this.texture[ i ].image.height = height; - this.texture[ i ].image.depth = depth; + addVectors( 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; - this.dispose(); + return this; - } + } - this.viewport.set( 0, 0, width, height ); - this.scissor.set( 0, 0, width, height ); + addScaledVector( v, s ) { + + this.x += v.x * s; + this.y += v.y * s; + this.z += v.z * s; + this.w += v.w * s; return this; } - copy( source ) { + sub( v, w ) { - this.dispose(); + if ( w !== undefined ) { - this.width = source.width; - this.height = source.height; - this.depth = source.depth; + console.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' ); + return this.subVectors( v, w ); - this.viewport.set( 0, 0, this.width, this.height ); - this.scissor.set( 0, 0, this.width, this.height ); + } - this.depthBuffer = source.depthBuffer; - this.stencilBuffer = source.stencilBuffer; - this.depthTexture = source.depthTexture; + this.x -= v.x; + this.y -= v.y; + this.z -= v.z; + this.w -= v.w; - this.texture.length = 0; + return this; - for ( let i = 0, il = source.texture.length; i < il; i ++ ) { + } - this.texture[ i ] = source.texture[ i ].clone(); + subScalar( s ) { - } + this.x -= s; + this.y -= s; + this.z -= s; + this.w -= s; return this; } -} + subVectors( a, b ) { -WebGLMultipleRenderTargets.prototype.isWebGLMultipleRenderTargets = true; + this.x = a.x - b.x; + this.y = a.y - b.y; + this.z = a.z - b.z; + this.w = a.w - b.w; -class WebGLMultisampleRenderTarget extends WebGLRenderTarget { + return this; - constructor( width, height, options = {} ) { + } - super( width, height, options ); + multiply( v ) { - this.samples = 4; + this.x *= v.x; + this.y *= v.y; + this.z *= v.z; + this.w *= v.w; - this.ignoreDepthForMultisampleCopy = options.ignoreDepth !== undefined ? options.ignoreDepth : true; - this.useRenderToTexture = ( options.useRenderToTexture !== undefined ) ? options.useRenderToTexture : false; - this.useRenderbuffer = this.useRenderToTexture === false; + return this; } - copy( source ) { - - super.copy.call( this, source ); + multiplyScalar( scalar ) { - this.samples = source.samples; - this.useRenderToTexture = source.useRenderToTexture; - this.useRenderbuffer = source.useRenderbuffer; + this.x *= scalar; + this.y *= scalar; + this.z *= scalar; + this.w *= scalar; return this; } -} - -WebGLMultisampleRenderTarget.prototype.isWebGLMultisampleRenderTarget = true; + applyMatrix4( m ) { -class Quaternion { + const x = this.x, y = this.y, z = this.z, w = this.w; + const e = m.elements; - constructor( x = 0, y = 0, z = 0, w = 1 ) { + 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; - this._x = x; - this._y = y; - this._z = z; - this._w = w; + return this; } - static slerp( qa, qb, qm, t ) { + divideScalar( scalar ) { - console.warn( 'THREE.Quaternion: Static .slerp() has been deprecated. Use qm.slerpQuaternions( qa, qb, t ) instead.' ); - return qm.slerpQuaternions( qa, qb, t ); + return this.multiplyScalar( 1 / scalar ); } - static slerpFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) { + setAxisAngleFromQuaternion( q ) { - // fuzz-free, array-based Quaternion SLERP operation + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm - let x0 = src0[ srcOffset0 + 0 ], - y0 = src0[ srcOffset0 + 1 ], - z0 = src0[ srcOffset0 + 2 ], - w0 = src0[ srcOffset0 + 3 ]; + // q is assumed to be normalized - const x1 = src1[ srcOffset1 + 0 ], - y1 = src1[ srcOffset1 + 1 ], - z1 = src1[ srcOffset1 + 2 ], - w1 = src1[ srcOffset1 + 3 ]; + this.w = 2 * Math.acos( q.w ); - if ( t === 0 ) { + const s = Math.sqrt( 1 - q.w * q.w ); - dst[ dstOffset + 0 ] = x0; - dst[ dstOffset + 1 ] = y0; - dst[ dstOffset + 2 ] = z0; - dst[ dstOffset + 3 ] = w0; - return; + if ( s < 0.0001 ) { - } + this.x = 1; + this.y = 0; + this.z = 0; - if ( t === 1 ) { + } else { - dst[ dstOffset + 0 ] = x1; - dst[ dstOffset + 1 ] = y1; - dst[ dstOffset + 2 ] = z1; - dst[ dstOffset + 3 ] = w1; - return; + this.x = q.x / s; + this.y = q.y / s; + this.z = q.z / s; } - if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) { - - let s = 1 - t; - const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1, - dir = ( cos >= 0 ? 1 : - 1 ), - sqrSin = 1 - cos * cos; - - // Skip the Slerp for tiny steps to avoid numeric problems: - if ( sqrSin > Number.EPSILON ) { + return this; - const sin = Math.sqrt( sqrSin ), - len = Math.atan2( sin, cos * dir ); + } - s = Math.sin( s * len ) / sin; - t = Math.sin( t * len ) / sin; + setAxisAngleFromRotationMatrix( m ) { - } + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm - const tDir = t * dir; + // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - x0 = x0 * s + x1 * tDir; - y0 = y0 * s + y1 * tDir; - z0 = z0 * s + z1 * tDir; - w0 = w0 * s + w1 * tDir; + let angle, x, y, z; // variables for result + const epsilon = 0.01, // margin to allow for rounding errors + epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees - // Normalize in case we just did a lerp: - if ( s === 1 - t ) { + te = m.elements, - const f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 ); + 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 ]; - x0 *= f; - y0 *= f; - z0 *= f; - w0 *= f; + 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 - } - - dst[ dstOffset ] = x0; - dst[ dstOffset + 1 ] = y0; - dst[ dstOffset + 2 ] = z0; - dst[ dstOffset + 3 ] = w0; + 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 - static multiplyQuaternionsFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) { + this.set( 1, 0, 0, 0 ); - const x0 = src0[ srcOffset0 ]; - const y0 = src0[ srcOffset0 + 1 ]; - const z0 = src0[ srcOffset0 + 2 ]; - const w0 = src0[ srcOffset0 + 3 ]; + return this; // zero angle, arbitrary axis - const x1 = src1[ srcOffset1 ]; - const y1 = src1[ srcOffset1 + 1 ]; - const z1 = src1[ srcOffset1 + 2 ]; - const w1 = src1[ srcOffset1 + 3 ]; + } - dst[ dstOffset ] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1; - dst[ dstOffset + 1 ] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1; - dst[ dstOffset + 2 ] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1; - dst[ dstOffset + 3 ] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1; + // otherwise this singularity is angle = 180 - return dst; + angle = Math.PI; - } + const xx = ( m11 + 1 ) / 2; + const yy = ( m22 + 1 ) / 2; + const zz = ( m33 + 1 ) / 2; + const xy = ( m12 + m21 ) / 4; + const xz = ( m13 + m31 ) / 4; + const yz = ( m23 + m32 ) / 4; - get x() { + if ( ( xx > yy ) && ( xx > zz ) ) { - return this._x; + // m11 is the largest diagonal term - } + if ( xx < epsilon ) { - set x( value ) { + x = 0; + y = 0.707106781; + z = 0.707106781; - this._x = value; - this._onChangeCallback(); + } else { - } + x = Math.sqrt( xx ); + y = xy / x; + z = xz / x; - get y() { + } - return this._y; + } else if ( yy > zz ) { - } + // m22 is the largest diagonal term - set y( value ) { + if ( yy < epsilon ) { - this._y = value; - this._onChangeCallback(); + x = 0.707106781; + y = 0; + z = 0.707106781; - } + } else { - get z() { + y = Math.sqrt( yy ); + x = xy / y; + z = yz / y; - return this._z; + } - } + } else { - set z( value ) { + // m33 is the largest diagonal term so base result on this - this._z = value; - this._onChangeCallback(); + if ( zz < epsilon ) { - } + x = 0.707106781; + y = 0.707106781; + z = 0; - get w() { + } else { - return this._w; + z = Math.sqrt( zz ); + x = xz / z; + y = yz / z; - } + } - set w( value ) { + } - this._w = value; - this._onChangeCallback(); + this.set( x, y, z, angle ); - } + return this; // return 180 deg rotation - set( x, y, z, w ) { + } - this._x = x; - this._y = y; - this._z = z; - this._w = w; + // as we have reached here there are no singularities so we can handle normally - this._onChangeCallback(); + let s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) + + ( m13 - m31 ) * ( m13 - m31 ) + + ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize - return this; + if ( Math.abs( s ) < 0.001 ) s = 1; - } + // prevent divide by zero, should not happen if matrix is orthogonal and should be + // caught by singularity test above, but I've left it in just in case - clone() { + this.x = ( m32 - m23 ) / s; + this.y = ( m13 - m31 ) / s; + this.z = ( m21 - m12 ) / s; + this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 ); - return new this.constructor( this._x, this._y, this._z, this._w ); + return this; } - copy( quaternion ) { - - this._x = quaternion.x; - this._y = quaternion.y; - this._z = quaternion.z; - this._w = quaternion.w; + min( v ) { - this._onChangeCallback(); + this.x = Math.min( this.x, v.x ); + this.y = Math.min( this.y, v.y ); + this.z = Math.min( this.z, v.z ); + this.w = Math.min( this.w, v.w ); return this; } - setFromEuler( euler, update ) { + max( v ) { - if ( ! ( euler && euler.isEuler ) ) { + this.x = Math.max( this.x, v.x ); + this.y = Math.max( this.y, v.y ); + this.z = Math.max( this.z, v.z ); + this.w = Math.max( this.w, v.w ); - throw new Error( 'THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.' ); + return this; - } + } - const x = euler._x, y = euler._y, z = euler._z, order = euler._order; + clamp( min, max ) { - // http://www.mathworks.com/matlabcentral/fileexchange/ - // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/ - // content/SpinCalc.m + // assumes min < max, componentwise - const cos = Math.cos; - const sin = Math.sin; + 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 ) ); + this.w = Math.max( min.w, Math.min( max.w, this.w ) ); - const c1 = cos( x / 2 ); - const c2 = cos( y / 2 ); - const c3 = cos( z / 2 ); + return this; - const s1 = sin( x / 2 ); - const s2 = sin( y / 2 ); - const s3 = sin( z / 2 ); + } - switch ( order ) { + clampScalar( minVal, maxVal ) { - case 'XYZ': - this._x = s1 * c2 * c3 + c1 * s2 * s3; - this._y = c1 * s2 * c3 - s1 * c2 * s3; - this._z = c1 * c2 * s3 + s1 * s2 * c3; - this._w = c1 * c2 * c3 - s1 * s2 * s3; - break; + this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); + this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); + this.z = Math.max( minVal, Math.min( maxVal, this.z ) ); + this.w = Math.max( minVal, Math.min( maxVal, this.w ) ); - case 'YXZ': - this._x = s1 * c2 * c3 + c1 * s2 * s3; - this._y = c1 * s2 * c3 - s1 * c2 * s3; - this._z = c1 * c2 * s3 - s1 * s2 * c3; - this._w = c1 * c2 * c3 + s1 * s2 * s3; - break; + return this; - case 'ZXY': - this._x = s1 * c2 * c3 - c1 * s2 * s3; - this._y = c1 * s2 * c3 + s1 * c2 * s3; - this._z = c1 * c2 * s3 + s1 * s2 * c3; - this._w = c1 * c2 * c3 - s1 * s2 * s3; - break; + } - case 'ZYX': - this._x = s1 * c2 * c3 - c1 * s2 * s3; - this._y = c1 * s2 * c3 + s1 * c2 * s3; - this._z = c1 * c2 * s3 - s1 * s2 * c3; - this._w = c1 * c2 * c3 + s1 * s2 * s3; - break; + clampLength( min, max ) { - case 'YZX': - this._x = s1 * c2 * c3 + c1 * s2 * s3; - this._y = c1 * s2 * c3 + s1 * c2 * s3; - this._z = c1 * c2 * s3 - s1 * s2 * c3; - this._w = c1 * c2 * c3 - s1 * s2 * s3; - break; + const length = this.length(); - case 'XZY': - this._x = s1 * c2 * c3 - c1 * s2 * s3; - this._y = c1 * s2 * c3 - s1 * c2 * s3; - this._z = c1 * c2 * s3 + s1 * s2 * c3; - this._w = c1 * c2 * c3 + s1 * s2 * s3; - break; + return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); - default: - console.warn( 'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order ); + } - } + floor() { - if ( update !== false ) this._onChangeCallback(); + this.x = Math.floor( this.x ); + this.y = Math.floor( this.y ); + this.z = Math.floor( this.z ); + this.w = Math.floor( this.w ); return this; } - setFromAxisAngle( axis, angle ) { - - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm - - // assumes axis is normalized - - const halfAngle = angle / 2, s = Math.sin( halfAngle ); - - this._x = axis.x * s; - this._y = axis.y * s; - this._z = axis.z * s; - this._w = Math.cos( halfAngle ); + ceil() { - this._onChangeCallback(); + this.x = Math.ceil( this.x ); + this.y = Math.ceil( this.y ); + this.z = Math.ceil( this.z ); + this.w = Math.ceil( this.w ); return this; } - setFromRotationMatrix( m ) { - - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm + round() { - // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) + this.x = Math.round( this.x ); + this.y = Math.round( this.y ); + this.z = Math.round( this.z ); + this.w = Math.round( this.w ); - const te = m.elements, + return this; - 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 ], + } - trace = m11 + m22 + m33; + roundToZero() { - if ( trace > 0 ) { + 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 ); + this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w ); - const s = 0.5 / Math.sqrt( trace + 1.0 ); + return this; - this._w = 0.25 / s; - this._x = ( m32 - m23 ) * s; - this._y = ( m13 - m31 ) * s; - this._z = ( m21 - m12 ) * s; + } - } else if ( m11 > m22 && m11 > m33 ) { + negate() { - const s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 ); + this.x = - this.x; + this.y = - this.y; + this.z = - this.z; + this.w = - this.w; - this._w = ( m32 - m23 ) / s; - this._x = 0.25 * s; - this._y = ( m12 + m21 ) / s; - this._z = ( m13 + m31 ) / s; + return this; - } else if ( m22 > m33 ) { + } - const s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 ); + dot( v ) { - this._w = ( m13 - m31 ) / s; - this._x = ( m12 + m21 ) / s; - this._y = 0.25 * s; - this._z = ( m23 + m32 ) / s; + return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w; - } else { + } - const s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 ); + lengthSq() { - this._w = ( m21 - m12 ) / s; - this._x = ( m13 + m31 ) / s; - this._y = ( m23 + m32 ) / s; - this._z = 0.25 * s; + return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; - } + } - this._onChangeCallback(); + length() { - return this; + return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w ); } - setFromUnitVectors( vFrom, vTo ) { + manhattanLength() { - // assumes direction vectors vFrom and vTo are normalized + return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w ); - let r = vFrom.dot( vTo ) + 1; + } - if ( r < Number.EPSILON ) { + normalize() { - // vFrom and vTo point in opposite directions + return this.divideScalar( this.length() || 1 ); - r = 0; + } - if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) { + setLength( length ) { - this._x = - vFrom.y; - this._y = vFrom.x; - this._z = 0; - this._w = r; + return this.normalize().multiplyScalar( length ); - } else { + } - this._x = 0; - this._y = - vFrom.z; - this._z = vFrom.y; - this._w = r; + lerp( v, alpha ) { - } + this.x += ( v.x - this.x ) * alpha; + this.y += ( v.y - this.y ) * alpha; + this.z += ( v.z - this.z ) * alpha; + this.w += ( v.w - this.w ) * alpha; - } else { + return this; - // crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3 + } - this._x = vFrom.y * vTo.z - vFrom.z * vTo.y; - this._y = vFrom.z * vTo.x - vFrom.x * vTo.z; - this._z = vFrom.x * vTo.y - vFrom.y * vTo.x; - this._w = r; + lerpVectors( v1, v2, alpha ) { - } + this.x = v1.x + ( v2.x - v1.x ) * alpha; + this.y = v1.y + ( v2.y - v1.y ) * alpha; + this.z = v1.z + ( v2.z - v1.z ) * alpha; + this.w = v1.w + ( v2.w - v1.w ) * alpha; - return this.normalize(); + return this; } - angleTo( q ) { + equals( v ) { - return 2 * Math.acos( Math.abs( clamp( this.dot( q ), - 1, 1 ) ) ); + return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) ); } - rotateTowards( q, step ) { + fromArray( array, offset = 0 ) { - const angle = this.angleTo( q ); + this.x = array[ offset ]; + this.y = array[ offset + 1 ]; + this.z = array[ offset + 2 ]; + this.w = array[ offset + 3 ]; - if ( angle === 0 ) return this; + return this; - const t = Math.min( 1, step / angle ); + } - this.slerp( q, t ); + toArray( array = [], offset = 0 ) { - return this; + array[ offset ] = this.x; + array[ offset + 1 ] = this.y; + array[ offset + 2 ] = this.z; + array[ offset + 3 ] = this.w; + + return array; } - identity() { + fromBufferAttribute( attribute, index, offset ) { - return this.set( 0, 0, 0, 1 ); + if ( offset !== undefined ) { - } + console.warn( 'THREE.Vector4: offset has been removed from .fromBufferAttribute().' ); - invert() { + } - // quaternion is assumed to have unit length + this.x = attribute.getX( index ); + this.y = attribute.getY( index ); + this.z = attribute.getZ( index ); + this.w = attribute.getW( index ); - return this.conjugate(); + return this; } - conjugate() { - - this._x *= - 1; - this._y *= - 1; - this._z *= - 1; + random() { - this._onChangeCallback(); + this.x = Math.random(); + this.y = Math.random(); + this.z = Math.random(); + this.w = Math.random(); return this; } - dot( v ) { + *[ Symbol.iterator ]() { - return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w; + yield this.x; + yield this.y; + yield this.z; + yield this.w; } - lengthSq() { +} - return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w; +Vector4.prototype.isVector4 = true; - } +/* + In options, we can specify: + * Texture parameters for an auto-generated target texture + * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers +*/ +class WebGLRenderTarget extends EventDispatcher { - length() { + constructor( width, height, options = {} ) { - return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w ); + super(); - } + this.width = width; + this.height = height; + this.depth = 1; - normalize() { + this.scissor = new Vector4( 0, 0, width, height ); + this.scissorTest = false; - let l = this.length(); + this.viewport = new Vector4( 0, 0, width, height ); - if ( l === 0 ) { + this.texture = new Texture( undefined, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding ); + this.texture.isRenderTargetTexture = true; - this._x = 0; - this._y = 0; - this._z = 0; - this._w = 1; + this.texture.image = { width: width, height: height, depth: 1 }; - } else { + this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false; + this.texture.internalFormat = options.internalFormat !== undefined ? options.internalFormat : null; + this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter; - l = 1 / l; + this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true; + this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : false; + this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null; - this._x = this._x * l; - this._y = this._y * l; - this._z = this._z * l; - this._w = this._w * l; + } - } + setTexture( texture ) { - this._onChangeCallback(); + texture.image = { + width: this.width, + height: this.height, + depth: this.depth + }; - return this; + this.texture = texture; } - multiply( q, p ) { + setSize( width, height, depth = 1 ) { - if ( p !== undefined ) { + if ( this.width !== width || this.height !== height || this.depth !== depth ) { - console.warn( 'THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.' ); - return this.multiplyQuaternions( q, p ); + this.width = width; + this.height = height; + this.depth = depth; + + this.texture.image.width = width; + this.texture.image.height = height; + this.texture.image.depth = depth; + + this.dispose(); } - return this.multiplyQuaternions( this, q ); + this.viewport.set( 0, 0, width, height ); + this.scissor.set( 0, 0, width, height ); } - premultiply( q ) { + clone() { - return this.multiplyQuaternions( q, this ); + return new this.constructor().copy( this ); } - multiplyQuaternions( a, b ) { + copy( source ) { - // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm + this.width = source.width; + this.height = source.height; + this.depth = source.depth; - const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w; - const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w; + this.viewport.copy( source.viewport ); - this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby; - this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz; - this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx; - this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz; + this.texture = source.texture.clone(); + this.texture.image = { ...this.texture.image }; // See #20328. - this._onChangeCallback(); + this.depthBuffer = source.depthBuffer; + this.stencilBuffer = source.stencilBuffer; + this.depthTexture = source.depthTexture; return this; } - slerp( qb, t ) { + dispose() { - if ( t === 0 ) return this; - if ( t === 1 ) return this.copy( qb ); - - const x = this._x, y = this._y, z = this._z, w = this._w; - - // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/ + this.dispatchEvent( { type: 'dispose' } ); - let cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z; + } - if ( cosHalfTheta < 0 ) { +} - this._w = - qb._w; - this._x = - qb._x; - this._y = - qb._y; - this._z = - qb._z; +WebGLRenderTarget.prototype.isWebGLRenderTarget = true; - cosHalfTheta = - cosHalfTheta; +class WebGLMultipleRenderTargets extends WebGLRenderTarget { - } else { + constructor( width, height, count ) { - this.copy( qb ); + super( width, height ); - } + const texture = this.texture; - if ( cosHalfTheta >= 1.0 ) { + this.texture = []; - this._w = w; - this._x = x; - this._y = y; - this._z = z; + for ( let i = 0; i < count; i ++ ) { - return this; + this.texture[ i ] = texture.clone(); } - const sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta; + } - if ( sqrSinHalfTheta <= Number.EPSILON ) { + setSize( width, height, depth = 1 ) { - const s = 1 - t; - this._w = s * w + t * this._w; - this._x = s * x + t * this._x; - this._y = s * y + t * this._y; - this._z = s * z + t * this._z; + if ( this.width !== width || this.height !== height || this.depth !== depth ) { - this.normalize(); - this._onChangeCallback(); + this.width = width; + this.height = height; + this.depth = depth; - return this; + for ( let i = 0, il = this.texture.length; i < il; i ++ ) { - } + this.texture[ i ].image.width = width; + this.texture[ i ].image.height = height; + this.texture[ i ].image.depth = depth; - const sinHalfTheta = Math.sqrt( sqrSinHalfTheta ); - const halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta ); - const ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta, - ratioB = Math.sin( t * halfTheta ) / sinHalfTheta; + } - this._w = ( w * ratioA + this._w * ratioB ); - this._x = ( x * ratioA + this._x * ratioB ); - this._y = ( y * ratioA + this._y * ratioB ); - this._z = ( z * ratioA + this._z * ratioB ); + this.dispose(); - this._onChangeCallback(); + } + + this.viewport.set( 0, 0, width, height ); + this.scissor.set( 0, 0, width, height ); return this; } - slerpQuaternions( qa, qb, t ) { + copy( source ) { - this.copy( qa ).slerp( qb, t ); + this.dispose(); - } + this.width = source.width; + this.height = source.height; + this.depth = source.depth; - random() { + this.viewport.set( 0, 0, this.width, this.height ); + this.scissor.set( 0, 0, this.width, this.height ); - // Derived from http://planning.cs.uiuc.edu/node198.html - // Note, this source uses w, x, y, z ordering, - // so we swap the order below. + this.depthBuffer = source.depthBuffer; + this.stencilBuffer = source.stencilBuffer; + this.depthTexture = source.depthTexture; - const u1 = Math.random(); - const sqrt1u1 = Math.sqrt( 1 - u1 ); - const sqrtu1 = Math.sqrt( u1 ); + this.texture.length = 0; - const u2 = 2 * Math.PI * Math.random(); + for ( let i = 0, il = source.texture.length; i < il; i ++ ) { - const u3 = 2 * Math.PI * Math.random(); + this.texture[ i ] = source.texture[ i ].clone(); - return this.set( - sqrt1u1 * Math.cos( u2 ), - sqrtu1 * Math.sin( u3 ), - sqrtu1 * Math.cos( u3 ), - sqrt1u1 * Math.sin( u2 ), - ); + } + + return this; } - equals( quaternion ) { +} - return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w ); +WebGLMultipleRenderTargets.prototype.isWebGLMultipleRenderTargets = true; - } +class WebGLMultisampleRenderTarget extends WebGLRenderTarget { - fromArray( array, offset = 0 ) { + constructor( width, height, options = {} ) { - this._x = array[ offset ]; - this._y = array[ offset + 1 ]; - this._z = array[ offset + 2 ]; - this._w = array[ offset + 3 ]; + super( width, height, options ); - this._onChangeCallback(); + this.samples = 4; - return this; + this.ignoreDepthForMultisampleCopy = options.ignoreDepth !== undefined ? options.ignoreDepth : true; + this.useRenderToTexture = ( options.useRenderToTexture !== undefined ) ? options.useRenderToTexture : false; + this.useRenderbuffer = this.useRenderToTexture === false; } - toArray( array = [], offset = 0 ) { + copy( source ) { - array[ offset ] = this._x; - array[ offset + 1 ] = this._y; - array[ offset + 2 ] = this._z; - array[ offset + 3 ] = this._w; + super.copy.call( this, source ); - return array; + this.samples = source.samples; + this.useRenderToTexture = source.useRenderToTexture; + this.useRenderbuffer = source.useRenderbuffer; + + return this; } - fromBufferAttribute( attribute, index ) { +} - this._x = attribute.getX( index ); - this._y = attribute.getY( index ); - this._z = attribute.getZ( index ); - this._w = attribute.getW( index ); +WebGLMultisampleRenderTarget.prototype.isWebGLMultisampleRenderTarget = true; - return this; +class Quaternion { - } + constructor( x = 0, y = 0, z = 0, w = 1 ) { - _onChange( callback ) { + this._x = x; + this._y = y; + this._z = z; + this._w = w; - this._onChangeCallback = callback; + } - return this; + static slerp( qa, qb, qm, t ) { + + console.warn( 'THREE.Quaternion: Static .slerp() has been deprecated. Use qm.slerpQuaternions( qa, qb, t ) instead.' ); + return qm.slerpQuaternions( qa, qb, t ); } - _onChangeCallback() {} + static slerpFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) { -} + // fuzz-free, array-based Quaternion SLERP operation -Quaternion.prototype.isQuaternion = true; + let x0 = src0[ srcOffset0 + 0 ], + y0 = src0[ srcOffset0 + 1 ], + z0 = src0[ srcOffset0 + 2 ], + w0 = src0[ srcOffset0 + 3 ]; -class Vector3 { + const x1 = src1[ srcOffset1 + 0 ], + y1 = src1[ srcOffset1 + 1 ], + z1 = src1[ srcOffset1 + 2 ], + w1 = src1[ srcOffset1 + 3 ]; - constructor( x = 0, y = 0, z = 0 ) { + if ( t === 0 ) { - this.x = x; - this.y = y; - this.z = z; + dst[ dstOffset + 0 ] = x0; + dst[ dstOffset + 1 ] = y0; + dst[ dstOffset + 2 ] = z0; + dst[ dstOffset + 3 ] = w0; + return; - } + } - set( x, y, z ) { + if ( t === 1 ) { - if ( z === undefined ) z = this.z; // sprite.scale.set(x,y) + dst[ dstOffset + 0 ] = x1; + dst[ dstOffset + 1 ] = y1; + dst[ dstOffset + 2 ] = z1; + dst[ dstOffset + 3 ] = w1; + return; - this.x = x; - this.y = y; - this.z = z; + } - return this; + if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) { - } + let s = 1 - t; + const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1, + dir = ( cos >= 0 ? 1 : - 1 ), + sqrSin = 1 - cos * cos; - setScalar( scalar ) { + // Skip the Slerp for tiny steps to avoid numeric problems: + if ( sqrSin > Number.EPSILON ) { - this.x = scalar; - this.y = scalar; - this.z = scalar; + const sin = Math.sqrt( sqrSin ), + len = Math.atan2( sin, cos * dir ); - return this; + s = Math.sin( s * len ) / sin; + t = Math.sin( t * len ) / sin; - } + } - setX( x ) { + const tDir = t * dir; - this.x = x; + x0 = x0 * s + x1 * tDir; + y0 = y0 * s + y1 * tDir; + z0 = z0 * s + z1 * tDir; + w0 = w0 * s + w1 * tDir; - return this; + // Normalize in case we just did a lerp: + if ( s === 1 - t ) { - } + const f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 ); - setY( y ) { + x0 *= f; + y0 *= f; + z0 *= f; + w0 *= f; - this.y = y; + } - return this; + } + + dst[ dstOffset ] = x0; + dst[ dstOffset + 1 ] = y0; + dst[ dstOffset + 2 ] = z0; + dst[ dstOffset + 3 ] = w0; } - setZ( z ) { + static multiplyQuaternionsFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) { - this.z = z; + const x0 = src0[ srcOffset0 ]; + const y0 = src0[ srcOffset0 + 1 ]; + const z0 = src0[ srcOffset0 + 2 ]; + const w0 = src0[ srcOffset0 + 3 ]; - return this; + const x1 = src1[ srcOffset1 ]; + const y1 = src1[ srcOffset1 + 1 ]; + const z1 = src1[ srcOffset1 + 2 ]; + const w1 = src1[ srcOffset1 + 3 ]; + + dst[ dstOffset ] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1; + dst[ dstOffset + 1 ] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1; + dst[ dstOffset + 2 ] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1; + dst[ dstOffset + 3 ] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1; + + return dst; } - setComponent( index, value ) { + get x() { - switch ( index ) { + return this._x; - 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 ); + } - } + set x( value ) { - return this; + this._x = value; + this._onChangeCallback(); } - getComponent( index ) { + get y() { - switch ( index ) { + return this._y; - 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 ); + } - } + set y( value ) { + + this._y = value; + this._onChangeCallback(); } - clone() { + get z() { - return new this.constructor( this.x, this.y, this.z ); + return this._z; } - copy( v ) { - - this.x = v.x; - this.y = v.y; - this.z = v.z; + set z( value ) { - return this; + this._z = value; + this._onChangeCallback(); } - add( v, w ) { - - if ( w !== undefined ) { + get w() { - console.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' ); - return this.addVectors( v, w ); + return this._w; - } + } - this.x += v.x; - this.y += v.y; - this.z += v.z; + set w( value ) { - return this; + this._w = value; + this._onChangeCallback(); } - addScalar( s ) { + set( x, y, z, w ) { - this.x += s; - this.y += s; - this.z += s; + this._x = x; + this._y = y; + this._z = z; + this._w = w; + + this._onChangeCallback(); return this; } - addVectors( a, b ) { - - this.x = a.x + b.x; - this.y = a.y + b.y; - this.z = a.z + b.z; + clone() { - return this; + return new this.constructor( this._x, this._y, this._z, this._w ); } - addScaledVector( v, s ) { + copy( quaternion ) { - this.x += v.x * s; - this.y += v.y * s; - this.z += v.z * s; + this._x = quaternion.x; + this._y = quaternion.y; + this._z = quaternion.z; + this._w = quaternion.w; + + this._onChangeCallback(); return this; } - sub( v, w ) { + setFromEuler( euler, update ) { - if ( w !== undefined ) { + if ( ! ( euler && euler.isEuler ) ) { - console.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' ); - return this.subVectors( v, w ); + throw new Error( 'THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.' ); } - this.x -= v.x; - this.y -= v.y; - this.z -= v.z; - - return this; + const x = euler._x, y = euler._y, z = euler._z, order = euler._order; - } + // http://www.mathworks.com/matlabcentral/fileexchange/ + // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/ + // content/SpinCalc.m - subScalar( s ) { + const cos = Math.cos; + const sin = Math.sin; - this.x -= s; - this.y -= s; - this.z -= s; + const c1 = cos( x / 2 ); + const c2 = cos( y / 2 ); + const c3 = cos( z / 2 ); - return this; + const s1 = sin( x / 2 ); + const s2 = sin( y / 2 ); + const s3 = sin( z / 2 ); - } + switch ( order ) { - subVectors( a, b ) { + case 'XYZ': + this._x = s1 * c2 * c3 + c1 * s2 * s3; + this._y = c1 * s2 * c3 - s1 * c2 * s3; + this._z = c1 * c2 * s3 + s1 * s2 * c3; + this._w = c1 * c2 * c3 - s1 * s2 * s3; + break; - this.x = a.x - b.x; - this.y = a.y - b.y; - this.z = a.z - b.z; + case 'YXZ': + this._x = s1 * c2 * c3 + c1 * s2 * s3; + this._y = c1 * s2 * c3 - s1 * c2 * s3; + this._z = c1 * c2 * s3 - s1 * s2 * c3; + this._w = c1 * c2 * c3 + s1 * s2 * s3; + break; - return this; + case 'ZXY': + this._x = s1 * c2 * c3 - c1 * s2 * s3; + this._y = c1 * s2 * c3 + s1 * c2 * s3; + this._z = c1 * c2 * s3 + s1 * s2 * c3; + this._w = c1 * c2 * c3 - s1 * s2 * s3; + break; - } + case 'ZYX': + this._x = s1 * c2 * c3 - c1 * s2 * s3; + this._y = c1 * s2 * c3 + s1 * c2 * s3; + this._z = c1 * c2 * s3 - s1 * s2 * c3; + this._w = c1 * c2 * c3 + s1 * s2 * s3; + break; - multiply( v, w ) { + case 'YZX': + this._x = s1 * c2 * c3 + c1 * s2 * s3; + this._y = c1 * s2 * c3 + s1 * c2 * s3; + this._z = c1 * c2 * s3 - s1 * s2 * c3; + this._w = c1 * c2 * c3 - s1 * s2 * s3; + break; - if ( w !== undefined ) { + case 'XZY': + this._x = s1 * c2 * c3 - c1 * s2 * s3; + this._y = c1 * s2 * c3 - s1 * c2 * s3; + this._z = c1 * c2 * s3 + s1 * s2 * c3; + this._w = c1 * c2 * c3 + s1 * s2 * s3; + break; - console.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' ); - return this.multiplyVectors( v, w ); + default: + console.warn( 'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order ); } - this.x *= v.x; - this.y *= v.y; - this.z *= v.z; + if ( update !== false ) this._onChangeCallback(); return this; } - multiplyScalar( scalar ) { + setFromAxisAngle( axis, angle ) { - this.x *= scalar; - this.y *= scalar; - this.z *= scalar; + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm - return this; + // assumes axis is normalized - } + const halfAngle = angle / 2, s = Math.sin( halfAngle ); - multiplyVectors( a, b ) { + this._x = axis.x * s; + this._y = axis.y * s; + this._z = axis.z * s; + this._w = Math.cos( halfAngle ); - this.x = a.x * b.x; - this.y = a.y * b.y; - this.z = a.z * b.z; + this._onChangeCallback(); return this; } - applyEuler( euler ) { - - if ( ! ( euler && euler.isEuler ) ) { + setFromRotationMatrix( m ) { - console.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' ); + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm - } + // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - return this.applyQuaternion( _quaternion$4.setFromEuler( euler ) ); + const 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 ], - applyAxisAngle( axis, angle ) { + trace = m11 + m22 + m33; - return this.applyQuaternion( _quaternion$4.setFromAxisAngle( axis, angle ) ); + if ( trace > 0 ) { - } + const s = 0.5 / Math.sqrt( trace + 1.0 ); - applyMatrix3( m ) { + this._w = 0.25 / s; + this._x = ( m32 - m23 ) * s; + this._y = ( m13 - m31 ) * s; + this._z = ( m21 - m12 ) * s; - const x = this.x, y = this.y, z = this.z; - const e = m.elements; + } else if ( m11 > m22 && m11 > m33 ) { - 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; + const s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 ); - return this; + this._w = ( m32 - m23 ) / s; + this._x = 0.25 * s; + this._y = ( m12 + m21 ) / s; + this._z = ( m13 + m31 ) / s; - } + } else if ( m22 > m33 ) { - applyNormalMatrix( m ) { + const s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 ); - return this.applyMatrix3( m ).normalize(); + this._w = ( m13 - m31 ) / s; + this._x = ( m12 + m21 ) / s; + this._y = 0.25 * s; + this._z = ( m23 + m32 ) / s; - } + } else { - applyMatrix4( m ) { + const s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 ); - const x = this.x, y = this.y, z = this.z; - const e = m.elements; + this._w = ( m21 - m12 ) / s; + this._x = ( m13 + m31 ) / s; + this._y = ( m23 + m32 ) / s; + this._z = 0.25 * s; - const w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] ); + } - 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._onChangeCallback(); return this; } - applyQuaternion( q ) { + setFromUnitVectors( vFrom, vTo ) { - const x = this.x, y = this.y, z = this.z; - const qx = q.x, qy = q.y, qz = q.z, qw = q.w; + // assumes direction vectors vFrom and vTo are normalized - // calculate quat * vector + let r = vFrom.dot( vTo ) + 1; - const ix = qw * x + qy * z - qz * y; - const iy = qw * y + qz * x - qx * z; - const iz = qw * z + qx * y - qy * x; - const iw = - qx * x - qy * y - qz * z; + if ( r < Number.EPSILON ) { - // calculate result * inverse quat + // vFrom and vTo point in opposite directions - 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; + r = 0; - return this; + if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) { - } + this._x = - vFrom.y; + this._y = vFrom.x; + this._z = 0; + this._w = r; - project( camera ) { + } else { - return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix ); + this._x = 0; + this._y = - vFrom.z; + this._z = vFrom.y; + this._w = r; - } + } - unproject( camera ) { + } else { - return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld ); + // crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3 - } + this._x = vFrom.y * vTo.z - vFrom.z * vTo.y; + this._y = vFrom.z * vTo.x - vFrom.x * vTo.z; + this._z = vFrom.x * vTo.y - vFrom.y * vTo.x; + this._w = r; - transformDirection( m ) { + } - // input: THREE.Matrix4 affine matrix - // vector interpreted as a direction + return this.normalize(); - const x = this.x, y = this.y, z = this.z; - const 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; + angleTo( q ) { - return this.normalize(); + return 2 * Math.acos( Math.abs( clamp( this.dot( q ), - 1, 1 ) ) ); } - divide( v ) { + rotateTowards( q, step ) { - this.x /= v.x; - this.y /= v.y; - this.z /= v.z; + const angle = this.angleTo( q ); - return this; + if ( angle === 0 ) return this; - } + const t = Math.min( 1, step / angle ); - divideScalar( scalar ) { + this.slerp( q, t ); - return this.multiplyScalar( 1 / scalar ); + return this; } - min( 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 ); + identity() { - return this; + return this.set( 0, 0, 0, 1 ); } - max( v ) { + invert() { - this.x = Math.max( this.x, v.x ); - this.y = Math.max( this.y, v.y ); - this.z = Math.max( this.z, v.z ); + // quaternion is assumed to have unit length - return this; + return this.conjugate(); } - clamp( min, max ) { + conjugate() { - // assumes min < max, componentwise + this._x *= - 1; + this._y *= - 1; + this._z *= - 1; - 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 ) ); + this._onChangeCallback(); return this; } - clampScalar( minVal, maxVal ) { - - this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); - this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); - this.z = Math.max( minVal, Math.min( maxVal, this.z ) ); + dot( v ) { - return this; + return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w; } - clampLength( min, max ) { - - const length = this.length(); + lengthSq() { - return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); + return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w; } - floor() { - - this.x = Math.floor( this.x ); - this.y = Math.floor( this.y ); - this.z = Math.floor( this.z ); + length() { - return this; + return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w ); } - ceil() { - - this.x = Math.ceil( this.x ); - this.y = Math.ceil( this.y ); - this.z = Math.ceil( this.z ); + normalize() { - return this; + let l = this.length(); - } + if ( l === 0 ) { - round() { + this._x = 0; + this._y = 0; + this._z = 0; + this._w = 1; - this.x = Math.round( this.x ); - this.y = Math.round( this.y ); - this.z = Math.round( this.z ); + } else { - return this; + l = 1 / l; - } + this._x = this._x * l; + this._y = this._y * l; + this._z = this._z * l; + this._w = this._w * l; - roundToZero() { + } - 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 ); + this._onChangeCallback(); return this; } - negate() { + multiply( q, p ) { - this.x = - this.x; - this.y = - this.y; - this.z = - this.z; + if ( p !== undefined ) { - return this; + console.warn( 'THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.' ); + return this.multiplyQuaternions( q, p ); + + } + + return this.multiplyQuaternions( this, q ); } - dot( v ) { + premultiply( q ) { - return this.x * v.x + this.y * v.y + this.z * v.z; + return this.multiplyQuaternions( q, this ); } - // TODO lengthSquared? + multiplyQuaternions( a, b ) { - lengthSq() { + // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm - return this.x * this.x + this.y * this.y + this.z * this.z; + const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w; + const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w; - } + this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby; + this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz; + this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx; + this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz; - length() { + this._onChangeCallback(); - return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); + return this; } - manhattanLength() { + slerp( qb, t ) { - return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ); + if ( t === 0 ) return this; + if ( t === 1 ) return this.copy( qb ); - } + const x = this._x, y = this._y, z = this._z, w = this._w; - normalize() { + // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/ - return this.divideScalar( this.length() || 1 ); + let cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z; - } + if ( cosHalfTheta < 0 ) { - setLength( length ) { + this._w = - qb._w; + this._x = - qb._x; + this._y = - qb._y; + this._z = - qb._z; - return this.normalize().multiplyScalar( length ); + cosHalfTheta = - cosHalfTheta; - } + } else { - lerp( v, alpha ) { + this.copy( qb ); - this.x += ( v.x - this.x ) * alpha; - this.y += ( v.y - this.y ) * alpha; - this.z += ( v.z - this.z ) * alpha; + } - return this; + if ( cosHalfTheta >= 1.0 ) { - } + this._w = w; + this._x = x; + this._y = y; + this._z = z; - lerpVectors( v1, v2, alpha ) { + return this; - this.x = v1.x + ( v2.x - v1.x ) * alpha; - this.y = v1.y + ( v2.y - v1.y ) * alpha; - this.z = v1.z + ( v2.z - v1.z ) * alpha; + } - return this; + const sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta; - } + if ( sqrSinHalfTheta <= Number.EPSILON ) { - cross( v, w ) { + const s = 1 - t; + this._w = s * w + t * this._w; + this._x = s * x + t * this._x; + this._y = s * y + t * this._y; + this._z = s * z + t * this._z; - if ( w !== undefined ) { + this.normalize(); + this._onChangeCallback(); - console.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' ); - return this.crossVectors( v, w ); + return this; } - return this.crossVectors( this, v ); - - } - - crossVectors( a, b ) { + const sinHalfTheta = Math.sqrt( sqrSinHalfTheta ); + const halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta ); + const ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta, + ratioB = Math.sin( t * halfTheta ) / sinHalfTheta; - const ax = a.x, ay = a.y, az = a.z; - const bx = b.x, by = b.y, bz = b.z; + this._w = ( w * ratioA + this._w * ratioB ); + this._x = ( x * ratioA + this._x * ratioB ); + this._y = ( y * ratioA + this._y * ratioB ); + this._z = ( z * ratioA + this._z * ratioB ); - this.x = ay * bz - az * by; - this.y = az * bx - ax * bz; - this.z = ax * by - ay * bx; + this._onChangeCallback(); return this; } - projectOnVector( v ) { + slerpQuaternions( qa, qb, t ) { - const denominator = v.lengthSq(); + return this.copy( qa ).slerp( qb, t ); - if ( denominator === 0 ) return this.set( 0, 0, 0 ); + } - const scalar = v.dot( this ) / denominator; + random() { - return this.copy( v ).multiplyScalar( scalar ); + // Derived from http://planning.cs.uiuc.edu/node198.html + // Note, this source uses w, x, y, z ordering, + // so we swap the order below. - } + const u1 = Math.random(); + const sqrt1u1 = Math.sqrt( 1 - u1 ); + const sqrtu1 = Math.sqrt( u1 ); - projectOnPlane( planeNormal ) { + const u2 = 2 * Math.PI * Math.random(); - _vector$c.copy( this ).projectOnVector( planeNormal ); + const u3 = 2 * Math.PI * Math.random(); - return this.sub( _vector$c ); + return this.set( + sqrt1u1 * Math.cos( u2 ), + sqrtu1 * Math.sin( u3 ), + sqrtu1 * Math.cos( u3 ), + sqrt1u1 * Math.sin( u2 ), + ); } - reflect( normal ) { - - // reflect incident vector off plane orthogonal to normal - // normal is assumed to have unit length + equals( quaternion ) { - return this.sub( _vector$c.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) ); + return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w ); } - angleTo( v ) { + fromArray( array, offset = 0 ) { - const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() ); + this._x = array[ offset ]; + this._y = array[ offset + 1 ]; + this._z = array[ offset + 2 ]; + this._w = array[ offset + 3 ]; - if ( denominator === 0 ) return Math.PI / 2; + this._onChangeCallback(); - const theta = this.dot( v ) / denominator; + return this; - // clamp, to handle numerical problems + } - return Math.acos( clamp( theta, - 1, 1 ) ); + toArray( array = [], offset = 0 ) { + + array[ offset ] = this._x; + array[ offset + 1 ] = this._y; + array[ offset + 2 ] = this._z; + array[ offset + 3 ] = this._w; + + return array; } - distanceTo( v ) { + fromBufferAttribute( attribute, index ) { - return Math.sqrt( this.distanceToSquared( v ) ); + this._x = attribute.getX( index ); + this._y = attribute.getY( index ); + this._z = attribute.getZ( index ); + this._w = attribute.getW( index ); + + return this; } - distanceToSquared( v ) { + _onChange( callback ) { - const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z; + this._onChangeCallback = callback; - return dx * dx + dy * dy + dz * dz; + return this; } - manhattanDistanceTo( v ) { + _onChangeCallback() {} - return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z ); +} - } +Quaternion.prototype.isQuaternion = true; - setFromSpherical( s ) { +class Vector3 { - return this.setFromSphericalCoords( s.radius, s.phi, s.theta ); + constructor( x = 0, y = 0, z = 0 ) { + + this.x = x; + this.y = y; + this.z = z; } - setFromSphericalCoords( radius, phi, theta ) { + set( x, y, z ) { - const sinPhiRadius = Math.sin( phi ) * radius; + if ( z === undefined ) z = this.z; // sprite.scale.set(x,y) - this.x = sinPhiRadius * Math.sin( theta ); - this.y = Math.cos( phi ) * radius; - this.z = sinPhiRadius * Math.cos( theta ); + this.x = x; + this.y = y; + this.z = z; return this; } - setFromCylindrical( c ) { + setScalar( scalar ) { - return this.setFromCylindricalCoords( c.radius, c.theta, c.y ); + this.x = scalar; + this.y = scalar; + this.z = scalar; + + return this; } - setFromCylindricalCoords( radius, theta, y ) { + setX( x ) { - this.x = radius * Math.sin( theta ); - this.y = y; - this.z = radius * Math.cos( theta ); + this.x = x; return this; } - setFromMatrixPosition( m ) { - - const e = m.elements; + setY( y ) { - this.x = e[ 12 ]; - this.y = e[ 13 ]; - this.z = e[ 14 ]; + this.y = y; return this; } - setFromMatrixScale( m ) { - - const sx = this.setFromMatrixColumn( m, 0 ).length(); - const sy = this.setFromMatrixColumn( m, 1 ).length(); - const sz = this.setFromMatrixColumn( m, 2 ).length(); + setZ( z ) { - this.x = sx; - this.y = sy; - this.z = sz; + this.z = z; return this; } - setFromMatrixColumn( m, index ) { + setComponent( index, value ) { - return this.fromArray( m.elements, index * 4 ); + 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 ); - setFromMatrix3Column( m, index ) { + } - return this.fromArray( m.elements, index * 3 ); + return this; } - equals( v ) { + getComponent( index ) { - return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) ); + 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 ); - fromArray( array, offset = 0 ) { + } - this.x = array[ offset ]; - this.y = array[ offset + 1 ]; - this.z = array[ offset + 2 ]; + } - return this; + clone() { + + return new this.constructor( this.x, this.y, this.z ); } - toArray( array = [], offset = 0 ) { + copy( v ) { - array[ offset ] = this.x; - array[ offset + 1 ] = this.y; - array[ offset + 2 ] = this.z; + this.x = v.x; + this.y = v.y; + this.z = v.z; - return array; + return this; } - fromBufferAttribute( attribute, index, offset ) { + add( v, w ) { - if ( offset !== undefined ) { + if ( w !== undefined ) { - console.warn( 'THREE.Vector3: offset has been removed from .fromBufferAttribute().' ); + console.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' ); + return this.addVectors( v, w ); } - this.x = attribute.getX( index ); - this.y = attribute.getY( index ); - this.z = attribute.getZ( index ); + this.x += v.x; + this.y += v.y; + this.z += v.z; return this; } - random() { + addScalar( s ) { - this.x = Math.random(); - this.y = Math.random(); - this.z = Math.random(); + this.x += s; + this.y += s; + this.z += s; return this; } - randomDirection() { - - // Derived from https://mathworld.wolfram.com/SpherePointPicking.html - - const u = ( Math.random() - 0.5 ) * 2; - const t = Math.random() * Math.PI * 2; - const f = Math.sqrt( 1 - u ** 2 ); + addVectors( a, b ) { - this.x = f * Math.cos( t ); - this.y = f * Math.sin( t ); - this.z = u; + this.x = a.x + b.x; + this.y = a.y + b.y; + this.z = a.z + b.z; return this; } - *[ Symbol.iterator ]() { + addScaledVector( v, s ) { - yield this.x; - yield this.y; - yield this.z; + this.x += v.x * s; + this.y += v.y * s; + this.z += v.z * s; + + return this; } -} + sub( v, w ) { -Vector3.prototype.isVector3 = true; + if ( w !== undefined ) { -const _vector$c = /*@__PURE__*/ new Vector3(); -const _quaternion$4 = /*@__PURE__*/ new Quaternion(); + console.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' ); + return this.subVectors( v, w ); -class Box3 { + } - constructor( min = new Vector3( + Infinity, + Infinity, + Infinity ), max = new Vector3( - Infinity, - Infinity, - Infinity ) ) { + this.x -= v.x; + this.y -= v.y; + this.z -= v.z; - this.min = min; - this.max = max; + return this; } - set( min, max ) { + subScalar( s ) { - this.min.copy( min ); - this.max.copy( max ); + this.x -= s; + this.y -= s; + this.z -= s; return this; } - setFromArray( array ) { + subVectors( a, b ) { - let minX = + Infinity; - let minY = + Infinity; - let minZ = + Infinity; + this.x = a.x - b.x; + this.y = a.y - b.y; + this.z = a.z - b.z; - let maxX = - Infinity; - let maxY = - Infinity; - let maxZ = - Infinity; + return this; - for ( let i = 0, l = array.length; i < l; i += 3 ) { + } - const x = array[ i ]; - const y = array[ i + 1 ]; - const z = array[ i + 2 ]; + multiply( v, w ) { - if ( x < minX ) minX = x; - if ( y < minY ) minY = y; - if ( z < minZ ) minZ = z; + if ( w !== undefined ) { - if ( x > maxX ) maxX = x; - if ( y > maxY ) maxY = y; - if ( z > maxZ ) maxZ = z; + console.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' ); + return this.multiplyVectors( v, w ); } - this.min.set( minX, minY, minZ ); - this.max.set( maxX, maxY, maxZ ); + this.x *= v.x; + this.y *= v.y; + this.z *= v.z; return this; } - setFromBufferAttribute( attribute ) { + multiplyScalar( scalar ) { - let minX = + Infinity; - let minY = + Infinity; - let minZ = + Infinity; + this.x *= scalar; + this.y *= scalar; + this.z *= scalar; - let maxX = - Infinity; - let maxY = - Infinity; - let maxZ = - Infinity; + return this; - for ( let i = 0, l = attribute.count; i < l; i ++ ) { + } - const x = attribute.getX( i ); - const y = attribute.getY( i ); - const z = attribute.getZ( i ); + multiplyVectors( a, b ) { - if ( x < minX ) minX = x; - if ( y < minY ) minY = y; - if ( z < minZ ) minZ = z; + this.x = a.x * b.x; + this.y = a.y * b.y; + this.z = a.z * b.z; - if ( x > maxX ) maxX = x; - if ( y > maxY ) maxY = y; - if ( z > maxZ ) maxZ = z; + return this; - } + } - this.min.set( minX, minY, minZ ); - this.max.set( maxX, maxY, maxZ ); + applyEuler( euler ) { - return this; + if ( ! ( euler && euler.isEuler ) ) { + + console.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' ); + + } + + return this.applyQuaternion( _quaternion$4.setFromEuler( euler ) ); } - setFromPoints( points ) { + applyAxisAngle( axis, angle ) { - this.makeEmpty(); + return this.applyQuaternion( _quaternion$4.setFromAxisAngle( axis, angle ) ); - for ( let i = 0, il = points.length; i < il; i ++ ) { + } - this.expandByPoint( points[ i ] ); + applyMatrix3( m ) { - } + const x = this.x, y = this.y, z = this.z; + const 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; } - setFromCenterAndSize( center, size ) { + applyNormalMatrix( m ) { - const halfSize = _vector$b.copy( size ).multiplyScalar( 0.5 ); + return this.applyMatrix3( m ).normalize(); - this.min.copy( center ).sub( halfSize ); - this.max.copy( center ).add( halfSize ); + } - return this; + applyMatrix4( m ) { - } + const x = this.x, y = this.y, z = this.z; + const e = m.elements; - setFromObject( object ) { + const w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] ); - this.makeEmpty(); + 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; - return this.expandByObject( object ); + return this; } - clone() { + applyQuaternion( q ) { - return new this.constructor().copy( this ); + const x = this.x, y = this.y, z = this.z; + const qx = q.x, qy = q.y, qz = q.z, qw = q.w; - } + // calculate quat * vector - copy( box ) { + const ix = qw * x + qy * z - qz * y; + const iy = qw * y + qz * x - qx * z; + const iz = qw * z + qx * y - qy * x; + const iw = - qx * x - qy * y - qz * z; - this.min.copy( box.min ); - this.max.copy( box.max ); + // 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; } - makeEmpty() { + project( camera ) { - this.min.x = this.min.y = this.min.z = + Infinity; - this.max.x = this.max.y = this.max.z = - Infinity; + return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix ); - return this; + } + + unproject( camera ) { + + return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld ); } - isEmpty() { + transformDirection( m ) { - // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes + // input: THREE.Matrix4 affine matrix + // vector interpreted as a direction - return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z ); + const x = this.x, y = this.y, z = this.z; + const 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; + + return this.normalize(); } - getCenter( target ) { + divide( v ) { - return this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 ); + this.x /= v.x; + this.y /= v.y; + this.z /= v.z; + + return this; } - getSize( target ) { + divideScalar( scalar ) { - return this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min ); + return this.multiplyScalar( 1 / scalar ); } - expandByPoint( point ) { + min( v ) { - this.min.min( point ); - this.max.max( point ); + 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; } - expandByVector( vector ) { + max( v ) { - this.min.sub( vector ); - this.max.add( vector ); + 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; } - expandByScalar( scalar ) { + clamp( min, max ) { - this.min.addScalar( - scalar ); - this.max.addScalar( scalar ); + // assumes min < max, componentwise + + 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; } - expandByObject( object ) { - - // Computes the world-axis-aligned bounding box of an object (including its children), - // accounting for both the object's, and children's, world transforms + clampScalar( minVal, maxVal ) { - object.updateWorldMatrix( false, false ); + this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); + this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); + this.z = Math.max( minVal, Math.min( maxVal, this.z ) ); - const geometry = object.geometry; + return this; - if ( geometry !== undefined ) { + } - if ( geometry.boundingBox === null ) { + clampLength( min, max ) { - geometry.computeBoundingBox(); + const length = this.length(); - } + return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); - _box$3.copy( geometry.boundingBox ); - _box$3.applyMatrix4( object.matrixWorld ); + } - this.union( _box$3 ); + floor() { - } + this.x = Math.floor( this.x ); + this.y = Math.floor( this.y ); + this.z = Math.floor( this.z ); - const children = object.children; + return this; - for ( let i = 0, l = children.length; i < l; i ++ ) { + } - this.expandByObject( children[ i ] ); + ceil() { - } + this.x = Math.ceil( this.x ); + this.y = Math.ceil( this.y ); + this.z = Math.ceil( this.z ); return this; } - containsPoint( point ) { + round() { - return point.x < this.min.x || point.x > this.max.x || - point.y < this.min.y || point.y > this.max.y || - point.z < this.min.z || point.z > this.max.z ? false : true; + this.x = Math.round( this.x ); + this.y = Math.round( this.y ); + this.z = Math.round( this.z ); + + return this; } - containsBox( box ) { + roundToZero() { - return this.min.x <= box.min.x && box.max.x <= this.max.x && - this.min.y <= box.min.y && box.max.y <= this.max.y && - this.min.z <= box.min.z && box.max.z <= this.max.z; + 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; } - getParameter( point, target ) { + negate() { - // This can potentially have a divide by zero if the box - // has a size dimension of 0. + this.x = - this.x; + this.y = - this.y; + this.z = - this.z; - return target.set( - ( point.x - this.min.x ) / ( this.max.x - this.min.x ), - ( point.y - this.min.y ) / ( this.max.y - this.min.y ), - ( point.z - this.min.z ) / ( this.max.z - this.min.z ) - ); + return this; } - intersectsBox( box ) { + dot( v ) { - // using 6 splitting planes to rule out intersections. - return box.max.x < this.min.x || box.min.x > this.max.x || - box.max.y < this.min.y || box.min.y > this.max.y || - box.max.z < this.min.z || box.min.z > this.max.z ? false : true; + return this.x * v.x + this.y * v.y + this.z * v.z; } - intersectsSphere( sphere ) { + // TODO lengthSquared? - // Find the point on the AABB closest to the sphere center. - this.clampPoint( sphere.center, _vector$b ); + lengthSq() { - // If that point is inside the sphere, the AABB and sphere intersect. - return _vector$b.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius ); + return this.x * this.x + this.y * this.y + this.z * this.z; } - intersectsPlane( plane ) { + length() { - // We compute the minimum and maximum dot product values. If those values - // are on the same side (back or front) of the plane, then there is no intersection. + return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); - let min, max; + } - if ( plane.normal.x > 0 ) { + manhattanLength() { - min = plane.normal.x * this.min.x; - max = plane.normal.x * this.max.x; + return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ); - } else { + } - min = plane.normal.x * this.max.x; - max = plane.normal.x * this.min.x; + normalize() { - } + return this.divideScalar( this.length() || 1 ); - if ( plane.normal.y > 0 ) { + } - min += plane.normal.y * this.min.y; - max += plane.normal.y * this.max.y; + setLength( length ) { - } else { + return this.normalize().multiplyScalar( length ); - min += plane.normal.y * this.max.y; - max += plane.normal.y * this.min.y; + } - } + lerp( v, alpha ) { - if ( plane.normal.z > 0 ) { + this.x += ( v.x - this.x ) * alpha; + this.y += ( v.y - this.y ) * alpha; + this.z += ( v.z - this.z ) * alpha; - min += plane.normal.z * this.min.z; - max += plane.normal.z * this.max.z; + return this; - } else { + } - min += plane.normal.z * this.max.z; - max += plane.normal.z * this.min.z; + lerpVectors( v1, v2, alpha ) { - } + this.x = v1.x + ( v2.x - v1.x ) * alpha; + this.y = v1.y + ( v2.y - v1.y ) * alpha; + this.z = v1.z + ( v2.z - v1.z ) * alpha; - return ( min <= - plane.constant && max >= - plane.constant ); + return this; } - intersectsTriangle( triangle ) { + cross( v, w ) { - if ( this.isEmpty() ) { + if ( w !== undefined ) { - return false; + console.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' ); + return this.crossVectors( v, w ); } - // compute box center and extents - this.getCenter( _center ); - _extents.subVectors( this.max, _center ); + return this.crossVectors( this, v ); - // translate triangle to aabb origin - _v0$2.subVectors( triangle.a, _center ); - _v1$7.subVectors( triangle.b, _center ); - _v2$3.subVectors( triangle.c, _center ); + } - // compute edge vectors for triangle - _f0.subVectors( _v1$7, _v0$2 ); - _f1.subVectors( _v2$3, _v1$7 ); - _f2.subVectors( _v0$2, _v2$3 ); + crossVectors( a, b ) { - // test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb - // make an axis testing of each of the 3 sides of the aabb against each of the 3 sides of the triangle = 9 axis of separation - // axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned) - let axes = [ - 0, - _f0.z, _f0.y, 0, - _f1.z, _f1.y, 0, - _f2.z, _f2.y, - _f0.z, 0, - _f0.x, _f1.z, 0, - _f1.x, _f2.z, 0, - _f2.x, - - _f0.y, _f0.x, 0, - _f1.y, _f1.x, 0, - _f2.y, _f2.x, 0 - ]; - if ( ! satForAxes( axes, _v0$2, _v1$7, _v2$3, _extents ) ) { + const ax = a.x, ay = a.y, az = a.z; + const bx = b.x, by = b.y, bz = b.z; - return false; + this.x = ay * bz - az * by; + this.y = az * bx - ax * bz; + this.z = ax * by - ay * bx; - } + return this; - // test 3 face normals from the aabb - axes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ]; - if ( ! satForAxes( axes, _v0$2, _v1$7, _v2$3, _extents ) ) { + } - return false; + projectOnVector( v ) { - } + const denominator = v.lengthSq(); - // finally testing the face normal of the triangle - // use already existing triangle edge vectors here - _triangleNormal.crossVectors( _f0, _f1 ); - axes = [ _triangleNormal.x, _triangleNormal.y, _triangleNormal.z ]; + if ( denominator === 0 ) return this.set( 0, 0, 0 ); - return satForAxes( axes, _v0$2, _v1$7, _v2$3, _extents ); + const scalar = v.dot( this ) / denominator; + + return this.copy( v ).multiplyScalar( scalar ); } - clampPoint( point, target ) { + projectOnPlane( planeNormal ) { - return target.copy( point ).clamp( this.min, this.max ); + _vector$c.copy( this ).projectOnVector( planeNormal ); + + return this.sub( _vector$c ); } - distanceToPoint( point ) { + reflect( normal ) { - const clampedPoint = _vector$b.copy( point ).clamp( this.min, this.max ); + // reflect incident vector off plane orthogonal to normal + // normal is assumed to have unit length - return clampedPoint.sub( point ).length(); + return this.sub( _vector$c.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) ); } - getBoundingSphere( target ) { + angleTo( v ) { - this.getCenter( target.center ); + const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() ); - target.radius = this.getSize( _vector$b ).length() * 0.5; + if ( denominator === 0 ) return Math.PI / 2; - return target; + const theta = this.dot( v ) / denominator; - } + // clamp, to handle numerical problems - intersect( box ) { + return Math.acos( clamp( theta, - 1, 1 ) ); - this.min.max( box.min ); - this.max.min( box.max ); + } - // ensure that if there is no overlap, the result is fully empty, not slightly empty with non-inf/+inf values that will cause subsequence intersects to erroneously return valid values. - if ( this.isEmpty() ) this.makeEmpty(); + distanceTo( v ) { - return this; + return Math.sqrt( this.distanceToSquared( v ) ); } - union( box ) { + distanceToSquared( v ) { - this.min.min( box.min ); - this.max.max( box.max ); + const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z; - return this; + return dx * dx + dy * dy + dz * dz; } - applyMatrix4( matrix ) { + manhattanDistanceTo( v ) { - // transform of empty box is an empty box. - if ( this.isEmpty() ) return this; + return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z ); - // NOTE: I am using a binary pattern to specify all 2^3 combinations below - _points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000 - _points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001 - _points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010 - _points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011 - _points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100 - _points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101 - _points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110 - _points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111 + } - this.setFromPoints( _points ); + setFromSpherical( s ) { - return this; + return this.setFromSphericalCoords( s.radius, s.phi, s.theta ); } - translate( offset ) { + setFromSphericalCoords( radius, phi, theta ) { - this.min.add( offset ); - this.max.add( offset ); + const sinPhiRadius = Math.sin( phi ) * radius; + + this.x = sinPhiRadius * Math.sin( theta ); + this.y = Math.cos( phi ) * radius; + this.z = sinPhiRadius * Math.cos( theta ); return this; } - equals( box ) { + setFromCylindrical( c ) { - return box.min.equals( this.min ) && box.max.equals( this.max ); + return this.setFromCylindricalCoords( c.radius, c.theta, c.y ); } -} - -Box3.prototype.isBox3 = true; - -const _points = [ - /*@__PURE__*/ new Vector3(), - /*@__PURE__*/ new Vector3(), - /*@__PURE__*/ new Vector3(), - /*@__PURE__*/ new Vector3(), - /*@__PURE__*/ new Vector3(), - /*@__PURE__*/ new Vector3(), - /*@__PURE__*/ new Vector3(), - /*@__PURE__*/ new Vector3() -]; + setFromCylindricalCoords( radius, theta, y ) { -const _vector$b = /*@__PURE__*/ new Vector3(); + this.x = radius * Math.sin( theta ); + this.y = y; + this.z = radius * Math.cos( theta ); -const _box$3 = /*@__PURE__*/ new Box3(); + return this; -// triangle centered vertices + } -const _v0$2 = /*@__PURE__*/ new Vector3(); -const _v1$7 = /*@__PURE__*/ new Vector3(); -const _v2$3 = /*@__PURE__*/ new Vector3(); + setFromMatrixPosition( m ) { -// triangle edge vectors + const e = m.elements; -const _f0 = /*@__PURE__*/ new Vector3(); -const _f1 = /*@__PURE__*/ new Vector3(); -const _f2 = /*@__PURE__*/ new Vector3(); + this.x = e[ 12 ]; + this.y = e[ 13 ]; + this.z = e[ 14 ]; -const _center = /*@__PURE__*/ new Vector3(); -const _extents = /*@__PURE__*/ new Vector3(); -const _triangleNormal = /*@__PURE__*/ new Vector3(); -const _testAxis = /*@__PURE__*/ new Vector3(); + return this; -function satForAxes( axes, v0, v1, v2, extents ) { + } - for ( let i = 0, j = axes.length - 3; i <= j; i += 3 ) { + setFromMatrixScale( m ) { - _testAxis.fromArray( axes, i ); - // project the aabb onto the seperating axis - const r = extents.x * Math.abs( _testAxis.x ) + extents.y * Math.abs( _testAxis.y ) + extents.z * Math.abs( _testAxis.z ); - // project all 3 vertices of the triangle onto the seperating axis - const p0 = v0.dot( _testAxis ); - const p1 = v1.dot( _testAxis ); - const p2 = v2.dot( _testAxis ); - // actual test, basically see if either of the most extreme of the triangle points intersects r - if ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) { + const sx = this.setFromMatrixColumn( m, 0 ).length(); + const sy = this.setFromMatrixColumn( m, 1 ).length(); + const sz = this.setFromMatrixColumn( m, 2 ).length(); - // points of the projected triangle are outside the projected half-length of the aabb - // the axis is seperating and we can exit - return false; + this.x = sx; + this.y = sy; + this.z = sz; - } + return this; } - return true; - -} + setFromMatrixColumn( m, index ) { -const _box$2 = /*@__PURE__*/ new Box3(); -const _v1$6 = /*@__PURE__*/ new Vector3(); -const _toFarthestPoint = /*@__PURE__*/ new Vector3(); -const _toPoint = /*@__PURE__*/ new Vector3(); + return this.fromArray( m.elements, index * 4 ); -class Sphere { + } - constructor( center = new Vector3(), radius = - 1 ) { + setFromMatrix3Column( m, index ) { - this.center = center; - this.radius = radius; + return this.fromArray( m.elements, index * 3 ); } - set( center, radius ) { - - this.center.copy( center ); - this.radius = radius; + equals( v ) { - return this; + return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) ); } - setFromPoints( points, optionalCenter ) { + fromArray( array, offset = 0 ) { - const center = this.center; + this.x = array[ offset ]; + this.y = array[ offset + 1 ]; + this.z = array[ offset + 2 ]; - if ( optionalCenter !== undefined ) { + return this; - center.copy( optionalCenter ); + } - } else { + toArray( array = [], offset = 0 ) { - _box$2.setFromPoints( points ).getCenter( center ); + array[ offset ] = this.x; + array[ offset + 1 ] = this.y; + array[ offset + 2 ] = this.z; - } + return array; - let maxRadiusSq = 0; + } - for ( let i = 0, il = points.length; i < il; i ++ ) { + fromBufferAttribute( attribute, index, offset ) { - maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) ); + if ( offset !== undefined ) { + + console.warn( 'THREE.Vector3: offset has been removed from .fromBufferAttribute().' ); } - this.radius = Math.sqrt( maxRadiusSq ); + this.x = attribute.getX( index ); + this.y = attribute.getY( index ); + this.z = attribute.getZ( index ); return this; } - copy( sphere ) { + random() { - this.center.copy( sphere.center ); - this.radius = sphere.radius; + this.x = Math.random(); + this.y = Math.random(); + this.z = Math.random(); return this; } - isEmpty() { - - return ( this.radius < 0 ); + randomDirection() { - } + // Derived from https://mathworld.wolfram.com/SpherePointPicking.html - makeEmpty() { + const u = ( Math.random() - 0.5 ) * 2; + const t = Math.random() * Math.PI * 2; + const f = Math.sqrt( 1 - u ** 2 ); - this.center.set( 0, 0, 0 ); - this.radius = - 1; + this.x = f * Math.cos( t ); + this.y = f * Math.sin( t ); + this.z = u; return this; } - containsPoint( point ) { + *[ Symbol.iterator ]() { - return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) ); + yield this.x; + yield this.y; + yield this.z; } - distanceToPoint( point ) { +} - return ( point.distanceTo( this.center ) - this.radius ); +Vector3.prototype.isVector3 = true; - } +const _vector$c = /*@__PURE__*/ new Vector3(); +const _quaternion$4 = /*@__PURE__*/ new Quaternion(); - intersectsSphere( sphere ) { +class Box3 { - const radiusSum = this.radius + sphere.radius; + constructor( min = new Vector3( + Infinity, + Infinity, + Infinity ), max = new Vector3( - Infinity, - Infinity, - Infinity ) ) { - return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum ); + this.min = min; + this.max = max; } - intersectsBox( box ) { - - return box.intersectsSphere( this ); - - } + set( min, max ) { - intersectsPlane( plane ) { + this.min.copy( min ); + this.max.copy( max ); - return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius; + return this; } - clampPoint( point, target ) { - - const deltaLengthSq = this.center.distanceToSquared( point ); - - target.copy( point ); - - if ( deltaLengthSq > ( this.radius * this.radius ) ) { - - target.sub( this.center ).normalize(); - target.multiplyScalar( this.radius ).add( this.center ); + setFromArray( array ) { - } + let minX = + Infinity; + let minY = + Infinity; + let minZ = + Infinity; - return target; + let maxX = - Infinity; + let maxY = - Infinity; + let maxZ = - Infinity; - } + for ( let i = 0, l = array.length; i < l; i += 3 ) { - getBoundingBox( target ) { + const x = array[ i ]; + const y = array[ i + 1 ]; + const z = array[ i + 2 ]; - if ( this.isEmpty() ) { + if ( x < minX ) minX = x; + if ( y < minY ) minY = y; + if ( z < minZ ) minZ = z; - // Empty sphere produces empty bounding box - target.makeEmpty(); - return target; + if ( x > maxX ) maxX = x; + if ( y > maxY ) maxY = y; + if ( z > maxZ ) maxZ = z; } - target.set( this.center, this.center ); - target.expandByScalar( this.radius ); - - return target; - - } - - applyMatrix4( matrix ) { - - this.center.applyMatrix4( matrix ); - this.radius = this.radius * matrix.getMaxScaleOnAxis(); - - return this; - - } - - translate( offset ) { - - this.center.add( offset ); + this.min.set( minX, minY, minZ ); + this.max.set( maxX, maxY, maxZ ); return this; } - expandByPoint( point ) { - - // from https://github.com/juj/MathGeoLib/blob/2940b99b99cfe575dd45103ef20f4019dee15b54/src/Geometry/Sphere.cpp#L649-L671 + setFromBufferAttribute( attribute ) { - _toPoint.subVectors( point, this.center ); + let minX = + Infinity; + let minY = + Infinity; + let minZ = + Infinity; - const lengthSq = _toPoint.lengthSq(); + let maxX = - Infinity; + let maxY = - Infinity; + let maxZ = - Infinity; - if ( lengthSq > ( this.radius * this.radius ) ) { + for ( let i = 0, l = attribute.count; i < l; i ++ ) { - const length = Math.sqrt( lengthSq ); - const missingRadiusHalf = ( length - this.radius ) * 0.5; + const x = attribute.getX( i ); + const y = attribute.getY( i ); + const z = attribute.getZ( i ); - // Nudge this sphere towards the target point. Add half the missing distance to radius, - // and the other half to position. This gives a tighter enclosure, instead of if - // the whole missing distance were just added to radius. + if ( x < minX ) minX = x; + if ( y < minY ) minY = y; + if ( z < minZ ) minZ = z; - this.center.add( _toPoint.multiplyScalar( missingRadiusHalf / length ) ); - this.radius += missingRadiusHalf; + if ( x > maxX ) maxX = x; + if ( y > maxY ) maxY = y; + if ( z > maxZ ) maxZ = z; } + this.min.set( minX, minY, minZ ); + this.max.set( maxX, maxY, maxZ ); + return this; } - union( sphere ) { + setFromPoints( points ) { - // from https://github.com/juj/MathGeoLib/blob/2940b99b99cfe575dd45103ef20f4019dee15b54/src/Geometry/Sphere.cpp#L759-L769 + this.makeEmpty(); - // To enclose another sphere into this sphere, we only need to enclose two points: - // 1) Enclose the farthest point on the other sphere into this sphere. - // 2) Enclose the opposite point of the farthest point into this sphere. + for ( let i = 0, il = points.length; i < il; i ++ ) { - if ( this.center.equals( sphere.center ) === true ) { + this.expandByPoint( points[ i ] ); - _toFarthestPoint.set( 0, 0, 1 ).multiplyScalar( sphere.radius ); + } + return this; - } else { + } - _toFarthestPoint.subVectors( sphere.center, this.center ).normalize().multiplyScalar( sphere.radius ); + setFromCenterAndSize( center, size ) { - } + const halfSize = _vector$b.copy( size ).multiplyScalar( 0.5 ); - this.expandByPoint( _v1$6.copy( sphere.center ).add( _toFarthestPoint ) ); - this.expandByPoint( _v1$6.copy( sphere.center ).sub( _toFarthestPoint ) ); + this.min.copy( center ).sub( halfSize ); + this.max.copy( center ).add( halfSize ); return this; } - equals( sphere ) { + setFromObject( object ) { - return sphere.center.equals( this.center ) && ( sphere.radius === this.radius ); + this.makeEmpty(); + + return this.expandByObject( object ); } @@ -4900,737 +4859,1351 @@ class Sphere { } -} + copy( box ) { -const _vector$a = /*@__PURE__*/ new Vector3(); -const _segCenter = /*@__PURE__*/ new Vector3(); -const _segDir = /*@__PURE__*/ new Vector3(); -const _diff = /*@__PURE__*/ new Vector3(); + this.min.copy( box.min ); + this.max.copy( box.max ); -const _edge1 = /*@__PURE__*/ new Vector3(); -const _edge2 = /*@__PURE__*/ new Vector3(); -const _normal$1 = /*@__PURE__*/ new Vector3(); + return this; -class Ray { + } - constructor( origin = new Vector3(), direction = new Vector3( 0, 0, - 1 ) ) { + makeEmpty() { - this.origin = origin; - this.direction = direction; + this.min.x = this.min.y = this.min.z = + Infinity; + this.max.x = this.max.y = this.max.z = - Infinity; + + return this; } - set( origin, direction ) { + isEmpty() { - this.origin.copy( origin ); - this.direction.copy( direction ); + // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes - return this; + return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z ); } - copy( ray ) { - - this.origin.copy( ray.origin ); - this.direction.copy( ray.direction ); + getCenter( target ) { - return this; + return this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 ); } - at( t, target ) { + getSize( target ) { - return target.copy( this.direction ).multiplyScalar( t ).add( this.origin ); + return this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min ); } - lookAt( v ) { + expandByPoint( point ) { - this.direction.copy( v ).sub( this.origin ).normalize(); + this.min.min( point ); + this.max.max( point ); return this; } - recast( t ) { + expandByVector( vector ) { - this.origin.copy( this.at( t, _vector$a ) ); + this.min.sub( vector ); + this.max.add( vector ); return this; } - closestPointToPoint( point, target ) { + expandByScalar( scalar ) { - target.subVectors( point, this.origin ); + this.min.addScalar( - scalar ); + this.max.addScalar( scalar ); - const directionDistance = target.dot( this.direction ); + return this; - if ( directionDistance < 0 ) { + } - return target.copy( this.origin ); + expandByObject( object ) { - } + // Computes the world-axis-aligned bounding box of an object (including its children), + // accounting for both the object's, and children's, world transforms - return target.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin ); + object.updateWorldMatrix( false, false ); - } + const geometry = object.geometry; - distanceToPoint( point ) { + if ( geometry !== undefined ) { - return Math.sqrt( this.distanceSqToPoint( point ) ); + if ( geometry.boundingBox === null ) { - } + geometry.computeBoundingBox(); - distanceSqToPoint( point ) { + } - const directionDistance = _vector$a.subVectors( point, this.origin ).dot( this.direction ); + _box$3.copy( geometry.boundingBox ); + _box$3.applyMatrix4( object.matrixWorld ); - // point behind the ray + this.union( _box$3 ); - if ( directionDistance < 0 ) { + } - return this.origin.distanceToSquared( point ); + const children = object.children; - } + for ( let i = 0, l = children.length; i < l; i ++ ) { - _vector$a.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin ); + this.expandByObject( children[ i ] ); - return _vector$a.distanceToSquared( point ); + } + + return this; } - distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) { + containsPoint( point ) { - // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteDistRaySegment.h - // It returns the min distance between the ray and the segment - // defined by v0 and v1 - // It can also set two optional targets : - // - The closest point on the ray - // - The closest point on the segment + return point.x < this.min.x || point.x > this.max.x || + point.y < this.min.y || point.y > this.max.y || + point.z < this.min.z || point.z > this.max.z ? false : true; - _segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 ); - _segDir.copy( v1 ).sub( v0 ).normalize(); - _diff.copy( this.origin ).sub( _segCenter ); + } - const segExtent = v0.distanceTo( v1 ) * 0.5; - const a01 = - this.direction.dot( _segDir ); - const b0 = _diff.dot( this.direction ); - const b1 = - _diff.dot( _segDir ); - const c = _diff.lengthSq(); - const det = Math.abs( 1 - a01 * a01 ); - let s0, s1, sqrDist, extDet; + containsBox( box ) { - if ( det > 0 ) { + return this.min.x <= box.min.x && box.max.x <= this.max.x && + this.min.y <= box.min.y && box.max.y <= this.max.y && + this.min.z <= box.min.z && box.max.z <= this.max.z; - // The ray and segment are not parallel. + } - s0 = a01 * b1 - b0; - s1 = a01 * b0 - b1; - extDet = segExtent * det; + getParameter( point, target ) { - if ( s0 >= 0 ) { + // This can potentially have a divide by zero if the box + // has a size dimension of 0. - if ( s1 >= - extDet ) { + return target.set( + ( point.x - this.min.x ) / ( this.max.x - this.min.x ), + ( point.y - this.min.y ) / ( this.max.y - this.min.y ), + ( point.z - this.min.z ) / ( this.max.z - this.min.z ) + ); - if ( s1 <= extDet ) { + } - // region 0 - // Minimum at interior points of ray and segment. + intersectsBox( box ) { - const invDet = 1 / det; - s0 *= invDet; - s1 *= invDet; - sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c; + // using 6 splitting planes to rule out intersections. + return box.max.x < this.min.x || box.min.x > this.max.x || + box.max.y < this.min.y || box.min.y > this.max.y || + box.max.z < this.min.z || box.min.z > this.max.z ? false : true; - } else { + } - // region 1 + intersectsSphere( sphere ) { - s1 = segExtent; - s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); - sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; + // Find the point on the AABB closest to the sphere center. + this.clampPoint( sphere.center, _vector$b ); - } + // If that point is inside the sphere, the AABB and sphere intersect. + return _vector$b.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius ); - } else { + } - // region 5 + intersectsPlane( plane ) { - s1 = - segExtent; - s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); - sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; + // We compute the minimum and maximum dot product values. If those values + // are on the same side (back or front) of the plane, then there is no intersection. - } + let min, max; - } else { + if ( plane.normal.x > 0 ) { - if ( s1 <= - extDet ) { + min = plane.normal.x * this.min.x; + max = plane.normal.x * this.max.x; - // region 4 + } else { - s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) ); - s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent ); - sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; + min = plane.normal.x * this.max.x; + max = plane.normal.x * this.min.x; - } else if ( s1 <= extDet ) { + } - // region 3 + if ( plane.normal.y > 0 ) { - s0 = 0; - s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent ); - sqrDist = s1 * ( s1 + 2 * b1 ) + c; + min += plane.normal.y * this.min.y; + max += plane.normal.y * this.max.y; - } else { + } else { - // region 2 + min += plane.normal.y * this.max.y; + max += plane.normal.y * this.min.y; - s0 = Math.max( 0, - ( a01 * segExtent + b0 ) ); - s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent ); - sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; + } - } + if ( plane.normal.z > 0 ) { - } + min += plane.normal.z * this.min.z; + max += plane.normal.z * this.max.z; } else { - // Ray and segment are parallel. - - s1 = ( a01 > 0 ) ? - segExtent : segExtent; - s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); - sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; + min += plane.normal.z * this.max.z; + max += plane.normal.z * this.min.z; } - if ( optionalPointOnRay ) { + return ( min <= - plane.constant && max >= - plane.constant ); - optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin ); + } - } + intersectsTriangle( triangle ) { - if ( optionalPointOnSegment ) { + if ( this.isEmpty() ) { - optionalPointOnSegment.copy( _segDir ).multiplyScalar( s1 ).add( _segCenter ); + return false; } - return sqrDist; + // compute box center and extents + this.getCenter( _center ); + _extents.subVectors( this.max, _center ); - } + // translate triangle to aabb origin + _v0$2.subVectors( triangle.a, _center ); + _v1$7.subVectors( triangle.b, _center ); + _v2$3.subVectors( triangle.c, _center ); - intersectSphere( sphere, target ) { + // compute edge vectors for triangle + _f0.subVectors( _v1$7, _v0$2 ); + _f1.subVectors( _v2$3, _v1$7 ); + _f2.subVectors( _v0$2, _v2$3 ); - _vector$a.subVectors( sphere.center, this.origin ); - const tca = _vector$a.dot( this.direction ); - const d2 = _vector$a.dot( _vector$a ) - tca * tca; - const radius2 = sphere.radius * sphere.radius; + // test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb + // make an axis testing of each of the 3 sides of the aabb against each of the 3 sides of the triangle = 9 axis of separation + // axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned) + let axes = [ + 0, - _f0.z, _f0.y, 0, - _f1.z, _f1.y, 0, - _f2.z, _f2.y, + _f0.z, 0, - _f0.x, _f1.z, 0, - _f1.x, _f2.z, 0, - _f2.x, + - _f0.y, _f0.x, 0, - _f1.y, _f1.x, 0, - _f2.y, _f2.x, 0 + ]; + if ( ! satForAxes( axes, _v0$2, _v1$7, _v2$3, _extents ) ) { - if ( d2 > radius2 ) return null; + return false; - const thc = Math.sqrt( radius2 - d2 ); + } - // t0 = first intersect point - entrance on front of sphere - const t0 = tca - thc; + // test 3 face normals from the aabb + axes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ]; + if ( ! satForAxes( axes, _v0$2, _v1$7, _v2$3, _extents ) ) { - // t1 = second intersect point - exit point on back of sphere - const t1 = tca + thc; + return false; - // test to see if both t0 and t1 are behind the ray - if so, return null - if ( t0 < 0 && t1 < 0 ) return null; + } - // test to see if t0 is behind the ray: - // if it is, the ray is inside the sphere, so return the second exit point scaled by t1, - // in order to always return an intersect point that is in front of the ray. - if ( t0 < 0 ) return this.at( t1, target ); + // finally testing the face normal of the triangle + // use already existing triangle edge vectors here + _triangleNormal.crossVectors( _f0, _f1 ); + axes = [ _triangleNormal.x, _triangleNormal.y, _triangleNormal.z ]; - // else t0 is in front of the ray, so return the first collision point scaled by t0 - return this.at( t0, target ); + return satForAxes( axes, _v0$2, _v1$7, _v2$3, _extents ); } - intersectsSphere( sphere ) { + clampPoint( point, target ) { - return this.distanceSqToPoint( sphere.center ) <= ( sphere.radius * sphere.radius ); + return target.copy( point ).clamp( this.min, this.max ); } - distanceToPlane( plane ) { + distanceToPoint( point ) { - const denominator = plane.normal.dot( this.direction ); + const clampedPoint = _vector$b.copy( point ).clamp( this.min, this.max ); - if ( denominator === 0 ) { + return clampedPoint.sub( point ).length(); - // line is coplanar, return origin - if ( plane.distanceToPoint( this.origin ) === 0 ) { + } - return 0; + getBoundingSphere( target ) { - } + this.getCenter( target.center ); - // Null is preferable to undefined since undefined means.... it is undefined + target.radius = this.getSize( _vector$b ).length() * 0.5; - return null; + return target; - } + } - const t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator; + intersect( box ) { - // Return if the ray never intersects the plane + this.min.max( box.min ); + this.max.min( box.max ); - return t >= 0 ? t : null; + // ensure that if there is no overlap, the result is fully empty, not slightly empty with non-inf/+inf values that will cause subsequence intersects to erroneously return valid values. + if ( this.isEmpty() ) this.makeEmpty(); + + return this; } - intersectPlane( plane, target ) { + union( box ) { - const t = this.distanceToPlane( plane ); + this.min.min( box.min ); + this.max.max( box.max ); - if ( t === null ) { + return this; - return null; + } - } + applyMatrix4( matrix ) { - return this.at( t, target ); + // transform of empty box is an empty box. + if ( this.isEmpty() ) return this; + + // NOTE: I am using a binary pattern to specify all 2^3 combinations below + _points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000 + _points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001 + _points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010 + _points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011 + _points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100 + _points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101 + _points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110 + _points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111 + + this.setFromPoints( _points ); + + return this; } - intersectsPlane( plane ) { + translate( offset ) { - // check if the ray lies on the plane first + this.min.add( offset ); + this.max.add( offset ); - const distToPoint = plane.distanceToPoint( this.origin ); + return this; - if ( distToPoint === 0 ) { + } - return true; + equals( box ) { - } + return box.min.equals( this.min ) && box.max.equals( this.max ); - const denominator = plane.normal.dot( this.direction ); + } - if ( denominator * distToPoint < 0 ) { +} - return true; +Box3.prototype.isBox3 = true; - } +const _points = [ + /*@__PURE__*/ new Vector3(), + /*@__PURE__*/ new Vector3(), + /*@__PURE__*/ new Vector3(), + /*@__PURE__*/ new Vector3(), + /*@__PURE__*/ new Vector3(), + /*@__PURE__*/ new Vector3(), + /*@__PURE__*/ new Vector3(), + /*@__PURE__*/ new Vector3() +]; - // ray origin is behind the plane (and is pointing behind it) +const _vector$b = /*@__PURE__*/ new Vector3(); - return false; +const _box$3 = /*@__PURE__*/ new Box3(); - } +// triangle centered vertices - intersectBox( box, target ) { +const _v0$2 = /*@__PURE__*/ new Vector3(); +const _v1$7 = /*@__PURE__*/ new Vector3(); +const _v2$3 = /*@__PURE__*/ new Vector3(); - let tmin, tmax, tymin, tymax, tzmin, tzmax; +// triangle edge vectors - const invdirx = 1 / this.direction.x, - invdiry = 1 / this.direction.y, - invdirz = 1 / this.direction.z; +const _f0 = /*@__PURE__*/ new Vector3(); +const _f1 = /*@__PURE__*/ new Vector3(); +const _f2 = /*@__PURE__*/ new Vector3(); - const origin = this.origin; +const _center = /*@__PURE__*/ new Vector3(); +const _extents = /*@__PURE__*/ new Vector3(); +const _triangleNormal = /*@__PURE__*/ new Vector3(); +const _testAxis = /*@__PURE__*/ new Vector3(); - if ( invdirx >= 0 ) { +function satForAxes( axes, v0, v1, v2, extents ) { - tmin = ( box.min.x - origin.x ) * invdirx; - tmax = ( box.max.x - origin.x ) * invdirx; + for ( let i = 0, j = axes.length - 3; i <= j; i += 3 ) { - } else { + _testAxis.fromArray( axes, i ); + // project the aabb onto the seperating axis + const r = extents.x * Math.abs( _testAxis.x ) + extents.y * Math.abs( _testAxis.y ) + extents.z * Math.abs( _testAxis.z ); + // project all 3 vertices of the triangle onto the seperating axis + const p0 = v0.dot( _testAxis ); + const p1 = v1.dot( _testAxis ); + const p2 = v2.dot( _testAxis ); + // actual test, basically see if either of the most extreme of the triangle points intersects r + if ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) { - tmin = ( box.max.x - origin.x ) * invdirx; - tmax = ( box.min.x - origin.x ) * invdirx; + // points of the projected triangle are outside the projected half-length of the aabb + // the axis is seperating and we can exit + return false; } - if ( invdiry >= 0 ) { + } - tymin = ( box.min.y - origin.y ) * invdiry; - tymax = ( box.max.y - origin.y ) * invdiry; + return true; - } else { +} - tymin = ( box.max.y - origin.y ) * invdiry; - tymax = ( box.min.y - origin.y ) * invdiry; +const _box$2 = /*@__PURE__*/ new Box3(); +const _v1$6 = /*@__PURE__*/ new Vector3(); +const _toFarthestPoint = /*@__PURE__*/ new Vector3(); +const _toPoint = /*@__PURE__*/ new Vector3(); - } +class Sphere { - if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null; + constructor( center = new Vector3(), radius = - 1 ) { - // These lines also handle the case where tmin or tmax is NaN - // (result of 0 * Infinity). x !== x returns true if x is NaN + this.center = center; + this.radius = radius; - if ( tymin > tmin || tmin !== tmin ) tmin = tymin; + } - if ( tymax < tmax || tmax !== tmax ) tmax = tymax; + set( center, radius ) { - if ( invdirz >= 0 ) { + this.center.copy( center ); + this.radius = radius; - tzmin = ( box.min.z - origin.z ) * invdirz; - tzmax = ( box.max.z - origin.z ) * invdirz; + return this; + + } + + setFromPoints( points, optionalCenter ) { + + const center = this.center; + + if ( optionalCenter !== undefined ) { + + center.copy( optionalCenter ); } else { - tzmin = ( box.max.z - origin.z ) * invdirz; - tzmax = ( box.min.z - origin.z ) * invdirz; + _box$2.setFromPoints( points ).getCenter( center ); } - if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null; + let maxRadiusSq = 0; - if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin; + for ( let i = 0, il = points.length; i < il; i ++ ) { - if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax; + maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) ); - //return point closest to the ray (positive side) + } - if ( tmax < 0 ) return null; + this.radius = Math.sqrt( maxRadiusSq ); - return this.at( tmin >= 0 ? tmin : tmax, target ); + return this; } - intersectsBox( box ) { + copy( sphere ) { - return this.intersectBox( box, _vector$a ) !== null; + this.center.copy( sphere.center ); + this.radius = sphere.radius; + + return this; } - intersectTriangle( a, b, c, backfaceCulling, target ) { + isEmpty() { - // Compute the offset origin, edges, and normal. + return ( this.radius < 0 ); - // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h + } - _edge1.subVectors( b, a ); - _edge2.subVectors( c, a ); - _normal$1.crossVectors( _edge1, _edge2 ); + makeEmpty() { - // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction, - // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by - // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2)) - // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q)) - // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N) - let DdN = this.direction.dot( _normal$1 ); - let sign; + this.center.set( 0, 0, 0 ); + this.radius = - 1; - if ( DdN > 0 ) { + return this; - if ( backfaceCulling ) return null; - sign = 1; + } - } else if ( DdN < 0 ) { + containsPoint( point ) { - sign = - 1; - DdN = - DdN; + return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) ); - } else { + } - return null; + distanceToPoint( point ) { - } + return ( point.distanceTo( this.center ) - this.radius ); - _diff.subVectors( this.origin, a ); - const DdQxE2 = sign * this.direction.dot( _edge2.crossVectors( _diff, _edge2 ) ); + } - // b1 < 0, no intersection - if ( DdQxE2 < 0 ) { + intersectsSphere( sphere ) { - return null; + const radiusSum = this.radius + sphere.radius; - } + return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum ); - const DdE1xQ = sign * this.direction.dot( _edge1.cross( _diff ) ); + } - // b2 < 0, no intersection - if ( DdE1xQ < 0 ) { + intersectsBox( box ) { - return null; + return box.intersectsSphere( this ); - } + } - // b1+b2 > 1, no intersection - if ( DdQxE2 + DdE1xQ > DdN ) { + intersectsPlane( plane ) { - return null; + return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius; - } + } - // Line intersects triangle, check if ray does. - const QdN = - sign * _diff.dot( _normal$1 ); + clampPoint( point, target ) { - // t < 0, no intersection - if ( QdN < 0 ) { + const deltaLengthSq = this.center.distanceToSquared( point ); - return null; + target.copy( point ); + + if ( deltaLengthSq > ( this.radius * this.radius ) ) { + + target.sub( this.center ).normalize(); + target.multiplyScalar( this.radius ).add( this.center ); } - // Ray intersects triangle. - return this.at( QdN / DdN, target ); + return target; } - applyMatrix4( matrix4 ) { + getBoundingBox( target ) { - this.origin.applyMatrix4( matrix4 ); - this.direction.transformDirection( matrix4 ); + if ( this.isEmpty() ) { - return this; + // Empty sphere produces empty bounding box + target.makeEmpty(); + return target; - } + } - equals( ray ) { + target.set( this.center, this.center ); + target.expandByScalar( this.radius ); - return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction ); + return target; } - clone() { + applyMatrix4( matrix ) { - return new this.constructor().copy( this ); + this.center.applyMatrix4( matrix ); + this.radius = this.radius * matrix.getMaxScaleOnAxis(); + + return this; } -} + translate( offset ) { -class Matrix4 { + this.center.add( offset ); - constructor() { + return this; - this.elements = [ + } - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 + expandByPoint( point ) { - ]; + // from https://github.com/juj/MathGeoLib/blob/2940b99b99cfe575dd45103ef20f4019dee15b54/src/Geometry/Sphere.cpp#L649-L671 - if ( arguments.length > 0 ) { + _toPoint.subVectors( point, this.center ); - console.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' ); + const lengthSq = _toPoint.lengthSq(); - } + if ( lengthSq > ( this.radius * this.radius ) ) { - } + const length = Math.sqrt( lengthSq ); + const missingRadiusHalf = ( length - this.radius ) * 0.5; - set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { + // Nudge this sphere towards the target point. Add half the missing distance to radius, + // and the other half to position. This gives a tighter enclosure, instead of if + // the whole missing distance were just added to radius. - const te = this.elements; + this.center.add( _toPoint.multiplyScalar( missingRadiusHalf / length ) ); + this.radius += missingRadiusHalf; - te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14; - te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24; - te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34; - te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44; + } return this; } - identity() { - - this.set( - - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 + union( sphere ) { - ); + // from https://github.com/juj/MathGeoLib/blob/2940b99b99cfe575dd45103ef20f4019dee15b54/src/Geometry/Sphere.cpp#L759-L769 - return this; + // To enclose another sphere into this sphere, we only need to enclose two points: + // 1) Enclose the farthest point on the other sphere into this sphere. + // 2) Enclose the opposite point of the farthest point into this sphere. - } + if ( this.center.equals( sphere.center ) === true ) { - clone() { + _toFarthestPoint.set( 0, 0, 1 ).multiplyScalar( sphere.radius ); - return new Matrix4().fromArray( this.elements ); - } + } else { - copy( m ) { + _toFarthestPoint.subVectors( sphere.center, this.center ).normalize().multiplyScalar( sphere.radius ); - const te = this.elements; - const me = m.elements; + } - te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ]; - te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; - te[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ]; - te[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ]; + this.expandByPoint( _v1$6.copy( sphere.center ).add( _toFarthestPoint ) ); + this.expandByPoint( _v1$6.copy( sphere.center ).sub( _toFarthestPoint ) ); return this; } - copyPosition( m ) { + equals( sphere ) { - const te = this.elements, me = m.elements; + return sphere.center.equals( this.center ) && ( sphere.radius === this.radius ); - te[ 12 ] = me[ 12 ]; - te[ 13 ] = me[ 13 ]; - te[ 14 ] = me[ 14 ]; + } - return this; + clone() { + + return new this.constructor().copy( this ); } - setFromMatrix3( m ) { +} - const me = m.elements; +const _vector$a = /*@__PURE__*/ new Vector3(); +const _segCenter = /*@__PURE__*/ new Vector3(); +const _segDir = /*@__PURE__*/ new Vector3(); +const _diff = /*@__PURE__*/ new Vector3(); - this.set( +const _edge1 = /*@__PURE__*/ new Vector3(); +const _edge2 = /*@__PURE__*/ new Vector3(); +const _normal$1 = /*@__PURE__*/ new Vector3(); - me[ 0 ], me[ 3 ], me[ 6 ], 0, - me[ 1 ], me[ 4 ], me[ 7 ], 0, - me[ 2 ], me[ 5 ], me[ 8 ], 0, - 0, 0, 0, 1 +class Ray { - ); + constructor( origin = new Vector3(), direction = new Vector3( 0, 0, - 1 ) ) { - return this; + this.origin = origin; + this.direction = direction; } - extractBasis( xAxis, yAxis, zAxis ) { + set( origin, direction ) { - xAxis.setFromMatrixColumn( this, 0 ); - yAxis.setFromMatrixColumn( this, 1 ); - zAxis.setFromMatrixColumn( this, 2 ); + this.origin.copy( origin ); + this.direction.copy( direction ); return this; } - makeBasis( xAxis, yAxis, zAxis ) { + copy( ray ) { - this.set( - xAxis.x, yAxis.x, zAxis.x, 0, - xAxis.y, yAxis.y, zAxis.y, 0, - xAxis.z, yAxis.z, zAxis.z, 0, - 0, 0, 0, 1 - ); + this.origin.copy( ray.origin ); + this.direction.copy( ray.direction ); return this; } - extractRotation( m ) { + at( t, target ) { - // this method does not support reflection matrices + return target.copy( this.direction ).multiplyScalar( t ).add( this.origin ); - const te = this.elements; - const me = m.elements; + } - const scaleX = 1 / _v1$5.setFromMatrixColumn( m, 0 ).length(); - const scaleY = 1 / _v1$5.setFromMatrixColumn( m, 1 ).length(); - const scaleZ = 1 / _v1$5.setFromMatrixColumn( m, 2 ).length(); + lookAt( v ) { - te[ 0 ] = me[ 0 ] * scaleX; - te[ 1 ] = me[ 1 ] * scaleX; - te[ 2 ] = me[ 2 ] * scaleX; - te[ 3 ] = 0; + this.direction.copy( v ).sub( this.origin ).normalize(); - te[ 4 ] = me[ 4 ] * scaleY; - te[ 5 ] = me[ 5 ] * scaleY; - te[ 6 ] = me[ 6 ] * scaleY; - te[ 7 ] = 0; + return this; - te[ 8 ] = me[ 8 ] * scaleZ; - te[ 9 ] = me[ 9 ] * scaleZ; - te[ 10 ] = me[ 10 ] * scaleZ; - te[ 11 ] = 0; + } - te[ 12 ] = 0; - te[ 13 ] = 0; - te[ 14 ] = 0; - te[ 15 ] = 1; + recast( t ) { + + this.origin.copy( this.at( t, _vector$a ) ); return this; } - makeRotationFromEuler( euler ) { - - if ( ! ( euler && euler.isEuler ) ) { + closestPointToPoint( point, target ) { - console.error( 'THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' ); + target.subVectors( point, this.origin ); - } + const directionDistance = target.dot( this.direction ); - const te = this.elements; + if ( directionDistance < 0 ) { - const x = euler.x, y = euler.y, z = euler.z; - const a = Math.cos( x ), b = Math.sin( x ); - const c = Math.cos( y ), d = Math.sin( y ); - const e = Math.cos( z ), f = Math.sin( z ); + return target.copy( this.origin ); - if ( euler.order === 'XYZ' ) { + } - const ae = a * e, af = a * f, be = b * e, bf = b * f; + return target.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin ); - te[ 0 ] = c * e; - te[ 4 ] = - c * f; - te[ 8 ] = d; + } - te[ 1 ] = af + be * d; - te[ 5 ] = ae - bf * d; - te[ 9 ] = - b * c; + distanceToPoint( point ) { - te[ 2 ] = bf - ae * d; - te[ 6 ] = be + af * d; - te[ 10 ] = a * c; + return Math.sqrt( this.distanceSqToPoint( point ) ); - } else if ( euler.order === 'YXZ' ) { + } - const ce = c * e, cf = c * f, de = d * e, df = d * f; + distanceSqToPoint( point ) { - te[ 0 ] = ce + df * b; - te[ 4 ] = de * b - cf; - te[ 8 ] = a * d; + const directionDistance = _vector$a.subVectors( point, this.origin ).dot( this.direction ); - te[ 1 ] = a * f; - te[ 5 ] = a * e; - te[ 9 ] = - b; + // point behind the ray - te[ 2 ] = cf * b - de; - te[ 6 ] = df + ce * b; - te[ 10 ] = a * c; + if ( directionDistance < 0 ) { - } else if ( euler.order === 'ZXY' ) { + return this.origin.distanceToSquared( point ); - const ce = c * e, cf = c * f, de = d * e, df = d * f; + } - te[ 0 ] = ce - df * b; - te[ 4 ] = - a * f; - te[ 8 ] = de + cf * b; + _vector$a.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin ); - te[ 1 ] = cf + de * b; - te[ 5 ] = a * e; - te[ 9 ] = df - ce * b; + return _vector$a.distanceToSquared( point ); - te[ 2 ] = - a * d; - te[ 6 ] = b; - te[ 10 ] = a * c; + } - } else if ( euler.order === 'ZYX' ) { + distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) { - const ae = a * e, af = a * f, be = b * e, bf = b * f; + // from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteDistRaySegment.h + // It returns the min distance between the ray and the segment + // defined by v0 and v1 + // It can also set two optional targets : + // - The closest point on the ray + // - The closest point on the segment - te[ 0 ] = c * e; - te[ 4 ] = be * d - af; - te[ 8 ] = ae * d + bf; + _segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 ); + _segDir.copy( v1 ).sub( v0 ).normalize(); + _diff.copy( this.origin ).sub( _segCenter ); - te[ 1 ] = c * f; - te[ 5 ] = bf * d + ae; - te[ 9 ] = af * d - be; + const segExtent = v0.distanceTo( v1 ) * 0.5; + const a01 = - this.direction.dot( _segDir ); + const b0 = _diff.dot( this.direction ); + const b1 = - _diff.dot( _segDir ); + const c = _diff.lengthSq(); + const det = Math.abs( 1 - a01 * a01 ); + let s0, s1, sqrDist, extDet; - te[ 2 ] = - d; - te[ 6 ] = b * c; - te[ 10 ] = a * c; + if ( det > 0 ) { - } else if ( euler.order === 'YZX' ) { + // The ray and segment are not parallel. + + s0 = a01 * b1 - b0; + s1 = a01 * b0 - b1; + extDet = segExtent * det; + + if ( s0 >= 0 ) { + + if ( s1 >= - extDet ) { + + if ( s1 <= extDet ) { + + // region 0 + // Minimum at interior points of ray and segment. + + const invDet = 1 / det; + s0 *= invDet; + s1 *= invDet; + sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c; + + } else { + + // region 1 + + s1 = segExtent; + s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); + sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; + + } + + } else { + + // region 5 + + s1 = - segExtent; + s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); + sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; + + } + + } else { + + if ( s1 <= - extDet ) { + + // region 4 + + s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) ); + s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent ); + sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; + + } else if ( s1 <= extDet ) { + + // region 3 + + s0 = 0; + s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent ); + sqrDist = s1 * ( s1 + 2 * b1 ) + c; + + } else { + + // region 2 + + s0 = Math.max( 0, - ( a01 * segExtent + b0 ) ); + s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent ); + sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; + + } + + } + + } else { + + // Ray and segment are parallel. + + s1 = ( a01 > 0 ) ? - segExtent : segExtent; + s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); + sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; + + } + + if ( optionalPointOnRay ) { + + optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin ); + + } + + if ( optionalPointOnSegment ) { + + optionalPointOnSegment.copy( _segDir ).multiplyScalar( s1 ).add( _segCenter ); + + } + + return sqrDist; + + } + + intersectSphere( sphere, target ) { + + _vector$a.subVectors( sphere.center, this.origin ); + const tca = _vector$a.dot( this.direction ); + const d2 = _vector$a.dot( _vector$a ) - tca * tca; + const radius2 = sphere.radius * sphere.radius; + + if ( d2 > radius2 ) return null; + + const thc = Math.sqrt( radius2 - d2 ); + + // t0 = first intersect point - entrance on front of sphere + const t0 = tca - thc; + + // t1 = second intersect point - exit point on back of sphere + const t1 = tca + thc; + + // test to see if both t0 and t1 are behind the ray - if so, return null + if ( t0 < 0 && t1 < 0 ) return null; + + // test to see if t0 is behind the ray: + // if it is, the ray is inside the sphere, so return the second exit point scaled by t1, + // in order to always return an intersect point that is in front of the ray. + if ( t0 < 0 ) return this.at( t1, target ); + + // else t0 is in front of the ray, so return the first collision point scaled by t0 + return this.at( t0, target ); + + } + + intersectsSphere( sphere ) { + + return this.distanceSqToPoint( sphere.center ) <= ( sphere.radius * sphere.radius ); + + } + + distanceToPlane( plane ) { + + const denominator = plane.normal.dot( this.direction ); + + if ( denominator === 0 ) { + + // line is coplanar, return origin + if ( plane.distanceToPoint( this.origin ) === 0 ) { + + return 0; + + } + + // Null is preferable to undefined since undefined means.... it is undefined + + return null; + + } + + const t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator; + + // Return if the ray never intersects the plane + + return t >= 0 ? t : null; + + } + + intersectPlane( plane, target ) { + + const t = this.distanceToPlane( plane ); + + if ( t === null ) { + + return null; + + } + + return this.at( t, target ); + + } + + intersectsPlane( plane ) { + + // check if the ray lies on the plane first + + const distToPoint = plane.distanceToPoint( this.origin ); + + if ( distToPoint === 0 ) { + + return true; + + } + + const denominator = plane.normal.dot( this.direction ); + + if ( denominator * distToPoint < 0 ) { + + return true; + + } + + // ray origin is behind the plane (and is pointing behind it) + + return false; + + } + + intersectBox( box, target ) { + + let tmin, tmax, tymin, tymax, tzmin, tzmax; + + const invdirx = 1 / this.direction.x, + invdiry = 1 / this.direction.y, + invdirz = 1 / this.direction.z; + + const origin = this.origin; + + if ( invdirx >= 0 ) { + + tmin = ( box.min.x - origin.x ) * invdirx; + tmax = ( box.max.x - origin.x ) * invdirx; + + } else { + + tmin = ( box.max.x - origin.x ) * invdirx; + tmax = ( box.min.x - origin.x ) * invdirx; + + } + + if ( invdiry >= 0 ) { + + tymin = ( box.min.y - origin.y ) * invdiry; + tymax = ( box.max.y - origin.y ) * invdiry; + + } else { + + tymin = ( box.max.y - origin.y ) * invdiry; + tymax = ( box.min.y - origin.y ) * invdiry; + + } + + if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null; + + // These lines also handle the case where tmin or tmax is NaN + // (result of 0 * Infinity). x !== x returns true if x is NaN + + if ( tymin > tmin || tmin !== tmin ) tmin = tymin; + + if ( tymax < tmax || tmax !== tmax ) tmax = tymax; + + if ( invdirz >= 0 ) { + + tzmin = ( box.min.z - origin.z ) * invdirz; + tzmax = ( box.max.z - origin.z ) * invdirz; + + } else { + + tzmin = ( box.max.z - origin.z ) * invdirz; + tzmax = ( box.min.z - origin.z ) * invdirz; + + } + + if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null; + + if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin; + + if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax; + + //return point closest to the ray (positive side) + + if ( tmax < 0 ) return null; + + return this.at( tmin >= 0 ? tmin : tmax, target ); + + } + + intersectsBox( box ) { + + return this.intersectBox( box, _vector$a ) !== null; + + } + + intersectTriangle( a, b, c, backfaceCulling, target ) { + + // Compute the offset origin, edges, and normal. + + // from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h + + _edge1.subVectors( b, a ); + _edge2.subVectors( c, a ); + _normal$1.crossVectors( _edge1, _edge2 ); + + // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction, + // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by + // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2)) + // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q)) + // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N) + let DdN = this.direction.dot( _normal$1 ); + let sign; + + if ( DdN > 0 ) { + + if ( backfaceCulling ) return null; + sign = 1; + + } else if ( DdN < 0 ) { + + sign = - 1; + DdN = - DdN; + + } else { + + return null; + + } + + _diff.subVectors( this.origin, a ); + const DdQxE2 = sign * this.direction.dot( _edge2.crossVectors( _diff, _edge2 ) ); + + // b1 < 0, no intersection + if ( DdQxE2 < 0 ) { + + return null; + + } + + const DdE1xQ = sign * this.direction.dot( _edge1.cross( _diff ) ); + + // b2 < 0, no intersection + if ( DdE1xQ < 0 ) { + + return null; + + } + + // b1+b2 > 1, no intersection + if ( DdQxE2 + DdE1xQ > DdN ) { + + return null; + + } + + // Line intersects triangle, check if ray does. + const QdN = - sign * _diff.dot( _normal$1 ); + + // t < 0, no intersection + if ( QdN < 0 ) { + + return null; + + } + + // Ray intersects triangle. + return this.at( QdN / DdN, target ); + + } + + applyMatrix4( matrix4 ) { + + this.origin.applyMatrix4( matrix4 ); + this.direction.transformDirection( matrix4 ); + + return this; + + } + + equals( ray ) { + + return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction ); + + } + + clone() { + + return new this.constructor().copy( this ); + + } + +} + +class Matrix4 { + + constructor() { + + this.elements = [ + + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + + ]; + + if ( arguments.length > 0 ) { + + console.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' ); + + } + + } + + set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { + + const te = this.elements; + + te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14; + te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24; + te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34; + te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44; + + return this; + + } + + identity() { + + this.set( + + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + + ); + + return this; + + } + + clone() { + + return new Matrix4().fromArray( this.elements ); + + } + + copy( m ) { + + const te = this.elements; + const me = m.elements; + + te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ]; + te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; + te[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ]; + te[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ]; + + return this; + + } + + copyPosition( m ) { + + const te = this.elements, me = m.elements; + + te[ 12 ] = me[ 12 ]; + te[ 13 ] = me[ 13 ]; + te[ 14 ] = me[ 14 ]; + + return this; + + } + + setFromMatrix3( m ) { + + const me = m.elements; + + this.set( + + me[ 0 ], me[ 3 ], me[ 6 ], 0, + me[ 1 ], me[ 4 ], me[ 7 ], 0, + me[ 2 ], me[ 5 ], me[ 8 ], 0, + 0, 0, 0, 1 + + ); + + return this; + + } + + extractBasis( xAxis, yAxis, zAxis ) { + + xAxis.setFromMatrixColumn( this, 0 ); + yAxis.setFromMatrixColumn( this, 1 ); + zAxis.setFromMatrixColumn( this, 2 ); + + return this; + + } + + makeBasis( xAxis, yAxis, zAxis ) { + + this.set( + xAxis.x, yAxis.x, zAxis.x, 0, + xAxis.y, yAxis.y, zAxis.y, 0, + xAxis.z, yAxis.z, zAxis.z, 0, + 0, 0, 0, 1 + ); + + return this; + + } + + extractRotation( m ) { + + // this method does not support reflection matrices + + const te = this.elements; + const me = m.elements; + + const scaleX = 1 / _v1$5.setFromMatrixColumn( m, 0 ).length(); + const scaleY = 1 / _v1$5.setFromMatrixColumn( m, 1 ).length(); + const scaleZ = 1 / _v1$5.setFromMatrixColumn( m, 2 ).length(); + + te[ 0 ] = me[ 0 ] * scaleX; + te[ 1 ] = me[ 1 ] * scaleX; + te[ 2 ] = me[ 2 ] * scaleX; + te[ 3 ] = 0; + + te[ 4 ] = me[ 4 ] * scaleY; + te[ 5 ] = me[ 5 ] * scaleY; + te[ 6 ] = me[ 6 ] * scaleY; + te[ 7 ] = 0; + + te[ 8 ] = me[ 8 ] * scaleZ; + te[ 9 ] = me[ 9 ] * scaleZ; + te[ 10 ] = me[ 10 ] * scaleZ; + te[ 11 ] = 0; + + te[ 12 ] = 0; + te[ 13 ] = 0; + te[ 14 ] = 0; + te[ 15 ] = 1; + + return this; + + } + + makeRotationFromEuler( euler ) { + + if ( ! ( euler && euler.isEuler ) ) { + + console.error( 'THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' ); + + } + + const te = this.elements; + + const x = euler.x, y = euler.y, z = euler.z; + const a = Math.cos( x ), b = Math.sin( x ); + const c = Math.cos( y ), d = Math.sin( y ); + const e = Math.cos( z ), f = Math.sin( z ); + + if ( euler.order === 'XYZ' ) { + + const ae = a * e, af = a * f, be = b * e, bf = b * f; + + te[ 0 ] = c * e; + te[ 4 ] = - c * f; + te[ 8 ] = d; + + te[ 1 ] = af + be * d; + te[ 5 ] = ae - bf * d; + te[ 9 ] = - b * c; + + te[ 2 ] = bf - ae * d; + te[ 6 ] = be + af * d; + te[ 10 ] = a * c; + + } else if ( euler.order === 'YXZ' ) { + + const ce = c * e, cf = c * f, de = d * e, df = d * f; + + te[ 0 ] = ce + df * b; + te[ 4 ] = de * b - cf; + te[ 8 ] = a * d; + + te[ 1 ] = a * f; + te[ 5 ] = a * e; + te[ 9 ] = - b; + + te[ 2 ] = cf * b - de; + te[ 6 ] = df + ce * b; + te[ 10 ] = a * c; + + } else if ( euler.order === 'ZXY' ) { + + const ce = c * e, cf = c * f, de = d * e, df = d * f; + + te[ 0 ] = ce - df * b; + te[ 4 ] = - a * f; + te[ 8 ] = de + cf * b; + + te[ 1 ] = cf + de * b; + te[ 5 ] = a * e; + te[ 9 ] = df - ce * b; + + te[ 2 ] = - a * d; + te[ 6 ] = b; + te[ 10 ] = a * c; + + } else if ( euler.order === 'ZYX' ) { + + const ae = a * e, af = a * f, be = b * e, bf = b * f; + + te[ 0 ] = c * e; + te[ 4 ] = be * d - af; + te[ 8 ] = ae * d + bf; + + te[ 1 ] = c * f; + te[ 5 ] = bf * d + ae; + te[ 9 ] = af * d - be; + + te[ 2 ] = - d; + te[ 6 ] = b * c; + te[ 10 ] = a * c; + + } else if ( euler.order === 'YZX' ) { const ac = a * c, ad = a * d, bc = b * c, bd = b * d; @@ -6720,837 +7293,305 @@ class Object3D extends EventDispatcher { }, quaternion: { configurable: true, - enumerable: true, - value: quaternion - }, - scale: { - configurable: true, - enumerable: true, - value: scale - }, - modelViewMatrix: { - value: new Matrix4() - }, - normalMatrix: { - value: new Matrix3() - } - } ); - - this.matrix = new Matrix4(); - this.matrixWorld = new Matrix4(); - - this.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate; - this.matrixWorldNeedsUpdate = false; - - this.layers = new Layers(); - this.visible = true; - - this.castShadow = false; - this.receiveShadow = false; - - this.frustumCulled = true; - this.renderOrder = 0; - - this.animations = []; - - this.userData = {}; - - } - - onBeforeRender( /* renderer, scene, camera, geometry, material, group */ ) {} - - onAfterRender( /* renderer, scene, camera, geometry, material, group */ ) {} - - applyMatrix4( matrix ) { - - if ( this.matrixAutoUpdate ) this.updateMatrix(); - - this.matrix.premultiply( matrix ); - - this.matrix.decompose( this.position, this.quaternion, this.scale ); - - } - - applyQuaternion( q ) { - - this.quaternion.premultiply( q ); - - return this; - - } - - setRotationFromAxisAngle( axis, angle ) { - - // assumes axis is normalized - - this.quaternion.setFromAxisAngle( axis, angle ); - - } - - setRotationFromEuler( euler ) { - - this.quaternion.setFromEuler( euler, true ); - - } - - setRotationFromMatrix( m ) { - - // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - - this.quaternion.setFromRotationMatrix( m ); - - } - - setRotationFromQuaternion( q ) { - - // assumes q is normalized - - this.quaternion.copy( q ); - - } - - rotateOnAxis( axis, angle ) { - - // rotate object on axis in object space - // axis is assumed to be normalized - - _q1.setFromAxisAngle( axis, angle ); - - this.quaternion.multiply( _q1 ); - - return this; - - } - - rotateOnWorldAxis( axis, angle ) { - - // rotate object on axis in world space - // axis is assumed to be normalized - // method assumes no rotated parent - - _q1.setFromAxisAngle( axis, angle ); - - this.quaternion.premultiply( _q1 ); - - return this; - - } - - rotateX( angle ) { - - return this.rotateOnAxis( _xAxis, angle ); - - } - - rotateY( angle ) { - - return this.rotateOnAxis( _yAxis, angle ); - - } - - rotateZ( angle ) { - - return this.rotateOnAxis( _zAxis, angle ); - - } - - translateOnAxis( axis, distance ) { - - // translate object by distance along axis in object space - // axis is assumed to be normalized - - _v1$4.copy( axis ).applyQuaternion( this.quaternion ); - - this.position.add( _v1$4.multiplyScalar( distance ) ); - - return this; - - } - - translateX( distance ) { - - return this.translateOnAxis( _xAxis, distance ); - - } - - translateY( distance ) { - - return this.translateOnAxis( _yAxis, distance ); - - } - - translateZ( distance ) { - - return this.translateOnAxis( _zAxis, distance ); - - } - - localToWorld( vector ) { - - return vector.applyMatrix4( this.matrixWorld ); - - } - - worldToLocal( vector ) { - - return vector.applyMatrix4( _m1$1.copy( this.matrixWorld ).invert() ); - - } - - lookAt( x, y, z ) { - - // This method does not support objects having non-uniformly-scaled parent(s) - - if ( x.isVector3 ) { - - _target.copy( x ); - - } else { - - _target.set( x, y, z ); - - } - - const parent = this.parent; - - this.updateWorldMatrix( true, false ); - - _position$3.setFromMatrixPosition( this.matrixWorld ); - - if ( this.isCamera || this.isLight ) { - - _m1$1.lookAt( _position$3, _target, this.up ); - - } else { - - _m1$1.lookAt( _target, _position$3, this.up ); - - } - - this.quaternion.setFromRotationMatrix( _m1$1 ); - - if ( parent ) { - - _m1$1.extractRotation( parent.matrixWorld ); - _q1.setFromRotationMatrix( _m1$1 ); - this.quaternion.premultiply( _q1.invert() ); - - } - - } - - add( object ) { - - if ( arguments.length > 1 ) { - - for ( let i = 0; i < arguments.length; i ++ ) { - - this.add( arguments[ i ] ); - - } - - return this; - - } - - if ( object === this ) { - - console.error( 'THREE.Object3D.add: object can\'t be added as a child of itself.', object ); - return this; - - } - - if ( object && object.isObject3D ) { - - if ( object.parent !== null ) { - - object.parent.remove( object ); - - } - - object.parent = this; - this.children.push( object ); - - object.dispatchEvent( _addedEvent ); - - } else { - - console.error( 'THREE.Object3D.add: object not an instance of THREE.Object3D.', object ); - - } - - return this; - - } - - remove( object ) { - - if ( arguments.length > 1 ) { - - for ( let i = 0; i < arguments.length; i ++ ) { - - this.remove( arguments[ i ] ); - - } - - return this; - - } - - const index = this.children.indexOf( object ); - - if ( index !== - 1 ) { - - object.parent = null; - this.children.splice( index, 1 ); - - object.dispatchEvent( _removedEvent ); - - } - - return this; - - } - - removeFromParent() { - - const parent = this.parent; - - if ( parent !== null ) { - - parent.remove( this ); - - } - - return this; - - } - - clear() { - - for ( let i = 0; i < this.children.length; i ++ ) { - - const object = this.children[ i ]; - - object.parent = null; - - object.dispatchEvent( _removedEvent ); - - } - - this.children.length = 0; - - return this; - - - } - - attach( object ) { - - // adds object as a child of this, while maintaining the object's world transform - - // Note: This method does not support scene graphs having non-uniformly-scaled nodes(s) - - this.updateWorldMatrix( true, false ); - - _m1$1.copy( this.matrixWorld ).invert(); - - if ( object.parent !== null ) { - - object.parent.updateWorldMatrix( true, false ); - - _m1$1.multiply( object.parent.matrixWorld ); - - } - - object.applyMatrix4( _m1$1 ); - - this.add( object ); - - object.updateWorldMatrix( false, true ); - - return this; - - } - - getObjectById( id ) { - - return this.getObjectByProperty( 'id', id ); - - } - - getObjectByName( name ) { - - return this.getObjectByProperty( 'name', name ); - - } - - getObjectByProperty( name, value ) { - - if ( this[ name ] === value ) return this; - - for ( let i = 0, l = this.children.length; i < l; i ++ ) { - - const child = this.children[ i ]; - const object = child.getObjectByProperty( name, value ); - - if ( object !== undefined ) { - - return object; - - } - - } - - return undefined; - - } - - getWorldPosition( target ) { - - this.updateWorldMatrix( true, false ); - - return target.setFromMatrixPosition( this.matrixWorld ); - - } - - getWorldQuaternion( target ) { - - this.updateWorldMatrix( true, false ); - - this.matrixWorld.decompose( _position$3, target, _scale$2 ); - - return target; - - } - - getWorldScale( target ) { - - this.updateWorldMatrix( true, false ); - - this.matrixWorld.decompose( _position$3, _quaternion$2, target ); - - return target; - - } - - getWorldDirection( target ) { - - this.updateWorldMatrix( true, false ); - - const e = this.matrixWorld.elements; - - return target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize(); - - } - - raycast( /* raycaster, intersects */ ) {} - - traverse( callback ) { - - callback( this ); - - const children = this.children; - - for ( let i = 0, l = children.length; i < l; i ++ ) { - - children[ i ].traverse( callback ); - - } - - } - - traverseVisible( callback ) { - - if ( this.visible === false ) return; - - callback( this ); - - const children = this.children; - - for ( let i = 0, l = children.length; i < l; i ++ ) { - - children[ i ].traverseVisible( callback ); - - } - - } - - traverseAncestors( callback ) { - - const parent = this.parent; - - if ( parent !== null ) { - - callback( parent ); - - parent.traverseAncestors( callback ); - - } - - } - - updateMatrix() { - - this.matrix.compose( this.position, this.quaternion, this.scale ); - - this.matrixWorldNeedsUpdate = true; - - } - - updateMatrixWorld( force ) { - - if ( this.matrixAutoUpdate ) this.updateMatrix(); - - if ( this.matrixWorldNeedsUpdate || force ) { - - if ( this.parent === null ) { - - this.matrixWorld.copy( this.matrix ); - - } else { - - this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix ); - + enumerable: true, + value: quaternion + }, + scale: { + configurable: true, + enumerable: true, + value: scale + }, + modelViewMatrix: { + value: new Matrix4() + }, + normalMatrix: { + value: new Matrix3() } + } ); - this.matrixWorldNeedsUpdate = false; - - force = true; + this.matrix = new Matrix4(); + this.matrixWorld = new Matrix4(); - } + this.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate; + this.matrixWorldNeedsUpdate = false; - // update children + this.layers = new Layers(); + this.visible = true; - const children = this.children; + this.castShadow = false; + this.receiveShadow = false; - for ( let i = 0, l = children.length; i < l; i ++ ) { + this.frustumCulled = true; + this.renderOrder = 0; - children[ i ].updateMatrixWorld( force ); + this.animations = []; - } + this.userData = {}; } - updateWorldMatrix( updateParents, updateChildren ) { - - const parent = this.parent; - - if ( updateParents === true && parent !== null ) { + onBeforeRender( /* renderer, scene, camera, geometry, material, group */ ) {} - parent.updateWorldMatrix( true, false ); + onAfterRender( /* renderer, scene, camera, geometry, material, group */ ) {} - } + applyMatrix4( matrix ) { if ( this.matrixAutoUpdate ) this.updateMatrix(); - if ( this.parent === null ) { + this.matrix.premultiply( matrix ); - this.matrixWorld.copy( this.matrix ); + this.matrix.decompose( this.position, this.quaternion, this.scale ); - } else { + } - this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix ); + applyQuaternion( q ) { - } + this.quaternion.premultiply( q ); - // update children + return this; - if ( updateChildren === true ) { + } - const children = this.children; + setRotationFromAxisAngle( axis, angle ) { - for ( let i = 0, l = children.length; i < l; i ++ ) { + // assumes axis is normalized - children[ i ].updateWorldMatrix( false, true ); + this.quaternion.setFromAxisAngle( axis, angle ); - } + } - } + setRotationFromEuler( euler ) { + + this.quaternion.setFromEuler( euler, true ); } - toJSON( meta ) { + setRotationFromMatrix( m ) { - // meta is a string when called from JSON.stringify - const isRootObject = ( meta === undefined || typeof meta === 'string' ); + // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - const output = {}; + this.quaternion.setFromRotationMatrix( m ); - // meta is a hash used to collect geometries, materials. - // not providing it implies that this is the root object - // being serialized. - if ( isRootObject ) { + } - // initialize meta obj - meta = { - geometries: {}, - materials: {}, - textures: {}, - images: {}, - shapes: {}, - skeletons: {}, - animations: {} - }; + setRotationFromQuaternion( q ) { - output.metadata = { - version: 4.5, - type: 'Object', - generator: 'Object3D.toJSON' - }; + // assumes q is normalized - } + this.quaternion.copy( q ); - // standard Object3D serialization + } - const object = {}; + rotateOnAxis( axis, angle ) { - object.uuid = this.uuid; - object.type = this.type; + // rotate object on axis in object space + // axis is assumed to be normalized - if ( this.name !== '' ) object.name = this.name; - if ( this.castShadow === true ) object.castShadow = true; - if ( this.receiveShadow === true ) object.receiveShadow = true; - if ( this.visible === false ) object.visible = false; - if ( this.frustumCulled === false ) object.frustumCulled = false; - if ( this.renderOrder !== 0 ) object.renderOrder = this.renderOrder; - if ( JSON.stringify( this.userData ) !== '{}' ) object.userData = this.userData; + _q1.setFromAxisAngle( axis, angle ); - object.layers = this.layers.mask; - object.matrix = this.matrix.toArray(); + this.quaternion.multiply( _q1 ); - if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false; + return this; - // object specific properties + } - if ( this.isInstancedMesh ) { + rotateOnWorldAxis( axis, angle ) { - object.type = 'InstancedMesh'; - object.count = this.count; - object.instanceMatrix = this.instanceMatrix.toJSON(); - if ( this.instanceColor !== null ) object.instanceColor = this.instanceColor.toJSON(); + // rotate object on axis in world space + // axis is assumed to be normalized + // method assumes no rotated parent - } + _q1.setFromAxisAngle( axis, angle ); - // + this.quaternion.premultiply( _q1 ); - function serialize( library, element ) { + return this; - if ( library[ element.uuid ] === undefined ) { + } - library[ element.uuid ] = element.toJSON( meta ); + rotateX( angle ) { - } + return this.rotateOnAxis( _xAxis, angle ); - return element.uuid; + } - } + rotateY( angle ) { - if ( this.isScene ) { + return this.rotateOnAxis( _yAxis, angle ); - if ( this.background ) { + } - if ( this.background.isColor ) { + rotateZ( angle ) { - object.background = this.background.toJSON(); + return this.rotateOnAxis( _zAxis, angle ); - } else if ( this.background.isTexture ) { + } - object.background = this.background.toJSON( meta ).uuid; + translateOnAxis( axis, distance ) { - } + // translate object by distance along axis in object space + // axis is assumed to be normalized - } + _v1$4.copy( axis ).applyQuaternion( this.quaternion ); - if ( this.environment && this.environment.isTexture ) { + this.position.add( _v1$4.multiplyScalar( distance ) ); - object.environment = this.environment.toJSON( meta ).uuid; + return this; - } + } - } else if ( this.isMesh || this.isLine || this.isPoints ) { + translateX( distance ) { - object.geometry = serialize( meta.geometries, this.geometry ); + return this.translateOnAxis( _xAxis, distance ); - const parameters = this.geometry.parameters; + } - if ( parameters !== undefined && parameters.shapes !== undefined ) { + translateY( distance ) { - const shapes = parameters.shapes; + return this.translateOnAxis( _yAxis, distance ); - if ( Array.isArray( shapes ) ) { + } - for ( let i = 0, l = shapes.length; i < l; i ++ ) { + translateZ( distance ) { - const shape = shapes[ i ]; + return this.translateOnAxis( _zAxis, distance ); - serialize( meta.shapes, shape ); + } - } + localToWorld( vector ) { - } else { + return vector.applyMatrix4( this.matrixWorld ); - serialize( meta.shapes, shapes ); + } - } + worldToLocal( vector ) { - } + return vector.applyMatrix4( _m1$1.copy( this.matrixWorld ).invert() ); - } + } - if ( this.isSkinnedMesh ) { + lookAt( x, y, z ) { - object.bindMode = this.bindMode; - object.bindMatrix = this.bindMatrix.toArray(); + // This method does not support objects having non-uniformly-scaled parent(s) - if ( this.skeleton !== undefined ) { + if ( x.isVector3 ) { - serialize( meta.skeletons, this.skeleton ); + _target.copy( x ); - object.skeleton = this.skeleton.uuid; + } else { - } + _target.set( x, y, z ); } - if ( this.material !== undefined ) { + const parent = this.parent; - if ( Array.isArray( this.material ) ) { + this.updateWorldMatrix( true, false ); - const uuids = []; + _position$3.setFromMatrixPosition( this.matrixWorld ); - for ( let i = 0, l = this.material.length; i < l; i ++ ) { + if ( this.isCamera || this.isLight ) { - uuids.push( serialize( meta.materials, this.material[ i ] ) ); + _m1$1.lookAt( _position$3, _target, this.up ); - } + } else { - object.material = uuids; + _m1$1.lookAt( _target, _position$3, this.up ); - } else { + } - object.material = serialize( meta.materials, this.material ); + this.quaternion.setFromRotationMatrix( _m1$1 ); - } + if ( parent ) { + + _m1$1.extractRotation( parent.matrixWorld ); + _q1.setFromRotationMatrix( _m1$1 ); + this.quaternion.premultiply( _q1.invert() ); } - // + } - if ( this.children.length > 0 ) { + add( object ) { - object.children = []; + if ( arguments.length > 1 ) { - for ( let i = 0; i < this.children.length; i ++ ) { + for ( let i = 0; i < arguments.length; i ++ ) { - object.children.push( this.children[ i ].toJSON( meta ).object ); + this.add( arguments[ i ] ); } + return this; + } - // + if ( object === this ) { - if ( this.animations.length > 0 ) { + console.error( 'THREE.Object3D.add: object can\'t be added as a child of itself.', object ); + return this; - object.animations = []; + } - for ( let i = 0; i < this.animations.length; i ++ ) { + if ( object && object.isObject3D ) { - const animation = this.animations[ i ]; + if ( object.parent !== null ) { - object.animations.push( serialize( meta.animations, animation ) ); + object.parent.remove( object ); } - } + object.parent = this; + this.children.push( object ); - if ( isRootObject ) { + object.dispatchEvent( _addedEvent ); - const geometries = extractFromCache( meta.geometries ); - const materials = extractFromCache( meta.materials ); - const textures = extractFromCache( meta.textures ); - const images = extractFromCache( meta.images ); - const shapes = extractFromCache( meta.shapes ); - const skeletons = extractFromCache( meta.skeletons ); - const animations = extractFromCache( meta.animations ); + } else { - if ( geometries.length > 0 ) output.geometries = geometries; - if ( materials.length > 0 ) output.materials = materials; - if ( textures.length > 0 ) output.textures = textures; - if ( images.length > 0 ) output.images = images; - if ( shapes.length > 0 ) output.shapes = shapes; - if ( skeletons.length > 0 ) output.skeletons = skeletons; - if ( animations.length > 0 ) output.animations = animations; + console.error( 'THREE.Object3D.add: object not an instance of THREE.Object3D.', object ); } - output.object = object; + return this; - return output; + } - // extract data from the cache hash - // remove metadata on each item - // and return as array - function extractFromCache( cache ) { + remove( object ) { - const values = []; - for ( const key in cache ) { + if ( arguments.length > 1 ) { - const data = cache[ key ]; - delete data.metadata; - values.push( data ); + for ( let i = 0; i < arguments.length; i ++ ) { + + this.remove( arguments[ i ] ); } - return values; + return this; } - } - - clone( recursive ) { - - return new this.constructor().copy( this, recursive ); - - } - - copy( source, recursive = true ) { - - this.name = source.name; - - this.up.copy( source.up ); - - this.position.copy( source.position ); - this.rotation.order = source.rotation.order; - this.quaternion.copy( source.quaternion ); - this.scale.copy( source.scale ); + const index = this.children.indexOf( object ); - this.matrix.copy( source.matrix ); - this.matrixWorld.copy( source.matrixWorld ); + if ( index !== - 1 ) { - this.matrixAutoUpdate = source.matrixAutoUpdate; - this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate; + object.parent = null; + this.children.splice( index, 1 ); - this.layers.mask = source.layers.mask; - this.visible = source.visible; + object.dispatchEvent( _removedEvent ); - this.castShadow = source.castShadow; - this.receiveShadow = source.receiveShadow; + } - this.frustumCulled = source.frustumCulled; - this.renderOrder = source.renderOrder; + return this; - this.userData = JSON.parse( JSON.stringify( source.userData ) ); + } - if ( recursive === true ) { + removeFromParent() { - for ( let i = 0; i < source.children.length; i ++ ) { + const parent = this.parent; - const child = source.children[ i ]; - this.add( child.clone() ); + if ( parent !== null ) { - } + parent.remove( this ); } @@ -7558,1395 +7599,1326 @@ class Object3D extends EventDispatcher { } -} - -Object3D.DefaultUp = new Vector3( 0, 1, 0 ); -Object3D.DefaultMatrixAutoUpdate = true; - -Object3D.prototype.isObject3D = true; + clear() { -const _v0$1 = /*@__PURE__*/ new Vector3(); -const _v1$3 = /*@__PURE__*/ new Vector3(); -const _v2$2 = /*@__PURE__*/ new Vector3(); -const _v3$1 = /*@__PURE__*/ new Vector3(); + for ( let i = 0; i < this.children.length; i ++ ) { -const _vab = /*@__PURE__*/ new Vector3(); -const _vac = /*@__PURE__*/ new Vector3(); -const _vbc = /*@__PURE__*/ new Vector3(); -const _vap = /*@__PURE__*/ new Vector3(); -const _vbp = /*@__PURE__*/ new Vector3(); -const _vcp = /*@__PURE__*/ new Vector3(); + const object = this.children[ i ]; -class Triangle { + object.parent = null; - constructor( a = new Vector3(), b = new Vector3(), c = new Vector3() ) { + object.dispatchEvent( _removedEvent ); - this.a = a; - this.b = b; - this.c = c; + } - } + this.children.length = 0; - static getNormal( a, b, c, target ) { + return this; - target.subVectors( c, b ); - _v0$1.subVectors( a, b ); - target.cross( _v0$1 ); - const targetLengthSq = target.lengthSq(); - if ( targetLengthSq > 0 ) { + } - return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) ); + attach( object ) { - } + // adds object as a child of this, while maintaining the object's world transform - return target.set( 0, 0, 0 ); + // Note: This method does not support scene graphs having non-uniformly-scaled nodes(s) - } + this.updateWorldMatrix( true, false ); - // static/instance method to calculate barycentric coordinates - // based on: http://www.blackpawn.com/texts/pointinpoly/default.html - static getBarycoord( point, a, b, c, target ) { + _m1$1.copy( this.matrixWorld ).invert(); - _v0$1.subVectors( c, a ); - _v1$3.subVectors( b, a ); - _v2$2.subVectors( point, a ); + if ( object.parent !== null ) { - const dot00 = _v0$1.dot( _v0$1 ); - const dot01 = _v0$1.dot( _v1$3 ); - const dot02 = _v0$1.dot( _v2$2 ); - const dot11 = _v1$3.dot( _v1$3 ); - const dot12 = _v1$3.dot( _v2$2 ); + object.parent.updateWorldMatrix( true, false ); - const denom = ( dot00 * dot11 - dot01 * dot01 ); + _m1$1.multiply( object.parent.matrixWorld ); - // collinear or singular triangle - if ( denom === 0 ) { + } - // arbitrary location outside of triangle? - // not sure if this is the best idea, maybe should be returning undefined - return target.set( - 2, - 1, - 1 ); + object.applyMatrix4( _m1$1 ); - } + this.add( object ); - const invDenom = 1 / denom; - const u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom; - const v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom; + object.updateWorldMatrix( false, true ); - // barycentric coordinates must always sum to 1 - return target.set( 1 - u - v, v, u ); + return this; } - static containsPoint( point, a, b, c ) { - - this.getBarycoord( point, a, b, c, _v3$1 ); + getObjectById( id ) { - return ( _v3$1.x >= 0 ) && ( _v3$1.y >= 0 ) && ( ( _v3$1.x + _v3$1.y ) <= 1 ); + return this.getObjectByProperty( 'id', id ); } - static getUV( point, p1, p2, p3, uv1, uv2, uv3, target ) { - - this.getBarycoord( point, p1, p2, p3, _v3$1 ); - - target.set( 0, 0 ); - target.addScaledVector( uv1, _v3$1.x ); - target.addScaledVector( uv2, _v3$1.y ); - target.addScaledVector( uv3, _v3$1.z ); + getObjectByName( name ) { - return target; + return this.getObjectByProperty( 'name', name ); } - static isFrontFacing( a, b, c, direction ) { - - _v0$1.subVectors( c, b ); - _v1$3.subVectors( a, b ); - - // strictly front facing - return ( _v0$1.cross( _v1$3 ).dot( direction ) < 0 ) ? true : false; + getObjectByProperty( name, value ) { - } + if ( this[ name ] === value ) return this; - set( a, b, c ) { + for ( let i = 0, l = this.children.length; i < l; i ++ ) { - this.a.copy( a ); - this.b.copy( b ); - this.c.copy( c ); + const child = this.children[ i ]; + const object = child.getObjectByProperty( name, value ); - return this; + if ( object !== undefined ) { - } + return object; - setFromPointsAndIndices( points, i0, i1, i2 ) { + } - this.a.copy( points[ i0 ] ); - this.b.copy( points[ i1 ] ); - this.c.copy( points[ i2 ] ); + } - return this; + return undefined; } - setFromAttributeAndIndices( attribute, i0, i1, i2 ) { + getWorldPosition( target ) { - this.a.fromBufferAttribute( attribute, i0 ); - this.b.fromBufferAttribute( attribute, i1 ); - this.c.fromBufferAttribute( attribute, i2 ); + this.updateWorldMatrix( true, false ); - return this; + return target.setFromMatrixPosition( this.matrixWorld ); } - clone() { - - return new this.constructor().copy( this ); - - } + getWorldQuaternion( target ) { - copy( triangle ) { + this.updateWorldMatrix( true, false ); - this.a.copy( triangle.a ); - this.b.copy( triangle.b ); - this.c.copy( triangle.c ); + this.matrixWorld.decompose( _position$3, target, _scale$2 ); - return this; + return target; } - getArea() { + getWorldScale( target ) { - _v0$1.subVectors( this.c, this.b ); - _v1$3.subVectors( this.a, this.b ); + this.updateWorldMatrix( true, false ); - return _v0$1.cross( _v1$3 ).length() * 0.5; + this.matrixWorld.decompose( _position$3, _quaternion$2, target ); - } + return target; - getMidpoint( target ) { + } - return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 ); + getWorldDirection( target ) { - } + this.updateWorldMatrix( true, false ); - getNormal( target ) { + const e = this.matrixWorld.elements; - return Triangle.getNormal( this.a, this.b, this.c, target ); + return target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize(); } - getPlane( target ) { - - return target.setFromCoplanarPoints( this.a, this.b, this.c ); + raycast( /* raycaster, intersects */ ) {} - } + traverse( callback ) { - getBarycoord( point, target ) { + callback( this ); - return Triangle.getBarycoord( point, this.a, this.b, this.c, target ); + const children = this.children; - } + for ( let i = 0, l = children.length; i < l; i ++ ) { - getUV( point, uv1, uv2, uv3, target ) { + children[ i ].traverse( callback ); - return Triangle.getUV( point, this.a, this.b, this.c, uv1, uv2, uv3, target ); + } } - containsPoint( point ) { - - return Triangle.containsPoint( point, this.a, this.b, this.c ); + traverseVisible( callback ) { - } + if ( this.visible === false ) return; - isFrontFacing( direction ) { + callback( this ); - return Triangle.isFrontFacing( this.a, this.b, this.c, direction ); + const children = this.children; - } + for ( let i = 0, l = children.length; i < l; i ++ ) { - intersectsBox( box ) { + children[ i ].traverseVisible( callback ); - return box.intersectsTriangle( this ); + } } - closestPointToPoint( p, target ) { + traverseAncestors( callback ) { - const a = this.a, b = this.b, c = this.c; - let v, w; + const parent = this.parent; - // algorithm thanks to Real-Time Collision Detection by Christer Ericson, - // published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc., - // under the accompanying license; see chapter 5.1.5 for detailed explanation. - // basically, we're distinguishing which of the voronoi regions of the triangle - // the point lies in with the minimum amount of redundant computation. + if ( parent !== null ) { - _vab.subVectors( b, a ); - _vac.subVectors( c, a ); - _vap.subVectors( p, a ); - const d1 = _vab.dot( _vap ); - const d2 = _vac.dot( _vap ); - if ( d1 <= 0 && d2 <= 0 ) { + callback( parent ); - // vertex region of A; barycentric coords (1, 0, 0) - return target.copy( a ); + parent.traverseAncestors( callback ); } - _vbp.subVectors( p, b ); - const d3 = _vab.dot( _vbp ); - const d4 = _vac.dot( _vbp ); - if ( d3 >= 0 && d4 <= d3 ) { + } - // vertex region of B; barycentric coords (0, 1, 0) - return target.copy( b ); + updateMatrix() { - } + this.matrix.compose( this.position, this.quaternion, this.scale ); - const vc = d1 * d4 - d3 * d2; - if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) { + this.matrixWorldNeedsUpdate = true; - v = d1 / ( d1 - d3 ); - // edge region of AB; barycentric coords (1-v, v, 0) - return target.copy( a ).addScaledVector( _vab, v ); + } - } + updateMatrixWorld( force ) { - _vcp.subVectors( p, c ); - const d5 = _vab.dot( _vcp ); - const d6 = _vac.dot( _vcp ); - if ( d6 >= 0 && d5 <= d6 ) { + if ( this.matrixAutoUpdate ) this.updateMatrix(); - // vertex region of C; barycentric coords (0, 0, 1) - return target.copy( c ); + if ( this.matrixWorldNeedsUpdate || force ) { - } + if ( this.parent === null ) { - const vb = d5 * d2 - d1 * d6; - if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) { + this.matrixWorld.copy( this.matrix ); - w = d2 / ( d2 - d6 ); - // edge region of AC; barycentric coords (1-w, 0, w) - return target.copy( a ).addScaledVector( _vac, w ); + } else { - } + this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix ); - const va = d3 * d6 - d5 * d4; - if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) { + } - _vbc.subVectors( c, b ); - w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) ); - // edge region of BC; barycentric coords (0, 1-w, w) - return target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC + this.matrixWorldNeedsUpdate = false; + + force = true; } - // face region - const denom = 1 / ( va + vb + vc ); - // u = va * denom - v = vb * denom; - w = vc * denom; + // update children - return target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w ); + const children = this.children; - } + for ( let i = 0, l = children.length; i < l; i ++ ) { - equals( triangle ) { + children[ i ].updateMatrixWorld( force ); - return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c ); + } } -} - -let materialId = 0; + updateWorldMatrix( updateParents, updateChildren ) { -class Material extends EventDispatcher { + const parent = this.parent; - constructor() { + if ( updateParents === true && parent !== null ) { - super(); + parent.updateWorldMatrix( true, false ); - Object.defineProperty( this, 'id', { value: materialId ++ } ); + } - this.uuid = generateUUID(); + if ( this.matrixAutoUpdate ) this.updateMatrix(); - this.name = ''; - this.type = 'Material'; + if ( this.parent === null ) { - this.fog = true; + this.matrixWorld.copy( this.matrix ); - this.blending = NormalBlending; - this.side = FrontSide; - this.vertexColors = false; + } else { - this.opacity = 1; - this.format = RGBAFormat; - this.transparent = false; + this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix ); - this.blendSrc = SrcAlphaFactor; - this.blendDst = OneMinusSrcAlphaFactor; - this.blendEquation = AddEquation; - this.blendSrcAlpha = null; - this.blendDstAlpha = null; - this.blendEquationAlpha = null; + } - this.depthFunc = LessEqualDepth; - this.depthTest = true; - this.depthWrite = true; + // update children - this.stencilWriteMask = 0xff; - this.stencilFunc = AlwaysStencilFunc; - this.stencilRef = 0; - this.stencilFuncMask = 0xff; - this.stencilFail = KeepStencilOp; - this.stencilZFail = KeepStencilOp; - this.stencilZPass = KeepStencilOp; - this.stencilWrite = false; + if ( updateChildren === true ) { - this.clippingPlanes = null; - this.clipIntersection = false; - this.clipShadows = false; + const children = this.children; - this.shadowSide = null; + for ( let i = 0, l = children.length; i < l; i ++ ) { - this.colorWrite = true; + children[ i ].updateWorldMatrix( false, true ); - this.precision = null; // override the renderer's default precision for this material + } - this.polygonOffset = false; - this.polygonOffsetFactor = 0; - this.polygonOffsetUnits = 0; + } - this.dithering = false; + } - this.alphaToCoverage = false; - this.premultipliedAlpha = false; + toJSON( meta ) { - this.visible = true; + // meta is a string when called from JSON.stringify + const isRootObject = ( meta === undefined || typeof meta === 'string' ); - this.toneMapped = true; + const output = {}; - this.userData = {}; + // meta is a hash used to collect geometries, materials. + // not providing it implies that this is the root object + // being serialized. + if ( isRootObject ) { - this.version = 0; + // initialize meta obj + meta = { + geometries: {}, + materials: {}, + textures: {}, + images: {}, + shapes: {}, + skeletons: {}, + animations: {} + }; - this._alphaTest = 0; + output.metadata = { + version: 4.5, + type: 'Object', + generator: 'Object3D.toJSON' + }; - } + } - get alphaTest() { + // standard Object3D serialization - return this._alphaTest; + const object = {}; - } + object.uuid = this.uuid; + object.type = this.type; - set alphaTest( value ) { + if ( this.name !== '' ) object.name = this.name; + if ( this.castShadow === true ) object.castShadow = true; + if ( this.receiveShadow === true ) object.receiveShadow = true; + if ( this.visible === false ) object.visible = false; + if ( this.frustumCulled === false ) object.frustumCulled = false; + if ( this.renderOrder !== 0 ) object.renderOrder = this.renderOrder; + if ( JSON.stringify( this.userData ) !== '{}' ) object.userData = this.userData; - if ( this._alphaTest > 0 !== value > 0 ) { + object.layers = this.layers.mask; + object.matrix = this.matrix.toArray(); - this.version ++; + if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false; - } + // object specific properties - this._alphaTest = value; + if ( this.isInstancedMesh ) { - } + object.type = 'InstancedMesh'; + object.count = this.count; + object.instanceMatrix = this.instanceMatrix.toJSON(); + if ( this.instanceColor !== null ) object.instanceColor = this.instanceColor.toJSON(); - onBuild( /* shaderobject, renderer */ ) {} + } - onBeforeRender( /* renderer, scene, camera, geometry, object, group */ ) {} + // - onBeforeCompile( /* shaderobject, renderer */ ) {} + function serialize( library, element ) { - customProgramCacheKey() { + if ( library[ element.uuid ] === undefined ) { - return this.onBeforeCompile.toString(); + library[ element.uuid ] = element.toJSON( meta ); - } + } - setValues( values ) { + return element.uuid; - if ( values === undefined ) return; + } - for ( const key in values ) { + if ( this.isScene ) { - const newValue = values[ key ]; + if ( this.background ) { - if ( newValue === undefined ) { + if ( this.background.isColor ) { - console.warn( 'THREE.Material: \'' + key + '\' parameter is undefined.' ); - continue; + object.background = this.background.toJSON(); - } + } else if ( this.background.isTexture ) { - // for backward compatability if shading is set in the constructor - if ( key === 'shading' ) { + object.background = this.background.toJSON( meta ).uuid; - console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' ); - this.flatShading = ( newValue === FlatShading ) ? true : false; - continue; + } } - const currentValue = this[ key ]; - - if ( currentValue === undefined ) { + if ( this.environment && this.environment.isTexture ) { - console.warn( 'THREE.' + this.type + ': \'' + key + '\' is not a property of this material.' ); - continue; + object.environment = this.environment.toJSON( meta ).uuid; } - if ( currentValue && currentValue.isColor ) { - - currentValue.set( newValue ); + } else if ( this.isMesh || this.isLine || this.isPoints ) { - } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) { + object.geometry = serialize( meta.geometries, this.geometry ); - currentValue.copy( newValue ); + const parameters = this.geometry.parameters; - } else { + if ( parameters !== undefined && parameters.shapes !== undefined ) { - this[ key ] = newValue; + const shapes = parameters.shapes; - } + if ( Array.isArray( shapes ) ) { - } + for ( let i = 0, l = shapes.length; i < l; i ++ ) { - } + const shape = shapes[ i ]; - toJSON( meta ) { + serialize( meta.shapes, shape ); - const isRoot = ( meta === undefined || typeof meta === 'string' ); + } - if ( isRoot ) { + } else { - meta = { - textures: {}, - images: {} - }; + serialize( meta.shapes, shapes ); - } + } - const data = { - metadata: { - version: 4.5, - type: 'Material', - generator: 'Material.toJSON' } - }; - - // standard Material serialization - data.uuid = this.uuid; - data.type = this.type; - if ( this.name !== '' ) data.name = this.name; + } - if ( this.color && this.color.isColor ) data.color = this.color.getHex(); + if ( this.isSkinnedMesh ) { - if ( this.roughness !== undefined ) data.roughness = this.roughness; - if ( this.metalness !== undefined ) data.metalness = this.metalness; + object.bindMode = this.bindMode; + object.bindMatrix = this.bindMatrix.toArray(); - if ( this.sheen !== undefined ) data.sheen = this.sheen; - if ( this.sheenColor && this.sheenColor.isColor ) data.sheenColor = this.sheenColor.getHex(); - if ( this.sheenRoughness !== undefined ) data.sheenRoughness = this.sheenRoughness; - if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex(); - if ( this.emissiveIntensity && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity; + if ( this.skeleton !== undefined ) { - if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex(); - if ( this.specularIntensity !== undefined ) data.specularIntensity = this.specularIntensity; - if ( this.specularColor && this.specularColor.isColor ) data.specularColor = this.specularColor.getHex(); - if ( this.shininess !== undefined ) data.shininess = this.shininess; - if ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat; - if ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness; + serialize( meta.skeletons, this.skeleton ); - if ( this.clearcoatMap && this.clearcoatMap.isTexture ) { + object.skeleton = this.skeleton.uuid; - data.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid; + } } - if ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) { + if ( this.material !== undefined ) { - data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON( meta ).uuid; + if ( Array.isArray( this.material ) ) { - } + const uuids = []; - if ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) { + for ( let i = 0, l = this.material.length; i < l; i ++ ) { - data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid; - data.clearcoatNormalScale = this.clearcoatNormalScale.toArray(); + uuids.push( serialize( meta.materials, this.material[ i ] ) ); - } + } - if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid; - if ( this.matcap && this.matcap.isTexture ) data.matcap = this.matcap.toJSON( meta ).uuid; - if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid; + object.material = uuids; - if ( this.lightMap && this.lightMap.isTexture ) { + } else { - data.lightMap = this.lightMap.toJSON( meta ).uuid; - data.lightMapIntensity = this.lightMapIntensity; + object.material = serialize( meta.materials, this.material ); + + } } - if ( this.aoMap && this.aoMap.isTexture ) { + // - data.aoMap = this.aoMap.toJSON( meta ).uuid; - data.aoMapIntensity = this.aoMapIntensity; + if ( this.children.length > 0 ) { - } + object.children = []; - if ( this.bumpMap && this.bumpMap.isTexture ) { + for ( let i = 0; i < this.children.length; i ++ ) { - data.bumpMap = this.bumpMap.toJSON( meta ).uuid; - data.bumpScale = this.bumpScale; + object.children.push( this.children[ i ].toJSON( meta ).object ); + + } } - if ( this.normalMap && this.normalMap.isTexture ) { + // - data.normalMap = this.normalMap.toJSON( meta ).uuid; - data.normalMapType = this.normalMapType; - data.normalScale = this.normalScale.toArray(); + if ( this.animations.length > 0 ) { - } + object.animations = []; - if ( this.displacementMap && this.displacementMap.isTexture ) { + for ( let i = 0; i < this.animations.length; i ++ ) { - data.displacementMap = this.displacementMap.toJSON( meta ).uuid; - data.displacementScale = this.displacementScale; - data.displacementBias = this.displacementBias; + const animation = this.animations[ i ]; - } + object.animations.push( serialize( meta.animations, animation ) ); - if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid; - if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid; + } - if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid; - if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid; - if ( this.specularIntensityMap && this.specularIntensityMap.isTexture ) data.specularIntensityMap = this.specularIntensityMap.toJSON( meta ).uuid; - if ( this.specularColorMap && this.specularColorMap.isTexture ) data.specularColorMap = this.specularColorMap.toJSON( meta ).uuid; + } - if ( this.envMap && this.envMap.isTexture ) { + if ( isRootObject ) { - data.envMap = this.envMap.toJSON( meta ).uuid; + const geometries = extractFromCache( meta.geometries ); + const materials = extractFromCache( meta.materials ); + const textures = extractFromCache( meta.textures ); + const images = extractFromCache( meta.images ); + const shapes = extractFromCache( meta.shapes ); + const skeletons = extractFromCache( meta.skeletons ); + const animations = extractFromCache( meta.animations ); - if ( this.combine !== undefined ) data.combine = this.combine; + if ( geometries.length > 0 ) output.geometries = geometries; + if ( materials.length > 0 ) output.materials = materials; + if ( textures.length > 0 ) output.textures = textures; + if ( images.length > 0 ) output.images = images; + if ( shapes.length > 0 ) output.shapes = shapes; + if ( skeletons.length > 0 ) output.skeletons = skeletons; + if ( animations.length > 0 ) output.animations = animations; } - if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity; - if ( this.reflectivity !== undefined ) data.reflectivity = this.reflectivity; - if ( this.refractionRatio !== undefined ) data.refractionRatio = this.refractionRatio; + output.object = object; - if ( this.gradientMap && this.gradientMap.isTexture ) { + return output; - data.gradientMap = this.gradientMap.toJSON( meta ).uuid; + // extract data from the cache hash + // remove metadata on each item + // and return as array + function extractFromCache( cache ) { - } + const values = []; + for ( const key in cache ) { - if ( this.transmission !== undefined ) data.transmission = this.transmission; - if ( this.transmissionMap && this.transmissionMap.isTexture ) data.transmissionMap = this.transmissionMap.toJSON( meta ).uuid; - if ( this.thickness !== undefined ) data.thickness = this.thickness; - if ( this.thicknessMap && this.thicknessMap.isTexture ) data.thicknessMap = this.thicknessMap.toJSON( meta ).uuid; - if ( this.attenuationDistance !== undefined ) data.attenuationDistance = this.attenuationDistance; - if ( this.attenuationColor !== undefined ) data.attenuationColor = this.attenuationColor.getHex(); + const data = cache[ key ]; + delete data.metadata; + values.push( data ); - if ( this.size !== undefined ) data.size = this.size; - if ( this.shadowSide !== null ) data.shadowSide = this.shadowSide; - if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation; + } - if ( this.blending !== NormalBlending ) data.blending = this.blending; - if ( this.side !== FrontSide ) data.side = this.side; - if ( this.vertexColors ) data.vertexColors = true; + return values; - if ( this.opacity < 1 ) data.opacity = this.opacity; - if ( this.format !== RGBAFormat ) data.format = this.format; - if ( this.transparent === true ) data.transparent = this.transparent; + } - data.depthFunc = this.depthFunc; - data.depthTest = this.depthTest; - data.depthWrite = this.depthWrite; - data.colorWrite = this.colorWrite; + } - data.stencilWrite = this.stencilWrite; - data.stencilWriteMask = this.stencilWriteMask; - data.stencilFunc = this.stencilFunc; - data.stencilRef = this.stencilRef; - data.stencilFuncMask = this.stencilFuncMask; - data.stencilFail = this.stencilFail; - data.stencilZFail = this.stencilZFail; - data.stencilZPass = this.stencilZPass; + clone( recursive ) { - // rotation (SpriteMaterial) - if ( this.rotation && this.rotation !== 0 ) data.rotation = this.rotation; + return new this.constructor().copy( this, recursive ); - if ( this.polygonOffset === true ) data.polygonOffset = true; - if ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor; - if ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits; + } - if ( this.linewidth && this.linewidth !== 1 ) data.linewidth = this.linewidth; - if ( this.dashSize !== undefined ) data.dashSize = this.dashSize; - if ( this.gapSize !== undefined ) data.gapSize = this.gapSize; - if ( this.scale !== undefined ) data.scale = this.scale; + copy( source, recursive = true ) { - if ( this.dithering === true ) data.dithering = true; + this.name = source.name; - if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest; - if ( this.alphaToCoverage === true ) data.alphaToCoverage = this.alphaToCoverage; - if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha; + this.up.copy( source.up ); - if ( this.wireframe === true ) data.wireframe = this.wireframe; - if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth; - if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap; - if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin; + this.position.copy( source.position ); + this.rotation.order = source.rotation.order; + this.quaternion.copy( source.quaternion ); + this.scale.copy( source.scale ); - if ( this.flatShading === true ) data.flatShading = this.flatShading; + this.matrix.copy( source.matrix ); + this.matrixWorld.copy( source.matrixWorld ); - if ( this.visible === false ) data.visible = false; + this.matrixAutoUpdate = source.matrixAutoUpdate; + this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate; - if ( this.toneMapped === false ) data.toneMapped = false; + this.layers.mask = source.layers.mask; + this.visible = source.visible; - if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData; + this.castShadow = source.castShadow; + this.receiveShadow = source.receiveShadow; - // TODO: Copied from Object3D.toJSON + this.frustumCulled = source.frustumCulled; + this.renderOrder = source.renderOrder; - function extractFromCache( cache ) { + this.userData = JSON.parse( JSON.stringify( source.userData ) ); - const values = []; + if ( recursive === true ) { - for ( const key in cache ) { + for ( let i = 0; i < source.children.length; i ++ ) { - const data = cache[ key ]; - delete data.metadata; - values.push( data ); + const child = source.children[ i ]; + this.add( child.clone() ); } - return values; - } - if ( isRoot ) { + return this; - const textures = extractFromCache( meta.textures ); - const images = extractFromCache( meta.images ); + } - if ( textures.length > 0 ) data.textures = textures; - if ( images.length > 0 ) data.images = images; +} - } +Object3D.DefaultUp = new Vector3( 0, 1, 0 ); +Object3D.DefaultMatrixAutoUpdate = true; - return data; +Object3D.prototype.isObject3D = true; - } +const _v0$1 = /*@__PURE__*/ new Vector3(); +const _v1$3 = /*@__PURE__*/ new Vector3(); +const _v2$2 = /*@__PURE__*/ new Vector3(); +const _v3$1 = /*@__PURE__*/ new Vector3(); - clone() { +const _vab = /*@__PURE__*/ new Vector3(); +const _vac = /*@__PURE__*/ new Vector3(); +const _vbc = /*@__PURE__*/ new Vector3(); +const _vap = /*@__PURE__*/ new Vector3(); +const _vbp = /*@__PURE__*/ new Vector3(); +const _vcp = /*@__PURE__*/ new Vector3(); - return new this.constructor().copy( this ); +class Triangle { - } + constructor( a = new Vector3(), b = new Vector3(), c = new Vector3() ) { - copy( source ) { + this.a = a; + this.b = b; + this.c = c; - this.name = source.name; + } - this.fog = source.fog; + static getNormal( a, b, c, target ) { - this.blending = source.blending; - this.side = source.side; - this.vertexColors = source.vertexColors; + target.subVectors( c, b ); + _v0$1.subVectors( a, b ); + target.cross( _v0$1 ); - this.opacity = source.opacity; - this.format = source.format; - this.transparent = source.transparent; + const targetLengthSq = target.lengthSq(); + if ( targetLengthSq > 0 ) { - this.blendSrc = source.blendSrc; - this.blendDst = source.blendDst; - this.blendEquation = source.blendEquation; - this.blendSrcAlpha = source.blendSrcAlpha; - this.blendDstAlpha = source.blendDstAlpha; - this.blendEquationAlpha = source.blendEquationAlpha; + return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) ); - this.depthFunc = source.depthFunc; - this.depthTest = source.depthTest; - this.depthWrite = source.depthWrite; + } - this.stencilWriteMask = source.stencilWriteMask; - this.stencilFunc = source.stencilFunc; - this.stencilRef = source.stencilRef; - this.stencilFuncMask = source.stencilFuncMask; - this.stencilFail = source.stencilFail; - this.stencilZFail = source.stencilZFail; - this.stencilZPass = source.stencilZPass; - this.stencilWrite = source.stencilWrite; + return target.set( 0, 0, 0 ); - const srcPlanes = source.clippingPlanes; - let dstPlanes = null; + } - if ( srcPlanes !== null ) { + // static/instance method to calculate barycentric coordinates + // based on: http://www.blackpawn.com/texts/pointinpoly/default.html + static getBarycoord( point, a, b, c, target ) { - const n = srcPlanes.length; - dstPlanes = new Array( n ); + _v0$1.subVectors( c, a ); + _v1$3.subVectors( b, a ); + _v2$2.subVectors( point, a ); - for ( let i = 0; i !== n; ++ i ) { + const dot00 = _v0$1.dot( _v0$1 ); + const dot01 = _v0$1.dot( _v1$3 ); + const dot02 = _v0$1.dot( _v2$2 ); + const dot11 = _v1$3.dot( _v1$3 ); + const dot12 = _v1$3.dot( _v2$2 ); - dstPlanes[ i ] = srcPlanes[ i ].clone(); + const denom = ( dot00 * dot11 - dot01 * dot01 ); - } + // collinear or singular triangle + if ( denom === 0 ) { + + // arbitrary location outside of triangle? + // not sure if this is the best idea, maybe should be returning undefined + return target.set( - 2, - 1, - 1 ); } - this.clippingPlanes = dstPlanes; - this.clipIntersection = source.clipIntersection; - this.clipShadows = source.clipShadows; + const invDenom = 1 / denom; + const u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom; + const v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom; - this.shadowSide = source.shadowSide; + // barycentric coordinates must always sum to 1 + return target.set( 1 - u - v, v, u ); - this.colorWrite = source.colorWrite; + } - this.precision = source.precision; + static containsPoint( point, a, b, c ) { - this.polygonOffset = source.polygonOffset; - this.polygonOffsetFactor = source.polygonOffsetFactor; - this.polygonOffsetUnits = source.polygonOffsetUnits; + this.getBarycoord( point, a, b, c, _v3$1 ); - this.dithering = source.dithering; + return ( _v3$1.x >= 0 ) && ( _v3$1.y >= 0 ) && ( ( _v3$1.x + _v3$1.y ) <= 1 ); - this.alphaTest = source.alphaTest; - this.alphaToCoverage = source.alphaToCoverage; - this.premultipliedAlpha = source.premultipliedAlpha; + } - this.visible = source.visible; + static getUV( point, p1, p2, p3, uv1, uv2, uv3, target ) { - this.toneMapped = source.toneMapped; + this.getBarycoord( point, p1, p2, p3, _v3$1 ); - this.userData = JSON.parse( JSON.stringify( source.userData ) ); + target.set( 0, 0 ); + target.addScaledVector( uv1, _v3$1.x ); + target.addScaledVector( uv2, _v3$1.y ); + target.addScaledVector( uv3, _v3$1.z ); - return this; + return target; } - dispose() { + static isFrontFacing( a, b, c, direction ) { - this.dispatchEvent( { type: 'dispose' } ); + _v0$1.subVectors( c, b ); + _v1$3.subVectors( a, b ); + + // strictly front facing + return ( _v0$1.cross( _v1$3 ).dot( direction ) < 0 ) ? true : false; } - set needsUpdate( value ) { + set( a, b, c ) { - if ( value === true ) this.version ++; + this.a.copy( a ); + this.b.copy( b ); + this.c.copy( c ); - } + return this; -} + } -Material.prototype.isMaterial = true; + setFromPointsAndIndices( points, i0, i1, i2 ) { -const _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, 'rebeccapurple': 0x663399, '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 }; + this.a.copy( points[ i0 ] ); + this.b.copy( points[ i1 ] ); + this.c.copy( points[ i2 ] ); -const _hslA = { h: 0, s: 0, l: 0 }; -const _hslB = { h: 0, s: 0, l: 0 }; + return this; -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; + setFromAttributeAndIndices( attribute, i0, i1, i2 ) { -} + this.a.fromBufferAttribute( attribute, i0 ); + this.b.fromBufferAttribute( attribute, i1 ); + this.c.fromBufferAttribute( attribute, i2 ); -function SRGBToLinear( c ) { + return this; - return ( c < 0.04045 ) ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 ); + } -} + clone() { -function LinearToSRGB( c ) { + return new this.constructor().copy( this ); - return ( c < 0.0031308 ) ? c * 12.92 : 1.055 * ( Math.pow( c, 0.41666 ) ) - 0.055; + } -} + copy( triangle ) { -class Color { + this.a.copy( triangle.a ); + this.b.copy( triangle.b ); + this.c.copy( triangle.c ); - constructor( r, g, b ) { + return this; - if ( g === undefined && b === undefined ) { + } - // r is THREE.Color, hex or string - return this.set( r ); + getArea() { - } + _v0$1.subVectors( this.c, this.b ); + _v1$3.subVectors( this.a, this.b ); - return this.setRGB( r, g, b ); + return _v0$1.cross( _v1$3 ).length() * 0.5; } - set( value ) { - - if ( value && value.isColor ) { + getMidpoint( target ) { - this.copy( value ); + return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 ); - } else if ( typeof value === 'number' ) { + } - this.setHex( value ); + getNormal( target ) { - } else if ( typeof value === 'string' ) { + return Triangle.getNormal( this.a, this.b, this.c, target ); - this.setStyle( value ); + } - } + getPlane( target ) { - return this; + return target.setFromCoplanarPoints( this.a, this.b, this.c ); } - setScalar( scalar ) { - - this.r = scalar; - this.g = scalar; - this.b = scalar; + getBarycoord( point, target ) { - return this; + return Triangle.getBarycoord( point, this.a, this.b, this.c, target ); } - setHex( hex ) { + getUV( point, uv1, uv2, uv3, target ) { - hex = Math.floor( hex ); + return Triangle.getUV( point, this.a, this.b, this.c, uv1, uv2, uv3, target ); - this.r = ( hex >> 16 & 255 ) / 255; - this.g = ( hex >> 8 & 255 ) / 255; - this.b = ( hex & 255 ) / 255; + } - return this; + containsPoint( point ) { - } + return Triangle.containsPoint( point, this.a, this.b, this.c ); - setRGB( r, g, b ) { + } - this.r = r; - this.g = g; - this.b = b; + isFrontFacing( direction ) { - return this; + return Triangle.isFrontFacing( this.a, this.b, this.c, direction ); } - setHSL( h, s, l ) { + intersectsBox( box ) { - // h,s,l ranges are in 0.0 - 1.0 - h = euclideanModulo( h, 1 ); - s = clamp( s, 0, 1 ); - l = clamp( l, 0, 1 ); + return box.intersectsTriangle( this ); - if ( s === 0 ) { + } - this.r = this.g = this.b = l; + closestPointToPoint( p, target ) { - } else { + const a = this.a, b = this.b, c = this.c; + let v, w; - const p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s ); - const q = ( 2 * l ) - p; + // algorithm thanks to Real-Time Collision Detection by Christer Ericson, + // published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc., + // under the accompanying license; see chapter 5.1.5 for detailed explanation. + // basically, we're distinguishing which of the voronoi regions of the triangle + // the point lies in with the minimum amount of redundant computation. - this.r = hue2rgb( q, p, h + 1 / 3 ); - this.g = hue2rgb( q, p, h ); - this.b = hue2rgb( q, p, h - 1 / 3 ); + _vab.subVectors( b, a ); + _vac.subVectors( c, a ); + _vap.subVectors( p, a ); + const d1 = _vab.dot( _vap ); + const d2 = _vac.dot( _vap ); + if ( d1 <= 0 && d2 <= 0 ) { + + // vertex region of A; barycentric coords (1, 0, 0) + return target.copy( a ); } - return this; + _vbp.subVectors( p, b ); + const d3 = _vab.dot( _vbp ); + const d4 = _vac.dot( _vbp ); + if ( d3 >= 0 && d4 <= d3 ) { - } + // vertex region of B; barycentric coords (0, 1, 0) + return target.copy( b ); - setStyle( style ) { + } - function handleAlpha( string ) { + const vc = d1 * d4 - d3 * d2; + if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) { - if ( string === undefined ) return; + v = d1 / ( d1 - d3 ); + // edge region of AB; barycentric coords (1-v, v, 0) + return target.copy( a ).addScaledVector( _vab, v ); - if ( parseFloat( string ) < 1 ) { + } - console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' ); + _vcp.subVectors( p, c ); + const d5 = _vab.dot( _vcp ); + const d6 = _vac.dot( _vcp ); + if ( d6 >= 0 && d5 <= d6 ) { - } + // vertex region of C; barycentric coords (0, 0, 1) + return target.copy( c ); } + const vb = d5 * d2 - d1 * d6; + if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) { - let m; + w = d2 / ( d2 - d6 ); + // edge region of AC; barycentric coords (1-w, 0, w) + return target.copy( a ).addScaledVector( _vac, w ); - if ( m = /^((?:rgb|hsl)a?)\(([^\)]*)\)/.exec( style ) ) { + } - // rgb / hsl + const va = d3 * d6 - d5 * d4; + if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) { - let color; - const name = m[ 1 ]; - const components = m[ 2 ]; + _vbc.subVectors( c, b ); + w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) ); + // edge region of BC; barycentric coords (0, 1-w, w) + return target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC - switch ( name ) { + } - case 'rgb': - case 'rgba': + // face region + const denom = 1 / ( va + vb + vc ); + // u = va * denom + v = vb * denom; + w = vc * denom; - if ( color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { + return target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w ); - // 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[ 4 ] ); + equals( triangle ) { - return this; + return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c ); - } + } - if ( color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\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; +let materialId = 0; - handleAlpha( color[ 4 ] ); +class Material extends EventDispatcher { - return this; + constructor() { - } + super(); - break; + Object.defineProperty( this, 'id', { value: materialId ++ } ); - case 'hsl': - case 'hsla': + this.uuid = generateUUID(); - if ( color = /^\s*(\d*\.?\d+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { + this.name = ''; + this.type = 'Material'; - // hsl(120,50%,50%) hsla(120,50%,50%,0.5) - const h = parseFloat( color[ 1 ] ) / 360; - const s = parseInt( color[ 2 ], 10 ) / 100; - const l = parseInt( color[ 3 ], 10 ) / 100; + this.fog = true; - handleAlpha( color[ 4 ] ); + this.blending = NormalBlending; + this.side = FrontSide; + this.vertexColors = false; - return this.setHSL( h, s, l ); + this.opacity = 1; + this.format = RGBAFormat; + this.transparent = false; - } + this.blendSrc = SrcAlphaFactor; + this.blendDst = OneMinusSrcAlphaFactor; + this.blendEquation = AddEquation; + this.blendSrcAlpha = null; + this.blendDstAlpha = null; + this.blendEquationAlpha = null; - break; + this.depthFunc = LessEqualDepth; + this.depthTest = true; + this.depthWrite = true; - } + this.stencilWriteMask = 0xff; + this.stencilFunc = AlwaysStencilFunc; + this.stencilRef = 0; + this.stencilFuncMask = 0xff; + this.stencilFail = KeepStencilOp; + this.stencilZFail = KeepStencilOp; + this.stencilZPass = KeepStencilOp; + this.stencilWrite = false; - } else if ( m = /^\#([A-Fa-f\d]+)$/.exec( style ) ) { + this.clippingPlanes = null; + this.clipIntersection = false; + this.clipShadows = false; - // hex color + this.shadowSide = null; - const hex = m[ 1 ]; - const size = hex.length; + this.colorWrite = true; - if ( size === 3 ) { + this.precision = null; // override the renderer's default precision for this material - // #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; + this.polygonOffset = false; + this.polygonOffsetFactor = 0; + this.polygonOffsetUnits = 0; - return this; + this.dithering = false; - } else if ( size === 6 ) { + this.alphaToCoverage = false; + this.premultipliedAlpha = false; - // #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; + this.visible = true; - return this; + this.toneMapped = true; - } + this.userData = {}; - } + this.version = 0; - if ( style && style.length > 0 ) { + this._alphaTest = 0; - return this.setColorName( style ); + } - } + get alphaTest() { - return this; + return this._alphaTest; } - setColorName( style ) { + set alphaTest( value ) { - // color keywords - const hex = _colorKeywords[ style.toLowerCase() ]; + if ( this._alphaTest > 0 !== value > 0 ) { - if ( hex !== undefined ) { + this.version ++; - // red - this.setHex( hex ); + } - } else { + this._alphaTest = value; - // unknown color - console.warn( 'THREE.Color: Unknown color ' + style ); + } - } + onBuild( /* shaderobject, renderer */ ) {} - return this; + onBeforeRender( /* renderer, scene, camera, geometry, object, group */ ) {} - } + onBeforeCompile( /* shaderobject, renderer */ ) {} - clone() { + customProgramCacheKey() { - return new this.constructor( this.r, this.g, this.b ); + return this.onBeforeCompile.toString(); } - copy( color ) { + setValues( values ) { + + if ( values === undefined ) return; + + for ( const key in values ) { - this.r = color.r; - this.g = color.g; - this.b = color.b; + const newValue = values[ key ]; - return this; + if ( newValue === undefined ) { - } + console.warn( 'THREE.Material: \'' + key + '\' parameter is undefined.' ); + continue; - copyGammaToLinear( color, gammaFactor = 2.0 ) { + } - this.r = Math.pow( color.r, gammaFactor ); - this.g = Math.pow( color.g, gammaFactor ); - this.b = Math.pow( color.b, gammaFactor ); + // for backward compatability if shading is set in the constructor + if ( key === 'shading' ) { - return this; + console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' ); + this.flatShading = ( newValue === FlatShading ) ? true : false; + continue; - } + } - copyLinearToGamma( color, gammaFactor = 2.0 ) { + const currentValue = this[ key ]; - const safeInverse = ( gammaFactor > 0 ) ? ( 1.0 / gammaFactor ) : 1.0; + if ( currentValue === undefined ) { - this.r = Math.pow( color.r, safeInverse ); - this.g = Math.pow( color.g, safeInverse ); - this.b = Math.pow( color.b, safeInverse ); + console.warn( 'THREE.' + this.type + ': \'' + key + '\' is not a property of this material.' ); + continue; - return this; + } - } + if ( currentValue && currentValue.isColor ) { - convertGammaToLinear( gammaFactor ) { + currentValue.set( newValue ); - this.copyGammaToLinear( this, gammaFactor ); + } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) { - return this; + currentValue.copy( newValue ); - } + } else { - convertLinearToGamma( gammaFactor ) { + this[ key ] = newValue; - this.copyLinearToGamma( this, gammaFactor ); + } - return this; + } } - copySRGBToLinear( color ) { + toJSON( meta ) { - this.r = SRGBToLinear( color.r ); - this.g = SRGBToLinear( color.g ); - this.b = SRGBToLinear( color.b ); + const isRoot = ( meta === undefined || typeof meta === 'string' ); - return this; + if ( isRoot ) { - } + meta = { + textures: {}, + images: {} + }; - copyLinearToSRGB( color ) { + } - this.r = LinearToSRGB( color.r ); - this.g = LinearToSRGB( color.g ); - this.b = LinearToSRGB( color.b ); + const data = { + metadata: { + version: 4.5, + type: 'Material', + generator: 'Material.toJSON' + } + }; - return this; + // standard Material serialization + data.uuid = this.uuid; + data.type = this.type; - } + if ( this.name !== '' ) data.name = this.name; - convertSRGBToLinear() { + if ( this.color && this.color.isColor ) data.color = this.color.getHex(); - this.copySRGBToLinear( this ); + if ( this.roughness !== undefined ) data.roughness = this.roughness; + if ( this.metalness !== undefined ) data.metalness = this.metalness; - return this; + if ( this.sheen !== undefined ) data.sheen = this.sheen; + if ( this.sheenColor && this.sheenColor.isColor ) data.sheenColor = this.sheenColor.getHex(); + if ( this.sheenRoughness !== undefined ) data.sheenRoughness = this.sheenRoughness; + if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex(); + if ( this.emissiveIntensity && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity; - } + if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex(); + if ( this.specularIntensity !== undefined ) data.specularIntensity = this.specularIntensity; + if ( this.specularColor && this.specularColor.isColor ) data.specularColor = this.specularColor.getHex(); + if ( this.shininess !== undefined ) data.shininess = this.shininess; + if ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat; + if ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness; - convertLinearToSRGB() { + if ( this.clearcoatMap && this.clearcoatMap.isTexture ) { - this.copyLinearToSRGB( this ); + data.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid; - return this; + } - } + if ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) { - getHex() { + data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON( meta ).uuid; - return ( this.r * 255 ) << 16 ^ ( this.g * 255 ) << 8 ^ ( this.b * 255 ) << 0; + } - } + if ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) { - getHexString() { + data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid; + data.clearcoatNormalScale = this.clearcoatNormalScale.toArray(); - return ( '000000' + this.getHex().toString( 16 ) ).slice( - 6 ); + } - } + if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid; + if ( this.matcap && this.matcap.isTexture ) data.matcap = this.matcap.toJSON( meta ).uuid; + if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid; - getHSL( target ) { + if ( this.lightMap && this.lightMap.isTexture ) { - // h,s,l ranges are in 0.0 - 1.0 + data.lightMap = this.lightMap.toJSON( meta ).uuid; + data.lightMapIntensity = this.lightMapIntensity; - const r = this.r, g = this.g, b = this.b; + } - const max = Math.max( r, g, b ); - const min = Math.min( r, g, b ); + if ( this.aoMap && this.aoMap.isTexture ) { - let hue, saturation; - const lightness = ( min + max ) / 2.0; + data.aoMap = this.aoMap.toJSON( meta ).uuid; + data.aoMapIntensity = this.aoMapIntensity; - if ( min === max ) { + } - hue = 0; - saturation = 0; + if ( this.bumpMap && this.bumpMap.isTexture ) { - } else { + data.bumpMap = this.bumpMap.toJSON( meta ).uuid; + data.bumpScale = this.bumpScale; - const delta = max - min; + } - saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min ); + if ( this.normalMap && this.normalMap.isTexture ) { - switch ( max ) { + data.normalMap = this.normalMap.toJSON( meta ).uuid; + data.normalMapType = this.normalMapType; + data.normalScale = this.normalScale.toArray(); - 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; + } - } + if ( this.displacementMap && this.displacementMap.isTexture ) { - hue /= 6; + data.displacementMap = this.displacementMap.toJSON( meta ).uuid; + data.displacementScale = this.displacementScale; + data.displacementBias = this.displacementBias; } - target.h = hue; - target.s = saturation; - target.l = lightness; + if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid; + if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid; - return target; + if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid; + if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid; + if ( this.specularIntensityMap && this.specularIntensityMap.isTexture ) data.specularIntensityMap = this.specularIntensityMap.toJSON( meta ).uuid; + if ( this.specularColorMap && this.specularColorMap.isTexture ) data.specularColorMap = this.specularColorMap.toJSON( meta ).uuid; - } + if ( this.envMap && this.envMap.isTexture ) { - getStyle() { + data.envMap = this.envMap.toJSON( meta ).uuid; - return 'rgb(' + ( ( this.r * 255 ) | 0 ) + ',' + ( ( this.g * 255 ) | 0 ) + ',' + ( ( this.b * 255 ) | 0 ) + ')'; + if ( this.combine !== undefined ) data.combine = this.combine; - } + } - offsetHSL( h, s, l ) { + if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity; + if ( this.reflectivity !== undefined ) data.reflectivity = this.reflectivity; + if ( this.refractionRatio !== undefined ) data.refractionRatio = this.refractionRatio; - this.getHSL( _hslA ); + if ( this.gradientMap && this.gradientMap.isTexture ) { - _hslA.h += h; _hslA.s += s; _hslA.l += l; + data.gradientMap = this.gradientMap.toJSON( meta ).uuid; - this.setHSL( _hslA.h, _hslA.s, _hslA.l ); + } - return this; + if ( this.transmission !== undefined ) data.transmission = this.transmission; + if ( this.transmissionMap && this.transmissionMap.isTexture ) data.transmissionMap = this.transmissionMap.toJSON( meta ).uuid; + if ( this.thickness !== undefined ) data.thickness = this.thickness; + if ( this.thicknessMap && this.thicknessMap.isTexture ) data.thicknessMap = this.thicknessMap.toJSON( meta ).uuid; + if ( this.attenuationDistance !== undefined ) data.attenuationDistance = this.attenuationDistance; + if ( this.attenuationColor !== undefined ) data.attenuationColor = this.attenuationColor.getHex(); - } + if ( this.size !== undefined ) data.size = this.size; + if ( this.shadowSide !== null ) data.shadowSide = this.shadowSide; + if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation; - add( color ) { + if ( this.blending !== NormalBlending ) data.blending = this.blending; + if ( this.side !== FrontSide ) data.side = this.side; + if ( this.vertexColors ) data.vertexColors = true; - this.r += color.r; - this.g += color.g; - this.b += color.b; + if ( this.opacity < 1 ) data.opacity = this.opacity; + if ( this.format !== RGBAFormat ) data.format = this.format; + if ( this.transparent === true ) data.transparent = this.transparent; - return this; + data.depthFunc = this.depthFunc; + data.depthTest = this.depthTest; + data.depthWrite = this.depthWrite; + data.colorWrite = this.colorWrite; - } + data.stencilWrite = this.stencilWrite; + data.stencilWriteMask = this.stencilWriteMask; + data.stencilFunc = this.stencilFunc; + data.stencilRef = this.stencilRef; + data.stencilFuncMask = this.stencilFuncMask; + data.stencilFail = this.stencilFail; + data.stencilZFail = this.stencilZFail; + data.stencilZPass = this.stencilZPass; - addColors( color1, color2 ) { + // rotation (SpriteMaterial) + if ( this.rotation && this.rotation !== 0 ) data.rotation = this.rotation; - this.r = color1.r + color2.r; - this.g = color1.g + color2.g; - this.b = color1.b + color2.b; + if ( this.polygonOffset === true ) data.polygonOffset = true; + if ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor; + if ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits; - return this; + if ( this.linewidth && this.linewidth !== 1 ) data.linewidth = this.linewidth; + if ( this.dashSize !== undefined ) data.dashSize = this.dashSize; + if ( this.gapSize !== undefined ) data.gapSize = this.gapSize; + if ( this.scale !== undefined ) data.scale = this.scale; - } + if ( this.dithering === true ) data.dithering = true; - addScalar( s ) { + if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest; + if ( this.alphaToCoverage === true ) data.alphaToCoverage = this.alphaToCoverage; + if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha; - this.r += s; - this.g += s; - this.b += s; + if ( this.wireframe === true ) data.wireframe = this.wireframe; + if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth; + if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap; + if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin; - return this; + if ( this.flatShading === true ) data.flatShading = this.flatShading; - } + if ( this.visible === false ) data.visible = false; - sub( color ) { + if ( this.toneMapped === false ) data.toneMapped = false; - this.r = Math.max( 0, this.r - color.r ); - this.g = Math.max( 0, this.g - color.g ); - this.b = Math.max( 0, this.b - color.b ); + if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData; - return this; + // TODO: Copied from Object3D.toJSON - } + function extractFromCache( cache ) { - multiply( color ) { + const values = []; - this.r *= color.r; - this.g *= color.g; - this.b *= color.b; + for ( const key in cache ) { - return this; + const data = cache[ key ]; + delete data.metadata; + values.push( data ); - } + } - multiplyScalar( s ) { + return values; - this.r *= s; - this.g *= s; - this.b *= s; + } - return this; + if ( isRoot ) { - } + const textures = extractFromCache( meta.textures ); + const images = extractFromCache( meta.images ); - lerp( color, alpha ) { + if ( textures.length > 0 ) data.textures = textures; + if ( images.length > 0 ) data.images = images; - this.r += ( color.r - this.r ) * alpha; - this.g += ( color.g - this.g ) * alpha; - this.b += ( color.b - this.b ) * alpha; + } - return this; + return data; } - lerpColors( color1, color2, alpha ) { - - this.r = color1.r + ( color2.r - color1.r ) * alpha; - this.g = color1.g + ( color2.g - color1.g ) * alpha; - this.b = color1.b + ( color2.b - color1.b ) * alpha; + clone() { - return this; + return new this.constructor().copy( this ); } - lerpHSL( color, alpha ) { + copy( source ) { - this.getHSL( _hslA ); - color.getHSL( _hslB ); + this.name = source.name; - const h = lerp( _hslA.h, _hslB.h, alpha ); - const s = lerp( _hslA.s, _hslB.s, alpha ); - const l = lerp( _hslA.l, _hslB.l, alpha ); + this.fog = source.fog; - this.setHSL( h, s, l ); + this.blending = source.blending; + this.side = source.side; + this.vertexColors = source.vertexColors; - return this; + this.opacity = source.opacity; + this.format = source.format; + this.transparent = source.transparent; - } + this.blendSrc = source.blendSrc; + this.blendDst = source.blendDst; + this.blendEquation = source.blendEquation; + this.blendSrcAlpha = source.blendSrcAlpha; + this.blendDstAlpha = source.blendDstAlpha; + this.blendEquationAlpha = source.blendEquationAlpha; - equals( c ) { + this.depthFunc = source.depthFunc; + this.depthTest = source.depthTest; + this.depthWrite = source.depthWrite; - return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b ); + this.stencilWriteMask = source.stencilWriteMask; + this.stencilFunc = source.stencilFunc; + this.stencilRef = source.stencilRef; + this.stencilFuncMask = source.stencilFuncMask; + this.stencilFail = source.stencilFail; + this.stencilZFail = source.stencilZFail; + this.stencilZPass = source.stencilZPass; + this.stencilWrite = source.stencilWrite; - } + const srcPlanes = source.clippingPlanes; + let dstPlanes = null; - fromArray( array, offset = 0 ) { + if ( srcPlanes !== null ) { - this.r = array[ offset ]; - this.g = array[ offset + 1 ]; - this.b = array[ offset + 2 ]; + const n = srcPlanes.length; + dstPlanes = new Array( n ); - return this; + for ( let i = 0; i !== n; ++ i ) { - } + dstPlanes[ i ] = srcPlanes[ i ].clone(); - toArray( array = [], offset = 0 ) { + } - array[ offset ] = this.r; - array[ offset + 1 ] = this.g; - array[ offset + 2 ] = this.b; + } - return array; + this.clippingPlanes = dstPlanes; + this.clipIntersection = source.clipIntersection; + this.clipShadows = source.clipShadows; - } + this.shadowSide = source.shadowSide; - fromBufferAttribute( attribute, index ) { + this.colorWrite = source.colorWrite; - this.r = attribute.getX( index ); - this.g = attribute.getY( index ); - this.b = attribute.getZ( index ); + this.precision = source.precision; - if ( attribute.normalized === true ) { + this.polygonOffset = source.polygonOffset; + this.polygonOffsetFactor = source.polygonOffsetFactor; + this.polygonOffsetUnits = source.polygonOffsetUnits; - // assuming Uint8Array + this.dithering = source.dithering; - this.r /= 255; - this.g /= 255; - this.b /= 255; + this.alphaTest = source.alphaTest; + this.alphaToCoverage = source.alphaToCoverage; + this.premultipliedAlpha = source.premultipliedAlpha; - } + this.visible = source.visible; + + this.toneMapped = source.toneMapped; + + this.userData = JSON.parse( JSON.stringify( source.userData ) ); return this; } - toJSON() { + dispose() { - return this.getHex(); + this.dispatchEvent( { type: 'dispose' } ); } -} + set needsUpdate( value ) { -Color.NAMES = _colorKeywords; + if ( value === true ) this.version ++; -Color.prototype.isColor = true; -Color.prototype.r = 1; -Color.prototype.g = 1; -Color.prototype.b = 1; + } + +} + +Material.prototype.isMaterial = true; /** * parameters = { @@ -9556,7 +9528,7 @@ class Float64BufferAttribute extends BufferAttribute { } -let _id = 0; +let _id$1 = 0; const _m1 = /*@__PURE__*/ new Matrix4(); const _obj = /*@__PURE__*/ new Object3D(); @@ -9571,7 +9543,7 @@ class BufferGeometry extends EventDispatcher { super(); - Object.defineProperty( this, 'id', { value: _id ++ } ); + Object.defineProperty( this, 'id', { value: _id$1 ++ } ); this.uuid = generateUUID(); @@ -11898,6 +11870,8 @@ class CubeCamera extends Object3D { renderer.xr.enabled = currentXrEnabled; + renderTarget.texture.needsPMREMUpdate = true; + } } @@ -12797,7 +12771,7 @@ var color_vertex = "#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#el var common = "#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal;\n#endif\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}"; -var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_maxMipLevel 8.0\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_maxTileSize 256.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\tfloat texelSize = 1.0 / ( 3.0 * cubeUV_maxTileSize );\n\t\tvec2 uv = getUV( direction, face ) * ( faceSize - 1.0 );\n\t\tvec2 f = fract( uv );\n\t\tuv += 0.5 - f;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tif ( mipInt < cubeUV_maxMipLevel ) {\n\t\t\tuv.y += 2.0 * cubeUV_maxTileSize;\n\t\t}\n\t\tuv.y += filterInt * 2.0 * cubeUV_minTileSize;\n\t\tuv.x += 3.0 * max( 0.0, cubeUV_maxTileSize - 2.0 * faceSize );\n\t\tuv *= texelSize;\n\t\tvec3 tl = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb;\n\t\tuv.x += texelSize;\n\t\tvec3 tr = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb;\n\t\tuv.y += texelSize;\n\t\tvec3 br = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb;\n\t\tuv.x -= texelSize;\n\t\tvec3 bl = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb;\n\t\tvec3 tm = mix( tl, tr, f.x );\n\t\tvec3 bm = mix( bl, br, f.x );\n\t\treturn mix( tm, bm, f.y );\n\t}\n\t#define r0 1.0\n\t#define v0 0.339\n\t#define m0 - 2.0\n\t#define r1 0.8\n\t#define v1 0.276\n\t#define m1 - 1.0\n\t#define r4 0.4\n\t#define v4 0.046\n\t#define m4 2.0\n\t#define r5 0.305\n\t#define v5 0.016\n\t#define m5 3.0\n\t#define r6 0.21\n\t#define v6 0.0038\n\t#define m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= r1 ) {\n\t\t\tmip = ( r0 - roughness ) * ( m1 - m0 ) / ( r0 - r1 ) + m0;\n\t\t} else if ( roughness >= r4 ) {\n\t\t\tmip = ( r1 - roughness ) * ( m4 - m1 ) / ( r1 - r4 ) + m1;\n\t\t} else if ( roughness >= r5 ) {\n\t\t\tmip = ( r4 - roughness ) * ( m5 - m4 ) / ( r4 - r5 ) + m4;\n\t\t} else if ( roughness >= r6 ) {\n\t\t\tmip = ( r5 - roughness ) * ( m6 - m5 ) / ( r5 - r6 ) + m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), m0, cubeUV_maxMipLevel );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif"; +var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_maxMipLevel 8.0\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_maxTileSize 256.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\tfloat texelSize = 1.0 / ( 3.0 * cubeUV_maxTileSize );\n\t\tvec2 uv = getUV( direction, face ) * ( faceSize - 1.0 ) + 0.5;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tif ( mipInt < cubeUV_maxMipLevel ) {\n\t\t\tuv.y += 2.0 * cubeUV_maxTileSize;\n\t\t}\n\t\tuv.y += filterInt * 2.0 * cubeUV_minTileSize;\n\t\tuv.x += 3.0 * max( 0.0, cubeUV_maxTileSize - 2.0 * faceSize );\n\t\tuv *= texelSize;\n\t\treturn texture2D( envMap, uv ).rgb;\n\t}\n\t#define r0 1.0\n\t#define v0 0.339\n\t#define m0 - 2.0\n\t#define r1 0.8\n\t#define v1 0.276\n\t#define m1 - 1.0\n\t#define r4 0.4\n\t#define v4 0.046\n\t#define m4 2.0\n\t#define r5 0.305\n\t#define v5 0.016\n\t#define m5 3.0\n\t#define r6 0.21\n\t#define v6 0.0038\n\t#define m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= r1 ) {\n\t\t\tmip = ( r0 - roughness ) * ( m1 - m0 ) / ( r0 - r1 ) + m0;\n\t\t} else if ( roughness >= r4 ) {\n\t\t\tmip = ( r1 - roughness ) * ( m4 - m1 ) / ( r1 - r4 ) + m1;\n\t\t} else if ( roughness >= r5 ) {\n\t\t\tmip = ( r4 - roughness ) * ( m5 - m4 ) / ( r4 - r5 ) + m4;\n\t\t} else if ( roughness >= r6 ) {\n\t\t\tmip = ( r5 - roughness ) * ( m6 - m5 ) / ( r5 - r6 ) + m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), m0, cubeUV_maxMipLevel );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif"; var defaultnormal_vertex = "vec3 transformedNormal = objectNormal;\n#ifdef USE_INSTANCING\n\tmat3 m = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( m[ 0 ], m[ 0 ] ), dot( m[ 1 ], m[ 1 ] ), dot( m[ 2 ], m[ 2 ] ) );\n\ttransformedNormal = m * transformedNormal;\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = ( modelViewMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif"; @@ -12805,15 +12779,15 @@ var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias );\n#endif"; -var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif"; +var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif"; var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif"; var encodings_fragment = "gl_FragColor = linearToOutputTexel( gl_FragColor );"; -var encodings_pars_fragment = "\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.rgb, vec3( gammaFactor ) ), value.a );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.rgb, vec3( 1.0 / gammaFactor ) ), value.a );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.a );\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * value.a * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.r, max( value.g, value.b ) );\n\tfloat M = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.r, max( value.g, value.b ) );\n\tfloat D = max( maxRange / maxRGB, 1.0 );\n\tD = clamp( floor( D ) / 255.0, 0.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}"; +var encodings_pars_fragment = "vec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}"; -var envmap_fragment = "#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t\tenvColor = envMapTexelToLinear( envColor );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 envColor = textureCubeUV( envMap, reflectVec, 0.0 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif"; +var envmap_fragment = "#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 envColor = textureCubeUV( envMap, reflectVec, 0.0 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif"; var envmap_common_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif"; @@ -12833,7 +12807,7 @@ var fog_pars_fragment = "#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying flo var gradientmap_pars_fragment = "#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn vec3( texture2D( gradientMap, coord ).r );\n\t#else\n\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t#endif\n}"; -var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\tvec3 lightMapIrradiance = lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tlightMapIrradiance *= PI;\n\t#endif\n\treflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif"; +var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tlightMapIrradiance *= PI;\n\t#endif\n\treflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif"; var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif"; @@ -12851,13 +12825,13 @@ var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor var lights_phong_pars_fragment = "varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )\t(0)"; -var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\t#ifdef SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULARINTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vUv ).a;\n\t\t#endif\n\t\t#ifdef USE_SPECULARCOLORMAP\n\t\t\tspecularColorFactor *= specularColorMapTexelToLinear( texture2D( specularColorMap, vUv ) ).rgb;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( ior - 1.0 ) / ( ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tmaterial.sheenColor *= sheenColorMapTexelToLinear( texture2D( sheenColorMap, vUv ) ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vUv ).a;\n\t#endif\n#endif"; +var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\t#ifdef SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULARINTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vUv ).a;\n\t\t#endif\n\t\t#ifdef USE_SPECULARCOLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vUv ).rgb;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( ior - 1.0 ) / ( ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vUv ).a;\n\t#endif\n#endif"; -var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n};\nvec3 clearcoatSpecular = vec3( 0.0 );\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\tvec3 FssEss = specularColor * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = specularColor + ( 1.0 - specularColor ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecular += ccIrradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.clearcoatNormal, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\treflectedLight.directSpecular += irradiance * BRDF_Sheen( directLight.direction, geometry.viewDir, geometry.normal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.roughness );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecular += clearcoatRadiance * EnvironmentBRDF( geometry.clearcoatNormal, geometry.viewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\tcomputeMultiscattering( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - ( singleScattering + multiScattering ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}"; +var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n};\nvec3 clearcoatSpecular = vec3( 0.0 );\nvec3 sheenSpecular = vec3( 0.0 );\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\tvec3 FssEss = specularColor * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = specularColor + ( 1.0 - specularColor ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecular += ccIrradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.clearcoatNormal, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * BRDF_Sheen( directLight.direction, geometry.viewDir, geometry.normal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.roughness );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecular += clearcoatRadiance * EnvironmentBRDF( geometry.clearcoatNormal, geometry.viewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * material.sheenColor * IBLSheenBRDF( geometry.normal, geometry.viewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\tcomputeMultiscattering( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - ( singleScattering + multiScattering ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}"; var lights_fragment_begin = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\n#ifdef USE_CLEARCOAT\n\tgeometry.clearcoatNormal = clearcoatNormal;\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\tirradiance += getLightProbeIrradiance( lightProbe, geometry.normal );\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry.normal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif"; -var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\t\tvec3 lightMapIrradiance = lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometry.normal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getIBLRadiance( geometry.viewDir, geometry.normal, material.roughness );\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif"; +var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometry.normal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getIBLRadiance( geometry.viewDir, geometry.normal, material.roughness );\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif"; var lights_fragment_end = "#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometry, material, reflectedLight );\n#endif"; @@ -12869,11 +12843,11 @@ var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_ var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n\t#else\n\t\tif ( isPerspectiveMatrix( projectionMatrix ) ) {\n\t\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\t\tgl_Position.z *= gl_Position.w;\n\t\t}\n\t#endif\n#endif"; -var map_fragment = "#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif"; +var map_fragment = "#ifdef USE_MAP\n\tvec4 sampledDiffuseColor = texture2D( map, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\tsampledDiffuseColor = vec4( mix( pow( sampledDiffuseColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), sampledDiffuseColor.rgb * 0.0773993808, vec3( lessThanEqual( sampledDiffuseColor.rgb, vec3( 0.04045 ) ) ) ), sampledDiffuseColor.w );\n\t#endif\n\tdiffuseColor *= sampledDiffuseColor;\n#endif"; var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif"; -var map_particle_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n#endif\n#ifdef USE_MAP\n\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif"; +var map_particle_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n#endif\n#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif"; var map_particle_pars_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tuniform mat3 uvTransform;\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif"; @@ -12947,7 +12921,7 @@ var tonemapping_pars_fragment = "#ifndef saturate\n#define saturate( a ) clamp( var transmission_fragment = "#ifdef USE_TRANSMISSION\n\tfloat transmissionAlpha = 1.0;\n\tfloat transmissionFactor = transmission;\n\tfloat thicknessFactor = thickness;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\ttransmissionFactor *= texture2D( transmissionMap, vUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tthicknessFactor *= texture2D( thicknessMap, vUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmission = getIBLVolumeRefraction(\n\t\tn, v, roughnessFactor, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, ior, thicknessFactor,\n\t\tattenuationColor, attenuationDistance );\n\ttotalDiffuse = mix( totalDiffuse, transmission.rgb, transmissionFactor );\n\ttransmissionAlpha = mix( transmissionAlpha, transmission.a, transmissionFactor );\n#endif"; -var transmission_pars_fragment = "#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tvec3 getVolumeTransmissionRay( vec3 n, vec3 v, float thickness, float ior, mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( float roughness, float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( vec2 fragCoord, float roughness, float ior ) {\n\t\tfloat framebufferLod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\treturn texture2DLodEXT( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n\t\t#else\n\t\t\treturn texture2D( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n\t\t#endif\n\t}\n\tvec3 applyVolumeAttenuation( vec3 radiance, float transmissionDistance, vec3 attenuationColor, float attenuationDistance ) {\n\t\tif ( attenuationDistance == 0.0 ) {\n\t\t\treturn radiance;\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance * radiance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( vec3 n, vec3 v, float roughness, vec3 diffuseColor, vec3 specularColor, float specularF90,\n\t\tvec3 position, mat4 modelMatrix, mat4 viewMatrix, mat4 projMatrix, float ior, float thickness,\n\t\tvec3 attenuationColor, float attenuationDistance ) {\n\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\trefractionCoords += 1.0;\n\t\trefractionCoords /= 2.0;\n\t\tvec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\tvec3 attenuatedColor = applyVolumeAttenuation( transmittedLight.rgb, length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor * diffuseColor, transmittedLight.a );\n\t}\n#endif"; +var transmission_pars_fragment = "#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat framebufferLod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\treturn texture2DLodEXT( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n\t\t#else\n\t\t\treturn texture2D( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n\t\t#endif\n\t}\n\tvec3 applyVolumeAttenuation( const in vec3 radiance, const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( attenuationDistance == 0.0 ) {\n\t\t\treturn radiance;\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance * radiance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\trefractionCoords += 1.0;\n\t\trefractionCoords /= 2.0;\n\t\tvec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\tvec3 attenuatedColor = applyVolumeAttenuation( transmittedLight.rgb, length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor * diffuseColor, transmittedLight.a );\n\t}\n#endif"; var uv_pars_fragment = "#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )\n\tvarying vec2 vUv;\n#endif"; @@ -12965,7 +12939,7 @@ var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defin const vertex$g = "varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}"; -const fragment$g = "uniform sampler2D t2D;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\tgl_FragColor = mapTexelToLinear( texColor );\n\t#include \n\t#include \n}"; +const fragment$g = "uniform sampler2D t2D;\nvarying vec2 vUv;\nvoid main() {\n\tgl_FragColor = texture2D( t2D, vUv );\n\t#include \n\t#include \n}"; const vertex$f = "varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}"; @@ -12981,7 +12955,7 @@ const fragment$d = "#define DISTANCE\nuniform vec3 referencePosition;\nuniform f const vertex$c = "varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}"; -const fragment$c = "uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tvec4 texColor = texture2D( tEquirect, sampleUV );\n\tgl_FragColor = mapTexelToLinear( texColor );\n\t#include \n\t#include \n}"; +const fragment$c = "uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\t#include \n\t#include \n}"; const vertex$b = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; @@ -12989,7 +12963,7 @@ const fragment$b = "uniform vec3 diffuse;\nuniform float opacity;\nuniform float const vertex$a = "#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; -const fragment$a = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\t\treflectedLight.indirectDiffuse += lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; +const fragment$a = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; const vertex$9 = "#define LAMBERT\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; @@ -12997,7 +12971,7 @@ const fragment$9 = "uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float const vertex$8 = "#define MATCAP\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n}"; -const fragment$8 = "#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t\tmatcapColor = matcapTexelToLinear( matcapColor );\n\t#else\n\t\tvec4 matcapColor = vec4( 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; +const fragment$8 = "#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t#else\n\t\tvec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; const vertex$7 = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}"; @@ -13009,7 +12983,7 @@ const fragment$6 = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive; const vertex$5 = "#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}"; -const fragment$5 = "#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULARINTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n\t#ifdef USE_SPECULARCOLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; +const fragment$5 = "#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULARINTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n\t#ifdef USE_SPECULARCOLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecular;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; const vertex$4 = "#define TOON\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}"; @@ -13670,7 +13644,7 @@ ShaderLib.physical = { sheen: { value: 0 }, sheenColor: { value: new Color( 0x000000 ) }, sheenColorMap: { value: null }, - sheenRoughness: { value: 0 }, + sheenRoughness: { value: 1 }, sheenRoughnessMap: { value: null }, transmission: { value: 0 }, transmissionMap: { value: null }, @@ -13680,7 +13654,7 @@ ShaderLib.physical = { thicknessMap: { value: null }, attenuationDistance: { value: 0 }, attenuationColor: { value: new Color( 0x000000 ) }, - specularIntensity: { value: 0 }, + specularIntensity: { value: 1 }, specularIntensityMap: { value: null }, specularColor: { value: new Color( 1, 1, 1 ) }, specularColorMap: { value: null }, @@ -14878,14 +14852,10 @@ function WebGLCubeMaps( renderer ) { if ( image && image.height > 0 ) { - const currentRenderTarget = renderer.getRenderTarget(); - const renderTarget = new WebGLCubeRenderTarget( image.height / 2 ); renderTarget.fromEquirectangularTexture( renderer, texture ); cubemaps.set( texture, renderTarget ); - renderer.setRenderTarget( currentRenderTarget ); - texture.addEventListener( 'dispose', onTextureDispose ); return mapTextureMapping( renderTarget.texture, texture.mapping ); @@ -15101,16 +15071,6 @@ const TOTAL_LODS = LOD_MAX - LOD_MIN + 1 + EXTRA_LOD_SIGMA.length; // samples and exit early, but not recompile the shader. const MAX_SAMPLES = 20; -const ENCODINGS = { - [ LinearEncoding ]: 0, - [ sRGBEncoding ]: 1, - [ RGBEEncoding ]: 2, - [ RGBM7Encoding ]: 3, - [ RGBM16Encoding ]: 4, - [ RGBDEncoding ]: 5, - [ GammaEncoding ]: 6 -}; - const _flatCamera = /*@__PURE__*/ new OrthographicCamera(); const { _lodPlanes, _sizeLods, _sigmas } = /*@__PURE__*/ _createPlanes(); const _clearColor = /*@__PURE__*/ new Color(); @@ -15192,23 +15152,23 @@ class PMREMGenerator { /** * Generates a PMREM from an equirectangular texture, which can be either LDR - * (RGBFormat) or HDR (RGBEFormat). The ideal input image size is 1k (1024 x 512), + * or HDR. The ideal input image size is 1k (1024 x 512), * as this matches best with the 256 x 256 cubemap output. */ - fromEquirectangular( equirectangular ) { + fromEquirectangular( equirectangular, renderTarget = null ) { - return this._fromTexture( equirectangular ); + return this._fromTexture( equirectangular, renderTarget ); } /** * Generates a PMREM from an cubemap texture, which can be either LDR - * (RGBFormat) or HDR (RGBEFormat). The ideal input cube size is 256 x 256, + * or HDR. The ideal input cube size is 256 x 256, * as this matches best with the 256 x 256 cubemap output. */ - fromCubemap( cubemap ) { + fromCubemap( cubemap, renderTarget = null ) { - return this._fromTexture( cubemap ); + return this._fromTexture( cubemap, renderTarget ); } @@ -15273,10 +15233,10 @@ class PMREMGenerator { } - _fromTexture( texture ) { + _fromTexture( texture, renderTarget ) { _oldTarget = this._renderer.getRenderTarget(); - const cubeUVRenderTarget = this._allocateTargets( texture ); + const cubeUVRenderTarget = renderTarget || this._allocateTargets( texture ); this._textureToCubeUV( texture, cubeUVRenderTarget ); this._applyPMREM( cubeUVRenderTarget ); this._cleanup( cubeUVRenderTarget ); @@ -15288,12 +15248,12 @@ class PMREMGenerator { _allocateTargets( texture ) { // warning: null texture is valid const params = { - magFilter: NearestFilter, - minFilter: NearestFilter, + magFilter: LinearFilter, + minFilter: LinearFilter, generateMipmaps: false, - type: UnsignedByteType, - format: RGBEFormat, - encoding: _isLDR( texture ) ? texture.encoding : RGBEEncoding, + type: HalfFloatType, + format: RGBAFormat, + encoding: LinearEncoding, depthBuffer: false }; @@ -15321,12 +15281,10 @@ class PMREMGenerator { const renderer = this._renderer; const originalAutoClear = renderer.autoClear; - const outputEncoding = renderer.outputEncoding; const toneMapping = renderer.toneMapping; renderer.getClearColor( _clearColor ); renderer.toneMapping = NoToneMapping; - renderer.outputEncoding = LinearEncoding; renderer.autoClear = false; const backgroundMaterial = new MeshBasicMaterial( { @@ -15396,26 +15354,11 @@ class PMREMGenerator { backgroundBox.material.dispose(); renderer.toneMapping = toneMapping; - renderer.outputEncoding = outputEncoding; renderer.autoClear = originalAutoClear; scene.background = background; } - _setEncoding( uniform, texture ) { - - if ( this._renderer.capabilities.isWebGL2 === true && texture.format === RGBAFormat && texture.type === UnsignedByteType && texture.encoding === sRGBEncoding ) { - - uniform.value = ENCODINGS[ LinearEncoding ]; - - } else { - - uniform.value = ENCODINGS[ texture.encoding ]; - - } - - } - _textureToCubeUV( texture, cubeUVRenderTarget ) { const renderer = this._renderer; @@ -15453,9 +15396,6 @@ class PMREMGenerator { } - this._setEncoding( uniforms[ 'inputEncoding' ], texture ); - this._setEncoding( uniforms[ 'outputEncoding' ], cubeUVRenderTarget.texture ); - _setViewport( cubeUVRenderTarget, 0, 0, 3 * SIZE_MAX, 2 * SIZE_MAX ); renderer.setRenderTarget( cubeUVRenderTarget ); @@ -15586,9 +15526,6 @@ class PMREMGenerator { blurUniforms[ 'dTheta' ].value = radiansPerPixel; blurUniforms[ 'mipInt' ].value = LOD_MAX - lodIn; - this._setEncoding( blurUniforms[ 'inputEncoding' ], targetIn.texture ); - this._setEncoding( blurUniforms[ 'outputEncoding' ], targetIn.texture ); - const outputSize = _sizeLods[ lodOut ]; const x = 3 * Math.max( 0, SIZE_MAX - 2 * outputSize ); const y = ( lodOut === 0 ? 0 : 2 * SIZE_MAX ) + 2 * outputSize * ( lodOut > LOD_MAX - LOD_MIN ? lodOut - LOD_MAX + LOD_MIN : 0 ); @@ -15601,14 +15538,6 @@ class PMREMGenerator { } -function _isLDR( texture ) { - - if ( texture === undefined || texture.type !== UnsignedByteType ) return false; - - return texture.encoding === LinearEncoding || texture.encoding === sRGBEncoding || texture.encoding === GammaEncoding; - -} - function _createPlanes() { const _lodPlanes = []; @@ -15721,9 +15650,7 @@ function _getBlurShader( maxSamples ) { 'latitudinal': { value: false }, 'dTheta': { value: 0 }, 'mipInt': { value: 0 }, - 'poleAxis': { value: poleAxis }, - 'inputEncoding': { value: ENCODINGS[ LinearEncoding ] }, - 'outputEncoding': { value: ENCODINGS[ LinearEncoding ] } + 'poleAxis': { value: poleAxis } }, vertexShader: _getCommonVertexShader(), @@ -15743,8 +15670,6 @@ function _getBlurShader( maxSamples ) { uniform float mipInt; uniform vec3 poleAxis; - ${ _getEncodings() } - #define ENVMAP_TYPE_CUBE_UV #include @@ -15789,8 +15714,6 @@ function _getBlurShader( maxSamples ) { } - gl_FragColor = linearToOutputTexel( gl_FragColor ); - } `, @@ -15813,9 +15736,7 @@ function _getEquirectShader() { uniforms: { 'envMap': { value: null }, - 'texelSize': { value: texelSize }, - 'inputEncoding': { value: ENCODINGS[ LinearEncoding ] }, - 'outputEncoding': { value: ENCODINGS[ LinearEncoding ] } + 'texelSize': { value: texelSize } }, vertexShader: _getCommonVertexShader(), @@ -15830,8 +15751,6 @@ function _getEquirectShader() { uniform sampler2D envMap; uniform vec2 texelSize; - ${ _getEncodings() } - #include void main() { @@ -15843,20 +15762,18 @@ function _getEquirectShader() { vec2 f = fract( uv / texelSize - 0.5 ); uv -= f * texelSize; - vec3 tl = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb; + vec3 tl = texture2D ( envMap, uv ).rgb; uv.x += texelSize.x; - vec3 tr = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb; + vec3 tr = texture2D ( envMap, uv ).rgb; uv.y += texelSize.y; - vec3 br = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb; + vec3 br = texture2D ( envMap, uv ).rgb; uv.x -= texelSize.x; - vec3 bl = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb; + vec3 bl = texture2D ( envMap, uv ).rgb; vec3 tm = mix( tl, tr, f.x ); vec3 bm = mix( bl, br, f.x ); gl_FragColor.rgb = mix( tm, bm, f.y ); - gl_FragColor = linearToOutputTexel( gl_FragColor ); - } `, @@ -15877,9 +15794,7 @@ function _getCubemapShader() { name: 'CubemapToCubeUV', uniforms: { - 'envMap': { value: null }, - 'inputEncoding': { value: ENCODINGS[ LinearEncoding ] }, - 'outputEncoding': { value: ENCODINGS[ LinearEncoding ] } + 'envMap': { value: null } }, vertexShader: _getCommonVertexShader(), @@ -15893,13 +15808,9 @@ function _getCubemapShader() { uniform samplerCube envMap; - ${ _getEncodings() } - void main() { - gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 ); - gl_FragColor.rgb = envMapTexelToLinear( textureCube( envMap, vec3( - vOutputDirection.x, vOutputDirection.yz ) ) ).rgb; - gl_FragColor = linearToOutputTexel( gl_FragColor ); + gl_FragColor = textureCube( envMap, vec3( - vOutputDirection.x, vOutputDirection.yz ) ); } `, @@ -15977,92 +15888,6 @@ function _getCommonVertexShader() { } -function _getEncodings() { - - return /* glsl */` - - uniform int inputEncoding; - uniform int outputEncoding; - - #include - - vec4 inputTexelToLinear( vec4 value ) { - - if ( inputEncoding == 0 ) { - - return value; - - } else if ( inputEncoding == 1 ) { - - return sRGBToLinear( value ); - - } else if ( inputEncoding == 2 ) { - - return RGBEToLinear( value ); - - } else if ( inputEncoding == 3 ) { - - return RGBMToLinear( value, 7.0 ); - - } else if ( inputEncoding == 4 ) { - - return RGBMToLinear( value, 16.0 ); - - } else if ( inputEncoding == 5 ) { - - return RGBDToLinear( value, 256.0 ); - - } else { - - return GammaToLinear( value, 2.2 ); - - } - - } - - vec4 linearToOutputTexel( vec4 value ) { - - if ( outputEncoding == 0 ) { - - return value; - - } else if ( outputEncoding == 1 ) { - - return LinearTosRGB( value ); - - } else if ( outputEncoding == 2 ) { - - return LinearToRGBE( value ); - - } else if ( outputEncoding == 3 ) { - - return LinearToRGBM( value, 7.0 ); - - } else if ( outputEncoding == 4 ) { - - return LinearToRGBM( value, 16.0 ); - - } else if ( outputEncoding == 5 ) { - - return LinearToRGBD( value, 256.0 ); - - } else { - - return LinearToGamma( value, 2.2 ); - - } - - } - - vec4 envMapTexelToLinear( vec4 color ) { - - return inputTexelToLinear( color ); - - } - `; - -} - function WebGLCubeUVMaps( renderer ) { let cubeUVmaps = new WeakMap(); @@ -16071,45 +15896,58 @@ function WebGLCubeUVMaps( renderer ) { function get( texture ) { - if ( texture && texture.isTexture && texture.isRenderTargetTexture === false ) { + if ( texture && texture.isTexture ) { const mapping = texture.mapping; const isEquirectMap = ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ); const isCubeMap = ( mapping === CubeReflectionMapping || mapping === CubeRefractionMapping ); + // equirect/cube map to cubeUV conversion + if ( isEquirectMap || isCubeMap ) { - // equirect/cube map to cubeUV conversion + if ( texture.isRenderTargetTexture && texture.needsPMREMUpdate === true ) { + + texture.needsPMREMUpdate = false; + + let renderTarget = cubeUVmaps.get( texture ); - if ( cubeUVmaps.has( texture ) ) { + if ( pmremGenerator === null ) pmremGenerator = new PMREMGenerator( renderer ); - return cubeUVmaps.get( texture ).texture; + renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture, renderTarget ) : pmremGenerator.fromCubemap( texture, renderTarget ); + cubeUVmaps.set( texture, renderTarget ); + + return renderTarget.texture; } else { - const image = texture.image; + if ( cubeUVmaps.has( texture ) ) { - if ( ( isEquirectMap && image && image.height > 0 ) || ( isCubeMap && image && isCubeTextureComplete( image ) ) ) { + return cubeUVmaps.get( texture ).texture; - const currentRenderTarget = renderer.getRenderTarget(); + } else { - if ( pmremGenerator === null ) pmremGenerator = new PMREMGenerator( renderer ); + const image = texture.image; - const renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture ) : pmremGenerator.fromCubemap( texture ); - cubeUVmaps.set( texture, renderTarget ); + if ( ( isEquirectMap && image && image.height > 0 ) || ( isCubeMap && image && isCubeTextureComplete( image ) ) ) { - renderer.setRenderTarget( currentRenderTarget ); + if ( pmremGenerator === null ) pmremGenerator = new PMREMGenerator( renderer ); - texture.addEventListener( 'dispose', onTextureDispose ); + const renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture ) : pmremGenerator.fromCubemap( texture ); + cubeUVmaps.set( texture, renderTarget ); - return renderTarget.texture; + texture.addEventListener( 'dispose', onTextureDispose ); - } else { + return renderTarget.texture; - // image not yet ready. try the conversion next frame + } else { - return null; + // image not yet ready. try the conversion next frame + + return null; + + } } @@ -16754,6 +16592,18 @@ function WebGLMorphtargets( gl, capabilities, textures ) { morphTextures.set( geometry, entry ); + function disposeTexture() { + + texture.dispose(); + + morphTextures.delete( geometry ); + + geometry.removeEventListener( 'dispose', disposeTexture ); + + } + + geometry.addEventListener( 'dispose', disposeTexture ); + } // @@ -18048,16 +17898,6 @@ function getEncodingComponents( encoding ) { return [ 'Linear', '( value )' ]; case sRGBEncoding: return [ 'sRGB', '( value )' ]; - case RGBEEncoding: - return [ 'RGBE', '( value )' ]; - case RGBM7Encoding: - return [ 'RGBM', '( value, 7.0 )' ]; - case RGBM16Encoding: - return [ 'RGBM', '( value, 16.0 )' ]; - case RGBDEncoding: - return [ 'RGBD', '( value, 256.0 )' ]; - case GammaEncoding: - return [ 'Gamma', '( value, float( GAMMA_FACTOR ) )' ]; default: console.warn( 'THREE.WebGLProgram: Unsupported encoding:', encoding ); return [ 'Linear', '( value )' ]; @@ -18080,13 +17920,6 @@ function getShaderErrors( gl, shader, type ) { } -function getTexelDecodingFunction( functionName, encoding ) { - - const components = getEncodingComponents( encoding ); - return 'vec4 ' + functionName + '( vec4 value ) { return ' + components[ 0 ] + 'ToLinear' + components[ 1 ] + '; }'; - -} - function getTexelEncodingFunction( functionName, encoding ) { const components = getEncodingComponents( encoding ); @@ -18418,9 +18251,6 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { const envMapModeDefine = generateEnvMapModeDefine( parameters ); const envMapBlendingDefine = generateEnvMapBlendingDefine( parameters ); - - const gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0; - const customExtensions = parameters.isWebGL2 ? '' : generateExtensions( parameters ); const customDefines = generateDefines( defines ); @@ -18472,8 +18302,6 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '', - '#define GAMMA_FACTOR ' + gammaFactorDefine, - '#define MAX_BONES ' + parameters.maxBones, ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '', ( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '', @@ -18622,8 +18450,6 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { customDefines, - '#define GAMMA_FACTOR ' + gammaFactorDefine, - ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '', ( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '', @@ -18663,6 +18489,8 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', + parameters.decodeVideoTexture ? '#define DECODE_VIDEO_TEXTURE' : '', + parameters.vertexTangents ? '#define USE_TANGENT' : '', parameters.vertexColors || parameters.instancingColor ? '#define USE_COLOR' : '', parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', @@ -18700,13 +18528,6 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.format === RGBFormat ? '#define OPAQUE' : '', ShaderChunk[ 'encodings_pars_fragment' ], // this code is required here because it is used by the various encoding/decoding function defined below - parameters.map ? getTexelDecodingFunction( 'mapTexelToLinear', parameters.mapEncoding ) : '', - parameters.matcap ? getTexelDecodingFunction( 'matcapTexelToLinear', parameters.matcapEncoding ) : '', - parameters.envMap ? getTexelDecodingFunction( 'envMapTexelToLinear', parameters.envMapEncoding ) : '', - parameters.emissiveMap ? getTexelDecodingFunction( 'emissiveMapTexelToLinear', parameters.emissiveMapEncoding ) : '', - parameters.specularColorMap ? getTexelDecodingFunction( 'specularColorMapTexelToLinear', parameters.specularColorMapEncoding ) : '', - parameters.sheenColorMap ? getTexelDecodingFunction( 'sheenColorMapTexelToLinear', parameters.sheenColorMapEncoding ) : '', - parameters.lightMap ? getTexelDecodingFunction( 'lightMapTexelToLinear', parameters.lightMapEncoding ) : '', getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputEncoding ), parameters.depthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '', @@ -18915,9 +18736,129 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { } +let _id = 0; + +class WebGLShaderCache { + + constructor() { + + this.shaderCache = new Map(); + this.materialCache = new Map(); + + } + + update( material ) { + + const vertexShader = material.vertexShader; + const fragmentShader = material.fragmentShader; + + const vertexShaderStage = this._getShaderStage( vertexShader ); + const fragmentShaderStage = this._getShaderStage( fragmentShader ); + + const materialShaders = this._getShaderCacheForMaterial( material ); + + if ( materialShaders.has( vertexShaderStage ) === false ) { + + materialShaders.add( vertexShaderStage ); + vertexShaderStage.usedTimes ++; + + } + + if ( materialShaders.has( fragmentShaderStage ) === false ) { + + materialShaders.add( fragmentShaderStage ); + fragmentShaderStage.usedTimes ++; + + } + + return this; + + } + + remove( material ) { + + const materialShaders = this.materialCache.get( material ); + + for ( const shaderStage of materialShaders ) { + + shaderStage.usedTimes --; + + if ( shaderStage.usedTimes === 0 ) this.shaderCache.delete( shaderStage ); + + } + + this.materialCache.delete( material ); + + return this; + + } + + getVertexShaderID( material ) { + + return this._getShaderStage( material.vertexShader ).id; + + } + + getFragmentShaderID( material ) { + + return this._getShaderStage( material.fragmentShader ).id; + + } + + dispose() { + + this.shaderCache.clear(); + this.materialCache.clear(); + + } + + _getShaderCacheForMaterial( material ) { + + const cache = this.materialCache; + + if ( cache.has( material ) === false ) { + + cache.set( material, new Set() ); + + } + + return cache.get( material ); + + } + + _getShaderStage( code ) { + + const cache = this.shaderCache; + + if ( cache.has( code ) === false ) { + + const stage = new WebGLShaderStage(); + cache.set( code, stage ); + + } + + return cache.get( code ); + + } + +} + +class WebGLShaderStage { + + constructor() { + + this.id = _id ++; + + this.usedTimes = 0; + + } + +} + function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ) { const _programLayers = new Layers(); + const _customShaders = new WebGLShaderCache(); const programs = []; const isWebGL2 = capabilities.isWebGL2; @@ -18981,35 +18922,6 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities } - function getTextureEncodingFromMap( map ) { - - let encoding; - - if ( map && map.isTexture ) { - - encoding = map.encoding; - - } else if ( map && map.isWebGLRenderTarget ) { - - console.warn( 'THREE.WebGLPrograms.getTextureEncodingFromMap: don\'t use render targets as textures. Use their .texture property instead.' ); - encoding = map.texture.encoding; - - } else { - - encoding = LinearEncoding; - - } - - if ( isWebGL2 && map && map.isTexture && map.format === RGBAFormat && map.type === UnsignedByteType && map.encoding === sRGBEncoding ) { - - encoding = LinearEncoding; // disable inline decode for sRGB textures in WebGL 2 - - } - - return encoding; - - } - function getParameters( material, lights, shadows, scene, object ) { const fog = scene.fog; @@ -19037,6 +18949,7 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities } let vertexShader, fragmentShader; + let customVertexShaderID, customFragmentShaderID; if ( shaderID ) { @@ -19050,6 +18963,11 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities vertexShader = material.vertexShader; fragmentShader = material.fragmentShader; + _customShaders.update( material ); + + customVertexShaderID = _customShaders.getVertexShaderID( material ); + customFragmentShaderID = _customShaders.getFragmentShaderID( material ); + } const currentRenderTarget = renderer.getRenderTarget(); @@ -19068,6 +18986,9 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities fragmentShader: fragmentShader, defines: material.defines, + customVertexShaderID: customVertexShaderID, + customFragmentShaderID: customFragmentShaderID, + isRawShaderMaterial: material.isRawShaderMaterial === true, glslVersion: material.glslVersion, @@ -19077,25 +18998,22 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities instancingColor: object.isInstancedMesh === true && object.instanceColor !== null, supportsVertexTextures: vertexTextures, - outputEncoding: ( currentRenderTarget !== null ) ? getTextureEncodingFromMap( currentRenderTarget.texture ) : renderer.outputEncoding, + outputEncoding: ( currentRenderTarget !== null ) ? currentRenderTarget.texture.encoding : renderer.outputEncoding, map: !! material.map, - mapEncoding: getTextureEncodingFromMap( material.map ), matcap: !! material.matcap, - matcapEncoding: getTextureEncodingFromMap( material.matcap ), envMap: !! envMap, envMapMode: envMap && envMap.mapping, - envMapEncoding: getTextureEncodingFromMap( envMap ), envMapCubeUV: ( !! envMap ) && ( ( envMap.mapping === CubeUVReflectionMapping ) || ( envMap.mapping === CubeUVRefractionMapping ) ), lightMap: !! material.lightMap, - lightMapEncoding: getTextureEncodingFromMap( material.lightMap ), aoMap: !! material.aoMap, emissiveMap: !! material.emissiveMap, - emissiveMapEncoding: getTextureEncodingFromMap( material.emissiveMap ), bumpMap: !! material.bumpMap, normalMap: !! material.normalMap, objectSpaceNormalMap: material.normalMapType === ObjectSpaceNormalMap, tangentSpaceNormalMap: material.normalMapType === TangentSpaceNormalMap, + decodeVideoTexture: !! material.map && ( material.map.isVideoTexture === true ) && ( material.map.encoding === sRGBEncoding ), + clearcoat: useClearcoat, clearcoatMap: useClearcoat && !! material.clearcoatMap, clearcoatRoughnessMap: useClearcoat && !! material.clearcoatRoughnessMap, @@ -19107,7 +19025,6 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities specularMap: !! material.specularMap, specularIntensityMap: !! material.specularIntensityMap, specularColorMap: !! material.specularColorMap, - specularColorMapEncoding: getTextureEncodingFromMap( material.specularColorMap ), alphaMap: !! material.alphaMap, alphaTest: useAlphaTest, @@ -19116,7 +19033,6 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities sheen: material.sheen > 0, sheenColorMap: !! material.sheenColorMap, - sheenColorMapEncoding: getTextureEncodingFromMap( material.sheenColorMap ), sheenRoughnessMap: !! material.sheenRoughnessMap, transmission: material.transmission > 0, @@ -19206,8 +19122,8 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities } else { - array.push( hashString( parameters.fragmentShader ) ); - array.push( hashString( parameters.vertexShader ) ); + array.push( parameters.customVertexShaderID ); + array.push( parameters.customFragmentShaderID ); } @@ -19227,7 +19143,6 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities getProgramCacheKeyParameters( array, parameters ); getProgramCacheKeyBooleans( array, parameters ); array.push( renderer.outputEncoding ); - array.push( renderer.gammaFactor ); } @@ -19241,12 +19156,7 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities array.push( parameters.precision ); array.push( parameters.outputEncoding ); - array.push( parameters.mapEncoding ); - array.push( parameters.matcapEncoding ); array.push( parameters.envMapMode ); - array.push( parameters.envMapEncoding ); - array.push( parameters.lightMapEncoding ); - array.push( parameters.emissiveMapEncoding ); array.push( parameters.combine ); array.push( parameters.vertexUvs ); array.push( parameters.fogExp2 ); @@ -19266,8 +19176,6 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities array.push( parameters.numClippingPlanes ); array.push( parameters.numClipIntersection ); array.push( parameters.format ); - array.push( parameters.specularColorMapEncoding ); - array.push( parameters.sheenColorMapEncoding ); } @@ -19387,6 +19295,8 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities _programLayers.enable( 20 ); if ( parameters.sheenRoughnessMap ) _programLayers.enable( 21 ); + if ( parameters.decodeVideoTexture ) + _programLayers.enable( 22 ); array.push( _programLayers.mask ); @@ -19459,14 +19369,28 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities } + function releaseShaderCache( material ) { + + _customShaders.remove( material ); + + } + + function dispose() { + + _customShaders.dispose(); + + } + return { getParameters: getParameters, getProgramCacheKey: getProgramCacheKey, getUniforms: getUniforms, acquireProgram: acquireProgram, releaseProgram: releaseProgram, + releaseShaderCache: releaseShaderCache, // Exposed for resource monitoring & error feedback via renderer.info: - programs: programs + programs: programs, + dispose: dispose }; } @@ -22156,7 +22080,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } - function getInternalFormat( internalFormatName, glFormat, glType, encoding ) { + function getInternalFormat( internalFormatName, glFormat, glType, encoding, isVideoTexture = false ) { if ( isWebGL2 === false ) return glFormat; @@ -22190,7 +22114,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( glType === 5126 ) internalFormat = 34836; if ( glType === 5131 ) internalFormat = 34842; - if ( glType === 5121 ) internalFormat = ( encoding === sRGBEncoding ) ? 35907 : 32856; + if ( glType === 5121 ) internalFormat = ( encoding === sRGBEncoding && isVideoTexture === false ) ? 35907 : 32856; } @@ -22576,13 +22500,14 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, _gl.pixelStorei( 37443, 0 ); const needsPowerOfTwo = textureNeedsPowerOfTwo( texture ) && isPowerOfTwo$1( texture.image ) === false; - const image = resizeImage( texture.image, needsPowerOfTwo, false, maxTextureSize ); + let image = resizeImage( texture.image, needsPowerOfTwo, false, maxTextureSize ); + image = verifyColorSpace( texture, image ); const supportsMips = isPowerOfTwo$1( image ) || isWebGL2, - glFormat = utils.convert( texture.format ); + glFormat = utils.convert( texture.format, texture.encoding ); let glType = utils.convert( texture.type ), - glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); + glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding, texture.isVideoTexture ); setTextureParameters( textureType, texture, supportsMips ); @@ -22926,11 +22851,13 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } + cubeImage[ i ] = verifyColorSpace( texture, cubeImage[ i ] ); + } const image = cubeImage[ 0 ], supportsMips = isPowerOfTwo$1( image ) || isWebGL2, - glFormat = utils.convert( texture.format ), + glFormat = utils.convert( texture.format, texture.encoding ), glType = utils.convert( texture.type ), glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); @@ -23095,7 +23022,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, // Setup storage for target texture and bind it to correct framebuffer function setupFrameBufferTexture( framebuffer, renderTarget, texture, attachment, textureTarget ) { - const glFormat = utils.convert( texture.format ); + const glFormat = utils.convert( texture.format, texture.encoding ); const glType = utils.convert( texture.type ); const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); const renderTargetProperties = properties.get( renderTarget ); @@ -23203,7 +23130,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, // Use the first texture for MRT so far const texture = renderTarget.isWebGLMultipleRenderTargets === true ? renderTarget.texture[ 0 ] : renderTarget.texture; - const glFormat = utils.convert( texture.format ); + const glFormat = utils.convert( texture.format, texture.encoding ); const glType = utils.convert( texture.type ); const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); const samples = getRenderTargetSamples( renderTarget ); @@ -23438,7 +23365,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, _gl.bindRenderbuffer( 36161, renderTargetProperties.__webglColorRenderbuffer ); - const glFormat = utils.convert( texture.format ); + const glFormat = utils.convert( texture.format, texture.encoding ); const glType = utils.convert( texture.type ); const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); const samples = getRenderTargetSamples( renderTarget ); @@ -23657,6 +23584,66 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } + function verifyColorSpace( texture, image ) { + + const encoding = texture.encoding; + const format = texture.format; + const type = texture.type; + + if ( texture.isCompressedTexture === true || texture.format === _SRGBFormat || texture.format === _SRGBAFormat ) return image; + + if ( encoding !== LinearEncoding ) { + + // sRGB + + if ( encoding === sRGBEncoding && texture.isVideoTexture !== true ) { + + if ( isWebGL2 === false ) { + + // in WebGL 1, try to use EXT_sRGB extension and unsized formats + + if ( extensions.has( 'EXT_sRGB' ) === true && ( format === RGBFormat || format === RGBAFormat ) ) { + + if ( format === RGBFormat ) texture.format = _SRGBFormat; + if ( format === RGBAFormat ) texture.format = _SRGBAFormat; + + // it's not possible to generate mips in WebGL 1 with the above formats + + texture.minFilter = LinearFilter; + texture.generateMipmaps = false; + + } else { + + // slow fallback (CPU decode) + + image = ImageUtils.sRGBToLinear( image ); + + } + + } else { + + // in WebGL 2 uncompressed textures can only be sRGB encoded if they have the RGBA8 format + + if ( format !== RGBAFormat || type !== UnsignedByteType ) { + + console.warn( 'THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType.' ); + + } + + } + + } else { + + console.error( 'THREE.WebGLTextures: Unsupported texture encoding:', encoding ); + + } + + } + + return image; + + } + // backwards compatibility let warnedTexture2D = false; @@ -23726,7 +23713,7 @@ function WebGLUtils( gl, extensions, capabilities ) { const isWebGL2 = capabilities.isWebGL2; - function convert( p ) { + function convert( p, encoding = null ) { let extension; @@ -23769,6 +23756,25 @@ function WebGLUtils( gl, extensions, capabilities ) { if ( p === DepthStencilFormat ) return 34041; if ( p === RedFormat ) return 6403; + // WebGL 1 sRGB fallback + + if ( p === _SRGBFormat || p === _SRGBAFormat ) { + + extension = extensions.get( 'EXT_sRGB' ); + + if ( extension !== null ) { + + if ( p === _SRGBFormat ) return extension.SRGB_EXT; + if ( p === _SRGBAFormat ) return extension.SRGB_ALPHA_EXT; + + } else { + + return null; + + } + + } + // WebGL2 formats. if ( p === RedIntegerFormat ) return 36244; @@ -23777,28 +23783,51 @@ function WebGLUtils( gl, extensions, capabilities ) { if ( p === RGBIntegerFormat ) return 36248; if ( p === RGBAIntegerFormat ) return 36249; - if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || - p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) { + // S3TC - extension = extensions.get( 'WEBGL_compressed_texture_s3tc' ); + if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) { - if ( extension !== null ) { + if ( encoding === sRGBEncoding ) { - if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT; - if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT; - if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT; - if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT; + extension = extensions.get( 'WEBGL_compressed_texture_s3tc_srgb' ); + + if ( extension !== null ) { + + if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_SRGB_S3TC_DXT1_EXT; + if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT; + if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT; + if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; + + } else { + + return null; + + } } else { - return null; + extension = extensions.get( 'WEBGL_compressed_texture_s3tc' ); + + if ( extension !== null ) { + + if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT; + if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT; + if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT; + if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT; + + } else { + + return null; + + } } } - if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || - p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) { + // PVRTC + + if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) { extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' ); @@ -23817,6 +23846,8 @@ function WebGLUtils( gl, extensions, capabilities ) { } + // ETC1 + if ( p === RGB_ETC1_Format ) { extension = extensions.get( 'WEBGL_compressed_texture_etc1' ); @@ -23833,37 +23864,51 @@ function WebGLUtils( gl, extensions, capabilities ) { } + // ETC2 + if ( p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format ) { extension = extensions.get( 'WEBGL_compressed_texture_etc' ); if ( extension !== null ) { - if ( p === RGB_ETC2_Format ) return extension.COMPRESSED_RGB8_ETC2; - if ( p === RGBA_ETC2_EAC_Format ) return extension.COMPRESSED_RGBA8_ETC2_EAC; + if ( p === RGB_ETC2_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2; + if ( p === RGBA_ETC2_EAC_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC; + + } else { + + return null; } } + // ASTC + if ( p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format || p === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format || p === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format || p === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format || - p === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format || - p === SRGB8_ALPHA8_ASTC_4x4_Format || p === SRGB8_ALPHA8_ASTC_5x4_Format || p === SRGB8_ALPHA8_ASTC_5x5_Format || - p === SRGB8_ALPHA8_ASTC_6x5_Format || p === SRGB8_ALPHA8_ASTC_6x6_Format || p === SRGB8_ALPHA8_ASTC_8x5_Format || - p === SRGB8_ALPHA8_ASTC_8x6_Format || p === SRGB8_ALPHA8_ASTC_8x8_Format || p === SRGB8_ALPHA8_ASTC_10x5_Format || - p === SRGB8_ALPHA8_ASTC_10x6_Format || p === SRGB8_ALPHA8_ASTC_10x8_Format || p === SRGB8_ALPHA8_ASTC_10x10_Format || - p === SRGB8_ALPHA8_ASTC_12x10_Format || p === SRGB8_ALPHA8_ASTC_12x12_Format ) { + p === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format ) { extension = extensions.get( 'WEBGL_compressed_texture_astc' ); if ( extension !== null ) { - // TODO Complete? - - return p; + if ( p === RGBA_ASTC_4x4_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : extension.COMPRESSED_RGBA_ASTC_4x4_KHR; + if ( p === RGBA_ASTC_5x4_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : extension.COMPRESSED_RGBA_ASTC_5x4_KHR; + if ( p === RGBA_ASTC_5x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : extension.COMPRESSED_RGBA_ASTC_5x5_KHR; + if ( p === RGBA_ASTC_6x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : extension.COMPRESSED_RGBA_ASTC_6x5_KHR; + if ( p === RGBA_ASTC_6x6_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : extension.COMPRESSED_RGBA_ASTC_6x6_KHR; + if ( p === RGBA_ASTC_8x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : extension.COMPRESSED_RGBA_ASTC_8x5_KHR; + if ( p === RGBA_ASTC_8x6_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : extension.COMPRESSED_RGBA_ASTC_8x6_KHR; + if ( p === RGBA_ASTC_8x8_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : extension.COMPRESSED_RGBA_ASTC_8x8_KHR; + if ( p === RGBA_ASTC_10x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : extension.COMPRESSED_RGBA_ASTC_10x5_KHR; + if ( p === RGBA_ASTC_10x6_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : extension.COMPRESSED_RGBA_ASTC_10x6_KHR; + if ( p === RGBA_ASTC_10x8_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : extension.COMPRESSED_RGBA_ASTC_10x8_KHR; + if ( p === RGBA_ASTC_10x10_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : extension.COMPRESSED_RGBA_ASTC_10x10_KHR; + if ( p === RGBA_ASTC_12x10_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : extension.COMPRESSED_RGBA_ASTC_12x10_KHR; + if ( p === RGBA_ASTC_12x12_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : extension.COMPRESSED_RGBA_ASTC_12x12_KHR; } else { @@ -23873,15 +23918,15 @@ function WebGLUtils( gl, extensions, capabilities ) { } + // BPTC + if ( p === RGBA_BPTC_Format ) { extension = extensions.get( 'EXT_texture_compression_bptc' ); if ( extension !== null ) { - // TODO Complete? - - return p; + if ( p === RGBA_BPTC_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT : extension.COMPRESSED_RGBA_BPTC_UNORM_EXT; } else { @@ -23891,6 +23936,8 @@ function WebGLUtils( gl, extensions, capabilities ) { } + // + if ( p === UnsignedInt248Type ) { if ( isWebGL2 ) return 34042; @@ -24508,7 +24555,12 @@ class WebXRManager extends EventDispatcher { newRenderTarget = new WebGLRenderTarget( glBaseLayer.framebufferWidth, - glBaseLayer.framebufferHeight + glBaseLayer.framebufferHeight, + { + format: RGBAFormat, + type: UnsignedByteType, + encoding: renderer.outputEncoding + } ); } else { @@ -24532,6 +24584,12 @@ class WebXRManager extends EventDispatcher { scaleFactor: framebufferScaleFactor }; + if ( renderer.outputEncoding === sRGBEncoding ) { + + projectionlayerInit.colorFormat = ( attributes.alpha || isMultisample ) ? 35907 : 35905; + + } + glBinding = new XRWebGLBinding( session, gl ); glProjLayer = glBinding.createProjectionLayer( projectionlayerInit ); @@ -25786,7 +25844,6 @@ function WebGLRenderer( parameters = {} ) { // physically based shading - this.gammaFactor = 2.0; // for backwards compatibility this.outputEncoding = LinearEncoding; // physical lights @@ -26249,6 +26306,7 @@ function WebGLRenderer( parameters = {} ) { cubeuvmaps.dispose(); objects.dispose(); bindingStates.dispose(); + programCache.dispose(); xr.dispose(); @@ -26333,6 +26391,12 @@ function WebGLRenderer( parameters = {} ) { } ); + if ( material.isShaderMaterial ) { + + programCache.releaseShaderCache( material ); + + } + } } @@ -27079,6 +27143,7 @@ function WebGLRenderer( parameters = {} ) { materialProperties.numIntersection = parameters.numClipIntersection; materialProperties.vertexAlphas = parameters.vertexAlphas; materialProperties.vertexTangents = parameters.vertexTangents; + materialProperties.toneMapping = parameters.toneMapping; } @@ -27097,6 +27162,7 @@ function WebGLRenderer( parameters = {} ) { const morphTargets = !! geometry.morphAttributes.position; const morphNormals = !! geometry.morphAttributes.normal; const morphTargetsCount = !! geometry.morphAttributes.position ? geometry.morphAttributes.position.length : 0; + const toneMapping = material.toneMapped ? _this.toneMapping : NoToneMapping; const materialProperties = properties.get( material ); const lights = currentRenderState.state.lights; @@ -27178,6 +27244,10 @@ function WebGLRenderer( parameters = {} ) { needsProgramChange = true; + } else if ( materialProperties.toneMapping !== toneMapping ) { + + needsProgramChange = true; + } else if ( capabilities.isWebGL2 === true && materialProperties.morphTargetsCount !== morphTargetsCount ) { needsProgramChange = true; @@ -31884,7 +31954,7 @@ CatmullRomCurve3.prototype.isCatmullRomCurve3 = true; /** * Bezier Curves formulas obtained from - * http://en.wikipedia.org/wiki/Bézier_curve + * https://en.wikipedia.org/wiki/B%C3%A9zier_curve */ function CatmullRom( t, p0, p1, p2, p3 ) { @@ -34779,14 +34849,75 @@ class LatheGeometry extends BufferGeometry { const indices = []; const vertices = []; const uvs = []; + const initNormals = []; + const normals = []; // helper variables const inverseSegments = 1.0 / segments; const vertex = new Vector3(); const uv = new Vector2(); + const normal = new Vector3(); + const curNormal = new Vector3(); + const prevNormal = new Vector3(); + let dx = 0; + let dy = 0; + + // pre-compute normals for initial "meridian" + + for ( let j = 0; j <= ( points.length - 1 ); j ++ ) { + + switch ( j ) { + + case 0: // special handling for 1st vertex on path + + dx = points[ j + 1 ].x - points[ j ].x; + dy = points[ j + 1 ].y - points[ j ].y; + + normal.x = dy * 1.0; + normal.y = - dx; + normal.z = dy * 0.0; + + prevNormal.copy( normal ); + + normal.normalize(); + + initNormals.push( normal.x, normal.y, normal.z ); + + break; + + case ( points.length - 1 ): // special handling for last Vertex on path + + initNormals.push( prevNormal.x, prevNormal.y, prevNormal.z ); + + break; + + default: // default handling for all vertices in between + + dx = points[ j + 1 ].x - points[ j ].x; + dy = points[ j + 1 ].y - points[ j ].y; - // generate vertices and uvs + normal.x = dy * 1.0; + normal.y = - dx; + normal.z = dy * 0.0; + + curNormal.copy( normal ); + + normal.x += prevNormal.x; + normal.y += prevNormal.y; + normal.z += prevNormal.z; + + normal.normalize(); + + initNormals.push( normal.x, normal.y, normal.z ); + + prevNormal.copy( curNormal ); + + } + + } + + // generate vertices, uvs and normals for ( let i = 0; i <= segments; i ++ ) { @@ -34812,6 +34943,13 @@ class LatheGeometry extends BufferGeometry { uvs.push( uv.x, uv.y ); + // normal + + const x = initNormals[ 3 * j + 0 ] * sin; + const y = initNormals[ 3 * j + 1 ]; + const z = initNormals[ 3 * j + 0 ] * cos; + + normals.push( x, y, z ); } @@ -34844,52 +34982,7 @@ class LatheGeometry extends BufferGeometry { this.setIndex( indices ); this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - - // generate normals - - this.computeVertexNormals(); - - // if the geometry is closed, we need to average the normals along the seam. - // because the corresponding vertices are identical (but still have different UVs). - - if ( phiLength === Math.PI * 2 ) { - - const normals = this.attributes.normal.array; - const n1 = new Vector3(); - const n2 = new Vector3(); - const n = new Vector3(); - - // this is the buffer offset for the last line of vertices - - const base = segments * points.length * 3; - - for ( let i = 0, j = 0; i < points.length; i ++, j += 3 ) { - - // select the normal of the vertex in the first line - - n1.x = normals[ j + 0 ]; - n1.y = normals[ j + 1 ]; - n1.z = normals[ j + 2 ]; - - // select the normal of the vertex in the last line - - n2.x = normals[ base + j + 0 ]; - n2.y = normals[ base + j + 1 ]; - n2.z = normals[ base + j + 2 ]; - - // average normals - - n.addVectors( n1, n2 ).normalize(); - - // assign the new values to both normals - - normals[ j + 0 ] = normals[ base + j + 0 ] = n.x; - normals[ j + 1 ] = normals[ base + j + 1 ] = n.y; - normals[ j + 2 ] = normals[ base + j + 2 ] = n.z; - - } - - } + this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); } @@ -39158,6 +39251,12 @@ class FileLoader extends Loader { } + if ( typeof ReadableStream === 'undefined' || response.body.getReader === undefined ) { + + return response; + + } + const callbacks = loading[ url ]; const reader = response.body.getReader(); const contentLength = response.headers.get( 'Content-Length' ); @@ -39166,7 +39265,7 @@ class FileLoader extends Loader { let loaded = 0; // periodically read data into the new stream tracking while download progress - return new ReadableStream( { + const stream = new ReadableStream( { start( controller ) { readData(); @@ -39204,6 +39303,8 @@ class FileLoader extends Loader { } ); + return new Response( stream ); + } else { throw Error( `fetch for "${response.url}" responded with ${response.status}: ${response.statusText}` ); @@ -39211,9 +39312,7 @@ class FileLoader extends Loader { } } ) - .then( stream => { - - const response = new Response( stream ); + .then( response => { switch ( this.responseType ) { @@ -45538,6 +45637,7 @@ class AnimationMixer extends EventDispatcher { if ( binding !== undefined ) { + ++ binding.referenceCount; bindings[ i ] = binding; } else { @@ -47494,7 +47594,7 @@ const _camera = /*@__PURE__*/ new Camera(); * - shows frustum, line of sight and up of the camera * - suitable for fast updates * - based on frustum visualization in lightgl.js shadowmap example - * http://evanw.github.com/lightgl.js/tests/shadowmap.html + * https://github.com/evanw/lightgl.js/blob/master/tests/shadowmap.html */ class CameraHelper extends LineSegments { @@ -49902,7 +50002,19 @@ Object.defineProperties( WebGLRenderer.prototype, { } }, + gammaFactor: { + get: function () { + + console.warn( 'THREE.WebGLRenderer: .gammaFactor has been removed.' ); + return 2; + + }, + set: function () { + + console.warn( 'THREE.WebGLRenderer: .gammaFactor has been removed.' ); + } + } } ); Object.defineProperties( WebGLShadowMap.prototype, { @@ -50291,4 +50403,4 @@ if ( typeof window !== 'undefined' ) { } -export { ACESFilmicToneMapping, AddEquation, AddOperation, AdditiveAnimationBlendMode, AdditiveBlending, AlphaFormat, AlwaysDepth, AlwaysStencilFunc, AmbientLight, AmbientLightProbe, AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, ArcCurve, ArrayCamera, ArrowHelper, Audio, AudioAnalyser, AudioContext, AudioListener, AudioLoader, AxesHelper, AxisHelper, BackSide, BasicDepthPacking, BasicShadowMap, BinaryTextureLoader, Bone, BooleanKeyframeTrack, BoundingBoxHelper, Box2, Box3, Box3Helper, BoxGeometry as BoxBufferGeometry, BoxGeometry, BoxHelper, BufferAttribute, BufferGeometry, BufferGeometryLoader, ByteType, Cache, Camera, CameraHelper, CanvasRenderer, CanvasTexture, CatmullRomCurve3, CineonToneMapping, CircleGeometry as CircleBufferGeometry, CircleGeometry, ClampToEdgeWrapping, Clock, Color, ColorKeyframeTrack, CompressedTexture, CompressedTextureLoader, ConeGeometry as ConeBufferGeometry, ConeGeometry, CubeCamera, CubeReflectionMapping, CubeRefractionMapping, CubeTexture, CubeTextureLoader, CubeUVReflectionMapping, CubeUVRefractionMapping, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceBack, CullFaceFront, CullFaceFrontBack, CullFaceNone, Curve, CurvePath, CustomBlending, CustomToneMapping, CylinderGeometry as CylinderBufferGeometry, CylinderGeometry, Cylindrical, DataTexture, DataTexture2DArray, DataTexture3D, DataTextureLoader, DataUtils, DecrementStencilOp, DecrementWrapStencilOp, DefaultLoadingManager, DepthFormat, DepthStencilFormat, DepthTexture, DirectionalLight, DirectionalLightHelper, DiscreteInterpolant, DodecahedronGeometry as DodecahedronBufferGeometry, DodecahedronGeometry, DoubleSide, DstAlphaFactor, DstColorFactor, DynamicBufferAttribute, DynamicCopyUsage, DynamicDrawUsage, DynamicReadUsage, EdgesGeometry, EdgesHelper, EllipseCurve, EqualDepth, EqualStencilFunc, EquirectangularReflectionMapping, EquirectangularRefractionMapping, Euler, EventDispatcher, ExtrudeGeometry as ExtrudeBufferGeometry, ExtrudeGeometry, FaceColors, FileLoader, FlatShading, Float16BufferAttribute, Float32Attribute, Float32BufferAttribute, Float64Attribute, Float64BufferAttribute, FloatType, Fog, FogExp2, Font, FontLoader, FramebufferTexture, FrontSide, Frustum, GLBufferAttribute, GLSL1, GLSL3, GammaEncoding, GreaterDepth, GreaterEqualDepth, GreaterEqualStencilFunc, GreaterStencilFunc, GridHelper, Group, HalfFloatType, HemisphereLight, HemisphereLightHelper, HemisphereLightProbe, IcosahedronGeometry as IcosahedronBufferGeometry, IcosahedronGeometry, ImageBitmapLoader, ImageLoader, ImageUtils, ImmediateRenderObject, IncrementStencilOp, IncrementWrapStencilOp, InstancedBufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InstancedMesh, Int16Attribute, Int16BufferAttribute, Int32Attribute, Int32BufferAttribute, Int8Attribute, Int8BufferAttribute, IntType, InterleavedBuffer, InterleavedBufferAttribute, Interpolant, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InvertStencilOp, JSONLoader, KeepStencilOp, KeyframeTrack, LOD, LatheGeometry as LatheBufferGeometry, LatheGeometry, Layers, LensFlare, LessDepth, LessEqualDepth, LessEqualStencilFunc, LessStencilFunc, Light, LightProbe, Line, Line3, LineBasicMaterial, LineCurve, LineCurve3, LineDashedMaterial, LineLoop, LinePieces, LineSegments, LineStrip, LinearEncoding, LinearFilter, LinearInterpolant, LinearMipMapLinearFilter, LinearMipMapNearestFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, LinearToneMapping, Loader, LoaderUtils, LoadingManager, LoopOnce, LoopPingPong, LoopRepeat, LuminanceAlphaFormat, LuminanceFormat, MOUSE, Material, MaterialLoader, MathUtils as Math, MathUtils, Matrix3, Matrix4, MaxEquation, Mesh, MeshBasicMaterial, MeshDepthMaterial, MeshDistanceMaterial, MeshFaceMaterial, MeshLambertMaterial, MeshMatcapMaterial, MeshNormalMaterial, MeshPhongMaterial, MeshPhysicalMaterial, MeshStandardMaterial, MeshToonMaterial, MinEquation, MirroredRepeatWrapping, MixOperation, MultiMaterial, MultiplyBlending, MultiplyOperation, NearestFilter, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, NeverDepth, NeverStencilFunc, NoBlending, NoColors, NoToneMapping, NormalAnimationBlendMode, NormalBlending, NotEqualDepth, NotEqualStencilFunc, NumberKeyframeTrack, Object3D, ObjectLoader, ObjectSpaceNormalMap, OctahedronGeometry as OctahedronBufferGeometry, OctahedronGeometry, OneFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, OrthographicCamera, PCFShadowMap, PCFSoftShadowMap, PMREMGenerator, ParametricGeometry, Particle, ParticleBasicMaterial, ParticleSystem, ParticleSystemMaterial, Path, PerspectiveCamera, Plane, PlaneGeometry as PlaneBufferGeometry, PlaneGeometry, PlaneHelper, PointCloud, PointCloudMaterial, PointLight, PointLightHelper, Points, PointsMaterial, PolarGridHelper, PolyhedronGeometry as PolyhedronBufferGeometry, PolyhedronGeometry, PositionalAudio, PropertyBinding, PropertyMixer, QuadraticBezierCurve, QuadraticBezierCurve3, Quaternion, QuaternionKeyframeTrack, QuaternionLinearInterpolant, REVISION, RGBADepthPacking, RGBAFormat, RGBAIntegerFormat, RGBA_ASTC_10x10_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGBDEncoding, RGBEEncoding, RGBEFormat, RGBFormat, RGBIntegerFormat, RGBM16Encoding, RGBM7Encoding, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGFormat, RGIntegerFormat, RawShaderMaterial, Ray, Raycaster, RectAreaLight, RedFormat, RedIntegerFormat, ReinhardToneMapping, RepeatWrapping, ReplaceStencilOp, ReverseSubtractEquation, RingGeometry as RingBufferGeometry, RingGeometry, SRGB8_ALPHA8_ASTC_10x10_Format, SRGB8_ALPHA8_ASTC_10x5_Format, SRGB8_ALPHA8_ASTC_10x6_Format, SRGB8_ALPHA8_ASTC_10x8_Format, SRGB8_ALPHA8_ASTC_12x10_Format, SRGB8_ALPHA8_ASTC_12x12_Format, SRGB8_ALPHA8_ASTC_4x4_Format, SRGB8_ALPHA8_ASTC_5x4_Format, SRGB8_ALPHA8_ASTC_5x5_Format, SRGB8_ALPHA8_ASTC_6x5_Format, SRGB8_ALPHA8_ASTC_6x6_Format, SRGB8_ALPHA8_ASTC_8x5_Format, SRGB8_ALPHA8_ASTC_8x6_Format, SRGB8_ALPHA8_ASTC_8x8_Format, Scene, SceneUtils, ShaderChunk, ShaderLib, ShaderMaterial, ShadowMaterial, Shape, ShapeGeometry as ShapeBufferGeometry, ShapeGeometry, ShapePath, ShapeUtils, ShortType, Skeleton, SkeletonHelper, SkinnedMesh, SmoothShading, Sphere, SphereGeometry as SphereBufferGeometry, SphereGeometry, Spherical, SphericalHarmonics3, SplineCurve, SpotLight, SpotLightHelper, Sprite, SpriteMaterial, SrcAlphaFactor, SrcAlphaSaturateFactor, SrcColorFactor, StaticCopyUsage, StaticDrawUsage, StaticReadUsage, StereoCamera, StreamCopyUsage, StreamDrawUsage, StreamReadUsage, StringKeyframeTrack, SubtractEquation, SubtractiveBlending, TOUCH, TangentSpaceNormalMap, TetrahedronGeometry as TetrahedronBufferGeometry, TetrahedronGeometry, TextGeometry, Texture, TextureLoader, TorusGeometry as TorusBufferGeometry, TorusGeometry, TorusKnotGeometry as TorusKnotBufferGeometry, TorusKnotGeometry, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TubeGeometry as TubeBufferGeometry, TubeGeometry, UVMapping, Uint16Attribute, Uint16BufferAttribute, Uint32Attribute, Uint32BufferAttribute, Uint8Attribute, Uint8BufferAttribute, Uint8ClampedAttribute, Uint8ClampedBufferAttribute, Uniform, UniformsLib, UniformsUtils, UnsignedByteType, UnsignedInt248Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShort565Type, UnsignedShortType, VSMShadowMap, Vector2, Vector3, Vector4, VectorKeyframeTrack, Vertex, VertexColors, VideoTexture, WebGL1Renderer, WebGLCubeRenderTarget, WebGLMultipleRenderTargets, WebGLMultisampleRenderTarget, WebGLRenderTarget, WebGLRenderTargetCube, WebGLRenderer, WebGLUtils, WireframeGeometry, WireframeHelper, WrapAroundEnding, XHRLoader, ZeroCurvatureEnding, ZeroFactor, ZeroSlopeEnding, ZeroStencilOp, sRGBEncoding }; +export { ACESFilmicToneMapping, AddEquation, AddOperation, AdditiveAnimationBlendMode, AdditiveBlending, AlphaFormat, AlwaysDepth, AlwaysStencilFunc, AmbientLight, AmbientLightProbe, AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, ArcCurve, ArrayCamera, ArrowHelper, Audio, AudioAnalyser, AudioContext, AudioListener, AudioLoader, AxesHelper, AxisHelper, BackSide, BasicDepthPacking, BasicShadowMap, BinaryTextureLoader, Bone, BooleanKeyframeTrack, BoundingBoxHelper, Box2, Box3, Box3Helper, BoxGeometry as BoxBufferGeometry, BoxGeometry, BoxHelper, BufferAttribute, BufferGeometry, BufferGeometryLoader, ByteType, Cache, Camera, CameraHelper, CanvasRenderer, CanvasTexture, CatmullRomCurve3, CineonToneMapping, CircleGeometry as CircleBufferGeometry, CircleGeometry, ClampToEdgeWrapping, Clock, Color, ColorKeyframeTrack, CompressedTexture, CompressedTextureLoader, ConeGeometry as ConeBufferGeometry, ConeGeometry, CubeCamera, CubeReflectionMapping, CubeRefractionMapping, CubeTexture, CubeTextureLoader, CubeUVReflectionMapping, CubeUVRefractionMapping, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceBack, CullFaceFront, CullFaceFrontBack, CullFaceNone, Curve, CurvePath, CustomBlending, CustomToneMapping, CylinderGeometry as CylinderBufferGeometry, CylinderGeometry, Cylindrical, DataTexture, DataTexture2DArray, DataTexture3D, DataTextureLoader, DataUtils, DecrementStencilOp, DecrementWrapStencilOp, DefaultLoadingManager, DepthFormat, DepthStencilFormat, DepthTexture, DirectionalLight, DirectionalLightHelper, DiscreteInterpolant, DodecahedronGeometry as DodecahedronBufferGeometry, DodecahedronGeometry, DoubleSide, DstAlphaFactor, DstColorFactor, DynamicBufferAttribute, DynamicCopyUsage, DynamicDrawUsage, DynamicReadUsage, EdgesGeometry, EdgesHelper, EllipseCurve, EqualDepth, EqualStencilFunc, EquirectangularReflectionMapping, EquirectangularRefractionMapping, Euler, EventDispatcher, ExtrudeGeometry as ExtrudeBufferGeometry, ExtrudeGeometry, FaceColors, FileLoader, FlatShading, Float16BufferAttribute, Float32Attribute, Float32BufferAttribute, Float64Attribute, Float64BufferAttribute, FloatType, Fog, FogExp2, Font, FontLoader, FramebufferTexture, FrontSide, Frustum, GLBufferAttribute, GLSL1, GLSL3, GreaterDepth, GreaterEqualDepth, GreaterEqualStencilFunc, GreaterStencilFunc, GridHelper, Group, HalfFloatType, HemisphereLight, HemisphereLightHelper, HemisphereLightProbe, IcosahedronGeometry as IcosahedronBufferGeometry, IcosahedronGeometry, ImageBitmapLoader, ImageLoader, ImageUtils, ImmediateRenderObject, IncrementStencilOp, IncrementWrapStencilOp, InstancedBufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InstancedMesh, Int16Attribute, Int16BufferAttribute, Int32Attribute, Int32BufferAttribute, Int8Attribute, Int8BufferAttribute, IntType, InterleavedBuffer, InterleavedBufferAttribute, Interpolant, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InvertStencilOp, JSONLoader, KeepStencilOp, KeyframeTrack, LOD, LatheGeometry as LatheBufferGeometry, LatheGeometry, Layers, LensFlare, LessDepth, LessEqualDepth, LessEqualStencilFunc, LessStencilFunc, Light, LightProbe, Line, Line3, LineBasicMaterial, LineCurve, LineCurve3, LineDashedMaterial, LineLoop, LinePieces, LineSegments, LineStrip, LinearEncoding, LinearFilter, LinearInterpolant, LinearMipMapLinearFilter, LinearMipMapNearestFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, LinearToneMapping, Loader, LoaderUtils, LoadingManager, LoopOnce, LoopPingPong, LoopRepeat, LuminanceAlphaFormat, LuminanceFormat, MOUSE, Material, MaterialLoader, MathUtils as Math, MathUtils, Matrix3, Matrix4, MaxEquation, Mesh, MeshBasicMaterial, MeshDepthMaterial, MeshDistanceMaterial, MeshFaceMaterial, MeshLambertMaterial, MeshMatcapMaterial, MeshNormalMaterial, MeshPhongMaterial, MeshPhysicalMaterial, MeshStandardMaterial, MeshToonMaterial, MinEquation, MirroredRepeatWrapping, MixOperation, MultiMaterial, MultiplyBlending, MultiplyOperation, NearestFilter, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, NeverDepth, NeverStencilFunc, NoBlending, NoColors, NoToneMapping, NormalAnimationBlendMode, NormalBlending, NotEqualDepth, NotEqualStencilFunc, NumberKeyframeTrack, Object3D, ObjectLoader, ObjectSpaceNormalMap, OctahedronGeometry as OctahedronBufferGeometry, OctahedronGeometry, OneFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, OrthographicCamera, PCFShadowMap, PCFSoftShadowMap, PMREMGenerator, ParametricGeometry, Particle, ParticleBasicMaterial, ParticleSystem, ParticleSystemMaterial, Path, PerspectiveCamera, Plane, PlaneGeometry as PlaneBufferGeometry, PlaneGeometry, PlaneHelper, PointCloud, PointCloudMaterial, PointLight, PointLightHelper, Points, PointsMaterial, PolarGridHelper, PolyhedronGeometry as PolyhedronBufferGeometry, PolyhedronGeometry, PositionalAudio, PropertyBinding, PropertyMixer, QuadraticBezierCurve, QuadraticBezierCurve3, Quaternion, QuaternionKeyframeTrack, QuaternionLinearInterpolant, REVISION, RGBADepthPacking, RGBAFormat, RGBAIntegerFormat, RGBA_ASTC_10x10_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGBFormat, RGBIntegerFormat, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGFormat, RGIntegerFormat, RawShaderMaterial, Ray, Raycaster, RectAreaLight, RedFormat, RedIntegerFormat, ReinhardToneMapping, RepeatWrapping, ReplaceStencilOp, ReverseSubtractEquation, RingGeometry as RingBufferGeometry, RingGeometry, Scene, SceneUtils, ShaderChunk, ShaderLib, ShaderMaterial, ShadowMaterial, Shape, ShapeGeometry as ShapeBufferGeometry, ShapeGeometry, ShapePath, ShapeUtils, ShortType, Skeleton, SkeletonHelper, SkinnedMesh, SmoothShading, Sphere, SphereGeometry as SphereBufferGeometry, SphereGeometry, Spherical, SphericalHarmonics3, SplineCurve, SpotLight, SpotLightHelper, Sprite, SpriteMaterial, SrcAlphaFactor, SrcAlphaSaturateFactor, SrcColorFactor, StaticCopyUsage, StaticDrawUsage, StaticReadUsage, StereoCamera, StreamCopyUsage, StreamDrawUsage, StreamReadUsage, StringKeyframeTrack, SubtractEquation, SubtractiveBlending, TOUCH, TangentSpaceNormalMap, TetrahedronGeometry as TetrahedronBufferGeometry, TetrahedronGeometry, TextGeometry, Texture, TextureLoader, TorusGeometry as TorusBufferGeometry, TorusGeometry, TorusKnotGeometry as TorusKnotBufferGeometry, TorusKnotGeometry, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TubeGeometry as TubeBufferGeometry, TubeGeometry, UVMapping, Uint16Attribute, Uint16BufferAttribute, Uint32Attribute, Uint32BufferAttribute, Uint8Attribute, Uint8BufferAttribute, Uint8ClampedAttribute, Uint8ClampedBufferAttribute, Uniform, UniformsLib, UniformsUtils, UnsignedByteType, UnsignedInt248Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShort565Type, UnsignedShortType, VSMShadowMap, Vector2, Vector3, Vector4, VectorKeyframeTrack, Vertex, VertexColors, VideoTexture, WebGL1Renderer, WebGLCubeRenderTarget, WebGLMultipleRenderTargets, WebGLMultisampleRenderTarget, WebGLRenderTarget, WebGLRenderTargetCube, WebGLRenderer, WebGLUtils, WireframeGeometry, WireframeHelper, WrapAroundEnding, XHRLoader, ZeroCurvatureEnding, ZeroFactor, ZeroSlopeEnding, ZeroStencilOp, _SRGBAFormat, _SRGBFormat, sRGBEncoding }; diff --git a/docs/api/ar/audio/AudioListener.html b/docs/api/ar/audio/AudioListener.html index 6835ac8ca37f2a..83995275893cfb 100644 --- a/docs/api/ar/audio/AudioListener.html +++ b/docs/api/ar/audio/AudioListener.html @@ -12,7 +12,7 @@

[name]

- يمثل هذا المكون [link:https://developer.mozilla.org/de/docs/Web/API/AudioListener listener] افتراضيًا من جميع المؤثرات الصوتية الموضعية وغير الموضعية في المشهد.
+ يمثل هذا المكون [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioListener listener] افتراضيًا من جميع المؤثرات الصوتية الموضعية وغير الموضعية في المشهد.
عادةً ما يُنشئ تطبيق three.js مثيلاً واحدًا من هذا الكائن. إنها معلمة تفسير إلزامية لكيانات الصوت مثل [page:Audio Audio] و [page:PositionalAudio PositionalAudio].
في معظم الحالات ، يكون الكائن المستمع هو كائن فرعي للكاميرا. لذا فإن التحول ثلاثي الأبعاد للكاميرا يمثل التحول ثلاثي الأبعاد للمستمع.

diff --git a/docs/api/en/Polyfills.html b/docs/api/en/Polyfills.html deleted file mode 100644 index 36e13a086d4082..00000000000000 --- a/docs/api/en/Polyfills.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - -

Polyfills

- -

Three.js includes polyfills for the following functions and constants.

- -

[page:Number.EPSILON Number.EPSILON]

-

- The difference between one and the smallest value greater than one that can be represented as a Number. - [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON MDN reference]. -

- -

[page:Math.sign Math.sign]( [page:Number x] )

-

- If the argument is a positive number, negative number, positive zero or negative zero, - the function will return 1, -1, 0 or -0 respectively. Otherwise, NaN is returned. - [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign MDN reference]. -

- -

[page:Function.prototype.name Function.prototype.name]( [page:Number x] )

-

- Returns the name of a function, or (before ES6 implementations) an empty string for anonymous functions. - [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name MDN reference]. -

- -

[page:Object.assign Object.assign]( [page:Object target], [page:Object ...sources] )

-

- The Object.assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object. - It will return the target object. - [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign MDN reference]. -

- -

Source

- -

- [link:https://github.com/mrdoob/three.js/blob/master/src/polyfills.js src/polyfills.js] -

- - diff --git a/docs/api/en/audio/AudioListener.html b/docs/api/en/audio/AudioListener.html index 06d57ced5f0fdb..cff1bd17247c6d 100644 --- a/docs/api/en/audio/AudioListener.html +++ b/docs/api/en/audio/AudioListener.html @@ -12,7 +12,7 @@

[name]

- The [name] represents a virtual [link:https://developer.mozilla.org/de/docs/Web/API/AudioListener listener] of the all positional and non-positional audio effects in the scene.
+ The [name] represents a virtual [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioListener listener] of the all positional and non-positional audio effects in the scene.
A three.js application usually creates a single instance of [name]. It is a mandatory construtor parameter for audios entities like [page:Audio Audio] and [page:PositionalAudio PositionalAudio].
In most cases, the listener object is a child of the camera. So the 3D transformation of the camera represents the 3D transformation of the listener.

diff --git a/docs/api/en/constants/Textures.html b/docs/api/en/constants/Textures.html index 19f1143c4cfe20..437926bf84c849 100644 --- a/docs/api/en/constants/Textures.html +++ b/docs/api/en/constants/Textures.html @@ -151,7 +151,6 @@

Formats

THREE.RGBAIntegerFormat THREE.LuminanceFormat THREE.LuminanceAlphaFormat - THREE.RGBEFormat THREE.DepthFormat THREE.DepthStencilFormat @@ -199,8 +198,6 @@

Formats

The same process occurs as for the [page:constant LuminanceFormat], except that the alpha channel may have values other than *1.0*.

- [page:constant RGBEFormat] is identical to [page:constant RGBAFormat].

- [page:constant DepthFormat] reads each element as a single depth value, converts it to floating point, and clamps to the range [0,1]. This is the default for [page:DepthTexture DepthTexture].

@@ -282,20 +279,6 @@

ASTC Compressed Texture Format

THREE.RGBA_ASTC_10x10_Format THREE.RGBA_ASTC_12x10_Format THREE.RGBA_ASTC_12x12_Format - THREE.SRGB8_ALPHA8_ASTC_4x4_Format - THREE.SRGB8_ALPHA8_ASTC_5x4_Format - THREE.SRGB8_ALPHA8_ASTC_5x5_Format - THREE.SRGB8_ALPHA8_ASTC_6x5_Format - THREE.SRGB8_ALPHA8_ASTC_6x6_Format - THREE.SRGB8_ALPHA8_ASTC_8x5_Format - THREE.SRGB8_ALPHA8_ASTC_8x6_Format - THREE.SRGB8_ALPHA8_ASTC_8x8_Format - THREE.SRGB8_ALPHA8_ASTC_10x5_Format - THREE.SRGB8_ALPHA8_ASTC_10x6_Format - THREE.SRGB8_ALPHA8_ASTC_10x8_Format - THREE.SRGB8_ALPHA8_ASTC_10x10_Format - THREE.SRGB8_ALPHA8_ASTC_12x10_Format - THREE.SRGB8_ALPHA8_ASTC_12x12_Format

For use with a [page:CompressedTexture CompressedTexture]'s [page:Texture.format format] property, @@ -559,11 +542,6 @@

Encoding

THREE.LinearEncoding THREE.sRGBEncoding - THREE.GammaEncoding - THREE.RGBEEncoding - THREE.RGBM7Encoding - THREE.RGBM16Encoding - THREE.RGBDEncoding THREE.BasicDepthPacking THREE.RGBADepthPacking diff --git a/docs/api/en/core/Raycaster.html b/docs/api/en/core/Raycaster.html index b320bc93ddf605..f547e476dff631 100644 --- a/docs/api/en/core/Raycaster.html +++ b/docs/api/en/core/Raycaster.html @@ -18,22 +18,22 @@

[name]

Code Example

const raycaster = new THREE.Raycaster(); - const mouse = new THREE.Vector2(); + const pointer = new THREE.Vector2(); - function onMouseMove( event ) { + function onPointerMove( event ) { - // calculate mouse position in normalized device coordinates + // calculate pointer position in normalized device coordinates // (-1 to +1) for both components - mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1; - mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1; + pointer.x = ( event.clientX / window.innerWidth ) * 2 - 1; + pointer.y = - ( event.clientY / window.innerHeight ) * 2 + 1; } function render() { - // update the picking ray with the camera and mouse position - raycaster.setFromCamera( mouse, camera ); + // update the picking ray with the camera and pointer position + raycaster.setFromCamera( pointer, camera ); // calculate objects intersecting the picking ray const intersects = raycaster.intersectObjects( scene.children ); @@ -48,7 +48,7 @@

Code Example

} - window.addEventListener( 'mousemove', onMouseMove, false ); + window.addEventListener( 'pointermove', onPointerMove ); window.requestAnimationFrame(render); diff --git a/docs/api/en/extras/PMREMGenerator.html b/docs/api/en/extras/PMREMGenerator.html index 1d4f0d67094933..1754bf12b13cbc 100644 --- a/docs/api/en/extras/PMREMGenerator.html +++ b/docs/api/en/extras/PMREMGenerator.html @@ -42,7 +42,7 @@

[method:WebGLRenderTarget fromEquirectangular]( [param:Texture equirectangul

[page:Texture equirectangular] - The equirectangular texture.

- Generates a PMREM from an equirectangular texture, which can be either LDR (RGBFormat) or HDR (RGBEFormat). + Generates a PMREM from an equirectangular texture, which can be either LDR or HDR. The ideal input image size is 1k (1024 x 512), as this matches best with the 256 x 256 cubemap output.

@@ -50,7 +50,7 @@

[method:WebGLRenderTarget fromCubemap]( [param:CubeTexture cubemap] )

[page:CubeTexture cubemap] - The cubemap texture.

- Generates a PMREM from an cubemap texture, which can be either LDR (RGBFormat) or HDR (RGBEFormat). + Generates a PMREM from an cubemap texture, which can be either LDR or HDR. The ideal input cube size is 256 x 256, as this matches best with the 256 x 256 cubemap output.

diff --git a/docs/api/en/math/Color.html b/docs/api/en/math/Color.html index fe63b8e85cd934..2bff7eea69e4ba 100644 --- a/docs/api/en/math/Color.html +++ b/docs/api/en/math/Color.html @@ -113,18 +113,6 @@

[method:this copy]( [param:Color color] )

Copies the [page:.r r], [page:.g g] and [page:.b b] parameters from [page:Color color] in to this color.

-

[method:this convertGammaToLinear]( [param:Float gammaFactor] )

-

- [page:Float gammaFactor] - (optional). Default is *2.0*.

- Converts this color from gamma space to linear space by taking [page:.r r], [page:.g g] and [page:.b b] to the power of [page:Float gammaFactor]. -

- -

[method:this convertLinearToGamma]( [param:Float gammaFactor] )

-

- [page:Float gammaFactor] - (optional). Default is *2.0*.

- Converts this color from linear space to gamma space by taking [page:.r r], [page:.g g] and [page:.b b] to the power of 1 / [page:Float gammaFactor]. -

-

[method:this convertLinearToSRGB]()

Converts this color from linear space to sRGB space. @@ -135,24 +123,6 @@

[method:this convertSRGBToLinear]()

Converts this color from sRGB space to linear space.

-

[method:this copyGammaToLinear]( [param:Color color], [param:Float gammaFactor] )

-

- [page:Color color] — Color to copy.
- [page:Float gammaFactor] - (optional). Default is *2.0*.

- - Copies the given color into this color, and then converts this color from gamma space to linear space - by taking [page:.r r], [page:.g g] and [page:.b b] to the power of [page:Float gammaFactor]. -

- -

[method:this copyLinearToGamma]( [param:Color color], [param:Float gammaFactor] )

-

- [page:Color color] — Color to copy.
- [page:Float gammaFactor] - (optional). Default is *2.0*.

- - Copies the given color into this color, and then converts this color from linear space to gamma space - by taking [page:.r r], [page:.g g] and [page:.b b] to the power of 1 / [page:Float gammaFactor]. -

-

[method:this copyLinearToSRGB]( [param:Color color]] )

[page:Color color] — Color to copy.
diff --git a/docs/api/en/objects/SkinnedMesh.html b/docs/api/en/objects/SkinnedMesh.html index 7af12ff8a88159..0eb51fe5fddc70 100644 --- a/docs/api/en/objects/SkinnedMesh.html +++ b/docs/api/en/objects/SkinnedMesh.html @@ -134,7 +134,7 @@

[method:undefined bind]( [param:Skeleton skeleton], [param:Matrix4 bindMatri

[method:SkinnedMesh clone]()

- Returns a clone of this SkinnedMesh object and any descendants. + This method does currently not clone an instance of [name] correctly. Please use [page:SkeletonUtils.clone]() in the meanwhile.

[method:undefined normalizeSkinWeights]()

@@ -147,11 +147,6 @@

[method:undefined pose]()

This method sets the skinned mesh in the rest pose (resets the pose).

-

[method:undefined updateMatrixWorld]( [param:Boolean force] )

-

- Updates the [page:Matrix4 MatrixWorld]. -

-

[method:Vector3 boneTransform]( [index:Integer], [target:Vector3] )

Calculates the position of the vertex at the given index relative to the current bone transformations. diff --git a/docs/api/en/renderers/WebGLRenderer.html b/docs/api/en/renderers/WebGLRenderer.html index 3954e06e223bd7..46e9747d194cc4 100644 --- a/docs/api/en/renderers/WebGLRenderer.html +++ b/docs/api/en/renderers/WebGLRenderer.html @@ -158,9 +158,6 @@

[property:Object extensions]

various WebGL extensions are supported.

-

[property:Float gammaFactor]

-

Default is *2*.

-

[property:number outputEncoding]

Defines the output encoding of the renderer. Default is [page:Textures THREE.LinearEncoding].

If a render target has been set using [page:WebGLRenderer.setRenderTarget .setRenderTarget] then renderTarget.texture.encoding will be used instead.

diff --git a/docs/api/ko/audio/AudioListener.html b/docs/api/ko/audio/AudioListener.html index 3e5e52bb3f9648..c9b791c887a74a 100644 --- a/docs/api/ko/audio/AudioListener.html +++ b/docs/api/ko/audio/AudioListener.html @@ -12,7 +12,7 @@

[name]

- [name]는 장면 안의 모든 지정 및 비지정 오디오 효과의 가상 [link:https://developer.mozilla.org/de/docs/Web/API/AudioListener listener]입니다.
+ [name]는 장면 안의 모든 지정 및 비지정 오디오 효과의 가상 [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioListener listener]입니다.
three.js 앱은 일반적으로 단일 [name] 인스턴스를 생성합니다. 이는 [page:Audio Audio]와 [page:PositionalAudio PositionalAudio] 같은 오디오 개체의 필수 생성자 파라미터입니다.
대부분의 경우, 리스너 오브젝트는 카메라의 자식입니다. 그래서 카메라의 3D 변환은 곧 리스너의 3D 변환이 됩니다.

diff --git a/docs/api/ko/constants/Textures.html b/docs/api/ko/constants/Textures.html index 6b8028012f3115..4de37425af4ce2 100644 --- a/docs/api/ko/constants/Textures.html +++ b/docs/api/ko/constants/Textures.html @@ -31,8 +31,8 @@

맵핑 모드

[page:Constant CubeReflectionMapping]은 [page:CubeTexture CubeTexture]의 기본값입니다.

[page:Constant EquirectangularReflectionMapping] 및 [page:Constant EquirectangularRefractionMapping]은 - 등장방향형도법 환경 맵과 함께 사용됩니다. 맵으로도 불리며, 등장방향형도법 텍스쳐는 - 수평 중심선을 따라 360도 시야를 나타내고 수직 축을 따라 180도 시야를 나타내며 + 등장방향형도법 환경 맵과 함께 사용됩니다. 맵으로도 불리며, 등장방향형도법 텍스쳐는 + 수평 중심선을 따라 360도 시야를 나타내고 수직 축을 따라 180도 시야를 나타내며 이미지의 상단과 하단 가장자리는 맵핑된 구의 북극과 남극에 해당합니다.

[example:webgl_materials_envmaps materials / envmaps] 예제를 참고하세요. @@ -63,17 +63,17 @@

확대 필터

- 텍스쳐의 [page:Texture.magFilter magFilter] 프로퍼티와 함께 사용되며, - 텍스처의 픽셀이 하나의 텍스처 요소(texel)보다 작거나 같은 영역에 매핑될 때 + 텍스쳐의 [page:Texture.magFilter magFilter] 프로퍼티와 함께 사용되며, + 텍스처의 픽셀이 하나의 텍스처 요소(texel)보다 작거나 같은 영역에 매핑될 때 사용할 텍스처 확대 함수를 정의합니다.

[page:constant NearestFilter]는 특정 텍스쳐 좌표와 가장 가까운(맨해튼 거리 단위로) 텍스쳐 요소의 값을 리턴합니다.

- [page:constant LinearFilter]이 기본값이며 지정된 텍스쳐 좌표에 가장 가까운 네 가지 텍스쳐 요소의 가중 평균을 리턴하며, + [page:constant LinearFilter]이 기본값이며 지정된 텍스쳐 좌표에 가장 가까운 네 가지 텍스쳐 요소의 가중 평균을 리턴하며, [page:Texture.wrapS wrapS] 및 [page:Texture.wrapT wrapT]의 값과 정확한 맵핑에 따라 텍스처의 다른 부분에서 랩핑되거나 반복된 항목을 포함할 수 있습니다. - +

축소 필터

@@ -87,28 +87,28 @@

축소 필터

- 텍스쳐의 [page:Texture.minFilter minFilter] 프로퍼티와 함께 사용하기 위해, - 텍스처의 픽셀이 하나의 텍스처 요소(texel)보다 큰 영역에 매핑될 때 + 텍스쳐의 [page:Texture.minFilter minFilter] 프로퍼티와 함께 사용하기 위해, + 텍스처의 픽셀이 하나의 텍스처 요소(texel)보다 큰 영역에 매핑될 때 사용할 텍스처 축소 함수를 정의합니다.

[page:constant NearestFilter] 및 [page:constant LinearFilter]와 함께, 아래 네 가지의 함수는 축소에 사용될 수 있습니다:

- [page:constant NearestMipmapNearestFilter]는 - 텍스처링되는 픽셀의 크기와 가장 근접한 mipmap을 선택하고 + [page:constant NearestMipmapNearestFilter]는 + 텍스처링되는 픽셀의 크기와 가장 근접한 mipmap을 선택하고 [page:constant NearestFilter] 기준(픽셀의 중심에 가장 가까운 texel)을 사용하여 텍스쳐 값을 생성합니다.

- [page:constant NearestMipmapLinearFilter]는 텍스처링되는 픽셀 크기와 가장 근접한 두 개의 mipmap을 선택하고 + [page:constant NearestMipmapLinearFilter]는 텍스처링되는 픽셀 크기와 가장 근접한 두 개의 mipmap을 선택하고 [page:constant NearstFilter] 기준을 사용하여 각 mipmap에서 텍스쳐 값을 생성합니다. 최종 텍스쳐 값은 이 두 값의 가중 평균입니다.

- [page:constant LinearMipmapNearestFilter]는 텍스쳐링되는 픽셀 크기와 가장 근접한 mipmap을 선택하고 + [page:constant LinearMipmapNearestFilter]는 텍스쳐링되는 픽셀 크기와 가장 근접한 mipmap을 선택하고 [page:constant LineFilter] 기준(픽셀의 중심에 가장 가까운 4개의 texel의 가중 평균)을 사용하여 텍스쳐 값을 생성합니다.

- [page:constant LinearMipmapLinearFilter]가 기본값이며 텍스처링되는 픽셀 크기와 가장 일치하는 두 개의 mipmap을 선택하고 - [page:constant LinearFilter] 기준을 사용하여 각 mipmap에서 텍스처 값을 생성합니다. + [page:constant LinearMipmapLinearFilter]가 기본값이며 텍스처링되는 픽셀 크기와 가장 일치하는 두 개의 mipmap을 선택하고 + [page:constant LinearFilter] 기준을 사용하여 각 mipmap에서 텍스처 값을 생성합니다. 최종 텍스처 값은 이 두 값의 가중 평균입니다.

[example:webgl_materials_texture_filters materials / texture / filters] 예제를 참고하세요. @@ -148,7 +148,6 @@

포맷

THREE.RGBAIntegerFormat THREE.LuminanceFormat THREE.LuminanceAlphaFormat - THREE.RGBEFormat THREE.DepthFormat THREE.DepthStencilFormat @@ -188,15 +187,13 @@

포맷



[page:constant LuminanceFormat]은 각 요소(element)를 단일 휘도 요소(component)로 읽어들입니다. - 그 다음에 부동 소수점으로 변환되어 [0,1] 범위에 고정한 다음 + 그 다음에 부동 소수점으로 변환되어 [0,1] 범위에 고정한 다음 휘도 값을 적색, 녹색 및 청색 채널에 배치하고 1.0을 알파 채널에 할당하여 RGBA 요소로 조립합니다.

[page:constant LuminanceAlphaFormat]은 각 요소(element)를 휘도/알파 소수로 읽어들입니다. The same process occurs as for the [page:constant LuminanceFormat]와 같은 절차가 이루어지며, 알파 채널에 *1.0* 이외의 값이 들어갈 수 있다는 점만 다릅니다.

- [page:constant RGBEFormat]은 [page:constant RGBAFormat]과 동일합니다..

- [page:constant DepthFormat]은 각 요소를 단일 깊이 값으로 일거들이며 부동 소수점으로 변환하고, [0,1]범위에 고정합니다. [page:DepthTexture DepthTexture]의 기본값이기도 합니다.

@@ -277,20 +274,6 @@

ASTC 압축 텍스쳐 포맷

THREE.RGBA_ASTC_10x10_Format THREE.RGBA_ASTC_12x10_Format THREE.RGBA_ASTC_12x12_Format - THREE.SRGB8_ALPHA8_ASTC_4x4_Format - THREE.SRGB8_ALPHA8_ASTC_5x4_Format - THREE.SRGB8_ALPHA8_ASTC_5x5_Format - THREE.SRGB8_ALPHA8_ASTC_6x5_Format - THREE.SRGB8_ALPHA8_ASTC_6x6_Format - THREE.SRGB8_ALPHA8_ASTC_8x5_Format - THREE.SRGB8_ALPHA8_ASTC_8x6_Format - THREE.SRGB8_ALPHA8_ASTC_8x8_Format - THREE.SRGB8_ALPHA8_ASTC_10x5_Format - THREE.SRGB8_ALPHA8_ASTC_10x6_Format - THREE.SRGB8_ALPHA8_ASTC_10x8_Format - THREE.SRGB8_ALPHA8_ASTC_10x10_Format - THREE.SRGB8_ALPHA8_ASTC_12x10_Format - THREE.SRGB8_ALPHA8_ASTC_12x12_Format

[page:CompressedTexture CompressedTexture]'s [page:Texture.format format] 프로퍼티와 함께 사용되며, @@ -541,11 +524,11 @@

내부 포맷

[page:Texture.format format], [page:Texture.internalFormat internalFormat], 및 [page:Texture.type type]과의 조합과 관련된 세부 내용에 관해서는 - [link:https://developer.mozilla.org/en/docs/Web/API/WebGLRenderingContext/texImage2D WebGLRenderingContext.texImage2D], + [link:https://developer.mozilla.org/en/docs/Web/API/WebGLRenderingContext/texImage2D WebGLRenderingContext.texImage2D], [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/texImage3D WebGL2RenderingContext.texImage3D]를 참고하세요.

- 내부 포맷과 관련된 심화 정보에 대해서는 직접 - [link:https://www.khronos.org/registry/webgl/specs/latest/2.0/ WebGL2 Specification] 및 + 내부 포맷과 관련된 심화 정보에 대해서는 직접 + [link:https://www.khronos.org/registry/webgl/specs/latest/2.0/ WebGL2 Specification] 및 [link:https://www.khronos.org/registry/OpenGL/specs/es/3.0/es_spec_3.0.pdf OpenGL ES 3.0 Specification]를 확인해보세요.

@@ -553,12 +536,6 @@

인코딩

THREE.LinearEncoding THREE.sRGBEncoding - THREE.GammaEncoding - THREE.RGBEEncoding - THREE.LogLuvEncoding - THREE.RGBM7Encoding - THREE.RGBM16Encoding - THREE.RGBDEncoding THREE.BasicDepthPacking THREE.RGBADepthPacking diff --git a/docs/api/ko/core/Raycaster.html b/docs/api/ko/core/Raycaster.html index f97af6ef9e8b7e..c7443c3c6be78b 100644 --- a/docs/api/ko/core/Raycaster.html +++ b/docs/api/ko/core/Raycaster.html @@ -17,22 +17,22 @@

[name]

코드 예제

const raycaster = new THREE.Raycaster(); - const mouse = new THREE.Vector2(); + const pointer = new THREE.Vector2(); - function onMouseMove( event ) { + function onPointerMove( event ) { - // calculate mouse position in normalized device coordinates + // calculate pointer position in normalized device coordinates // (-1 to +1) for both components - mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1; - mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1; + pointer.x = ( event.clientX / window.innerWidth ) * 2 - 1; + pointer.y = - ( event.clientY / window.innerHeight ) * 2 + 1; } function render() { - // update the picking ray with the camera and mouse position - raycaster.setFromCamera( mouse, camera ); + // update the picking ray with the camera and pointer position + raycaster.setFromCamera( pointer, camera ); // calculate objects intersecting the picking ray const intersects = raycaster.intersectObjects( scene.children ); @@ -47,7 +47,7 @@

코드 예제

} - window.addEventListener( 'mousemove', onMouseMove, false ); + window.addEventListener( 'pointermove', onPointerMove ); window.requestAnimationFrame(render); diff --git a/docs/api/ko/extras/PMREMGenerator.html b/docs/api/ko/extras/PMREMGenerator.html index 2dd845dcf77c98..e6f5a2b69cec1d 100644 --- a/docs/api/ko/extras/PMREMGenerator.html +++ b/docs/api/ko/extras/PMREMGenerator.html @@ -11,7 +11,7 @@

[name]

이 클래스는 큐브맵 환경 텍스처로부터 사전 필터링된 Mipmap Radiance Environment Map(PMREM)을 생성합니다. -이를 통해 재질의 거칠기에 따라 다양한 수준의 블러를 빠르게 적용할 수 있습니다. RGBE와 같은 비선형 형식을 지원할 수 있도록 사용자 지정 보간을 수행할 수 있는 특수 CubeUV 형식으로 포장되어 있습니다. +이를 통해 재질의 거칠기에 따라 다양한 수준의 블러를 빠르게 적용할 수 있습니다. RGBE와 같은 비선형 형식을 지원할 수 있도록 사용자 지정 보간을 수행할 수 있는 특수 CubeUV 형식으로 포장되어 있습니다. 기존의 mipmap 체인과는 달리, LOD_MIN 수준까지만 내려가며(위), 더 높은 거칠기 수준과 연관된 동일한 LOD_MIN 해상도에서 훨씬 더 많은 필터링된 'mips'를 생성합니다. 이러한 방법으로 샘플링 계산을 제한하면서 확산 조명을 부드럽게 보간하기 위한 해상도를 유지합니다.

@@ -40,7 +40,7 @@

[method:WebGLRenderTarget fromEquirectangular]( [param:Texture equirectangul

[page:Texture equirectangular] - 등장방형 텍스쳐입니다.

- LDR(RGBFormat) 또는 HDR(RGBEFormat)일 수 있는 등장방형 텍스처로부터 PMREM을 생성합니다. + LDR 또는 HDR일 수 있는 등장방형 텍스처로부터 PMREM을 생성합니다. 이상적인 입력 이미지 크기는 1k(1024 x 512)로, 256 x 256 큐브 맵 출력과 가장 잘 일치합니다.

@@ -48,7 +48,7 @@

[method:WebGLRenderTarget fromCubemap]( [param:CubeTexture cubemap] )

[page:CubeTexture cubemap] - 큐브맵 텍스쳐입니다.

- LDR(RGBFormat) 또는 HDR(RGBEFormat)일 수 있는 큐브맵 텍스처로부터 PMREM을 생성합니다. + LDR 또는 HDR일 수 있는 큐브맵 텍스처로부터 PMREM을 생성합니다. 이상적인 입력 이미지 크기는 1k(1024 x 512)로, 256 x 256 큐브 맵 출력과 가장 잘 일치합니다.

@@ -64,8 +64,8 @@

[method:undefined compileEquirectangularShader]()

[method:undefined dispose]()

- PMREM 제너레이터의 내장 메모리를 폐기합니다. - PMREMGenerator는 정적 클래스이므로 두 개 이상의 PMREMGenerator 개체가 필요하지 않습니다. + PMREM 제너레이터의 내장 메모리를 폐기합니다. + PMREMGenerator는 정적 클래스이므로 두 개 이상의 PMREMGenerator 개체가 필요하지 않습니다. 이 경우 둘 중 하나에 대해 dispose()를 호출하면 다른 항목도 사용할 수 없게 됩니다.

diff --git a/docs/api/zh/Polyfills.html b/docs/api/zh/Polyfills.html deleted file mode 100644 index 328c5e894e9ece..00000000000000 --- a/docs/api/zh/Polyfills.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - -

差异化支持(腻子)

- -

Three.js 包含以下方法和常量的差异化支持.

- -

[page:Number.EPSILON Number.EPSILON]

-

- 表示1和大于1的最小差值,可表示为 Number. - [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON MDN reference]. -

- -

[page:Math.sign Math.sign]( [page:Number x] )

-

- 如果参数为 正数,负数,正零 或 负零, - 该方法将分别返回 1, -1, 0 或 -0 . 否则, 返回 NaN. - [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign MDN reference]. -

- -

[page:Function.prototype.name Function.prototype.name]( [page:Number x] )

-

- 返回方法的名字, 或 (在 ES6 实现之前) 为匿名方法返回一个空字符串. - [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name MDN reference]. -

- -

[page:Object.assign Object.assign]( [page:Object target], [page:Object ...sources] )

-

- Object.assign() 方法用于从一个或多个源对象拷贝所有可枚举自身属性到目标对象. - 该方法将返回目标对象. - [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign MDN reference]. -

- -

源码

- -

- [link:https://github.com/mrdoob/three.js/blob/master/src/polyfills.js src/polyfills.js] -

- - diff --git a/docs/api/zh/audio/AudioListener.html b/docs/api/zh/audio/AudioListener.html index f3542044d0c30a..7299a4636892b2 100644 --- a/docs/api/zh/audio/AudioListener.html +++ b/docs/api/zh/audio/AudioListener.html @@ -12,7 +12,7 @@

[name]

- [name] 用一个虚拟的[link:https://developer.mozilla.org/de/docs/Web/API/AudioListener listener]表示在场景中所有的位置和非位置相关的音效.
+ [name] 用一个虚拟的[link:https://developer.mozilla.org/en-US/docs/Web/API/AudioListener listener]表示在场景中所有的位置和非位置相关的音效.
一个three.js程序通常创建一个[name]. 它是音频实体构造函数的必须参数,比如 [page:Audio Audio] and [page:PositionalAudio PositionalAudio].
大多数情况下, listener对象是camera的子对象. Camera的3D变换表示了listener的3D变换.

diff --git a/docs/api/zh/constants/Textures.html b/docs/api/zh/constants/Textures.html index 290cc02f3c4a16..07b9017fc509f8 100644 --- a/docs/api/zh/constants/Textures.html +++ b/docs/api/zh/constants/Textures.html @@ -141,7 +141,6 @@

格式

THREE.RGBAIntegerFormat THREE.LuminanceFormat THREE.LuminanceAlphaFormat - THREE.RGBEFormat THREE.DepthFormat THREE.DepthStencilFormat
@@ -185,8 +184,6 @@

格式

[page:constant LuminanceAlphaFormat] 将每个元素同时作为亮度分量和Alpha分量来读取。 和上面[page:constant LuminanceFormat]的处理过程是一致的,除了Alpha分量具有除了*1.0*以外的值。

- [page:constant RGBEFormat] 与 [page:constant RGBAFormat] 是相同的。

- [page:constant DepthFormat]将每个元素作为单独的深度值来读取,将其转换为范围限制在[0,1]区间的浮点数。 它是[page:DepthTexture DepthTexture]的默认值。

@@ -271,20 +268,6 @@

ASTC Compressed Texture Format

THREE.RGBA_ASTC_10x10_Format THREE.RGBA_ASTC_12x10_Format THREE.RGBA_ASTC_12x12_Format - THREE.SRGB8_ALPHA8_ASTC_4x4_Format - THREE.SRGB8_ALPHA8_ASTC_5x4_Format - THREE.SRGB8_ALPHA8_ASTC_5x5_Format - THREE.SRGB8_ALPHA8_ASTC_6x5_Format - THREE.SRGB8_ALPHA8_ASTC_6x6_Format - THREE.SRGB8_ALPHA8_ASTC_8x5_Format - THREE.SRGB8_ALPHA8_ASTC_8x6_Format - THREE.SRGB8_ALPHA8_ASTC_8x8_Format - THREE.SRGB8_ALPHA8_ASTC_10x5_Format - THREE.SRGB8_ALPHA8_ASTC_10x6_Format - THREE.SRGB8_ALPHA8_ASTC_10x8_Format - THREE.SRGB8_ALPHA8_ASTC_10x10_Format - THREE.SRGB8_ALPHA8_ASTC_12x10_Format - THREE.SRGB8_ALPHA8_ASTC_12x12_Format

For use with a [page:CompressedTexture CompressedTexture]'s [page:Texture.format format] property, @@ -548,12 +531,6 @@

编码

THREE.LinearEncoding THREE.sRGBEncoding - THREE.GammaEncoding - THREE.RGBEEncoding - THREE.LogLuvEncoding - THREE.RGBM7Encoding - THREE.RGBM16Encoding - THREE.RGBDEncoding THREE.BasicDepthPacking THREE.RGBADepthPacking diff --git a/docs/api/zh/core/Raycaster.html b/docs/api/zh/core/Raycaster.html index 99090f1dfc1f6a..fcafbbb3836c99 100644 --- a/docs/api/zh/core/Raycaster.html +++ b/docs/api/zh/core/Raycaster.html @@ -17,21 +17,21 @@

光线投射[name]

代码示例

const raycaster = new THREE.Raycaster(); - const mouse = new THREE.Vector2(); + const pointer = new THREE.Vector2(); - function onMouseMove( event ) { + function onPointerMove( event ) { // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1) - mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1; - mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1; + pointer.x = ( event.clientX / window.innerWidth ) * 2 - 1; + pointer.y = - ( event.clientY / window.innerHeight ) * 2 + 1; } function render() { // 通过摄像机和鼠标位置更新射线 - raycaster.setFromCamera( mouse, camera ); + raycaster.setFromCamera( pointer, camera ); // 计算物体和射线的焦点 const intersects = raycaster.intersectObjects( scene.children ); @@ -46,7 +46,7 @@

代码示例

} - window.addEventListener( 'mousemove', onMouseMove, false ); + window.addEventListener( 'pointermove', onPointerMove ); window.requestAnimationFrame(render); diff --git a/docs/api/zh/extras/PMREMGenerator.html b/docs/api/zh/extras/PMREMGenerator.html index 310dfc309c88be..98576d94aa5783 100644 --- a/docs/api/zh/extras/PMREMGenerator.html +++ b/docs/api/zh/extras/PMREMGenerator.html @@ -42,7 +42,7 @@

[method:WebGLRenderTarget fromEquirectangular]( [param:Texture equirectangul

[page:Texture equirectangular] - The equirectangular texture.

- Generates a PMREM from an equirectangular texture, which can be either LDR (RGBFormat) or HDR (RGBEFormat). + Generates a PMREM from an equirectangular texture, which can be either LDR or HDR. The ideal input image size is 1k (1024 x 512), as this matches best with the 256 x 256 cubemap output.

@@ -50,7 +50,7 @@

[method:WebGLRenderTarget fromCubemap]( [param:CubeTexture cubemap] )

[page:CubeTexture cubemap] - The cubemap texture.

- Generates a PMREM from an cubemap texture, which can be either LDR (RGBFormat) or HDR (RGBEFormat). + Generates a PMREM from an cubemap texture, which can be either LDR or HDR. The ideal input cube size is 256 x 256, as this matches best with the 256 x 256 cubemap output.

diff --git a/docs/api/zh/math/Color.html b/docs/api/zh/math/Color.html index 7b133cc7537a26..aa9e39a0665c04 100644 --- a/docs/api/zh/math/Color.html +++ b/docs/api/zh/math/Color.html @@ -113,18 +113,6 @@

[method:this copy]( [param:Color color] )

从 [page:Color color] 中拷贝 [page:.r r], [page:.g g] 和 [page:.b b] 值到当前的颜色。

-

[method:this convertGammaToLinear]( [param:Float gammaFactor] )

-

- [page:Float gammaFactor] - (可选参数). 默认值 *2.0*.

- 通过取颜色 [page:.r r], [page:.g g] and [page:.b b] 的 [page:Float gammaFactor] 次方将颜色从伽马空间转换成线性空间。 -

- -

[method:this convertLinearToGamma]( [param:Float gammaFactor] )

-

- [page:Float gammaFactor] - (可选参数). 默认值 *2.0*.

- 通过取颜色 [page:.r r], [page:.g g] and [page:.b b] 的 1/[page:Float gammaFactor] 次方将颜色从线性空间转换成伽马空间。 -

-

[method:this convertLinearToSRGB]()

将此颜色从线性空间转换成sRGB空间。 @@ -135,22 +123,6 @@

[method:this convertSRGBToLinear]()

将此颜色从sRGB空间转换成线性空间。

-

[method:this copyGammaToLinear]( [param:Color color], [param:Float gammaFactor] )

-

- [page:Color color] — 需要拷贝的颜色。
- [page:Float gammaFactor] - (可选参数). 默认值为 *2.0*.

- - 将传入的 [param:Color color] 从伽马空间转换到线性空间然后复制给当前颜色。 -

- -

[method:this copyLinearToGamma]( [param:Color color], [param:Float gammaFactor] )

-

- [page:Color color] — 需要拷贝的颜色。
- [page:Float gammaFactor] - (可选参数). 默认值为 *2.0*.

- - 将传入的 [param:Color color] 从线性空间转换到伽马空间然后复制给当前颜色。 -

-

[method:this copyLinearToSRGB]( [param:Color color]] )

[page:Color color] — 需要拷贝的颜色。
diff --git a/docs/api/zh/objects/SkinnedMesh.html b/docs/api/zh/objects/SkinnedMesh.html index 42e2883808f2e2..5ea6000fe25662 100644 --- a/docs/api/zh/objects/SkinnedMesh.html +++ b/docs/api/zh/objects/SkinnedMesh.html @@ -136,7 +136,7 @@

[method:undefined bind]( [param:Skeleton skeleton], [param:Matrix4 bindMatri

[method:SkinnedMesh clone]()

- 返回当前SkinnedMesh对象的一个克隆及其任何后代。 + This method does currently not clone an instance of [name] correctly. Please use [page:SkeletonUtils.clone]() in the meanwhile.

[method:undefined normalizeSkinWeights]()

@@ -149,11 +149,6 @@

[method:undefined pose]()

这个方法设置了在“休息”状态下蒙皮网格的姿势(重置姿势)。

-

[method:undefined updateMatrixWorld]( [param:Boolean force] )

-

- 更新[page:Matrix4 MatrixWorld]矩阵。 -

-

源代码

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] diff --git a/docs/api/zh/renderers/WebGLRenderer.html b/docs/api/zh/renderers/WebGLRenderer.html index 1473a28e1a79d7..2982250e00ef7f 100644 --- a/docs/api/zh/renderers/WebGLRenderer.html +++ b/docs/api/zh/renderers/WebGLRenderer.html @@ -137,9 +137,6 @@

[property:Object extensions]

[page:WebGLRenderer.extensions.get .extensions.get]方法的包装, 用于检查是否支持各种WebGL扩展

-

[property:Float gammaFactor]

-

默认是 *2*.

-

[property:number outputEncoding]

定义渲染器的输出编码。默认为[page:Textures THREE.LinearEncoding]

如果渲染目标已经使用 [page:WebGLRenderer.setRenderTarget .setRenderTarget]、之后将直接使用renderTarget.texture.encoding

diff --git a/docs/examples/en/controls/ArcballControls.html b/docs/examples/en/controls/ArcballControls.html index 297e31d8b186ad..db1a185a52aba1 100644 --- a/docs/examples/en/controls/ArcballControls.html +++ b/docs/examples/en/controls/ArcballControls.html @@ -252,11 +252,6 @@

[method:Boolean setMouseAction] ( [param:String operation], mouse, key )

-

[method:undefined setTarget] ( [param:Float x], [param:Float y], [param:Float z] )

-

- Set the trackball center point. -

-

[method:Boolean unsetMouseAction] ( mouse, key )

Removes a mouse action by specifying its mouse/key combination.

diff --git a/docs/examples/en/loaders/BasisTextureLoader.html b/docs/examples/en/loaders/BasisTextureLoader.html deleted file mode 100644 index 56301be20ab131..00000000000000 --- a/docs/examples/en/loaders/BasisTextureLoader.html +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - - - - - [page:Loader] → - -

[name]

- -

- Loader for Basis Universal GPU Texture Codec.

- - [link:https://github.com/BinomialLLC/basis_universal/ Basis Universal] is a - "supercompressed" GPU texture and texture video compression system that - outputs a highly compressed intermediate file format (.basis) that can be - quickly transcoded to a wide variety of GPU texture compression formats. -

- -

- This loader parallelizes the transcoding process across a configurable number - of web workers, before transferring the transcoded compressed texture back - to the main thread. The required WASM transcoder and JS wrapper are available from the - [link:https://github.com/mrdoob/three.js/tree/dev/examples/js/libs/basis examples/js/libs/basis] - directory. -

- -

Code Example

- - - const basisLoader = new BasisTextureLoader(); - basisLoader.setTranscoderPath( 'examples/js/libs/basis/' ); - basisLoader.detectSupport( renderer ); - basisLoader.load( 'diffuse.basis', function ( texture ) { - - const material = new THREE.MeshStandardMaterial( { map: texture } ); - - }, function () { - - console.log( 'onProgress' ); - - }, function ( e ) { - - console.error( e ); - - } ); - - -

Examples

- -

- [example:webgl_loader_texture_basis] -

- -

Browser compatibility

- -

- BasisTextureLoader transcodes input textures in '.basis' format to an - appropriate compressed texture format for the target device, where - possible. This allows the same source texture to be served across - desktop, Android, and iOS devices, and transcoded into ASTC, DXT, ETC1, - or PVRTC1. Other output formats may be supported in the future. -

-

- Transcoding to PVRTC1 (for iOS) requires square power-of-two textures. -

-

- This loader relies on ES6 Promises and Web Assembly, which are not - supported in IE11. -

- -
-
- -

Constructor

- -

[name]( [param:LoadingManager manager] )

-

- [page:LoadingManager manager] — The [page:LoadingManager] for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager]. -

-

- Creates a new [name]. -

- -

Properties

-

See the base [page:Loader] class for common properties.

- -

Methods

-

See the base [page:Loader] class for common methods.

- -

[method:CompressedTexture load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] )

-

- [page:String url] — A string containing the path/URL of the .basis file.
- [page:Function onLoad] — A function to be called after the loading is successfully completed.
- [page:Function onProgress] — (optional) A function to be called while the loading is in progress. The argument will be the XMLHttpRequest instance, that contains .[page:Integer total] and .[page:Integer loaded] bytes. If the server does not set the Content-Length header; .[page:Integer total] will be 0.
- [page:Function onError] — (optional) A function to be called if an error occurs during loading. The function receives error as an argument.
-

-

- Load from url and call the onLoad function with the transcoded [page:CompressedTexture]. -

- -

[method:this detectSupport]( [param:WebGLRenderer renderer] )

-

- [page:WebGLRenderer renderer] — A renderer instance. -

-

- Detects hardware support for available compressed texture formats, to determine - the output format for the transcoder. Must be called before loading a texture. -

- -

[method:this setTranscoderPath]( [param:String path] )

-

- [page:String path] — Path to folder containing the WASM transcoder and JS wrapper. -

-

- The WASM transcoder and JS wrapper are available from the - [link:https://github.com/mrdoob/three.js/tree/dev/examples/js/libs/basis examples/js/libs/basis] - directory. -

- -

[method:this setWorkerLimit]( [param:Number limit] )

-

- [page:Number limit] — Maximum number of workers. Default is '4'. -

-

- Sets the maximum number of web workers to be allocated by this instance. -

- -

[method:this dispose]()

-

- Disposes the loader object, de-allocating any Web Workers created. -

- -

Source

- -

- [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/loaders/BasisTextureLoader.js examples/jsm/loaders/BasisTextureLoader.js] -

- - diff --git a/docs/examples/en/loaders/KTX2Loader.html b/docs/examples/en/loaders/KTX2Loader.html index e6bc503ea59d50..41a9b24942b238 100644 --- a/docs/examples/en/loaders/KTX2Loader.html +++ b/docs/examples/en/loaders/KTX2Loader.html @@ -21,9 +21,8 @@

[name]

- This loader parses the KTX 2.0 container and then relies on - [page:BasisTextureLoader] to complete the transcoding process. - The required WASM transcoder and JS wrapper are available from the + This loader parses the KTX 2.0 container and transcodes to a supported GPU compressed + texture format. The required WASM transcoder and JS wrapper are available from the [link:https://github.com/mrdoob/three.js/tree/dev/examples/js/libs/basis examples/js/libs/basis] directory.

diff --git a/docs/examples/ko/controls/OrbitControls.html b/docs/examples/ko/controls/OrbitControls.html index 4aa5ec5880f7c9..d4f0786526ed1b 100644 --- a/docs/examples/ko/controls/OrbitControls.html +++ b/docs/examples/ko/controls/OrbitControls.html @@ -144,7 +144,7 @@

[property:Object keys]

BOTTOM: 'ArrowDown' // 아래쪽 화살표 }
- 전체 키코드 목록은 [link:https://developer.mozilla.org/ko/docs/Web/API/KeyboardEvent/code KeyboardEvent.code] 를 참조하세요. + 전체 키코드 목록은 [link:https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code KeyboardEvent.code] 를 참조하세요.

[property:Float maxAzimuthAngle]

diff --git a/docs/examples/zh/loaders/BasisTextureLoader.html b/docs/examples/zh/loaders/BasisTextureLoader.html deleted file mode 100644 index b6be8feba13c3d..00000000000000 --- a/docs/examples/zh/loaders/BasisTextureLoader.html +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - - - - - [page:Loader] → - -

[name]

- -

- Loader for Basis Universal GPU Texture Codec.

- - [link:https://github.com/BinomialLLC/basis_universal/ Basis Universal] is a - "supercompressed" GPU texture and texture video compression system that - outputs a highly compressed intermediate file format (.basis) that can be - quickly transcoded to a wide variety of GPU texture compression formats. -

- -

- This loader parallelizes the transcoding process across a configurable number - of web workers, before transferring the transcoded compressed texture back - to the main thread. The required WASM transcoder and JS wrapper are available from the - [link:https://github.com/mrdoob/three.js/tree/dev/examples/js/libs/basis examples/js/libs/basis] - directory. -

- -

代码示例

- - - const basisLoader = new BasisTextureLoader(); - basisLoader.setTranscoderPath( 'examples/js/libs/basis/' ); - basisLoader.detectSupport( renderer ); - basisLoader.load( 'diffuse.basis', function ( texture ) { - - const material = new THREE.MeshStandardMaterial( { map: texture } ); - - }, function () { - - console.log( 'onProgress' ); - - }, function ( e ) { - - console.error( e ); - - } ); - - -

例子

- -

- [example:webgl_loader_texture_basis] -

- -

Browser compatibility

- -

- BasisTextureLoader transcodes input textures in '.basis' format to an - appropriate compressed texture format for the target device, where - possible. This allows the same source texture to be served across - desktop, Android, and iOS devices, and transcoded into ASTC, DXT, ETC1, - or PVRTC1. Other output formats may be supported in the future. -

-

- Transcoding to PVRTC1 (for iOS) requires square power-of-two textures. -

-

- This loader relies on ES6 Promises and Web Assembly, which are not - supported in IE11. -

- -
-
- -

Constructor

- -

[name]( [param:LoadingManager manager] )

-

- [page:LoadingManager manager] — The [page:LoadingManager] for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager]. -

-

- Creates a new [name]. -

- -

Properties

-

See the base [page:Loader] class for common properties.

- -

Methods

-

See the base [page:Loader] class for common methods.

- -

[method:CompressedTexture load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] )

-

- [page:String url] — A string containing the path/URL of the .basis file.
- [page:Function onLoad] — A function to be called after the loading is successfully completed.
- [page:Function onProgress] — (optional) A function to be called while the loading is in progress. The argument will be the XMLHttpRequest instance, that contains .[page:Integer total] and .[page:Integer loaded] bytes.
- [page:Function onError] — (optional) A function to be called if an error occurs during loading. The function receives error as an argument.
-

-

- Load from url and call the onLoad function with the transcoded [page:CompressedTexture]. -

- -

[method:this detectSupport]( [param:WebGLRenderer renderer] )

-

- [page:WebGLRenderer renderer] — A renderer instance. -

-

- Detects hardware support for available compressed texture formats, to determine - the output format for the transcoder. Must be called before loading a texture. -

- -

[method:this setTranscoderPath]( [param:String path] )

-

- [page:String path] — Path to folder containing the WASM transcoder and JS wrapper. -

-

- The WASM transcoder and JS wrapper are available from the - [link:https://github.com/mrdoob/three.js/tree/dev/examples/js/libs/basis examples/js/libs/basis] - directory. -

- -

[method:this setWorkerLimit]( [param:Number limit] )

-

- [page:Number limit] — Maximum number of workers. Default is '4'. -

-

- Sets the maximum number of web workers to be allocated by this instance. -

- -

[method:this dispose]()

-

- Disposes the loader object, de-allocating any Web Workers created. -

- -

Source

- -

- [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/loaders/BasisTextureLoader.js examples/jsm/loaders/BasisTextureLoader.js] -

- - diff --git a/docs/list.json b/docs/list.json index 6fe57ef0a039c8..19b57818f77cdc 100644 --- a/docs/list.json +++ b/docs/list.json @@ -362,7 +362,6 @@ "Loaders": { "3DMLoader": "examples/en/loaders/3DMLoader", - "BasisTextureLoader": "examples/en/loaders/BasisTextureLoader", "DRACOLoader": "examples/en/loaders/DRACOLoader", "FontLoader": "examples/en/loaders/FontLoader", "GLTFLoader": "examples/en/loaders/GLTFLoader", @@ -423,10 +422,6 @@ "Developer Reference": { - "Polyfills": { - "Polyfills": "api/en/Polyfills" - }, - "WebGLRenderer": { "WebGLProgram": "api/en/renderers/webgl/WebGLProgram" } @@ -863,7 +858,6 @@ }, "加载器": { - "BasisTextureLoader": "examples/zh/loaders/BasisTextureLoader", "DRACOLoader": "examples/zh/loaders/DRACOLoader", "FontLoader": "examples/zh/loaders/FontLoader", "GLTFLoader": "examples/zh/loaders/GLTFLoader", @@ -921,10 +915,6 @@ "开发者参考": { - "差异化支持": { - "Polyfills": "api/zh/Polyfills" - }, - "WebGL渲染器": { "WebGLProgram": "api/zh/renderers/webgl/WebGLProgram" } diff --git a/docs/manual/ar/buildTools/Testing-with-NPM.html b/docs/manual/ar/buildTools/Testing-with-NPM.html index 7ffb49239676f7..02e270e0f4aace 100644 --- a/docs/manual/ar/buildTools/Testing-with-NPM.html +++ b/docs/manual/ar/buildTools/Testing-with-NPM.html @@ -123,7 +123,7 @@

أضف three.js

$ npm install three@0.84.0 --save - (0.84.0 في هذا المثال). - حفظ يجعل هذا تبعية لهذا المشروع ، بدلاً من dev تبعية. انظر المستندات هنا [link:https://www.npmjs.org/doc/json.html here] لمزيد من المعلومات. + (0.84.0 في هذا المثال). - حفظ يجعل هذا تبعية لهذا المشروع ، بدلاً من dev تبعية. انظر المستندات هنا [link:https://docs.npmjs.com/cli/v8/configuring-npm/package-json here] لمزيد من المعلومات. diff --git a/docs/manual/ar/introduction/WebGL-compatibility-check.html b/docs/manual/ar/introduction/WebGL-compatibility-check.html index 007685088508bf..4c38fca58c2914 100644 --- a/docs/manual/ar/introduction/WebGL-compatibility-check.html +++ b/docs/manual/ar/introduction/WebGL-compatibility-check.html @@ -14,18 +14,18 @@

فحص توافق WebGL

- أضف [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/WebGL.js] إلى جافا سكريبت الخاص بك وقم بتشغيل ما يلي قبل محاولة تقديم أي شيء. + أضف [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/capabilities/WebGL.js] إلى جافا سكريبت الخاص بك وقم بتشغيل ما يلي قبل محاولة تقديم أي شيء.

- if ( WEBGL.isWebGLAvailable() ) { + if ( WebGL.isWebGLAvailable() ) { // Initiate function or other initializations here animate(); } else { - const warning = WEBGL.getWebGLErrorMessage(); + const warning = WebGL.getWebGLErrorMessage(); document.getElementById( 'container' ).appendChild( warning ); } diff --git a/docs/manual/en/buildTools/Testing-with-NPM.html b/docs/manual/en/buildTools/Testing-with-NPM.html index 781f163d3ed5a0..b05fc9166be5c1 100644 --- a/docs/manual/en/buildTools/Testing-with-NPM.html +++ b/docs/manual/en/buildTools/Testing-with-NPM.html @@ -135,7 +135,7 @@

Add three.js

$ npm install three@0.84.0 --save
(0.84.0 in this example). --save makes this a dependency of this project, rather than - dev dependency. See the docs [link:https://www.npmjs.org/doc/json.html here] for more info. + dev dependency. See the docs [link:https://docs.npmjs.com/cli/v8/configuring-npm/package-json here] for more info. diff --git a/docs/manual/en/introduction/WebGL-compatibility-check.html b/docs/manual/en/introduction/WebGL-compatibility-check.html index 406832f83f813f..10a36fe2c82134 100644 --- a/docs/manual/en/introduction/WebGL-compatibility-check.html +++ b/docs/manual/en/introduction/WebGL-compatibility-check.html @@ -14,19 +14,19 @@

[name]

- Add [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/WebGL.js] + Add [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/capabilities/WebGL.js] to your javascript and run the following before attempting to render anything.

- if ( WEBGL.isWebGLAvailable() ) { + if ( WebGL.isWebGLAvailable() ) { // Initiate function or other initializations here animate(); } else { - const warning = WEBGL.getWebGLErrorMessage(); + const warning = WebGL.getWebGLErrorMessage(); document.getElementById( 'container' ).appendChild( warning ); } diff --git a/docs/manual/ja/buildTools/Testing-with-NPM.html b/docs/manual/ja/buildTools/Testing-with-NPM.html index 3a5f23813c9e68..2be66f7900f4d4 100644 --- a/docs/manual/ja/buildTools/Testing-with-NPM.html +++ b/docs/manual/ja/buildTools/Testing-with-NPM.html @@ -116,7 +116,7 @@

three.jsを追加する

こうすると使用可能なバージョンが分かります。npmに使用したいバージョンを伝えましょう。 $ npm install three@0.84.0 --save - (この例では0.84.0をインストールしています)。--saveは、これをdevの依存関係ではなく、このプロジェクトの依存関係にします。詳しくは、ドキュメント([link:https://www.npmjs.org/doc/json.html here])をご覧ください。 + (この例では0.84.0をインストールしています)。--saveは、これをdevの依存関係ではなく、このプロジェクトの依存関係にします。詳しくは、ドキュメント([link:https://docs.npmjs.com/cli/v8/configuring-npm/package-json here])をご覧ください。 @@ -229,4 +229,4 @@

Dealing with dependencies(依存関係に対処する)

- \ No newline at end of file + diff --git a/docs/manual/ja/introduction/WebGL-compatibility-check.html b/docs/manual/ja/introduction/WebGL-compatibility-check.html index 3cd43fa9afe73c..9eff4e290daaa0 100644 --- a/docs/manual/ja/introduction/WebGL-compatibility-check.html +++ b/docs/manual/ja/introduction/WebGL-compatibility-check.html @@ -13,18 +13,18 @@

[name]

- javascriptのコードに[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/WebGL.js]を付け加えて、何かを描画する前に以下のコードを実行してください。 + javascriptのコードに[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/capabilities/WebGL.js]を付け加えて、何かを描画する前に以下のコードを実行してください。

- if ( WEBGL.isWebGLAvailable() ) { + if ( WebGL.isWebGLAvailable() ) { // Initiate function or other initializations here animate(); } else { - const warning = WEBGL.getWebGLErrorMessage(); + const warning = WebGL.getWebGLErrorMessage(); document.getElementById( 'container' ).appendChild( warning ); } diff --git a/docs/manual/ko/buildTools/Testing-with-NPM.html b/docs/manual/ko/buildTools/Testing-with-NPM.html index 6faa49f6a9051b..e92cdf19bae82f 100644 --- a/docs/manual/ko/buildTools/Testing-with-NPM.html +++ b/docs/manual/ko/buildTools/Testing-with-NPM.html @@ -10,7 +10,7 @@

NPM 테스트([name])

- 이 문서에서는 [link:https://nodejs.org/en/ node.js] 환경에서 three.js를 사용해 자동 테스트를 진행해보는 방법을 알려드립니다. + 이 문서에서는 [link:https://nodejs.org/en/ node.js] 환경에서 three.js를 사용해 자동 테스트를 진행해보는 방법을 알려드립니다. 테스트는 커맨드 라인으로 실행이 가능하며 [link:https://travis-ci.org/ Travis]같은 CI 툴을 통해 자동으로 실행이 가능합니다.

@@ -87,7 +87,7 @@

mocha 추가하기

$ npm install mocha --save-dev
node_modules/이 생성되어 있고 파일들이 있어야 합니다. - 그리고 package.json의 내용이 업데이트 되었는지도 확인해봐야 합니다. + 그리고 package.json의 내용이 업데이트 되었는지도 확인해봐야 합니다. --save-dev를 통해 devDependencies 속성에 업데이트가 되어있어야 합니다.
@@ -131,7 +131,7 @@

three.js 추가

$ npm install three@0.84.0 --save (이 예제에서는 0.84.0 버전을 사용했습니다.). --save 는 dev 설정이 아닌 이 프로젝트의 의존성으로 추가하는 명령어입니다. - 여기([link:https://www.npmjs.org/doc/json.html link])에서 더 많은 내용을 확인하세요. + 여기([link:https://docs.npmjs.com/cli/v8/configuring-npm/package-json link])에서 더 많은 내용을 확인하세요. @@ -185,7 +185,7 @@

자신의 코드 추가하기

  • - nodeJS에서 알아볼 수 있는, require를 사용해 기능들을 내보내기 하세요. + nodeJS에서 알아볼 수 있는, require를 사용해 기능들을 내보내기 하세요. 여기([link:https://github.com/air/encounter/blob/master/js/Physics.js link])를 참고하세요.
  • @@ -247,4 +247,4 @@

    의존성 관리

    - \ No newline at end of file + diff --git a/docs/manual/ko/introduction/WebGL-compatibility-check.html b/docs/manual/ko/introduction/WebGL-compatibility-check.html index 14001f43ba6075..86c25ab993f440 100644 --- a/docs/manual/ko/introduction/WebGL-compatibility-check.html +++ b/docs/manual/ko/introduction/WebGL-compatibility-check.html @@ -14,18 +14,18 @@

    WebGL 호환성 검사([name])

    - [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/WebGL.js]를 스크립트에 추가하고 무언가를 렌더링하기 전에 아래 코드를 실행해보세요. + [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/capabilities/WebGL.js]를 스크립트에 추가하고 무언가를 렌더링하기 전에 아래 코드를 실행해보세요.

    - if ( WEBGL.isWebGLAvailable() ) { + if ( WebGL.isWebGLAvailable() ) { // Initiate function or other initializations here animate(); } else { - const warning = WEBGL.getWebGLErrorMessage(); + const warning = WebGL.getWebGLErrorMessage(); document.getElementById( 'container' ).appendChild( warning ); } diff --git a/docs/manual/zh/buildTools/Testing-with-NPM.html b/docs/manual/zh/buildTools/Testing-with-NPM.html index 36ce7b8a8b1293..6771e52fb0c613 100644 --- a/docs/manual/zh/buildTools/Testing-with-NPM.html +++ b/docs/manual/zh/buildTools/Testing-with-NPM.html @@ -130,7 +130,7 @@

    添加three.js

    $ npm install three@0.84.0 --save
    (例子中用的是0.84.0)。 --save 指令将此加入项目的dependency而不是dev dependency。 - 更多信息请参阅这份文档。 + 更多信息请参阅这份文档。 diff --git a/docs/manual/zh/introduction/WebGL-compatibility-check.html b/docs/manual/zh/introduction/WebGL-compatibility-check.html index 37d65b89a11aeb..9fafed7a07d30e 100644 --- a/docs/manual/zh/introduction/WebGL-compatibility-check.html +++ b/docs/manual/zh/introduction/WebGL-compatibility-check.html @@ -13,15 +13,15 @@

    WebGL兼容性检查([name])

    - 请将[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/WebGL.js]引入到你的文件,并在尝试开始渲染之前先运行该文件。 + 请将[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/capabilities/WebGL.js]引入到你的文件,并在尝试开始渲染之前先运行该文件。

    -if (WEBGL.isWebGLAvailable()) { +if (WebGL.isWebGLAvailable()) { // Initiate function or other initializations here animate(); } else { - const warning = WEBGL.getWebGLErrorMessage(); + const warning = WebGL.getWebGLErrorMessage(); document.getElementById('container').appendChild(warning); } diff --git a/docs/scenes/geometry-browser.html b/docs/scenes/geometry-browser.html index 8f9ba69eeb1d9f..da20628c73282c 100644 --- a/docs/scenes/geometry-browser.html +++ b/docs/scenes/geometry-browser.html @@ -696,8 +696,14 @@ } // + + const selectedGeometry = window.location.hash.substring( 1 ); - document.getElementById( 'newWindow' ).href += window.location.hash; + if ( guis[ selectedGeometry ] !== undefined ) { + + document.getElementById( 'newWindow' ).href += window.location.hash; + + } const gui = new GUI(); diff --git a/editor/js/Editor.js b/editor/js/Editor.js index 7abf8db4e4507d..a846f894e10712 100644 --- a/editor/js/Editor.js +++ b/editor/js/Editor.js @@ -424,6 +424,10 @@ Editor.prototype = { helper = new THREE.SkeletonHelper( object.skeleton.bones[ 0 ] ); + } else if ( object.isBone === true && object.parent?.isBone !== true ) { + + helper = new THREE.SkeletonHelper( object ); + } else { // no helper for this object type diff --git a/editor/js/Loader.js b/editor/js/Loader.js index 65c062a6450f56..8acc12596dc04f 100644 --- a/editor/js/Loader.js +++ b/editor/js/Loader.js @@ -392,7 +392,6 @@ function Loader( editor ) { var { LDrawLoader } = await import( '../../examples/jsm/loaders/LDrawLoader.js' ); var loader = new LDrawLoader(); - loader.fileMap = {}; // TODO Uh... loader.setPath( '../../examples/models/ldraw/officialLibrary/' ); loader.parse( event.target.result, undefined, function ( group ) { diff --git a/editor/js/libs/signals.min.js b/editor/js/libs/signals.min.js index 768988c7c5e92b..a4e36e8dcc0d68 100644 --- a/editor/js/libs/signals.min.js +++ b/editor/js/libs/signals.min.js @@ -3,11 +3,12 @@ JS Signals Released under the MIT license Author: Miller Medeiros - Version: 0.7.4 - Build: 252 (2012/02/24 10:30 PM) + Version: 1.0.0 - Build: 268 (2012/11/29 05:48 PM) */ -(function(h){function g(a,b,c,d,e){this._listener=b;this._isOnce=c;this.context=d;this._signal=a;this._priority=e||0}function f(a,b){if(typeof a!=="function")throw Error("listener is a required param of {fn}() and should be a Function.".replace("{fn}",b));}var e={VERSION:"0.7.4"};g.prototype={active:!0,params:null,execute:function(a){var b;this.active&&this._listener&&(a=this.params?this.params.concat(a):a,b=this._listener.apply(this.context,a),this._isOnce&&this.detach());return b},detach:function(){return this.isBound()? -this._signal.remove(this._listener,this.context):null},isBound:function(){return!!this._signal&&!!this._listener},getListener:function(){return this._listener},_destroy:function(){delete this._signal;delete this._listener;delete this.context},isOnce:function(){return this._isOnce},toString:function(){return"[SignalBinding isOnce:"+this._isOnce+", isBound:"+this.isBound()+", active:"+this.active+"]"}};e.Signal=function(){this._bindings=[];this._prevParams=null};e.Signal.prototype={memorize:!1,_shouldPropagate:!0, -active:!0,_registerListener:function(a,b,c,d){var e=this._indexOfListener(a,c);if(e!==-1){if(a=this._bindings[e],a.isOnce()!==b)throw Error("You cannot add"+(b?"":"Once")+"() then add"+(!b?"":"Once")+"() the same listener without removing the relationship first.");}else a=new g(this,a,b,c,d),this._addBinding(a);this.memorize&&this._prevParams&&a.execute(this._prevParams);return a},_addBinding:function(a){var b=this._bindings.length;do--b;while(this._bindings[b]&&a._priority<=this._bindings[b]._priority); -this._bindings.splice(b+1,0,a)},_indexOfListener:function(a,b){for(var c=this._bindings.length,d;c--;)if(d=this._bindings[c],d._listener===a&&d.context===b)return c;return-1},has:function(a,b){return this._indexOfListener(a,b)!==-1},add:function(a,b,c){f(a,"add");return this._registerListener(a,!1,b,c)},addOnce:function(a,b,c){f(a,"addOnce");return this._registerListener(a,!0,b,c)},remove:function(a,b){f(a,"remove");var c=this._indexOfListener(a,b);c!==-1&&(this._bindings[c]._destroy(),this._bindings.splice(c, -1));return a},removeAll:function(){for(var a=this._bindings.length;a--;)this._bindings[a]._destroy();this._bindings.length=0},getNumListeners:function(){return this._bindings.length},halt:function(){this._shouldPropagate=!1},dispatch:function(a){if(this.active){var b=Array.prototype.slice.call(arguments),c=this._bindings.length,d;if(this.memorize)this._prevParams=b;if(c){d=this._bindings.slice();this._shouldPropagate=!0;do c--;while(d[c]&&this._shouldPropagate&&d[c].execute(b)!==!1)}}},forget:function(){this._prevParams= -null},dispose:function(){this.removeAll();delete this._bindings;delete this._prevParams},toString:function(){return"[Signal active:"+this.active+" numListeners:"+this.getNumListeners()+"]"}};typeof define==="function"&&define.amd?define(e):typeof module!=="undefined"&&module.exports?module.exports=e:h.signals=e})(this); \ No newline at end of file +(function(i){function h(a,b,c,d,e){this._listener=b;this._isOnce=c;this.context=d;this._signal=a;this._priority=e||0}function g(a,b){if(typeof a!=="function")throw Error("listener is a required param of {fn}() and should be a Function.".replace("{fn}",b));}function e(){this._bindings=[];this._prevParams=null;var a=this;this.dispatch=function(){e.prototype.dispatch.apply(a,arguments)}}h.prototype={active:!0,params:null,execute:function(a){var b;this.active&&this._listener&&(a=this.params?this.params.concat(a): +a,b=this._listener.apply(this.context,a),this._isOnce&&this.detach());return b},detach:function(){return this.isBound()?this._signal.remove(this._listener,this.context):null},isBound:function(){return!!this._signal&&!!this._listener},isOnce:function(){return this._isOnce},getListener:function(){return this._listener},getSignal:function(){return this._signal},_destroy:function(){delete this._signal;delete this._listener;delete this.context},toString:function(){return"[SignalBinding isOnce:"+this._isOnce+ +", isBound:"+this.isBound()+", active:"+this.active+"]"}};e.prototype={VERSION:"1.0.0",memorize:!1,_shouldPropagate:!0,active:!0,_registerListener:function(a,b,c,d){var e=this._indexOfListener(a,c);if(e!==-1){if(a=this._bindings[e],a.isOnce()!==b)throw Error("You cannot add"+(b?"":"Once")+"() then add"+(!b?"":"Once")+"() the same listener without removing the relationship first.");}else a=new h(this,a,b,c,d),this._addBinding(a);this.memorize&&this._prevParams&&a.execute(this._prevParams);return a}, +_addBinding:function(a){var b=this._bindings.length;do--b;while(this._bindings[b]&&a._priority<=this._bindings[b]._priority);this._bindings.splice(b+1,0,a)},_indexOfListener:function(a,b){for(var c=this._bindings.length,d;c--;)if(d=this._bindings[c],d._listener===a&&d.context===b)return c;return-1},has:function(a,b){return this._indexOfListener(a,b)!==-1},add:function(a,b,c){g(a,"add");return this._registerListener(a,!1,b,c)},addOnce:function(a,b,c){g(a,"addOnce");return this._registerListener(a, +!0,b,c)},remove:function(a,b){g(a,"remove");var c=this._indexOfListener(a,b);c!==-1&&(this._bindings[c]._destroy(),this._bindings.splice(c,1));return a},removeAll:function(){for(var a=this._bindings.length;a--;)this._bindings[a]._destroy();this._bindings.length=0},getNumListeners:function(){return this._bindings.length},halt:function(){this._shouldPropagate=!1},dispatch:function(a){if(this.active){var b=Array.prototype.slice.call(arguments),c=this._bindings.length,d;if(this.memorize)this._prevParams= +b;if(c){d=this._bindings.slice();this._shouldPropagate=!0;do c--;while(d[c]&&this._shouldPropagate&&d[c].execute(b)!==!1)}}},forget:function(){this._prevParams=null},dispose:function(){this.removeAll();delete this._bindings;delete this._prevParams},toString:function(){return"[Signal active:"+this.active+" numListeners:"+this.getNumListeners()+"]"}};var f=e;f.Signal=e;typeof define==="function"&&define.amd?define(function(){return f}):typeof module!=="undefined"&&module.exports?module.exports=f:i.signals= +f})(this); \ No newline at end of file diff --git a/editor/js/libs/ui.three.js b/editor/js/libs/ui.three.js index bc85373e4a5921..a2460788fd557a 100644 --- a/editor/js/libs/ui.three.js +++ b/editor/js/libs/ui.three.js @@ -50,13 +50,13 @@ class UITexture extends UISpan { const extension = file.name.split( '.' ).pop().toLowerCase(); const reader = new FileReader(); - if ( extension === 'hdr' ) { + if ( extension === 'hdr' || extension === 'pic' ) { reader.addEventListener( 'load', function ( event ) { // assuming RGBE/Radiance HDR iamge format - const loader = new RGBELoader().setDataType( THREE.FloatType ); + const loader = new RGBELoader(); loader.load( event.target.result, function ( hdrTexture ) { hdrTexture.sourceFile = file.name; diff --git a/editor/sw.js b/editor/sw.js index a21cc72a8dbfdc..c4dd3725abc176 100644 --- a/editor/sw.js +++ b/editor/sw.js @@ -1,4 +1,4 @@ -// r135 +// r136 const cacheName = 'threejs-editor'; diff --git a/examples/css3d_molecules.html b/examples/css3d_molecules.html index 43b1fc36480f0a..461d8743cd3c0d 100644 --- a/examples/css3d_molecules.html +++ b/examples/css3d_molecules.html @@ -86,31 +86,31 @@ let visualizationType = 2; const MOLECULES = { - "Ethanol": "ethanol.pdb", - "Aspirin": "aspirin.pdb", - "Caffeine": "caffeine.pdb", - "Nicotine": "nicotine.pdb", - "LSD": "lsd.pdb", - "Cocaine": "cocaine.pdb", - "Cholesterol": "cholesterol.pdb", - "Lycopene": "lycopene.pdb", - "Glucose": "glucose.pdb", - "Aluminium oxide": "Al2O3.pdb", - "Cubane": "cubane.pdb", - "Copper": "cu.pdb", - "Fluorite": "caf2.pdb", - "Salt": "nacl.pdb", - "YBCO superconductor": "ybco.pdb", - "Buckyball": "buckyball.pdb", - //"Diamond": "diamond.pdb", - "Graphite": "graphite.pdb" + 'Ethanol': 'ethanol.pdb', + 'Aspirin': 'aspirin.pdb', + 'Caffeine': 'caffeine.pdb', + 'Nicotine': 'nicotine.pdb', + 'LSD': 'lsd.pdb', + 'Cocaine': 'cocaine.pdb', + 'Cholesterol': 'cholesterol.pdb', + 'Lycopene': 'lycopene.pdb', + 'Glucose': 'glucose.pdb', + 'Aluminium oxide': 'Al2O3.pdb', + 'Cubane': 'cubane.pdb', + 'Copper': 'cu.pdb', + 'Fluorite': 'caf2.pdb', + 'Salt': 'nacl.pdb', + 'YBCO superconductor': 'ybco.pdb', + 'Buckyball': 'buckyball.pdb', + // 'Diamond': 'diamond.pdb', + 'Graphite': 'graphite.pdb' }; const loader = new PDBLoader(); const colorSpriteMap = {}; const baseSprite = document.createElement( 'img' ); - const menu = document.getElementById( "menu" ); + const menu = document.getElementById( 'menu' ); init(); animate(); @@ -140,7 +140,7 @@ baseSprite.onload = function () { - loadMolecule( "models/pdb/caffeine.pdb" ); + loadMolecule( 'models/pdb/caffeine.pdb' ); createMenu(); }; @@ -173,15 +173,15 @@ button.innerHTML = m; menu.appendChild( button ); - const url = "models/pdb/" + MOLECULES[ m ]; + const url = 'models/pdb/' + MOLECULES[ m ]; button.addEventListener( 'click', generateButtonCallback( url ) ); } - const b_a = document.getElementById( "b_a" ); - const b_b = document.getElementById( "b_b" ); - const b_ab = document.getElementById( "b_ab" ); + const b_a = document.getElementById( 'b_a' ); + const b_b = document.getElementById( 'b_b' ); + const b_ab = document.getElementById( 'b_ab' ); b_a.addEventListener( 'click', function () { @@ -214,12 +214,12 @@ if ( object instanceof CSS3DSprite ) { - object.element.style.display = ""; + object.element.style.display = ''; object.visible = true; } else { - object.element.style.display = "none"; + object.element.style.display = 'none'; object.visible = false; } @@ -236,12 +236,12 @@ if ( object instanceof CSS3DSprite ) { - object.element.style.display = "none"; + object.element.style.display = 'none'; object.visible = false; } else { - object.element.style.display = ""; + object.element.style.display = ''; object.element.style.height = object.userData.bondLengthFull; object.visible = true; @@ -257,7 +257,7 @@ const object = objects[ i ]; - object.element.style.display = ""; + object.element.style.display = ''; object.visible = true; if ( ! ( object instanceof CSS3DSprite ) ) { @@ -397,15 +397,15 @@ // let bond = document.createElement( 'div' ); - bond.className = "bond"; - bond.style.height = bondLength + "px"; + bond.className = 'bond'; + bond.style.height = bondLength + 'px'; let object = new CSS3DObject( bond ); object.position.copy( start ); object.position.lerp( end, 0.5 ); - object.userData.bondLengthShort = bondLength + "px"; - object.userData.bondLengthFull = ( bondLength + 55 ) + "px"; + object.userData.bondLengthShort = bondLength + 'px'; + object.userData.bondLengthFull = ( bondLength + 55 ) + 'px'; // @@ -426,8 +426,8 @@ // bond = document.createElement( 'div' ); - bond.className = "bond"; - bond.style.height = bondLength + "px"; + bond.className = 'bond'; + bond.style.height = bondLength + 'px'; const joint = new THREE.Object3D( bond ); joint.position.copy( start ); @@ -445,8 +445,8 @@ object.matrixAutoUpdate = false; object.updateMatrix(); - object.userData.bondLengthShort = bondLength + "px"; - object.userData.bondLengthFull = ( bondLength + 55 ) + "px"; + object.userData.bondLengthShort = bondLength + 'px'; + object.userData.bondLengthFull = ( bondLength + 55 ) + 'px'; object.userData.joint = joint; diff --git a/examples/css3d_periodictable.html b/examples/css3d_periodictable.html index 5b23c515d67ea6..dee39e71f06d4c 100644 --- a/examples/css3d_periodictable.html +++ b/examples/css3d_periodictable.html @@ -100,124 +100,124 @@ import { CSS3DRenderer, CSS3DObject } from './jsm/renderers/CSS3DRenderer.js'; const table = [ - "H", "Hydrogen", "1.00794", 1, 1, - "He", "Helium", "4.002602", 18, 1, - "Li", "Lithium", "6.941", 1, 2, - "Be", "Beryllium", "9.012182", 2, 2, - "B", "Boron", "10.811", 13, 2, - "C", "Carbon", "12.0107", 14, 2, - "N", "Nitrogen", "14.0067", 15, 2, - "O", "Oxygen", "15.9994", 16, 2, - "F", "Fluorine", "18.9984032", 17, 2, - "Ne", "Neon", "20.1797", 18, 2, - "Na", "Sodium", "22.98976...", 1, 3, - "Mg", "Magnesium", "24.305", 2, 3, - "Al", "Aluminium", "26.9815386", 13, 3, - "Si", "Silicon", "28.0855", 14, 3, - "P", "Phosphorus", "30.973762", 15, 3, - "S", "Sulfur", "32.065", 16, 3, - "Cl", "Chlorine", "35.453", 17, 3, - "Ar", "Argon", "39.948", 18, 3, - "K", "Potassium", "39.948", 1, 4, - "Ca", "Calcium", "40.078", 2, 4, - "Sc", "Scandium", "44.955912", 3, 4, - "Ti", "Titanium", "47.867", 4, 4, - "V", "Vanadium", "50.9415", 5, 4, - "Cr", "Chromium", "51.9961", 6, 4, - "Mn", "Manganese", "54.938045", 7, 4, - "Fe", "Iron", "55.845", 8, 4, - "Co", "Cobalt", "58.933195", 9, 4, - "Ni", "Nickel", "58.6934", 10, 4, - "Cu", "Copper", "63.546", 11, 4, - "Zn", "Zinc", "65.38", 12, 4, - "Ga", "Gallium", "69.723", 13, 4, - "Ge", "Germanium", "72.63", 14, 4, - "As", "Arsenic", "74.9216", 15, 4, - "Se", "Selenium", "78.96", 16, 4, - "Br", "Bromine", "79.904", 17, 4, - "Kr", "Krypton", "83.798", 18, 4, - "Rb", "Rubidium", "85.4678", 1, 5, - "Sr", "Strontium", "87.62", 2, 5, - "Y", "Yttrium", "88.90585", 3, 5, - "Zr", "Zirconium", "91.224", 4, 5, - "Nb", "Niobium", "92.90628", 5, 5, - "Mo", "Molybdenum", "95.96", 6, 5, - "Tc", "Technetium", "(98)", 7, 5, - "Ru", "Ruthenium", "101.07", 8, 5, - "Rh", "Rhodium", "102.9055", 9, 5, - "Pd", "Palladium", "106.42", 10, 5, - "Ag", "Silver", "107.8682", 11, 5, - "Cd", "Cadmium", "112.411", 12, 5, - "In", "Indium", "114.818", 13, 5, - "Sn", "Tin", "118.71", 14, 5, - "Sb", "Antimony", "121.76", 15, 5, - "Te", "Tellurium", "127.6", 16, 5, - "I", "Iodine", "126.90447", 17, 5, - "Xe", "Xenon", "131.293", 18, 5, - "Cs", "Caesium", "132.9054", 1, 6, - "Ba", "Barium", "132.9054", 2, 6, - "La", "Lanthanum", "138.90547", 4, 9, - "Ce", "Cerium", "140.116", 5, 9, - "Pr", "Praseodymium", "140.90765", 6, 9, - "Nd", "Neodymium", "144.242", 7, 9, - "Pm", "Promethium", "(145)", 8, 9, - "Sm", "Samarium", "150.36", 9, 9, - "Eu", "Europium", "151.964", 10, 9, - "Gd", "Gadolinium", "157.25", 11, 9, - "Tb", "Terbium", "158.92535", 12, 9, - "Dy", "Dysprosium", "162.5", 13, 9, - "Ho", "Holmium", "164.93032", 14, 9, - "Er", "Erbium", "167.259", 15, 9, - "Tm", "Thulium", "168.93421", 16, 9, - "Yb", "Ytterbium", "173.054", 17, 9, - "Lu", "Lutetium", "174.9668", 18, 9, - "Hf", "Hafnium", "178.49", 4, 6, - "Ta", "Tantalum", "180.94788", 5, 6, - "W", "Tungsten", "183.84", 6, 6, - "Re", "Rhenium", "186.207", 7, 6, - "Os", "Osmium", "190.23", 8, 6, - "Ir", "Iridium", "192.217", 9, 6, - "Pt", "Platinum", "195.084", 10, 6, - "Au", "Gold", "196.966569", 11, 6, - "Hg", "Mercury", "200.59", 12, 6, - "Tl", "Thallium", "204.3833", 13, 6, - "Pb", "Lead", "207.2", 14, 6, - "Bi", "Bismuth", "208.9804", 15, 6, - "Po", "Polonium", "(209)", 16, 6, - "At", "Astatine", "(210)", 17, 6, - "Rn", "Radon", "(222)", 18, 6, - "Fr", "Francium", "(223)", 1, 7, - "Ra", "Radium", "(226)", 2, 7, - "Ac", "Actinium", "(227)", 4, 10, - "Th", "Thorium", "232.03806", 5, 10, - "Pa", "Protactinium", "231.0588", 6, 10, - "U", "Uranium", "238.02891", 7, 10, - "Np", "Neptunium", "(237)", 8, 10, - "Pu", "Plutonium", "(244)", 9, 10, - "Am", "Americium", "(243)", 10, 10, - "Cm", "Curium", "(247)", 11, 10, - "Bk", "Berkelium", "(247)", 12, 10, - "Cf", "Californium", "(251)", 13, 10, - "Es", "Einstenium", "(252)", 14, 10, - "Fm", "Fermium", "(257)", 15, 10, - "Md", "Mendelevium", "(258)", 16, 10, - "No", "Nobelium", "(259)", 17, 10, - "Lr", "Lawrencium", "(262)", 18, 10, - "Rf", "Rutherfordium", "(267)", 4, 7, - "Db", "Dubnium", "(268)", 5, 7, - "Sg", "Seaborgium", "(271)", 6, 7, - "Bh", "Bohrium", "(272)", 7, 7, - "Hs", "Hassium", "(270)", 8, 7, - "Mt", "Meitnerium", "(276)", 9, 7, - "Ds", "Darmstadium", "(281)", 10, 7, - "Rg", "Roentgenium", "(280)", 11, 7, - "Cn", "Copernicium", "(285)", 12, 7, - "Nh", "Nihonium", "(286)", 13, 7, - "Fl", "Flerovium", "(289)", 14, 7, - "Mc", "Moscovium", "(290)", 15, 7, - "Lv", "Livermorium", "(293)", 16, 7, - "Ts", "Tennessine", "(294)", 17, 7, - "Og", "Oganesson", "(294)", 18, 7 + 'H', 'Hydrogen', '1.00794', 1, 1, + 'He', 'Helium', '4.002602', 18, 1, + 'Li', 'Lithium', '6.941', 1, 2, + 'Be', 'Beryllium', '9.012182', 2, 2, + 'B', 'Boron', '10.811', 13, 2, + 'C', 'Carbon', '12.0107', 14, 2, + 'N', 'Nitrogen', '14.0067', 15, 2, + 'O', 'Oxygen', '15.9994', 16, 2, + 'F', 'Fluorine', '18.9984032', 17, 2, + 'Ne', 'Neon', '20.1797', 18, 2, + 'Na', 'Sodium', '22.98976...', 1, 3, + 'Mg', 'Magnesium', '24.305', 2, 3, + 'Al', 'Aluminium', '26.9815386', 13, 3, + 'Si', 'Silicon', '28.0855', 14, 3, + 'P', 'Phosphorus', '30.973762', 15, 3, + 'S', 'Sulfur', '32.065', 16, 3, + 'Cl', 'Chlorine', '35.453', 17, 3, + 'Ar', 'Argon', '39.948', 18, 3, + 'K', 'Potassium', '39.948', 1, 4, + 'Ca', 'Calcium', '40.078', 2, 4, + 'Sc', 'Scandium', '44.955912', 3, 4, + 'Ti', 'Titanium', '47.867', 4, 4, + 'V', 'Vanadium', '50.9415', 5, 4, + 'Cr', 'Chromium', '51.9961', 6, 4, + 'Mn', 'Manganese', '54.938045', 7, 4, + 'Fe', 'Iron', '55.845', 8, 4, + 'Co', 'Cobalt', '58.933195', 9, 4, + 'Ni', 'Nickel', '58.6934', 10, 4, + 'Cu', 'Copper', '63.546', 11, 4, + 'Zn', 'Zinc', '65.38', 12, 4, + 'Ga', 'Gallium', '69.723', 13, 4, + 'Ge', 'Germanium', '72.63', 14, 4, + 'As', 'Arsenic', '74.9216', 15, 4, + 'Se', 'Selenium', '78.96', 16, 4, + 'Br', 'Bromine', '79.904', 17, 4, + 'Kr', 'Krypton', '83.798', 18, 4, + 'Rb', 'Rubidium', '85.4678', 1, 5, + 'Sr', 'Strontium', '87.62', 2, 5, + 'Y', 'Yttrium', '88.90585', 3, 5, + 'Zr', 'Zirconium', '91.224', 4, 5, + 'Nb', 'Niobium', '92.90628', 5, 5, + 'Mo', 'Molybdenum', '95.96', 6, 5, + 'Tc', 'Technetium', '(98)', 7, 5, + 'Ru', 'Ruthenium', '101.07', 8, 5, + 'Rh', 'Rhodium', '102.9055', 9, 5, + 'Pd', 'Palladium', '106.42', 10, 5, + 'Ag', 'Silver', '107.8682', 11, 5, + 'Cd', 'Cadmium', '112.411', 12, 5, + 'In', 'Indium', '114.818', 13, 5, + 'Sn', 'Tin', '118.71', 14, 5, + 'Sb', 'Antimony', '121.76', 15, 5, + 'Te', 'Tellurium', '127.6', 16, 5, + 'I', 'Iodine', '126.90447', 17, 5, + 'Xe', 'Xenon', '131.293', 18, 5, + 'Cs', 'Caesium', '132.9054', 1, 6, + 'Ba', 'Barium', '132.9054', 2, 6, + 'La', 'Lanthanum', '138.90547', 4, 9, + 'Ce', 'Cerium', '140.116', 5, 9, + 'Pr', 'Praseodymium', '140.90765', 6, 9, + 'Nd', 'Neodymium', '144.242', 7, 9, + 'Pm', 'Promethium', '(145)', 8, 9, + 'Sm', 'Samarium', '150.36', 9, 9, + 'Eu', 'Europium', '151.964', 10, 9, + 'Gd', 'Gadolinium', '157.25', 11, 9, + 'Tb', 'Terbium', '158.92535', 12, 9, + 'Dy', 'Dysprosium', '162.5', 13, 9, + 'Ho', 'Holmium', '164.93032', 14, 9, + 'Er', 'Erbium', '167.259', 15, 9, + 'Tm', 'Thulium', '168.93421', 16, 9, + 'Yb', 'Ytterbium', '173.054', 17, 9, + 'Lu', 'Lutetium', '174.9668', 18, 9, + 'Hf', 'Hafnium', '178.49', 4, 6, + 'Ta', 'Tantalum', '180.94788', 5, 6, + 'W', 'Tungsten', '183.84', 6, 6, + 'Re', 'Rhenium', '186.207', 7, 6, + 'Os', 'Osmium', '190.23', 8, 6, + 'Ir', 'Iridium', '192.217', 9, 6, + 'Pt', 'Platinum', '195.084', 10, 6, + 'Au', 'Gold', '196.966569', 11, 6, + 'Hg', 'Mercury', '200.59', 12, 6, + 'Tl', 'Thallium', '204.3833', 13, 6, + 'Pb', 'Lead', '207.2', 14, 6, + 'Bi', 'Bismuth', '208.9804', 15, 6, + 'Po', 'Polonium', '(209)', 16, 6, + 'At', 'Astatine', '(210)', 17, 6, + 'Rn', 'Radon', '(222)', 18, 6, + 'Fr', 'Francium', '(223)', 1, 7, + 'Ra', 'Radium', '(226)', 2, 7, + 'Ac', 'Actinium', '(227)', 4, 10, + 'Th', 'Thorium', '232.03806', 5, 10, + 'Pa', 'Protactinium', '231.0588', 6, 10, + 'U', 'Uranium', '238.02891', 7, 10, + 'Np', 'Neptunium', '(237)', 8, 10, + 'Pu', 'Plutonium', '(244)', 9, 10, + 'Am', 'Americium', '(243)', 10, 10, + 'Cm', 'Curium', '(247)', 11, 10, + 'Bk', 'Berkelium', '(247)', 12, 10, + 'Cf', 'Californium', '(251)', 13, 10, + 'Es', 'Einstenium', '(252)', 14, 10, + 'Fm', 'Fermium', '(257)', 15, 10, + 'Md', 'Mendelevium', '(258)', 16, 10, + 'No', 'Nobelium', '(259)', 17, 10, + 'Lr', 'Lawrencium', '(262)', 18, 10, + 'Rf', 'Rutherfordium', '(267)', 4, 7, + 'Db', 'Dubnium', '(268)', 5, 7, + 'Sg', 'Seaborgium', '(271)', 6, 7, + 'Bh', 'Bohrium', '(272)', 7, 7, + 'Hs', 'Hassium', '(270)', 8, 7, + 'Mt', 'Meitnerium', '(276)', 9, 7, + 'Ds', 'Darmstadium', '(281)', 10, 7, + 'Rg', 'Roentgenium', '(280)', 11, 7, + 'Cn', 'Copernicium', '(285)', 12, 7, + 'Nh', 'Nihonium', '(286)', 13, 7, + 'Fl', 'Flerovium', '(289)', 14, 7, + 'Mc', 'Moscovium', '(290)', 15, 7, + 'Lv', 'Livermorium', '(293)', 16, 7, + 'Ts', 'Tennessine', '(294)', 17, 7, + 'Og', 'Oganesson', '(294)', 18, 7 ]; let camera, scene, renderer; diff --git a/examples/css3d_youtube.html b/examples/css3d_youtube.html index c4c17f66d7988b..d4931bd18418ea 100644 --- a/examples/css3d_youtube.html +++ b/examples/css3d_youtube.html @@ -53,7 +53,7 @@ return object; - }; + } init(); animate(); diff --git a/examples/files.json b/examples/files.json index 23348435a642cc..4c4a3f9cac2b86 100644 --- a/examples/files.json +++ b/examples/files.json @@ -108,7 +108,6 @@ "webgl_loader_stl", "webgl_loader_svg", "webgl_loader_tilt", - "webgl_loader_texture_basis", "webgl_loader_texture_dds", "webgl_loader_texture_exr", "webgl_loader_texture_hdr", diff --git a/examples/games_fps.html b/examples/games_fps.html index bc3736f63b86dd..bac4ddb39dd808 100644 --- a/examples/games_fps.html +++ b/examples/games_fps.html @@ -422,14 +422,18 @@ } ); - function teleportPlayerIfOob(){ - if (camera.position.y <= -25){ + function teleportPlayerIfOob() { + + if ( camera.position.y <= - 25 ) { + playerCollider.start.set( 0, 0.35, 0 ); playerCollider.end.set( 0, 1, 0 ); - playerCollider.radius = 0.35; + playerCollider.radius = 0.35; camera.position.copy( playerCollider.end ); camera.rotation.set( 0, 0, 0 ); + } + } diff --git a/examples/index.html b/examples/index.html index 64ad421c73b1c5..007f34037415a1 100644 --- a/examples/index.html +++ b/examples/index.html @@ -114,6 +114,13 @@

    three.js

    } + if ( viewer.src === '' ) { + + viewer.srcdoc = document.getElementById( 'PlaceholderHTML' ).innerHTML; + viewer.style.display = 'unset'; + + } + filterInput.value = extractQuery(); if ( filterInput.value !== '' ) { @@ -283,7 +290,7 @@

    three.js

    if ( search ) { - let link = sectionLink.href.split( /[?#]/ )[ 0 ]; + const link = sectionLink.href.split( /[?#]/ )[ 0 ]; sectionLink.href = `${link}?q=${search}`; } else { @@ -391,6 +398,31 @@

    three.js

    } - + diff --git a/examples/js/WebGL.js b/examples/js/WebGL.js deleted file mode 100644 index bd1e877041cbf0..00000000000000 --- a/examples/js/WebGL.js +++ /dev/null @@ -1,90 +0,0 @@ -( function () { - - class WEBGL { - - static isWebGLAvailable() { - - try { - - const canvas = document.createElement( 'canvas' ); - return !! ( window.WebGLRenderingContext && ( canvas.getContext( 'webgl' ) || canvas.getContext( 'experimental-webgl' ) ) ); - - } catch ( e ) { - - return false; - - } - - } - - static isWebGL2Available() { - - try { - - const canvas = document.createElement( 'canvas' ); - return !! ( window.WebGL2RenderingContext && canvas.getContext( 'webgl2' ) ); - - } catch ( e ) { - - return false; - - } - - } - - static getWebGLErrorMessage() { - - return this.getErrorMessage( 1 ); - - } - - static getWebGL2ErrorMessage() { - - return this.getErrorMessage( 2 ); - - } - - static getErrorMessage( version ) { - - const names = { - 1: 'WebGL', - 2: 'WebGL 2' - }; - const contexts = { - 1: window.WebGLRenderingContext, - 2: window.WebGL2RenderingContext - }; - let message = 'Your $0 does not seem to support $1'; - const element = document.createElement( 'div' ); - element.id = 'webglmessage'; - element.style.fontFamily = 'monospace'; - element.style.fontSize = '13px'; - element.style.fontWeight = 'normal'; - element.style.textAlign = 'center'; - element.style.background = '#fff'; - element.style.color = '#000'; - element.style.padding = '1.5em'; - element.style.width = '400px'; - element.style.margin = '5em auto 0'; - - if ( contexts[ version ] ) { - - message = message.replace( '$0', 'graphics card' ); - - } else { - - message = message.replace( '$0', 'browser' ); - - } - - message = message.replace( '$1', names[ version ] ); - element.innerHTML = message; - return element; - - } - - } - - THREE.WEBGL = WEBGL; - -} )(); diff --git a/examples/js/animation/CCDIKSolver.js b/examples/js/animation/CCDIKSolver.js index 904991a9f0a9c5..452bde7052aa8f 100644 --- a/examples/js/animation/CCDIKSolver.js +++ b/examples/js/animation/CCDIKSolver.js @@ -145,7 +145,6 @@ } angle = math.acos( angle ); // skip if changing angle is too small to prevent vibration of bone - // Refer to http://www20.atpages.jp/katwat/three.js_r58/examples/mytest37/mmd.three.js if ( angle < 1e-5 ) continue; diff --git a/examples/js/animation/MMDPhysics.js b/examples/js/animation/MMDPhysics.js index 320eb88a282527..712aa0c44ffa7c 100644 --- a/examples/js/animation/MMDPhysics.js +++ b/examples/js/animation/MMDPhysics.js @@ -821,7 +821,7 @@ return new Ammo.btCapsuleShape( p.width, p.height ); default: - throw 'unknown shape type ' + p.shapeType; + throw new Error( 'unknown shape type ' + p.shapeType ); } @@ -1086,7 +1086,6 @@ for ( let i = 0; i < 6; i ++ ) { - // this parameter is from http://www20.atpages.jp/katwat/three.js_r58/examples/mytest37/mmd.three.js constraint.setParam( 2, 0.475, i ); } @@ -1221,8 +1220,7 @@ } - } // copy from http://www20.atpages.jp/katwat/three.js_r58/examples/mytest37/mytest37.js?ver=20160815 - + } function createCapsuleGeometry( radius, cylinderHeight, segmentsRadius, segmentsHeight ) { diff --git a/examples/js/controls/ArcballControls.js b/examples/js/controls/ArcballControls.js index feef2d10d55df9..da267cdea73f16 100644 --- a/examples/js/controls/ArcballControls.js +++ b/examples/js/controls/ArcballControls.js @@ -44,6 +44,12 @@ const _raycaster = new THREE.Raycaster(); const _offset = new THREE.Vector3(); + + const _gizmoMatrixStateTemp = new THREE.Matrix4(); + + const _cameraMatrixStateTemp = new THREE.Matrix4(); + + const _scalePointTemp = new THREE.Vector3(); /** * * @param {Camera} camera Virtual camera used in the scene @@ -567,28 +573,6 @@ }; - this.onKeyDown = event => { - - if ( event.key == 'c' ) { - - if ( event.ctrlKey || event.metaKey ) { - - this.copyState(); - - } - - } else if ( event.key == 'v' ) { - - if ( event.ctrlKey || event.metaKey ) { - - this.pasteState(); - - } - - } - - }; - this.onSinglePanStart = ( event, operation ) => { if ( this.enabled ) { @@ -1621,13 +1605,13 @@ this._translationMatrix.makeTranslation( _offset.x, _offset.y, _offset.z ); - const gizmoStateTemp = this._gizmoMatrixState.clone(); + _gizmoMatrixStateTemp.copy( this._gizmoMatrixState ); this._gizmoMatrixState.premultiply( this._translationMatrix ); this._gizmoMatrixState.decompose( this._gizmos.position, this._gizmos.quaternion, this._gizmos.scale ); - const cameraStateTemp = this._cameraMatrixState.clone(); + _cameraMatrixStateTemp.copy( this._cameraMatrixState ); this._cameraMatrixState.premultiply( this._translationMatrix ); @@ -1640,9 +1624,9 @@ } - this._gizmoMatrixState.copy( gizmoStateTemp ); + this._gizmoMatrixState.copy( _gizmoMatrixStateTemp ); - this._cameraMatrixState.copy( cameraStateTemp ); + this._cameraMatrixState.copy( _cameraMatrixStateTemp ); }; @@ -1710,7 +1694,6 @@ window.removeEventListener( 'pointermove', this.onPointerMove ); window.removeEventListener( 'pointerup', this.onPointerUp ); window.removeEventListener( 'resize', this.onWindowResize ); - window.removeEventListener( 'keydown', this.onKeyDown ); if ( this.scene !== null ) this.scene.remove( this._gizmos ); this.disposeGrid(); @@ -2163,7 +2146,8 @@ this.scale = ( size, point, scaleGizmos = true ) => { - const scalePoint = point.clone(); + _scalePointTemp.copy( point ); + let sizeInverse = 1 / size; if ( this.camera.isOrthographicCamera ) { @@ -2199,11 +2183,13 @@ this._m4_2.multiply( this._translationMatrix ); //move camera and gizmos to obtain pinch effect - scalePoint.sub( this._v3_1 ); - const amount = scalePoint.clone().multiplyScalar( sizeInverse ); - scalePoint.sub( amount ); + _scalePointTemp.sub( this._v3_1 ); + + const amount = _scalePointTemp.clone().multiplyScalar( sizeInverse ); + + _scalePointTemp.sub( amount ); - this._m4_1.makeTranslation( scalePoint.x, scalePoint.y, scalePoint.z ); + this._m4_1.makeTranslation( _scalePointTemp.x, _scalePointTemp.y, _scalePointTemp.z ); this._m4_2.premultiply( this._m4_1 ); @@ -2217,7 +2203,7 @@ this._v3_2.setFromMatrixPosition( this._gizmoMatrixState ); //move camera - let distance = this._v3_1.distanceTo( scalePoint ); + let distance = this._v3_1.distanceTo( _scalePointTemp ); let amount = distance - distance * sizeInverse; //check min and max distance @@ -2235,7 +2221,7 @@ } - _offset.copy( scalePoint ).sub( this._v3_1 ).normalize().multiplyScalar( amount ); + _offset.copy( _scalePointTemp ).sub( this._v3_1 ).normalize().multiplyScalar( amount ); this._m4_1.makeTranslation( _offset.x, _offset.y, _offset.z ); @@ -2243,10 +2229,10 @@ //scale gizmos so they appear in the same spot having the same dimension const pos = this._v3_2; - distance = pos.distanceTo( scalePoint ); + distance = pos.distanceTo( _scalePointTemp ); amount = distance - distance * sizeInverse; - _offset.copy( scalePoint ).sub( this._v3_2 ).normalize().multiplyScalar( amount ); + _offset.copy( _scalePointTemp ).sub( this._v3_2 ).normalize().multiplyScalar( amount ); this._translationMatrix.makeTranslation( pos.x, pos.y, pos.z ); @@ -2285,19 +2271,6 @@ }; - this.setTarget = ( x, y, z ) => { - - this.target.set( x, y, z ); - - this._gizmos.position.set( x, y, z ); //for correct radius calculation - - - this._tbRadius = this.calculateTbRadius( this.camera ); - this.makeGizmos( this.target, this._tbRadius ); - this.camera.lookAt( this.target ); - - }; - this.zRotate = ( point, angle ) => { this._rotationMatrix.makeRotationAxis( this._rotationAxis, angle ); @@ -2579,7 +2552,20 @@ this.update = () => { - const EPS = 0.000001; //check min/max parameters + const EPS = 0.000001; + + if ( this.target.equals( this._currentTarget ) === false ) { + + this._gizmos.position.copy( this.target ); //for correct radius calculation + + + this._tbRadius = this.calculateTbRadius( this.camera ); + this.makeGizmos( this.target, this._tbRadius ); + + this._currentTarget.copy( this.target ); + + } //check min/max parameters + if ( this.camera.isOrthographicCamera ) { @@ -2684,7 +2670,8 @@ this.camera = null; this.domElement = domElement; this.scene = scene; - this.target = new THREE.Vector3( 0, 0, 0 ); + this.target = new THREE.Vector3(); + this._currentTarget = new THREE.Vector3(); this.radiusFactor = 0.67; this.mouseActions = []; this._mouseOp = null; //global vectors and matrices that are used in some operations to avoid creating new objects every time (e.g. every time cursor moves) @@ -2827,7 +2814,6 @@ this.domElement.addEventListener( 'wheel', this.onWheel ); this.domElement.addEventListener( 'pointerdown', this.onPointerDown ); this.domElement.addEventListener( 'pointercancel', this.onPointerCancel ); - window.addEventListener( 'keydown', this.onKeyDown ); window.addEventListener( 'resize', this.onWindowResize ); } //listeners diff --git a/examples/js/controls/TransformControls.js b/examples/js/controls/TransformControls.js index f4b1e34135b556..a53daf97edbbec 100644 --- a/examples/js/controls/TransformControls.js +++ b/examples/js/controls/TransformControls.js @@ -649,7 +649,13 @@ function onPointerDown( event ) { if ( ! this.enabled ) return; - this.domElement.setPointerCapture( event.pointerId ); + + if ( ! document.pointerLockElement ) { + + this.domElement.setPointerCapture( event.pointerId ); + + } + this.domElement.addEventListener( 'pointermove', this._onPointerMove ); this.pointerHover( this._getPointer( event ) ); this.pointerDown( this._getPointer( event ) ); diff --git a/examples/js/curves/CurveExtras.js b/examples/js/curves/CurveExtras.js index 793fba841f9f2a..32af39bfd71614 100644 --- a/examples/js/curves/CurveExtras.js +++ b/examples/js/curves/CurveExtras.js @@ -5,9 +5,7 @@ * * Formulas collected from various sources * http://mathworld.wolfram.com/HeartCurve.html - * http://mathdl.maa.org/images/upload_library/23/stemkoski/knots/page6.html * http://en.wikipedia.org/wiki/Viviani%27s_curve - * http://mathdl.maa.org/images/upload_library/23/stemkoski/knots/page4.html * http://www.mi.sanu.ac.rs/vismath/taylorapril2011/Taylor.pdf * https://prideout.net/blog/old/blog/index.html@p=44.html */ diff --git a/examples/js/effects/AsciiEffect.js b/examples/js/effects/AsciiEffect.js index cf32d04a0d68c6..39326fd69f17c6 100644 --- a/examples/js/effects/AsciiEffect.js +++ b/examples/js/effects/AsciiEffect.js @@ -49,13 +49,7 @@ }; - this.domElement = domElement; // Throw in ascii library from https://github.com/hassadee/jsascii/blob/master/jsascii.js - - /* - * jsAscii 0.1 - * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/ - * MIT License [http://www.nihilogic.dk/licenses/mit-license.txt] - */ + this.domElement = domElement; // Throw in ascii library from https://github.com/hassadee/jsascii/blob/master/jsascii.js (MIT License) function initAsciiSize() { diff --git a/examples/js/exporters/GLTFExporter.js b/examples/js/exporters/GLTFExporter.js index b2a595f62c1b68..aba9b29d97fc89 100644 --- a/examples/js/exporters/GLTFExporter.js +++ b/examples/js/exporters/GLTFExporter.js @@ -2034,7 +2034,7 @@ /** * Specular-Glossiness Extension * - * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness + * Specification: https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Archived/KHR_materials_pbrSpecularGlossiness */ diff --git a/examples/js/exporters/MMDExporter.js b/examples/js/exporters/MMDExporter.js index c3dabde628344c..90fd2326d6991e 100644 --- a/examples/js/exporters/MMDExporter.js +++ b/examples/js/exporters/MMDExporter.js @@ -161,7 +161,7 @@ if ( value === undefined ) { - throw 'cannot convert charcode 0x' + code.toString( 16 ); + throw new Error( 'cannot convert charcode 0x' + code.toString( 16 ) ); } else if ( value > 0xff ) { diff --git a/examples/js/geometries/TeapotGeometry.js b/examples/js/geometries/TeapotGeometry.js index 05c7d6598a6c2f..e5395a23f9df63 100644 --- a/examples/js/geometries/TeapotGeometry.js +++ b/examples/js/geometries/TeapotGeometry.js @@ -42,7 +42,6 @@ * * Code converted from my ancient SPD software, http://tog.acm.org/resources/SPD/ * Created for the Udacity course "Interactive Rendering", http://bit.ly/ericity - * Lesson: https://www.udacity.com/course/viewer#!/c-cs291/l-68866048/m-106482448 * YouTube video on teapot history: https://www.youtube.com/watch?v=DxMfblPzFNc * * See https://en.wikipedia.org/wiki/Utah_teapot for the history of the teapot diff --git a/examples/js/loaders/AMFLoader.js b/examples/js/loaders/AMFLoader.js index 366db1ff639d63..03e8a90b9d77d9 100644 --- a/examples/js/loaders/AMFLoader.js +++ b/examples/js/loaders/AMFLoader.js @@ -4,8 +4,6 @@ * Description: Early release of an AMF THREE.Loader following the pattern of the * example loaders in the three.js project. * - * More information about the AMF format: http://amf.wikispaces.com - * * Usage: * const loader = new AMFLoader(); * loader.load('/path/to/project.amf', function(objecttree) { diff --git a/examples/js/loaders/BasisTextureLoader.js b/examples/js/loaders/BasisTextureLoader.js index 5326584247e9d5..dcfb7a458536e9 100644 --- a/examples/js/loaders/BasisTextureLoader.js +++ b/examples/js/loaders/BasisTextureLoader.js @@ -28,6 +28,7 @@ this.workerNextTaskID = 1; this.workerSourceURL = ''; this.workerConfig = null; + console.warn( 'THREE.BasisTextureLoader: This loader is deprecated, and will be removed in a future release. ' + 'Instead, use Basis Universal compression in KTX2 (.ktx2) files with THREE.KTX2Loader.' ); } diff --git a/examples/js/loaders/EXRLoader.js b/examples/js/loaders/EXRLoader.js index fc7f59ed8b424e..02ea18ac6937bd 100644 --- a/examples/js/loaders/EXRLoader.js +++ b/examples/js/loaders/EXRLoader.js @@ -106,39 +106,6 @@ const LOSSY_DCT = 1; const RLE = 2; const logBase = Math.pow( 2.7182818, 2.2 ); - var tmpDataView = new DataView( new ArrayBuffer( 8 ) ); - - function frexp( value ) { - - if ( value === 0 ) return [ value, 0 ]; - tmpDataView.setFloat64( 0, value ); - var bits = tmpDataView.getUint32( 0 ) >>> 20 & 0x7FF; - - if ( bits === 0 ) { - - // denormal - tmpDataView.setFloat64( 0, value * Math.pow( 2, 64 ) ); // exp + 64 - - bits = ( tmpDataView.getUint32( 0 ) >>> 20 & 0x7FF ) - 64; - - } - - var exponent = bits - 1022; - var mantissa = ldexp( value, - exponent ); - return [ mantissa, exponent ]; - - } - - function ldexp( mantissa, exponent ) { - - var steps = Math.min( 3, Math.ceil( Math.abs( exponent ) / 1023 ) ); - var result = mantissa; - - for ( var i = 0; i < steps; i ++ ) result *= Math.pow( 2, Math.floor( ( exponent + i ) / steps ) ); - - return result; - - } function reverseLutFromBitmap( bitmap, lut ) { @@ -243,7 +210,7 @@ if ( p.value - inOffset.value > ni ) { - throw 'Something wrong with hufUnpackEncTable'; + throw new Error( 'Something wrong with hufUnpackEncTable' ); } @@ -254,7 +221,7 @@ if ( im + zerun > iM + 1 ) { - throw 'Something wrong with hufUnpackEncTable'; + throw new Error( 'Something wrong with hufUnpackEncTable' ); } @@ -268,7 +235,7 @@ if ( im + zerun > iM + 1 ) { - throw 'Something wrong with hufUnpackEncTable'; + throw new Error( 'Something wrong with hufUnpackEncTable' ); } @@ -305,7 +272,7 @@ if ( c >> l ) { - throw 'Invalid table entry'; + throw new Error( 'Invalid table entry' ); } @@ -315,7 +282,7 @@ if ( pl.len ) { - throw 'Invalid table entry'; + throw new Error( 'Invalid table entry' ); } @@ -350,7 +317,7 @@ if ( pl.len || pl.p ) { - throw 'Invalid table entry'; + throw new Error( 'Invalid table entry' ); } @@ -609,7 +576,7 @@ if ( ! pl.p ) { - throw 'hufDecode issues'; + throw new Error( 'hufDecode issues' ); } @@ -645,7 +612,7 @@ if ( j == pl.lit ) { - throw 'hufDecode issues'; + throw new Error( 'hufDecode issues' ); } @@ -672,7 +639,7 @@ } else { - throw 'hufDecode issues'; + throw new Error( 'hufDecode issues' ); } @@ -696,7 +663,7 @@ if ( im < 0 || im >= HUF_ENCSIZE || iM < 0 || iM >= HUF_ENCSIZE ) { - throw 'Something wrong with HUF_ENCSIZE'; + throw new Error( 'Something wrong with HUF_ENCSIZE' ); } @@ -708,7 +675,7 @@ if ( nBits > 8 * ( nCompressed - ( inOffset.value - initialInOffset ) ) ) { - throw 'Something wrong with hufUncompress'; + throw new Error( 'Something wrong with hufUncompress' ); } @@ -1207,8 +1174,7 @@ var inOffset = { value: info.offset.value }; - var tmpBufSize = info.width * scanlineBlockSize * ( EXRHeader.channels.length * info.type ); - var outBuffer = new Uint16Array( tmpBufSize ); + var outBuffer = new Uint16Array( info.width * info.scanlineBlockSize * ( info.channels * info.type ) ); var bitmap = new Uint8Array( BITMAP_SIZE ); // Setup channel info var outBufferEnd = 0; @@ -1232,7 +1198,7 @@ if ( maxNonZero >= BITMAP_SIZE ) { - throw 'Something is wrong with PIZ_COMPRESSION BITMAP_SIZE'; + throw new Error( 'Something is wrong with PIZ_COMPRESSION BITMAP_SIZE' ); } @@ -1365,7 +1331,7 @@ var inOffset = { value: info.offset.value }; - var outBuffer = new Uint8Array( info.width * info.lines * ( EXRHeader.channels.length * info.type * INT16_SIZE ) ); // Read compression header information + var outBuffer = new Uint8Array( info.width * info.lines * ( info.channels * info.type * INT16_SIZE ) ); // Read compression header information var dwaHeader = { version: parseInt64( inDataView, inOffset ), @@ -1380,7 +1346,7 @@ totalDcUncompressedCount: parseInt64( inDataView, inOffset ), acCompression: parseInt64( inDataView, inOffset ) }; - if ( dwaHeader.version < 2 ) throw 'EXRLoader.parse: ' + EXRHeader.compression + ' version ' + dwaHeader.version + ' is unsupported'; // Read channel ruleset information + if ( dwaHeader.version < 2 ) throw new Error( 'EXRLoader.parse: ' + EXRHeader.compression + ' version ' + dwaHeader.version + ' is unsupported' ); // Read channel ruleset information var channelRules = new Array(); var ruleSize = parseUint16( inDataView, inOffset ) - INT16_SIZE; @@ -1557,7 +1523,7 @@ case LOSSY_DCT: // skip default: - throw 'EXRLoader.parse: unsupported channel compression'; + throw new Error( 'EXRLoader.parse: unsupported channel compression' ); } @@ -1592,14 +1558,6 @@ } - function parseUlong( dataView, offset ) { - - var uLong = dataView.getUint32( 0, true ); - offset.value = offset.value + ULONG_SIZE; - return uLong; - - } - function parseRational( dataView, offset ) { var x = parseInt32( dataView, offset ); @@ -1857,283 +1815,272 @@ } - var bufferDataView = new DataView( buffer ); - var uInt8Array = new Uint8Array( buffer ); - var EXRHeader = {}; - bufferDataView.getUint32( 0, true ); // magic + function parseHeader( dataView, buffer, offset ) { - bufferDataView.getUint8( 4, true ); // versionByteZero + const EXRHeader = {}; - bufferDataView.getUint8( 5, true ); // fullMask - // start of header + if ( dataView.getUint32( 0, true ) != 20000630 ) { - var offset = { - value: 8 - }; // start at 8, after magic stuff + // magic + throw new Error( 'THREE.EXRLoader: provided file doesn\'t appear to be in OpenEXR format.' ); - var keepReading = true; + } - while ( keepReading ) { + EXRHeader.version = dataView.getUint8( 4, true ); + const spec = dataView.getUint8( 5, true ); // fullMask - var attributeName = parseNullTerminatedString( buffer, offset ); + EXRHeader.spec = { + singleTile: !! ( spec & 1 ), + longName: !! ( spec & 2 ), + deepFormat: !! ( spec & 4 ), + multiPart: !! ( spec & 8 ) + }; // start of header - if ( attributeName == 0 ) { + offset.value = 8; // start at 8 - after pre-amble - keepReading = false; + var keepReading = true; - } else { + while ( keepReading ) { - var attributeType = parseNullTerminatedString( buffer, offset ); - var attributeSize = parseUint32( bufferDataView, offset ); - var attributeValue = parseValue( bufferDataView, buffer, offset, attributeType, attributeSize ); + var attributeName = parseNullTerminatedString( buffer, offset ); - if ( attributeValue === undefined ) { + if ( attributeName == 0 ) { - console.warn( `EXRLoader.parse: skipped unknown header attribute type \'${attributeType}\'.` ); + keepReading = false; } else { - EXRHeader[ attributeName ] = attributeValue; + var attributeType = parseNullTerminatedString( buffer, offset ); + var attributeSize = parseUint32( dataView, offset ); + var attributeValue = parseValue( dataView, buffer, offset, attributeType, attributeSize ); - } + if ( attributeValue === undefined ) { - } + console.warn( `EXRLoader.parse: skipped unknown header attribute type \'${attributeType}\'.` ); - } // offsets - - - var dataWindowHeight = EXRHeader.dataWindow.yMax + 1; - var uncompress; - var scanlineBlockSize; - - switch ( EXRHeader.compression ) { - - case 'NO_COMPRESSION': - scanlineBlockSize = 1; - uncompress = uncompressRAW; - break; + } else { - case 'RLE_COMPRESSION': - scanlineBlockSize = 1; - uncompress = uncompressRLE; - break; + EXRHeader[ attributeName ] = attributeValue; - case 'ZIPS_COMPRESSION': - scanlineBlockSize = 1; - uncompress = uncompressZIP; - break; + } - case 'ZIP_COMPRESSION': - scanlineBlockSize = 16; - uncompress = uncompressZIP; - break; + } - case 'PIZ_COMPRESSION': - scanlineBlockSize = 32; - uncompress = uncompressPIZ; - break; + } - case 'PXR24_COMPRESSION': - scanlineBlockSize = 16; - uncompress = uncompressPXR; - break; + if ( spec != 0 ) { - case 'DWAA_COMPRESSION': - scanlineBlockSize = 32; - uncompress = uncompressDWA; - break; + console.error( 'EXRHeader:', EXRHeader ); + throw new Error( 'THREE.EXRLoader: provided file is currently unsupported.' ); - case 'DWAB_COMPRESSION': - scanlineBlockSize = 256; - uncompress = uncompressDWA; - break; + } - default: - throw 'EXRLoader.parse: ' + EXRHeader.compression + ' is unsupported'; + return EXRHeader; } - var size_t; - var getValue; // mixed pixelType not supported + function setupDecoder( EXRHeader, dataView, uInt8Array, offset, outputType ) { - var pixelType = EXRHeader.channels[ 0 ].pixelType; + const EXRDecoder = { + size: 0, + viewer: dataView, + array: uInt8Array, + offset: offset, + width: EXRHeader.dataWindow.xMax - EXRHeader.dataWindow.xMin + 1, + height: EXRHeader.dataWindow.yMax - EXRHeader.dataWindow.yMin + 1, + channels: EXRHeader.channels.length, + bytesPerLine: null, + lines: null, + inputSize: null, + type: EXRHeader.channels[ 0 ].pixelType, + uncompress: null, + getter: null, + format: null, + encoding: null + }; - if ( pixelType === 1 ) { + switch ( EXRHeader.compression ) { - // half - switch ( this.type ) { + case 'NO_COMPRESSION': + EXRDecoder.lines = 1; + EXRDecoder.uncompress = uncompressRAW; + break; - case THREE.UnsignedByteType: - case THREE.FloatType: - getValue = parseFloat16; - size_t = INT16_SIZE; + case 'RLE_COMPRESSION': + EXRDecoder.lines = 1; + EXRDecoder.uncompress = uncompressRLE; break; - case THREE.HalfFloatType: - getValue = parseUint16; - size_t = INT16_SIZE; + case 'ZIPS_COMPRESSION': + EXRDecoder.lines = 1; + EXRDecoder.uncompress = uncompressZIP; break; - } + case 'ZIP_COMPRESSION': + EXRDecoder.lines = 16; + EXRDecoder.uncompress = uncompressZIP; + break; - } else if ( pixelType === 2 ) { + case 'PIZ_COMPRESSION': + EXRDecoder.lines = 32; + EXRDecoder.uncompress = uncompressPIZ; + break; - // float - switch ( this.type ) { + case 'PXR24_COMPRESSION': + EXRDecoder.lines = 16; + EXRDecoder.uncompress = uncompressPXR; + break; - case THREE.UnsignedByteType: - case THREE.FloatType: - getValue = parseFloat32; - size_t = FLOAT32_SIZE; + case 'DWAA_COMPRESSION': + EXRDecoder.lines = 32; + EXRDecoder.uncompress = uncompressDWA; break; - case THREE.HalfFloatType: - getValue = decodeFloat32; - size_t = FLOAT32_SIZE; + case 'DWAB_COMPRESSION': + EXRDecoder.lines = 256; + EXRDecoder.uncompress = uncompressDWA; + break; + + default: + throw new Error( 'EXRLoader.parse: ' + EXRHeader.compression + ' is unsupported' ); } - } else { + EXRDecoder.scanlineBlockSize = EXRDecoder.lines; - throw 'EXRLoader.parse: unsupported pixelType ' + pixelType + ' for ' + EXRHeader.compression + '.'; + if ( EXRDecoder.type == 1 ) { - } + // half + switch ( outputType ) { - var numBlocks = dataWindowHeight / scanlineBlockSize; + case THREE.FloatType: + EXRDecoder.getter = parseFloat16; + EXRDecoder.inputSize = INT16_SIZE; + break; - for ( var i = 0; i < numBlocks; i ++ ) { + case THREE.HalfFloatType: + EXRDecoder.getter = parseUint16; + EXRDecoder.inputSize = INT16_SIZE; + break; - parseUlong( bufferDataView, offset ); // scanlineOffset + } - } // we should be passed the scanline offset table, start reading pixel data + } else if ( EXRDecoder.type == 2 ) { + // float + switch ( outputType ) { - var width = EXRHeader.dataWindow.xMax - EXRHeader.dataWindow.xMin + 1; - var height = EXRHeader.dataWindow.yMax - EXRHeader.dataWindow.yMin + 1; // Firefox only supports RGBA (half) float textures - // var numChannels = EXRHeader.channels.length; + case THREE.FloatType: + EXRDecoder.getter = parseFloat32; + EXRDecoder.inputSize = FLOAT32_SIZE; + break; - var numChannels = 4; - var size = width * height * numChannels; // Fill initially with 1s for the alpha value if the texture is not RGBA, RGB values will be overwritten + case THREE.HalfFloatType: + EXRDecoder.getter = decodeFloat32; + EXRDecoder.inputSize = FLOAT32_SIZE; - switch ( this.type ) { + } - case THREE.UnsignedByteType: - case THREE.FloatType: - var byteArray = new Float32Array( size ); + } else { - if ( EXRHeader.channels.length < numChannels ) { + throw new Error( 'EXRLoader.parse: unsupported pixelType ' + EXRDecoder.type + ' for ' + EXRHeader.compression + '.' ); - byteArray.fill( 1, 0, size ); + } - } + EXRDecoder.blockCount = ( EXRHeader.dataWindow.yMax + 1 ) / EXRDecoder.scanlineBlockSize; - break; + for ( var i = 0; i < EXRDecoder.blockCount; i ++ ) parseInt64( dataView, offset ); // scanlineOffset + // we should be passed the scanline offset table, ready to start reading pixel data. + // RGB images will be converted to RGBA format, preventing software emulation in select devices. - case THREE.HalfFloatType: - var byteArray = new Uint16Array( size ); - if ( EXRHeader.channels.length < numChannels ) { + EXRDecoder.outputChannels = EXRDecoder.channels == 3 ? 4 : EXRDecoder.channels; + const size = EXRDecoder.width * EXRDecoder.height * EXRDecoder.outputChannels; - byteArray.fill( 0x3C00, 0, size ); // Uint16Array holds half float data, 0x3C00 is 1 + switch ( outputType ) { - } + case THREE.FloatType: + EXRDecoder.byteArray = new Float32Array( size ); // Fill initially with 1s for the alpha value if the texture is not RGBA, RGB values will be overwritten - break; + if ( EXRDecoder.channels < EXRDecoder.outputChannels ) EXRDecoder.byteArray.fill( 1, 0, size ); + break; - default: - console.error( 'THREE.EXRLoader: unsupported type: ', this.type ); - break; + case THREE.HalfFloatType: + EXRDecoder.byteArray = new Uint16Array( size ); + if ( EXRDecoder.channels < EXRDecoder.outputChannels ) EXRDecoder.byteArray.fill( 0x3C00, 0, size ); // Uint16Array holds half float data, 0x3C00 is 1 - } + break; - var channelOffsets = { - R: 0, - G: 1, - B: 2, - A: 3 - }; - var compressionInfo = { - size: 0, - width: width, - lines: scanlineBlockSize, - offset: offset, - array: uInt8Array, - viewer: bufferDataView, - type: pixelType, - channels: EXRHeader.channels.length - }; - var line; - var size; - var viewer; - var tmpOffset = { - value: 0 - }; + default: + console.error( 'THREE.EXRLoader: unsupported type: ', outputType ); + break; - for ( var scanlineBlockIdx = 0; scanlineBlockIdx < height / scanlineBlockSize; scanlineBlockIdx ++ ) { + } - line = parseUint32( bufferDataView, offset ); // line_no + EXRDecoder.bytesPerLine = EXRDecoder.width * EXRDecoder.inputSize * EXRDecoder.channels; - size = parseUint32( bufferDataView, offset ); // data_len + if ( EXRDecoder.outputChannels == 4 ) { - compressionInfo.lines = line + scanlineBlockSize > height ? height - line : scanlineBlockSize; - compressionInfo.offset = offset; - compressionInfo.size = size; - viewer = uncompress( compressionInfo ); - offset.value += size; + EXRDecoder.format = THREE.RGBAFormat; + EXRDecoder.encoding = THREE.LinearEncoding; - for ( var line_y = 0; line_y < scanlineBlockSize; line_y ++ ) { + } else { - var true_y = line_y + scanlineBlockIdx * scanlineBlockSize; - if ( true_y >= height ) break; + EXRDecoder.format = THREE.RedFormat; + EXRDecoder.encoding = THREE.LinearEncoding; - for ( var channelID = 0; channelID < EXRHeader.channels.length; channelID ++ ) { + } - var cOff = channelOffsets[ EXRHeader.channels[ channelID ].name ]; + return EXRDecoder; - for ( var x = 0; x < width; x ++ ) { + } // start parsing file [START] - var idx = line_y * ( EXRHeader.channels.length * width ) + channelID * width + x; - tmpOffset.value = idx * size_t; - var val = getValue( viewer, tmpOffset ); - byteArray[ ( height - 1 - true_y ) * ( width * numChannels ) + x * numChannels + cOff ] = val; - } + const bufferDataView = new DataView( buffer ); + const uInt8Array = new Uint8Array( buffer ); + const offset = { + value: 0 + }; // get header information and validate format. - } + const EXRHeader = parseHeader( bufferDataView, buffer, offset ); // get input compression information and prepare decoding. - } + const EXRDecoder = setupDecoder( EXRHeader, bufferDataView, uInt8Array, offset, this.type ); + const tmpOffset = { + value: 0 + }; + const channelOffsets = { + R: 0, + G: 1, + B: 2, + A: 3, + Y: 0 + }; - } + for ( let scanlineBlockIdx = 0; scanlineBlockIdx < EXRDecoder.height / EXRDecoder.scanlineBlockSize; scanlineBlockIdx ++ ) { - if ( this.type === THREE.UnsignedByteType ) { + const line = parseUint32( bufferDataView, offset ); // line_no - let v, i; - const size = byteArray.length; - const RGBEArray = new Uint8Array( size ); + EXRDecoder.size = parseUint32( bufferDataView, offset ); // data_len - for ( let h = 0; h < height; ++ h ) { + EXRDecoder.lines = line + EXRDecoder.scanlineBlockSize > EXRDecoder.height ? EXRDecoder.height - line : EXRDecoder.scanlineBlockSize; + const isCompressed = EXRDecoder.size < EXRDecoder.lines * EXRDecoder.bytesPerLine; + const viewer = isCompressed ? EXRDecoder.uncompress( EXRDecoder ) : uncompressRAW( EXRDecoder ); + offset.value += EXRDecoder.size; - for ( let w = 0; w < width; ++ w ) { + for ( let line_y = 0; line_y < EXRDecoder.scanlineBlockSize; line_y ++ ) { - i = h * width * 4 + w * 4; - const red = byteArray[ i ]; - const green = byteArray[ i + 1 ]; - const blue = byteArray[ i + 2 ]; - v = red > green ? red : green; - v = blue > v ? blue : v; + const true_y = line_y + scanlineBlockIdx * EXRDecoder.scanlineBlockSize; + if ( true_y >= EXRDecoder.height ) break; - if ( v < 1e-32 ) { + for ( let channelID = 0; channelID < EXRDecoder.channels; channelID ++ ) { - RGBEArray[ i ] = RGBEArray[ i + 1 ] = RGBEArray[ i + 2 ] = RGBEArray[ i + 3 ] = 0; + const cOff = channelOffsets[ EXRHeader.channels[ channelID ].name ]; - } else { + for ( let x = 0; x < EXRDecoder.width; x ++ ) { - const res = frexp( v ); - v = res[ 0 ] * 256 / v; - RGBEArray[ i ] = red * v; - RGBEArray[ i + 1 ] = green * v; - RGBEArray[ i + 2 ] = blue * v; - RGBEArray[ i + 3 ] = res[ 1 ] + 128; + tmpOffset.value = ( line_y * ( EXRDecoder.channels * EXRDecoder.width ) + channelID * EXRDecoder.width + x ) * EXRDecoder.inputSize; + const outIndex = ( EXRDecoder.height - 1 - true_y ) * ( EXRDecoder.width * EXRDecoder.outputChannels ) + x * EXRDecoder.outputChannels + cOff; + EXRDecoder.byteArray[ outIndex ] = EXRDecoder.getter( viewer, tmpOffset ); } @@ -2141,17 +2088,15 @@ } - byteArray = RGBEArray; - } - const format = this.type === THREE.UnsignedByteType ? THREE.RGBEFormat : numChannels === 4 ? THREE.RGBAFormat : THREE.RGBFormat; return { header: EXRHeader, - width: width, - height: height, - data: byteArray, - format: format, + width: EXRDecoder.width, + height: EXRDecoder.height, + data: EXRDecoder.byteArray, + format: EXRDecoder.format, + encoding: EXRDecoder.encoding, type: this.type }; @@ -2168,27 +2113,11 @@ function onLoadCallback( texture, texData ) { - switch ( texture.type ) { - - case THREE.UnsignedByteType: - texture.encoding = THREE.RGBEEncoding; - texture.minFilter = THREE.NearestFilter; - texture.magFilter = THREE.NearestFilter; - texture.generateMipmaps = false; - texture.flipY = false; - break; - - case THREE.FloatType: - case THREE.HalfFloatType: - texture.encoding = THREE.LinearEncoding; - texture.minFilter = THREE.LinearFilter; - texture.magFilter = THREE.LinearFilter; - texture.generateMipmaps = false; - texture.flipY = false; - break; - - } - + texture.encoding = texData.encoding; + texture.minFilter = THREE.LinearFilter; + texture.magFilter = THREE.LinearFilter; + texture.generateMipmaps = false; + texture.flipY = false; if ( onLoad ) onLoad( texture, texData ); } diff --git a/examples/js/loaders/FBXLoader.js b/examples/js/loaders/FBXLoader.js index 9ba11064acc92c..14dd5e29129f90 100644 --- a/examples/js/loaders/FBXLoader.js +++ b/examples/js/loaders/FBXLoader.js @@ -9,11 +9,10 @@ * Morph normals / blend shape normals * * FBX format references: - * https://wiki.blender.org/index.php/User:Mont29/Foundation/FBX_File_Structure - * http://help.autodesk.com/view/FBX/2017/ENU/?guid=__cpp_ref_index_html (C++ SDK reference) + * https://help.autodesk.com/view/FBX/2017/ENU/?guid=__cpp_ref_index_html (C++ SDK reference) * - * Binary format specification: - * https://code.blender.org/2013/08/fbx-binary-file-format-specification/ + * Binary format specification: + * https://code.blender.org/2013/08/fbx-binary-file-format-specification/ */ let fbxTree; diff --git a/examples/js/loaders/GLTFLoader.js b/examples/js/loaders/GLTFLoader.js index e2d7168d09f610..32eff233dc6425 100644 --- a/examples/js/loaders/GLTFLoader.js +++ b/examples/js/loaders/GLTFLoader.js @@ -1310,7 +1310,7 @@ /** * Specular-Glossiness Extension * - * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness + * Specification: https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Archived/KHR_materials_pbrSpecularGlossiness */ /** @@ -1329,7 +1329,7 @@ const specularMapParsFragmentChunk = [ '#ifdef USE_SPECULARMAP', ' uniform sampler2D specularMap;', '#endif' ].join( '\n' ); const glossinessMapParsFragmentChunk = [ '#ifdef USE_GLOSSINESSMAP', ' uniform sampler2D glossinessMap;', '#endif' ].join( '\n' ); - const specularMapFragmentChunk = [ 'vec3 specularFactor = specular;', '#ifdef USE_SPECULARMAP', ' vec4 texelSpecular = texture2D( specularMap, vUv );', ' texelSpecular = sRGBToLinear( texelSpecular );', ' // reads channel RGB, compatible with a glTF Specular-Glossiness (RGBA) texture', ' specularFactor *= texelSpecular.rgb;', '#endif' ].join( '\n' ); + const specularMapFragmentChunk = [ 'vec3 specularFactor = specular;', '#ifdef USE_SPECULARMAP', ' vec4 texelSpecular = texture2D( specularMap, vUv );', ' // reads channel RGB, compatible with a glTF Specular-Glossiness (RGBA) texture', ' specularFactor *= texelSpecular.rgb;', '#endif' ].join( '\n' ); const glossinessMapFragmentChunk = [ 'float glossinessFactor = glossiness;', '#ifdef USE_GLOSSINESSMAP', ' vec4 texelGlossiness = texture2D( glossinessMap, vUv );', ' // reads channel A, compatible with a glTF Specular-Glossiness (RGBA) texture', ' glossinessFactor *= texelGlossiness.a;', '#endif' ].join( '\n' ); const lightPhysicalFragmentChunk = [ 'PhysicalMaterial material;', 'material.diffuseColor = diffuseColor.rgb * ( 1. - max( specularFactor.r, max( specularFactor.g, specularFactor.b ) ) );', 'vec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );', 'float geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );', 'material.roughness = max( 1.0 - glossinessFactor, 0.0525 ); // 0.0525 corresponds to the base mip of a 256 cubemap.', 'material.roughness += geometryRoughness;', 'material.roughness = min( material.roughness, 1.0 );', 'material.specularColor = specularFactor;' ].join( '\n' ); const uniforms = { @@ -2006,7 +2006,7 @@ this.nodeNamesUsed = {}; // Use an THREE.ImageBitmapLoader if imageBitmaps are supported. Moves much of the // expensive work of uploading a texture to the GPU off the main thread. - if ( typeof createImageBitmap !== 'undefined' && /Firefox/.test( navigator.userAgent ) === false ) { + if ( typeof createImageBitmap !== 'undefined' && /Firefox|Safari/.test( navigator.userAgent ) === false ) { this.textureLoader = new THREE.ImageBitmapLoader( this.options.manager ); diff --git a/examples/js/loaders/HDRCubeTextureLoader.js b/examples/js/loaders/HDRCubeTextureLoader.js index 668e39638cfbd2..4df9192e37256e 100644 --- a/examples/js/loaders/HDRCubeTextureLoader.js +++ b/examples/js/loaders/HDRCubeTextureLoader.js @@ -28,14 +28,6 @@ switch ( texture.type ) { - case THREE.UnsignedByteType: - texture.encoding = THREE.RGBEEncoding; - texture.format = THREE.RGBAFormat; - texture.minFilter = THREE.NearestFilter; - texture.magFilter = THREE.NearestFilter; - texture.generateMipmaps = false; - break; - case THREE.FloatType: texture.encoding = THREE.LinearEncoding; texture.format = THREE.RGBFormat; diff --git a/examples/js/loaders/LDrawLoader.js b/examples/js/loaders/LDrawLoader.js index 576d5473c171b0..817e6e4720f931 100644 --- a/examples/js/loaders/LDrawLoader.js +++ b/examples/js/loaders/LDrawLoader.js @@ -142,7 +142,29 @@ } - function smoothNormals( faces, lineSegments ) { + function generateFaceNormals( faces ) { + + for ( let i = 0, l = faces.length; i < l; i ++ ) { + + const face = faces[ i ]; + const vertices = face.vertices; + const v0 = vertices[ 0 ]; + const v1 = vertices[ 1 ]; + const v2 = vertices[ 2 ]; + + _tempVec0.subVectors( v1, v0 ); + + _tempVec1.subVectors( v2, v1 ); + + face.faceNormal = new THREE.Vector3().crossVectors( _tempVec0, _tempVec1 ).normalize(); + + } + + } + + const _ray = new THREE.Ray(); + + function smoothNormals( faces, lineSegments, checkSubSegments = false ) { function hashVertex( v ) { @@ -160,9 +182,27 @@ return `${hashVertex( v0 )}_${hashVertex( v1 )}`; + } // converts the two vertices to a ray with a normalized direction and origin of 0, 0, 0 projected + // onto the original line. + + + function toNormalizedRay( v0, v1, targetRay ) { + + targetRay.direction.subVectors( v1, v0 ).normalize(); + const scalar = v0.dot( targetRay.direction ); + targetRay.origin.copy( v0 ).addScaledVector( targetRay.direction, - scalar ); + return targetRay; + + } + + function hashRay( ray ) { + + return hashEdge( ray.origin, ray.direction ); + } const hardEdges = new Set(); + const hardEdgeRays = new Map(); const halfEdgeList = {}; const normals = []; // Save the list of hard edges by hash @@ -173,7 +213,43 @@ const v0 = vertices[ 0 ]; const v1 = vertices[ 1 ]; hardEdges.add( hashEdge( v0, v1 ) ); - hardEdges.add( hashEdge( v1, v0 ) ); + hardEdges.add( hashEdge( v1, v0 ) ); // only generate the hard edge ray map if we're checking subsegments because it's more expensive to check + // and requires more memory. + + if ( checkSubSegments ) { + + // add both ray directions to the map + const ray = toNormalizedRay( v0, v1, new THREE.Ray() ); + const rh1 = hashRay( ray ); + + if ( ! hardEdgeRays.has( rh1 ) ) { + + toNormalizedRay( v1, v0, ray ); + const rh2 = hashRay( ray ); + const info = { + ray, + distances: [] + }; + hardEdgeRays.set( rh1, info ); + hardEdgeRays.set( rh2, info ); + + } // store both segments ends in min, max order in the distances array to check if a face edge is a + // subsegment later. + + + const info = hardEdgeRays.get( rh1 ); + let d0 = info.ray.direction.dot( v0 ); + let d1 = info.ray.direction.dot( v1 ); + + if ( d0 > d1 ) { + + [ d0, d1 ] = [ d1, d0 ]; + + } + + info.distances.push( d0, d1 ); + + } } // track the half edges associated with each triangle @@ -192,7 +268,58 @@ const v1 = vertices[ next ]; const hash = hashEdge( v0, v1 ); // don't add the triangle if the edge is supposed to be hard - if ( hardEdges.has( hash ) ) continue; + if ( hardEdges.has( hash ) ) { + + continue; + + } // if checking subsegments then check to see if this edge lies on a hard edge ray and whether its within any ray bounds + + + if ( checkSubSegments ) { + + toNormalizedRay( v0, v1, _ray ); + const rayHash = hashRay( _ray ); + + if ( hardEdgeRays.has( rayHash ) ) { + + const info = hardEdgeRays.get( rayHash ); + const { + ray, + distances + } = info; + let d0 = ray.direction.dot( v0 ); + let d1 = ray.direction.dot( v1 ); + + if ( d0 > d1 ) { + + [ d0, d1 ] = [ d1, d0 ]; + + } // return early if the face edge is found to be a subsegment of a line edge meaning the edge will have "hard" normals + + + let found = false; + + for ( let i = 0, l = distances.length; i < l; i += 2 ) { + + if ( d0 >= distances[ i ] && d1 <= distances[ i + 1 ] ) { + + found = true; + break; + + } + + } + + if ( found ) { + + continue; + + } + + } + + } + const info = { index: index, tri: tri @@ -433,6 +560,12 @@ } + getVector() { + + return new THREE.Vector3( parseFloat( this.getToken() ), parseFloat( this.getToken() ), parseFloat( this.getToken() ) ); + + } + getRemainingString() { return this.line.substring( this.currentCharIndex, this.lineLength ); @@ -635,10 +768,25 @@ positions[ index + 1 ] = v.y; positions[ index + 2 ] = v.z; - } + } // create the normals array if this is a set of faces + if ( elementSize === 3 ) { + if ( ! elem.faceNormal ) { + + const v0 = vertices[ 0 ]; + const v1 = vertices[ 1 ]; + const v2 = vertices[ 2 ]; + + _tempVec0.subVectors( v1, v0 ); + + _tempVec1.subVectors( v2, v1 ); + + elem.faceNormal = new THREE.Vector3().crossVectors( _tempVec0, _tempVec1 ).normalize(); + + } + let elemNormals = elem.normals; if ( elemNormals.length === 4 ) { @@ -655,6 +803,7 @@ for ( let j = 0, l = elemNormals.length; j < l; j ++ ) { + // use face normal if a vertex normal is not provided let n = elem.faceNormal; if ( elemNormals[ j ] ) { @@ -781,13 +930,10 @@ this.cache = new LDrawFileCache( this ); // This object is a map from file names to paths. It agilizes the paths search. If it is not set then files will be searched by trial and error. - this.fileMap = null; + this.fileMap = {}; this.rootParseScope = this.newParseScopeLevel(); // Add default main triangle and line edge materials (used in pieces that can be coloured with a main color) - this.setMaterials( [ this.parseColourMetaDirective( new LineParser( 'Main_Colour CODE 16 VALUE #FF8080 EDGE #333333' ) ), this.parseColourMetaDirective( new LineParser( 'Edge_Colour CODE 24 VALUE #A0A0A0 EDGE #333333' ) ) ] ); // If this flag is set to true, each subobject will be a Object. - // If not (the default), only one object which contains all the merged primitives will be created. - - this.separateObjects = false; // If this flag is set to true the vertex normals will be smoothed. + this.setMaterials( [ this.parseColourMetaDirective( new LineParser( 'Main_Colour CODE 16 VALUE #FF8080 EDGE #333333' ) ), this.parseColourMetaDirective( new LineParser( 'Edge_Colour CODE 24 VALUE #A0A0A0 EDGE #333333' ) ) ] ); // If this flag is set to true the vertex normals will be smoothed. this.smoothNormals = true; // The path to load parts from the LDraw parts library from. @@ -833,12 +979,6 @@ load( url, onLoad, onProgress, onError ) { - if ( ! this.fileMap ) { - - this.fileMap = {}; - - } - const fileLoader = new THREE.FileLoader( this.manager ); fileLoader.setPath( this.path ); fileLoader.setRequestHeader( this.requestHeader ); @@ -914,15 +1054,16 @@ currentFileName: null, mainColourCode: parentScope ? parentScope.mainColourCode : '16', mainEdgeColourCode: parentScope ? parentScope.mainEdgeColourCode : '24', - currentMatrix: new THREE.Matrix4(), matrix: new THREE.Matrix4(), type: 'Model', + groupObject: null, // If false, it is a root material scope previous to parse isFromParse: true, faces: [], lineSegments: [], conditionalSegments: [], totalFaces: 0, + faceMaterials: new Set(), // If true, this object is the start of a construction step startingConstructionStep: false }; @@ -996,7 +1137,7 @@ if ( ! name ) { - throw 'LDrawLoader: Material name was expected after "!COLOUR tag' + lineParser.getLineNumberString() + '.'; + throw new Error( 'LDrawLoader: Material name was expected after "!COLOUR tag' + lineParser.getLineNumberString() + '.' ); } // Parse tag tokens and their parameters @@ -1028,7 +1169,7 @@ } else if ( ! colour.startsWith( '#' ) ) { - throw 'LDrawLoader: Invalid colour while parsing material' + lineParser.getLineNumberString() + '.'; + throw new Error( 'LDrawLoader: Invalid colour while parsing material' + lineParser.getLineNumberString() + '.' ); } @@ -1048,7 +1189,7 @@ if ( ! edgeMaterial ) { - throw 'LDrawLoader: Invalid edge colour while parsing material' + lineParser.getLineNumberString() + '.'; + throw new Error( 'LDrawLoader: Invalid edge colour while parsing material' + lineParser.getLineNumberString() + '.' ); } // Get the edge material for this triangle material @@ -1064,7 +1205,7 @@ if ( isNaN( alpha ) ) { - throw 'LDrawLoader: Invalid alpha value in material definition' + lineParser.getLineNumberString() + '.'; + throw new Error( 'LDrawLoader: Invalid alpha value in material definition' + lineParser.getLineNumberString() + '.' ); } @@ -1083,7 +1224,7 @@ if ( isNaN( luminance ) ) { - throw 'LDrawLoader: Invalid luminance value in material definition' + LineParser.getLineNumberString() + '.'; + throw new Error( 'LDrawLoader: Invalid luminance value in material definition' + LineParser.getLineNumberString() + '.' ); } @@ -1116,8 +1257,7 @@ break; default: - throw 'LDrawLoader: Unknown token "' + token + '" while parsing material' + lineParser.getLineNumberString() + '.'; - break; + throw new Error( 'LDrawLoader: Unknown token "' + token + '" while parsing material' + lineParser.getLineNumberString() + '.' ); } @@ -1263,9 +1403,8 @@ let bfcCull = true; let type = ''; let startingConstructionStep = false; - const scope = this; - function parseColourCode( lineParser, forEdge ) { + const parseColourCode = ( lineParser, forEdge ) => { // Parses next colour code and returns a THREE.Material let colourCode = lineParser.getToken(); @@ -1282,31 +1421,17 @@ } - const material = scope.getMaterial( colourCode, currentParseScope ); + const material = this.getMaterial( colourCode, currentParseScope ); if ( ! material ) { - throw 'LDrawLoader: Unknown colour code "' + colourCode + '" is used' + lineParser.getLineNumberString() + ' but it was not defined previously.'; + throw new Error( 'LDrawLoader: Unknown colour code "' + colourCode + '" is used' + lineParser.getLineNumberString() + ' but it was not defined previously.' ); } return material; - } - - function parseVector( lp ) { - - const v = new THREE.Vector3( parseFloat( lp.getToken() ), parseFloat( lp.getToken() ), parseFloat( lp.getToken() ) ); - - if ( ! scope.separateObjects ) { - - v.applyMatrix4( currentParseScope.currentMatrix ); - - } - - return v; - - } // Parse all line commands + }; // Parse all line commands for ( let lineIndex = 0; lineIndex < numLines; lineIndex ++ ) { @@ -1351,7 +1476,7 @@ let inverted; let ccw; let doubleSided; - let v0, v1, v2, v3, c0, c1, faceNormal; + let v0, v1, v2, v3, c0, c1; switch ( lineType ) { @@ -1367,23 +1492,6 @@ case '!LDRAW_ORG': type = lp.getToken(); currentParseScope.type = type; - const isRoot = ! parentParseScope.isFromParse; - - if ( isRoot || scope.separateObjects && ! isPrimitiveType( type ) ) { - - currentParseScope.groupObject = new THREE.Group(); - currentParseScope.groupObject.userData.startingConstructionStep = currentParseScope.startingConstructionStep; - - } // If the scale of the object is negated then the triangle winding order - // needs to be flipped. - - - if ( currentParseScope.matrix.determinant() < 0 && ( scope.separateObjects && isPrimitiveType( type ) || ! scope.separateObjects ) ) { - - currentParseScope.inverted = ! currentParseScope.inverted; - - } - faces = currentParseScope.faces; lineSegments = currentParseScope.lineSegments; conditionalSegments = currentParseScope.conditionalSegments; @@ -1513,10 +1621,10 @@ const matrix = new THREE.Matrix4().set( m0, m1, m2, posX, m3, m4, m5, posY, m6, m7, m8, posZ, 0, 0, 0, 1 ); let fileName = lp.getRemainingString().trim().replace( /\\/g, '/' ); - if ( scope.fileMap[ fileName ] ) { + if ( this.fileMap[ fileName ] ) { // Found the subobject path in the preloaded file path map - fileName = scope.fileMap[ fileName ]; + fileName = this.fileMap[ fileName ]; } else { @@ -1546,8 +1654,8 @@ case '2': material = parseColourCode( lp, true ); - v0 = parseVector( lp ); - v1 = parseVector( lp ); + v0 = lp.getVector(); + v1 = lp.getVector(); segment = { material: material.userData.edgeMaterial, colourCode: material.userData.code, @@ -1561,10 +1669,10 @@ case '5': material = parseColourCode( lp, true ); - v0 = parseVector( lp ); - v1 = parseVector( lp ); - c0 = parseVector( lp ); - c1 = parseVector( lp ); + v0 = lp.getVector(); + v1 = lp.getVector(); + c0 = lp.getVector(); + c1 = lp.getVector(); segment = { material: material.userData.edgeMaterial.userData.conditionalEdgeMaterial, colourCode: material.userData.code, @@ -1583,27 +1691,22 @@ if ( ccw === true ) { - v0 = parseVector( lp ); - v1 = parseVector( lp ); - v2 = parseVector( lp ); + v0 = lp.getVector(); + v1 = lp.getVector(); + v2 = lp.getVector(); } else { - v2 = parseVector( lp ); - v1 = parseVector( lp ); - v0 = parseVector( lp ); + v2 = lp.getVector(); + v1 = lp.getVector(); + v0 = lp.getVector(); } - _tempVec0.subVectors( v1, v0 ); - - _tempVec1.subVectors( v2, v1 ); - - faceNormal = new THREE.Vector3().crossVectors( _tempVec0, _tempVec1 ).normalize(); faces.push( { material: material, colourCode: material.userData.code, - faceNormal: faceNormal, + faceNormal: null, vertices: [ v0, v1, v2 ], normals: [ null, null, null ] } ); @@ -1614,7 +1717,7 @@ faces.push( { material: material, colourCode: material.userData.code, - faceNormal: faceNormal, + faceNormal: null, vertices: [ v2, v1, v0 ], normals: [ null, null, null ] } ); @@ -1622,6 +1725,7 @@ } + currentParseScope.faceMaterials.add( material ); break; // Line type 4: Quadrilateral @@ -1633,31 +1737,26 @@ if ( ccw === true ) { - v0 = parseVector( lp ); - v1 = parseVector( lp ); - v2 = parseVector( lp ); - v3 = parseVector( lp ); + v0 = lp.getVector(); + v1 = lp.getVector(); + v2 = lp.getVector(); + v3 = lp.getVector(); } else { - v3 = parseVector( lp ); - v2 = parseVector( lp ); - v1 = parseVector( lp ); - v0 = parseVector( lp ); - - } - - _tempVec0.subVectors( v1, v0 ); + v3 = lp.getVector(); + v2 = lp.getVector(); + v1 = lp.getVector(); + v0 = lp.getVector(); - _tempVec1.subVectors( v2, v1 ); - - faceNormal = new THREE.Vector3().crossVectors( _tempVec0, _tempVec1 ).normalize(); // specifically place the triangle diagonal in the v0 and v1 slots so we can + } // specifically place the triangle diagonal in the v0 and v1 slots so we can // account for the doubling of vertices later when smoothing normals. + faces.push( { material: material, colourCode: material.userData.code, - faceNormal: faceNormal, + faceNormal: null, vertices: [ v0, v1, v2, v3 ], normals: [ null, null, null, null ] } ); @@ -1668,7 +1767,7 @@ faces.push( { material: material, colourCode: material.userData.code, - faceNormal: faceNormal, + faceNormal: null, vertices: [ v3, v2, v1, v0 ], normals: [ null, null, null, null ] } ); @@ -1679,8 +1778,7 @@ break; default: - throw 'LDrawLoader: Unknown line type "' + lineType + '"' + lp.getLineNumberString() + '.'; - break; + throw new Error( 'LDrawLoader: Unknown line type "' + lineType + '"' + lp.getLineNumberString() + '.' ); } @@ -1697,6 +1795,14 @@ currentParseScope.subobjects = subobjects; currentParseScope.numSubobjects = subobjects.length; currentParseScope.subobjectIndex = 0; + const isRoot = ! parentParseScope.isFromParse; + + if ( isRoot || ! isPrimitiveType( type ) ) { + + currentParseScope.groupObject = new THREE.Group(); + currentParseScope.groupObject.userData.startingConstructionStep = currentParseScope.startingConstructionStep; + + } } @@ -1736,17 +1842,21 @@ // is added directly into the parent model (meaning it will never get smoothed by // being added to a part) - const doSmooth = isPartType( subobjectParseScope.type ) || ! isPartType( subobjectParseScope.type ) && ! isModelType( subobjectParseScope.type ) && isModelType( subobjectParseScope.parentScope.type ); + const doSmooth = isPartType( subobjectParseScope.type ) || isPrimitiveType( subobjectParseScope.type ) && isModelType( subobjectParseScope.parentScope.type ); if ( this.smoothNormals && doSmooth ) { - smoothNormals( subobjectParseScope.faces, subobjectParseScope.lineSegments ); + generateFaceNormals( subobjectParseScope.faces ); // only check subsetgments if we have multiple materials in a single part because this seems to be the case where it's needed most -- + // there may be cases where a single edge line crosses over polygon edges that are broken up by multiple materials. + + const checkSubSegments = subobjectParseScope.faceMaterials.size > 1; + smoothNormals( subobjectParseScope.faces, subobjectParseScope.lineSegments, checkSubSegments ); } const isRoot = ! parentParseScope.isFromParse; - if ( this.separateObjects && ! isPrimitiveType( subobjectParseScope.type ) || isRoot ) { + if ( ! isPrimitiveType( subobjectParseScope.type ) || isRoot ) { const objGroup = subobjectParseScope.groupObject; @@ -1780,26 +1890,23 @@ } else { - const separateObjects = this.separateObjects; const parentLineSegments = parentParseScope.lineSegments; const parentConditionalSegments = parentParseScope.conditionalSegments; const parentFaces = parentParseScope.faces; + const parentFaceMaterials = parentParseScope.faceMaterials; const lineSegments = subobjectParseScope.lineSegments; const conditionalSegments = subobjectParseScope.conditionalSegments; const faces = subobjectParseScope.faces; + const faceMaterials = subobjectParseScope.faceMaterials; + const matrix = subobjectParseScope.matrix; + const matrixScaleInverted = matrix.determinant() < 0; for ( let i = 0, l = lineSegments.length; i < l; i ++ ) { const ls = lineSegments[ i ]; - - if ( separateObjects ) { - - const vertices = ls.vertices; - vertices[ 0 ].applyMatrix4( subobjectParseScope.matrix ); - vertices[ 1 ].applyMatrix4( subobjectParseScope.matrix ); - - } - + const vertices = ls.vertices; + vertices[ 0 ].applyMatrix4( matrix ); + vertices[ 1 ].applyMatrix4( matrix ); parentLineSegments.push( ls ); } @@ -1807,18 +1914,12 @@ for ( let i = 0, l = conditionalSegments.length; i < l; i ++ ) { const os = conditionalSegments[ i ]; - - if ( separateObjects ) { - - const vertices = os.vertices; - const controlPoints = os.controlPoints; - vertices[ 0 ].applyMatrix4( subobjectParseScope.matrix ); - vertices[ 1 ].applyMatrix4( subobjectParseScope.matrix ); - controlPoints[ 0 ].applyMatrix4( subobjectParseScope.matrix ); - controlPoints[ 1 ].applyMatrix4( subobjectParseScope.matrix ); - - } - + const vertices = os.vertices; + const controlPoints = os.controlPoints; + vertices[ 0 ].applyMatrix4( matrix ); + vertices[ 1 ].applyMatrix4( matrix ); + controlPoints[ 0 ].applyMatrix4( matrix ); + controlPoints[ 1 ].applyMatrix4( matrix ); parentConditionalSegments.push( os ); } @@ -1826,22 +1927,19 @@ for ( let i = 0, l = faces.length; i < l; i ++ ) { const tri = faces[ i ]; + const vertices = tri.vertices; - if ( separateObjects ) { - - const vertices = tri.vertices; + for ( let i = 0, l = vertices.length; i < l; i ++ ) { - for ( let i = 0, l = vertices.length; i < l; i ++ ) { + vertices[ i ].applyMatrix4( matrix ); - vertices[ i ] = vertices[ i ].clone().applyMatrix4( subobjectParseScope.matrix ); - - } + } // If the scale of the object is negated then the triangle winding order + // needs to be flipped. - _tempVec0.subVectors( vertices[ 1 ], vertices[ 0 ] ); - _tempVec1.subVectors( vertices[ 2 ], vertices[ 1 ] ); + if ( matrixScaleInverted ) { - tri.faceNormal.crossVectors( _tempVec0, _tempVec1 ).normalize(); + vertices.reverse(); } @@ -1850,6 +1948,7 @@ } parentParseScope.totalFaces += subobjectParseScope.totalFaces; + faceMaterials.forEach( material => parentFaceMaterials.add( material ) ); } @@ -1864,7 +1963,6 @@ if ( subobject ) { - parseScope.currentMatrix.multiplyMatrices( parentParseScope.currentMatrix, subobject.matrix ); parseScope.matrix.copy( subobject.matrix ); parseScope.inverted = subobject.inverted; parseScope.startingConstructionStep = subobject.startingConstructionStep; @@ -1911,9 +2009,10 @@ return scope.processObject( text, subobject, url, parseScope ); - } ).catch( function () { + } ).catch( function ( err ) { - console.warn( 'LDrawLoader: Subobject "' + subobject.fileName + '" could not be found.' ); + console.warn( 'LDrawLoader: Subobject "' + subobject.fileName + '" could not be loaded.' ); + console.warn( err ); return null; } ); diff --git a/examples/js/loaders/MMDLoader.js b/examples/js/loaders/MMDLoader.js index 42957709eac83e..cc0aeaa317f361 100644 --- a/examples/js/loaders/MMDLoader.js +++ b/examples/js/loaders/MMDLoader.js @@ -287,7 +287,6 @@ /* * base64 encoded defalut toon textures toon00.bmp - toon10.bmp. * We don't need to request external toon image files. - * This idea is from http://www20.atpages.jp/katwat/three.js_r58/examples/mytest37/mmd.three.js */ diff --git a/examples/js/loaders/NRRDLoader.js b/examples/js/loaders/NRRDLoader.js index 280477f8640296..aaee0de130322a 100644 --- a/examples/js/loaders/NRRDLoader.js +++ b/examples/js/loaders/NRRDLoader.js @@ -207,7 +207,10 @@ if ( ! headerObject.vectors ) { //if no space direction is set, let's use the identity - headerObject.vectors = [ new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 0, 1 ) ]; //apply spacing if defined + headerObject.vectors = []; + headerObject.vectors.push( [ 1, 0, 0 ] ); + headerObject.vectors.push( [ 0, 1, 0 ] ); + headerObject.vectors.push( [ 0, 0, 1 ] ); //apply spacing if defined if ( headerObject.spacings ) { @@ -215,7 +218,11 @@ if ( ! isNaN( headerObject.spacings[ i ] ) ) { - headerObject.vectors[ i ].multiplyScalar( headerObject.spacings[ i ] ); + for ( let j = 0; j <= 2; j ++ ) { + + headerObject.vectors[ i ][ j ] *= headerObject.spacings[ i ]; + + } } diff --git a/examples/js/loaders/OBJLoader.js b/examples/js/loaders/OBJLoader.js index 93e8ba1cc564f5..1f8043b6a0c56e 100644 --- a/examples/js/loaders/OBJLoader.js +++ b/examples/js/loaders/OBJLoader.js @@ -583,8 +583,6 @@ /* * http://paulbourke.net/dataformats/obj/ - * or - * http://www.cs.utah.edu/~boulos/cs3505/obj_spec.pdf * * From chapter "Grouping" Syntax explanation "s group_number": * "group_number is the smoothing group number. To turn off smoothing groups, use a value of 0 or off. diff --git a/examples/js/loaders/PLYLoader.js b/examples/js/loaders/PLYLoader.js index 9cfa6b666c3556..71e46473e4d6d2 100644 --- a/examples/js/loaders/PLYLoader.js +++ b/examples/js/loaders/PLYLoader.js @@ -79,7 +79,7 @@ function parseHeader( data ) { - const patternHeader = /ply([\s\S]*)end_header\r?\n/; + const patternHeader = /^ply([\s\S]*)end_header\r?\n/; let headerText = ''; let headerLength = 0; const result = patternHeader.exec( data ); diff --git a/examples/js/loaders/RGBELoader.js b/examples/js/loaders/RGBELoader.js index de6169bd8cf7bc..af77824d3de891 100644 --- a/examples/js/loaders/RGBELoader.js +++ b/examples/js/loaders/RGBELoader.js @@ -374,13 +374,6 @@ switch ( this.type ) { - case THREE.UnsignedByteType: - data = image_rgba_data; - format = THREE.RGBEFormat; // handled as THREE.RGBAFormat in shaders - - type = THREE.UnsignedByteType; - break; - case THREE.FloatType: numElements = image_rgba_data.length / 4; const floatArray = new Float32Array( numElements * 3 ); @@ -449,14 +442,6 @@ switch ( texture.type ) { - case THREE.UnsignedByteType: - texture.encoding = THREE.RGBEEncoding; - texture.minFilter = THREE.NearestFilter; - texture.magFilter = THREE.NearestFilter; - texture.generateMipmaps = false; - texture.flipY = true; - break; - case THREE.FloatType: texture.encoding = THREE.LinearEncoding; texture.minFilter = THREE.LinearFilter; diff --git a/examples/js/loaders/RGBMLoader.js b/examples/js/loaders/RGBMLoader.js index 8570b442b248cc..a613d1ab0fc945 100644 --- a/examples/js/loaders/RGBMLoader.js +++ b/examples/js/loaders/RGBMLoader.js @@ -2,6 +2,28 @@ class RGBMLoader extends THREE.DataTextureLoader { + constructor( manager ) { + + super( manager ); + this.type = THREE.HalfFloatType; + this.maxRange = 7; // more information about this property at https://iwasbeingirony.blogspot.com/2010/06/difference-between-rgbm-and-rgbd.html + + } + + setDataType( value ) { + + this.type = value; + return this; + + } + + setMaxRange( value ) { + + this.maxRange = value; + return this; + + } + loadCubemap( urls, onLoad, onProgress, onError ) { const texture = new THREE.CubeTexture(); @@ -32,7 +54,7 @@ } - texture.encoding = THREE.RGBM7Encoding; + texture.type = this.type; texture.format = THREE.RGBAFormat; texture.minFilter = THREE.LinearFilter; texture.generateMipmaps = false; @@ -44,14 +66,42 @@ const img = UPNG.decode( buffer ); const rgba = UPNG.toRGBA8( img )[ 0 ]; + const data = new Uint8Array( rgba ); + const size = img.width * img.height * 4; + const output = this.type === THREE.HalfFloatType ? new Uint16Array( size ) : new Float32Array( size ); // decode RGBM + + for ( let i = 0; i < data.length; i += 4 ) { + + const r = data[ i + 0 ] / 255; + const g = data[ i + 1 ] / 255; + const b = data[ i + 2 ] / 255; + const a = data[ i + 3 ] / 255; + + if ( this.type === THREE.HalfFloatType ) { + + output[ i + 0 ] = THREE.DataUtils.toHalfFloat( Math.min( r * a * this.maxRange, 65504 ) ); + output[ i + 1 ] = THREE.DataUtils.toHalfFloat( Math.min( g * a * this.maxRange, 65504 ) ); + output[ i + 2 ] = THREE.DataUtils.toHalfFloat( Math.min( b * a * this.maxRange, 65504 ) ); + output[ i + 3 ] = THREE.DataUtils.toHalfFloat( 1 ); + + } else { + + output[ i + 0 ] = r * a * this.maxRange; + output[ i + 1 ] = g * a * this.maxRange; + output[ i + 2 ] = b * a * this.maxRange; + output[ i + 3 ] = 1; + + } + + } + return { width: img.width, height: img.height, - data: new Uint8Array( rgba ), + data: output, format: THREE.RGBAFormat, - type: THREE.UnsignedByteType, - flipY: true, - encoding: THREE.RGBM7Encoding + type: this.type, + flipY: true }; } @@ -343,7 +393,7 @@ var mgck = [ 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a ]; - for ( var i = 0; i < 8; i ++ ) if ( data[ i ] != mgck[ i ] ) throw 'The input is not a PNG file!'; + for ( var i = 0; i < 8; i ++ ) if ( data[ i ] != mgck[ i ] ) throw new Error( 'The input is not a PNG file!' ); while ( offset < data.length ) { diff --git a/examples/js/loaders/VRMLLoader.js b/examples/js/loaders/VRMLLoader.js index 8c9a6ec3ae75a0..ecd91aa6ab3f4c 100644 --- a/examples/js/loaders/VRMLLoader.js +++ b/examples/js/loaders/VRMLLoader.js @@ -139,7 +139,7 @@ const StringLiteral = createToken( { name: 'StringLiteral', - pattern: /"(:?[^\\"\n\r]+|\\(:?[bfnrtv"\\/]|u[0-9a-fA-F]{4}))*"/ + pattern: /"(?:[^\\"\n\r]|\\[bfnrtv"\\/]|\\u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])*"/ } ); const HexLiteral = createToken( { name: 'HexLiteral', diff --git a/examples/js/math/ImprovedNoise.js b/examples/js/math/ImprovedNoise.js index 9282e88528ac03..a5aa4045c45daf 100644 --- a/examples/js/math/ImprovedNoise.js +++ b/examples/js/math/ImprovedNoise.js @@ -1,6 +1,6 @@ ( function () { - // http://mrl.nyu.edu/~perlin/noise/ + // https://cs.nyu.edu/~perlin/noise/ const _p = [ 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180 ]; for ( let i = 0; i < 256; i ++ ) { diff --git a/examples/js/misc/Volume.js b/examples/js/misc/Volume.js index eb7907cf12b955..cb5d7ed42370fd 100644 --- a/examples/js/misc/Volume.js +++ b/examples/js/misc/Volume.js @@ -104,7 +104,7 @@ case 'unsigned long long int': case 'uint64': case 'uint64_t': - throw 'Error in Volume constructor : this type is not supported in JavaScript'; + throw new Error( 'Error in Volume constructor : this type is not supported in JavaScript' ); break; case 'Float32': @@ -126,7 +126,7 @@ if ( this.data.length !== this.xLength * this.yLength * this.zLength ) { - throw 'Error in Volume constructor, lengths are not matching arrayBuffer size'; + throw new Error( 'Error in Volume constructor, lengths are not matching arrayBuffer size' ); } diff --git a/examples/js/modifiers/EdgeSplitModifier.js b/examples/js/modifiers/EdgeSplitModifier.js index 8921897a3c1265..106b9bc1b9ee53 100644 --- a/examples/js/modifiers/EdgeSplitModifier.js +++ b/examples/js/modifiers/EdgeSplitModifier.js @@ -168,7 +168,7 @@ if ( THREE.BufferGeometryUtils === undefined ) { - throw 'THREE.EdgeSplitModifier relies on THREE.BufferGeometryUtils'; + throw new Error( 'THREE.EdgeSplitModifier relies on THREE.BufferGeometryUtils' ); } diff --git a/examples/js/modifiers/SimplifyModifier.js b/examples/js/modifiers/SimplifyModifier.js index 81e33cb707c095..3e6b5cd2c97588 100644 --- a/examples/js/modifiers/SimplifyModifier.js +++ b/examples/js/modifiers/SimplifyModifier.js @@ -17,7 +17,7 @@ if ( THREE.BufferGeometryUtils === undefined ) { - throw 'THREE.SimplifyModifier relies on THREE.BufferGeometryUtils'; + throw new Error( 'THREE.SimplifyModifier relies on THREE.BufferGeometryUtils' ); } diff --git a/examples/js/objects/Sky.js b/examples/js/objects/Sky.js index ae3bebdfc08bf7..2df0893e9a4df5 100644 --- a/examples/js/objects/Sky.js +++ b/examples/js/objects/Sky.js @@ -6,7 +6,7 @@ * https://www.researchgate.net/publication/220720443_A_Practical_Analytic_Model_for_Daylight * * First implemented by Simon Wallner - * http://www.simonwallner.at/projects/atmospheric-scattering + * http://simonwallner.at/project/atmospheric-scattering/ * * Improved by Martin Upitis * http://blenderartists.org/forum/showthread.php?245954-preethams-sky-impementation-HDR diff --git a/examples/js/objects/Water.js b/examples/js/objects/Water.js index 21ee8deb5e7dec..329b961965a791 100644 --- a/examples/js/objects/Water.js +++ b/examples/js/objects/Water.js @@ -2,8 +2,8 @@ /** * Work based on : - * http://slayvin.net : Flat mirror for three.js - * http://www.adelphi.edu/~stemkoski : An implementation of water shader based on the flat mirror + * https://github.com/Slayvin: Flat mirror for three.js + * https://home.adelphi.edu/~stemkoski/ : An implementation of water shader based on the flat mirror * http://29a.ch/ && http://29a.ch/slides/2012/webglwater/ : Water shader explanations in WebGL */ diff --git a/examples/js/objects/Water2.js b/examples/js/objects/Water2.js index 07b9c23dbb6990..f57155cb5237b5 100644 --- a/examples/js/objects/Water2.js +++ b/examples/js/objects/Water2.js @@ -2,8 +2,8 @@ /** * References: - * http://www.valvesoftware.com/publications/2010/siggraph2010_vlachos_waterflow.pdf - * http://graphicsrunner.blogspot.de/2010/08/water-using-flow-maps.html + * https://alex.vlachos.com/graphics/Vlachos-SIGGRAPH10-WaterFlow.pdf + * http://graphicsrunner.blogspot.de/2010/08/water-using-flow-maps.html * */ diff --git a/examples/js/shaders/GammaCorrectionShader.js b/examples/js/shaders/GammaCorrectionShader.js index 04c579dd7eff1d..8a579bdf55119e 100644 --- a/examples/js/shaders/GammaCorrectionShader.js +++ b/examples/js/shaders/GammaCorrectionShader.js @@ -34,7 +34,7 @@ vec4 tex = texture2D( tDiffuse, vUv ); - gl_FragColor = LinearTosRGB( tex ); // optional: LinearToGamma( tex, float( GAMMA_FACTOR ) ); + gl_FragColor = LinearTosRGB( tex ); }` }; diff --git a/examples/js/shaders/SSRShader.js b/examples/js/shaders/SSRShader.js index 217cb41ab18712..62d0969c106eb9 100644 --- a/examples/js/shaders/SSRShader.js +++ b/examples/js/shaders/SSRShader.js @@ -197,7 +197,7 @@ vec3 vP=getViewPosition( uv, d, cW ); #ifdef PERSPECTIVE_CAMERA - // https://www.comp.nus.edu.sg/~lowkl/publications/lowk_persp_interp_techrep.pdf + // https://comp.nus.edu.sg/~lowkl/publications/lowk_persp_interp_techrep.pdf float recipVPZ=1./viewPosition.z; float viewReflectRayZ=1./(recipVPZ+s*(1./d1viewPosition.z-recipVPZ)); #else diff --git a/examples/js/shaders/SSRrShader.js b/examples/js/shaders/SSRrShader.js index 925b4f3e8b4921..2d1bc5b55dcb56 100644 --- a/examples/js/shaders/SSRrShader.js +++ b/examples/js/shaders/SSRrShader.js @@ -215,7 +215,7 @@ vec3 vP=getViewPosition( uv, d, cW ); #ifdef PERSPECTIVE_CAMERA - // https://www.comp.nus.edu.sg/~lowkl/publications/lowk_persp_interp_techrep.pdf + // https://comp.nus.edu.sg/~lowkl/publications/lowk_persp_interp_techrep.pdf float recipVPZ=1./viewPosition.z; float viewRefractRayZ=1./(recipVPZ+s*(1./d1viewPosition.z-recipVPZ)); float sD=surfDist*cW; diff --git a/examples/js/utils/GeometryUtils.js b/examples/js/utils/GeometryUtils.js index 90b08937a0ea3d..1c4b5bd4d10186 100644 --- a/examples/js/utils/GeometryUtils.js +++ b/examples/js/utils/GeometryUtils.js @@ -41,7 +41,7 @@ * Generates 3D-Coordinates in a very fast way. * * Based on work by: - * @link http://www.openprocessing.org/visuals/?visualID=15599 + * @link https://openprocessing.org/user/5654 * * @param center Center of Hilbert curve. * @param size Total width of Hilbert curve. diff --git a/examples/js/utils/RoughnessMipmapper.js b/examples/js/utils/RoughnessMipmapper.js deleted file mode 100644 index 38b90c23c63b4c..00000000000000 --- a/examples/js/utils/RoughnessMipmapper.js +++ /dev/null @@ -1,266 +0,0 @@ -( function () { - - /** - * This class generates custom mipmaps for a roughness map by encoding the lost variation in the - * normal map mip levels as increased roughness in the corresponding roughness mip levels. This - * helps with rendering accuracy for MeshStandardMaterial, and also helps with anti-aliasing when - * using PMREM. If the normal map is larger than the roughness map, the roughness map will be - * enlarged to match the dimensions of the normal map. - */ - - const _mipmapMaterial = _getMipmapMaterial(); - - const _mesh = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), _mipmapMaterial ); - - const _flatCamera = new THREE.OrthographicCamera( 0, 1, 0, 1, 0, 1 ); - - let _tempTarget = null; - let _renderer = null; - - class RoughnessMipmapper { - - constructor( renderer ) { - - _renderer = renderer; - - _renderer.compile( _mesh, _flatCamera ); - - } - - generateMipmaps( material ) { - - if ( 'roughnessMap' in material === false ) return; - const { - roughnessMap, - normalMap - } = material; - if ( roughnessMap === null || normalMap === null || ! roughnessMap.generateMipmaps || material.userData.roughnessUpdated ) return; - material.userData.roughnessUpdated = true; - let width = Math.max( roughnessMap.image.width, normalMap.image.width ); - let height = Math.max( roughnessMap.image.height, normalMap.image.height ); - if ( ! THREE.MathUtils.isPowerOfTwo( width ) || ! THREE.MathUtils.isPowerOfTwo( height ) ) return; - - const oldTarget = _renderer.getRenderTarget(); - - const autoClear = _renderer.autoClear; - _renderer.autoClear = false; - - if ( _tempTarget === null || _tempTarget.width !== width || _tempTarget.height !== height ) { - - if ( _tempTarget !== null ) _tempTarget.dispose(); - _tempTarget = new THREE.WebGLRenderTarget( width, height, { - depthBuffer: false - } ); - _tempTarget.scissorTest = true; - - } - - const newRoughnessTexture = new THREE.FramebufferTexture( width, height, roughnessMap.format ); - newRoughnessTexture.wrapS = roughnessMap.wrapS; - newRoughnessTexture.wrapT = roughnessMap.wrapT; - newRoughnessTexture.minFilter = roughnessMap.minFilter; - newRoughnessTexture.magFilter = roughnessMap.magFilter; - material.roughnessMap = newRoughnessTexture; - if ( material.metalnessMap == roughnessMap ) material.metalnessMap = material.roughnessMap; - if ( material.aoMap == roughnessMap ) material.aoMap = material.roughnessMap; // Copy UV transform parameters - - material.roughnessMap.offset.copy( roughnessMap.offset ); - material.roughnessMap.repeat.copy( roughnessMap.repeat ); - material.roughnessMap.center.copy( roughnessMap.center ); - material.roughnessMap.rotation = roughnessMap.rotation; - material.roughnessMap.matrixAutoUpdate = roughnessMap.matrixAutoUpdate; - material.roughnessMap.matrix.copy( roughnessMap.matrix ); - _mipmapMaterial.uniforms.roughnessMap.value = roughnessMap; - _mipmapMaterial.uniforms.normalMap.value = normalMap; - const position = new THREE.Vector2( 0, 0 ); - const texelSize = _mipmapMaterial.uniforms.texelSize.value; - - for ( let mip = 0; width >= 1 && height >= 1; ++ mip, width /= 2, height /= 2 ) { - - // Rendering to a mip level is not allowed in webGL1. Instead we must set - // up a secondary texture to write the result to, then copy it back to the - // proper mipmap level. - texelSize.set( 1.0 / width, 1.0 / height ); - if ( mip == 0 ) texelSize.set( 0.0, 0.0 ); - - _tempTarget.viewport.set( position.x, position.y, width, height ); - - _tempTarget.scissor.set( position.x, position.y, width, height ); - - _renderer.setRenderTarget( _tempTarget ); - - _renderer.render( _mesh, _flatCamera ); - - _renderer.copyFramebufferToTexture( position, material.roughnessMap, mip ); - - _mipmapMaterial.uniforms.roughnessMap.value = material.roughnessMap; - - } - - roughnessMap.dispose(); - - _renderer.setRenderTarget( oldTarget ); - - _renderer.autoClear = autoClear; - - } - - dispose() { - - _mipmapMaterial.dispose(); - - _mesh.geometry.dispose(); - - if ( _tempTarget != null ) _tempTarget.dispose(); - - } - - } - - function _getMipmapMaterial() { - - const shaderMaterial = new THREE.RawShaderMaterial( { - uniforms: { - roughnessMap: { - value: null - }, - normalMap: { - value: null - }, - texelSize: { - value: new THREE.Vector2( 1, 1 ) - } - }, - vertexShader: - /* glsl */ - ` - precision mediump float; - precision mediump int; - - attribute vec3 position; - attribute vec2 uv; - - varying vec2 vUv; - - void main() { - - vUv = uv; - - gl_Position = vec4( position, 1.0 ); - - } - `, - fragmentShader: - /* glsl */ - ` - precision mediump float; - precision mediump int; - - varying vec2 vUv; - - uniform sampler2D roughnessMap; - uniform sampler2D normalMap; - uniform vec2 texelSize; - - #define ENVMAP_TYPE_CUBE_UV - - vec4 envMapTexelToLinear( vec4 a ) { return a; } - - #include - - float roughnessToVariance( float roughness ) { - - float variance = 0.0; - - if ( roughness >= r1 ) { - - variance = ( r0 - roughness ) * ( v1 - v0 ) / ( r0 - r1 ) + v0; - - } else if ( roughness >= r4 ) { - - variance = ( r1 - roughness ) * ( v4 - v1 ) / ( r1 - r4 ) + v1; - - } else if ( roughness >= r5 ) { - - variance = ( r4 - roughness ) * ( v5 - v4 ) / ( r4 - r5 ) + v4; - - } else { - - float roughness2 = roughness * roughness; - - variance = 1.79 * roughness2 * roughness2; - - } - - return variance; - - } - - float varianceToRoughness( float variance ) { - - float roughness = 0.0; - - if ( variance >= v1 ) { - - roughness = ( v0 - variance ) * ( r1 - r0 ) / ( v0 - v1 ) + r0; - - } else if ( variance >= v4 ) { - - roughness = ( v1 - variance ) * ( r4 - r1 ) / ( v1 - v4 ) + r1; - - } else if ( variance >= v5 ) { - - roughness = ( v4 - variance ) * ( r5 - r4 ) / ( v4 - v5 ) + r4; - - } else { - - roughness = pow( 0.559 * variance, 0.25 ); // 0.559 = 1.0 / 1.79 - - } - - return roughness; - - } - - void main() { - - gl_FragColor = texture2D( roughnessMap, vUv, - 1.0 ); - - if ( texelSize.x == 0.0 ) return; - - float roughness = gl_FragColor.g; - - float variance = roughnessToVariance( roughness ); - - vec3 avgNormal; - - for ( float x = - 1.0; x < 2.0; x += 2.0 ) { - - for ( float y = - 1.0; y < 2.0; y += 2.0 ) { - - vec2 uv = vUv + vec2( x, y ) * 0.25 * texelSize; - - avgNormal += normalize( texture2D( normalMap, uv, - 1.0 ).xyz - 0.5 ); - - } - - } - - variance += 1.0 - 0.25 * length( avgNormal ); - - gl_FragColor.g = varianceToRoughness( variance ); - - } - `, - blending: THREE.NoBlending, - depthTest: false, - depthWrite: false - } ); - shaderMaterial.type = 'RoughnessMipmapper'; - return shaderMaterial; - - } - - THREE.RoughnessMipmapper = RoughnessMipmapper; - -} )(); diff --git a/examples/jsm/animation/CCDIKSolver.js b/examples/jsm/animation/CCDIKSolver.js index 9fad4bdc72d677..1de2fdf2785d46 100644 --- a/examples/jsm/animation/CCDIKSolver.js +++ b/examples/jsm/animation/CCDIKSolver.js @@ -149,7 +149,6 @@ class CCDIKSolver { angle = math.acos( angle ); // skip if changing angle is too small to prevent vibration of bone - // Refer to http://www20.atpages.jp/katwat/three.js_r58/examples/mytest37/mmd.three.js if ( angle < 1e-5 ) continue; if ( ik.minAngle !== undefined && angle < ik.minAngle ) { diff --git a/examples/jsm/animation/MMDPhysics.js b/examples/jsm/animation/MMDPhysics.js index 2c7720a5fba76c..6ea434da1a7c62 100644 --- a/examples/jsm/animation/MMDPhysics.js +++ b/examples/jsm/animation/MMDPhysics.js @@ -894,7 +894,7 @@ class RigidBody { return new Ammo.btCapsuleShape( p.width, p.height ); default: - throw 'unknown shape type ' + p.shapeType; + throw new Error( 'unknown shape type ' + p.shapeType ); } @@ -1203,7 +1203,6 @@ class Constraint { for ( let i = 0; i < 6; i ++ ) { - // this parameter is from http://www20.atpages.jp/katwat/three.js_r58/examples/mytest37/mmd.three.js constraint.setParam( 2, 0.475, i ); } @@ -1368,7 +1367,6 @@ class MMDPhysicsHelper extends Object3D { } - // copy from http://www20.atpages.jp/katwat/three.js_r58/examples/mytest37/mytest37.js?ver=20160815 function createCapsuleGeometry( radius, cylinderHeight, segmentsRadius, segmentsHeight ) { var geometry = new CylinderGeometry( radius, radius, cylinderHeight, segmentsRadius, segmentsHeight, true ); diff --git a/examples/jsm/capabilities/ImportMaps.js b/examples/jsm/capabilities/ImportMaps.js new file mode 100644 index 00000000000000..a88cb4deb561c0 --- /dev/null +++ b/examples/jsm/capabilities/ImportMaps.js @@ -0,0 +1,32 @@ +class ImportMaps { + + static isAvailable() { + + return ( 'supports' in HTMLScriptElement && HTMLScriptElement.supports( 'importmap' ) ); + + } + + static getErrorMessage() { + + const message = 'Your browser does not support Import Maps'; + + const element = document.createElement( 'div' ); + element.style.fontFamily = 'monospace'; + element.style.fontSize = '13px'; + element.style.fontWeight = 'normal'; + element.style.textAlign = 'center'; + element.style.background = '#fff'; + element.style.color = '#000'; + element.style.padding = '1.5em'; + element.style.width = '400px'; + element.style.margin = '5em auto 0'; + + element.innerHTML = message; + + return element; + + } + +} + +export default ImportMaps; diff --git a/examples/jsm/WebGL.js b/examples/jsm/capabilities/WebGL.js similarity index 97% rename from examples/jsm/WebGL.js rename to examples/jsm/capabilities/WebGL.js index dc18eaa8aa7479..08666feb103f91 100644 --- a/examples/jsm/WebGL.js +++ b/examples/jsm/capabilities/WebGL.js @@ -1,4 +1,4 @@ -class WEBGL { +class WebGL { static isWebGLAvailable() { @@ -88,4 +88,4 @@ class WEBGL { } -export { WEBGL }; +export default WebGL; diff --git a/examples/jsm/renderers/webgpu/WebGPU.js b/examples/jsm/capabilities/WebGPU.js similarity index 91% rename from examples/jsm/renderers/webgpu/WebGPU.js rename to examples/jsm/capabilities/WebGPU.js index fff6e9d3600a57..5351ea38e23c51 100644 --- a/examples/jsm/renderers/webgpu/WebGPU.js +++ b/examples/jsm/capabilities/WebGPU.js @@ -8,7 +8,7 @@ class WebGPU { static getErrorMessage() { - const message = 'Your browser does not support WebGPU.'; + const message = 'Your browser does not support WebGPU'; const element = document.createElement( 'div' ); element.id = 'webgpumessage'; diff --git a/examples/jsm/controls/ArcballControls.js b/examples/jsm/controls/ArcballControls.js index b31c57b4495d09..a6fb3a109dd845 100644 --- a/examples/jsm/controls/ArcballControls.js +++ b/examples/jsm/controls/ArcballControls.js @@ -67,7 +67,9 @@ const _endEvent = { type: 'end' }; const _raycaster = new Raycaster(); const _offset = new Vector3(); - +const _gizmoMatrixStateTemp = new Matrix4(); +const _cameraMatrixStateTemp = new Matrix4(); +const _scalePointTemp = new Vector3(); /** * * @param {Camera} camera Virtual camera used in the scene @@ -82,7 +84,8 @@ class ArcballControls extends EventDispatcher { this.camera = null; this.domElement = domElement; this.scene = scene; - this.target = new Vector3( 0, 0, 0 ); + this.target = new Vector3(); + this._currentTarget = new Vector3(); this.radiusFactor = 0.67; this.mouseActions = []; @@ -232,7 +235,6 @@ class ArcballControls extends EventDispatcher { this.domElement.addEventListener( 'pointerdown', this.onPointerDown ); this.domElement.addEventListener( 'pointercancel', this.onPointerCancel ); - window.addEventListener( 'keydown', this.onKeyDown ); window.addEventListener( 'resize', this.onWindowResize ); } @@ -774,28 +776,6 @@ class ArcballControls extends EventDispatcher { }; - onKeyDown = ( event ) => { - - if ( event.key == 'c' ) { - - if ( event.ctrlKey || event.metaKey ) { - - this.copyState(); - - } - - } else if ( event.key == 'v' ) { - - if ( event.ctrlKey || event.metaKey ) { - - this.pasteState(); - - } - - } - - }; - onSinglePanStart = ( event, operation ) => { if ( this.enabled ) { @@ -2006,11 +1986,11 @@ class ArcballControls extends EventDispatcher { _offset.copy( point ).sub( this._gizmos.position ).multiplyScalar( amount ); this._translationMatrix.makeTranslation( _offset.x, _offset.y, _offset.z ); - const gizmoStateTemp = this._gizmoMatrixState.clone(); + _gizmoMatrixStateTemp.copy( this._gizmoMatrixState ); this._gizmoMatrixState.premultiply( this._translationMatrix ); this._gizmoMatrixState.decompose( this._gizmos.position, this._gizmos.quaternion, this._gizmos.scale ); - const cameraStateTemp = this._cameraMatrixState.clone(); + _cameraMatrixStateTemp.copy( this._cameraMatrixState ); this._cameraMatrixState.premultiply( this._translationMatrix ); this._cameraMatrixState.decompose( this.camera.position, this.camera.quaternion, this.camera.scale ); @@ -2021,8 +2001,8 @@ class ArcballControls extends EventDispatcher { } - this._gizmoMatrixState.copy( gizmoStateTemp ); - this._cameraMatrixState.copy( cameraStateTemp ); + this._gizmoMatrixState.copy( _gizmoMatrixStateTemp ); + this._cameraMatrixState.copy( _cameraMatrixStateTemp ); }; @@ -2098,7 +2078,6 @@ class ArcballControls extends EventDispatcher { window.removeEventListener( 'pointerup', this.onPointerUp ); window.removeEventListener( 'resize', this.onWindowResize ); - window.removeEventListener( 'keydown', this.onKeyDown ); if ( this.scene !== null ) this.scene.remove( this._gizmos ); this.disposeGrid(); @@ -2623,7 +2602,7 @@ class ArcballControls extends EventDispatcher { */ scale = ( size, point, scaleGizmos = true ) => { - const scalePoint = point.clone(); + _scalePointTemp.copy( point ); let sizeInverse = 1 / size; if ( this.camera.isOrthographicCamera ) { @@ -2658,12 +2637,12 @@ class ArcballControls extends EventDispatcher { //move camera and gizmos to obtain pinch effect - scalePoint.sub( this._v3_1 ); + _scalePointTemp.sub( this._v3_1 ); - const amount = scalePoint.clone().multiplyScalar( sizeInverse ); - scalePoint.sub( amount ); + const amount = _scalePointTemp.clone().multiplyScalar( sizeInverse ); + _scalePointTemp.sub( amount ); - this._m4_1.makeTranslation( scalePoint.x, scalePoint.y, scalePoint.z ); + this._m4_1.makeTranslation( _scalePointTemp.x, _scalePointTemp.y, _scalePointTemp.z ); this._m4_2.premultiply( this._m4_1 ); this.setTransformationMatrices( this._m4_1, this._m4_2 ); @@ -2675,7 +2654,7 @@ class ArcballControls extends EventDispatcher { this._v3_2.setFromMatrixPosition( this._gizmoMatrixState ); //move camera - let distance = this._v3_1.distanceTo( scalePoint ); + let distance = this._v3_1.distanceTo( _scalePointTemp ); let amount = distance - ( distance * sizeInverse ); //check min and max distance @@ -2692,7 +2671,7 @@ class ArcballControls extends EventDispatcher { } - _offset.copy( scalePoint ).sub( this._v3_1 ).normalize().multiplyScalar( amount ); + _offset.copy( _scalePointTemp ).sub( this._v3_1 ).normalize().multiplyScalar( amount ); this._m4_1.makeTranslation( _offset.x, _offset.y, _offset.z ); @@ -2702,9 +2681,9 @@ class ArcballControls extends EventDispatcher { //scale gizmos so they appear in the same spot having the same dimension const pos = this._v3_2; - distance = pos.distanceTo( scalePoint ); + distance = pos.distanceTo( _scalePointTemp ); amount = distance - ( distance * sizeInverse ); - _offset.copy( scalePoint ).sub( this._v3_2 ).normalize().multiplyScalar( amount ); + _offset.copy( _scalePointTemp ).sub( this._v3_2 ).normalize().multiplyScalar( amount ); this._translationMatrix.makeTranslation( pos.x, pos.y, pos.z ); this._scaleMatrix.makeScale( sizeInverse, sizeInverse, sizeInverse ); @@ -2745,23 +2724,6 @@ class ArcballControls extends EventDispatcher { }; - /** - * Set the trackball's center point - * @param {Number} x X coordinate - * @param {Number} y Y coordinate - * @param {Number} z Z coordinate - */ - setTarget = ( x, y, z ) => { - - this.target.set( x, y, z ); - this._gizmos.position.set( x, y, z ); //for correct radius calculation - this._tbRadius = this.calculateTbRadius( this.camera ); - - this.makeGizmos( this.target, this._tbRadius ); - this.camera.lookAt( this.target ); - - }; - /** * Set values in transformation object * @param {Matrix4} camera Transformation to be applied to the camera @@ -3123,6 +3085,15 @@ class ArcballControls extends EventDispatcher { const EPS = 0.000001; + if ( this.target.equals( this._currentTarget ) === false ) { + + this._gizmos.position.copy( this.target ); //for correct radius calculation + this._tbRadius = this.calculateTbRadius( this.camera ); + this.makeGizmos( this.target, this._tbRadius ); + this._currentTarget.copy( this.target ); + + } + //check min/max parameters if ( this.camera.isOrthographicCamera ) { diff --git a/examples/jsm/controls/TransformControls.js b/examples/jsm/controls/TransformControls.js index 76f949f3820565..7069c6313879b3 100644 --- a/examples/jsm/controls/TransformControls.js +++ b/examples/jsm/controls/TransformControls.js @@ -688,7 +688,11 @@ function onPointerDown( event ) { if ( ! this.enabled ) return; - this.domElement.setPointerCapture( event.pointerId ); + if ( ! document.pointerLockElement ) { + + this.domElement.setPointerCapture( event.pointerId ); + + } this.domElement.addEventListener( 'pointermove', this._onPointerMove ); diff --git a/examples/jsm/curves/CurveExtras.js b/examples/jsm/curves/CurveExtras.js index ba41152fce1188..9b14df63e623ea 100644 --- a/examples/jsm/curves/CurveExtras.js +++ b/examples/jsm/curves/CurveExtras.js @@ -8,9 +8,7 @@ import { * * Formulas collected from various sources * http://mathworld.wolfram.com/HeartCurve.html - * http://mathdl.maa.org/images/upload_library/23/stemkoski/knots/page6.html * http://en.wikipedia.org/wiki/Viviani%27s_curve - * http://mathdl.maa.org/images/upload_library/23/stemkoski/knots/page4.html * http://www.mi.sanu.ac.rs/vismath/taylorapril2011/Taylor.pdf * https://prideout.net/blog/old/blog/index.html@p=44.html */ diff --git a/examples/jsm/effects/AsciiEffect.js b/examples/jsm/effects/AsciiEffect.js index 32c8a5506b3ff7..7ce14525196b26 100644 --- a/examples/jsm/effects/AsciiEffect.js +++ b/examples/jsm/effects/AsciiEffect.js @@ -56,13 +56,7 @@ class AsciiEffect { this.domElement = domElement; - // Throw in ascii library from https://github.com/hassadee/jsascii/blob/master/jsascii.js - - /* - * jsAscii 0.1 - * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/ - * MIT License [http://www.nihilogic.dk/licenses/mit-license.txt] - */ + // Throw in ascii library from https://github.com/hassadee/jsascii/blob/master/jsascii.js (MIT License) function initAsciiSize() { diff --git a/examples/jsm/exporters/GLTFExporter.js b/examples/jsm/exporters/GLTFExporter.js index 6124560a75e0eb..798a84d1ae5842 100644 --- a/examples/jsm/exporters/GLTFExporter.js +++ b/examples/jsm/exporters/GLTFExporter.js @@ -2199,7 +2199,7 @@ class GLTFMaterialsUnlitExtension { /** * Specular-Glossiness Extension * - * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness + * Specification: https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Archived/KHR_materials_pbrSpecularGlossiness */ class GLTFMaterialsPBRSpecularGlossiness { diff --git a/examples/jsm/exporters/MMDExporter.js b/examples/jsm/exporters/MMDExporter.js index 15b24e357d5261..cc558f56468d9b 100644 --- a/examples/jsm/exporters/MMDExporter.js +++ b/examples/jsm/exporters/MMDExporter.js @@ -186,7 +186,7 @@ function unicodeToShiftjis( str ) { if ( value === undefined ) { - throw 'cannot convert charcode 0x' + code.toString( 16 ); + throw new Error( 'cannot convert charcode 0x' + code.toString( 16 ) ); } else if ( value > 0xff ) { diff --git a/examples/jsm/geometries/TeapotGeometry.js b/examples/jsm/geometries/TeapotGeometry.js index 3f621653d519b0..fc1a4ecee34ddc 100644 --- a/examples/jsm/geometries/TeapotGeometry.js +++ b/examples/jsm/geometries/TeapotGeometry.js @@ -48,7 +48,6 @@ import { * * Code converted from my ancient SPD software, http://tog.acm.org/resources/SPD/ * Created for the Udacity course "Interactive Rendering", http://bit.ly/ericity - * Lesson: https://www.udacity.com/course/viewer#!/c-cs291/l-68866048/m-106482448 * YouTube video on teapot history: https://www.youtube.com/watch?v=DxMfblPzFNc * * See https://en.wikipedia.org/wiki/Utah_teapot for the history of the teapot diff --git a/examples/jsm/libs/lil-gui.module.min.js b/examples/jsm/libs/lil-gui.module.min.js index f27672682266ba..877ffbd605d5d0 100644 --- a/examples/jsm/libs/lil-gui.module.min.js +++ b/examples/jsm/libs/lil-gui.module.min.js @@ -1,8 +1,8 @@ /** * lil-gui * https://lil-gui.georgealways.com - * @version 0.11.0 + * @version 0.16.0 * @author George Michael Brower * @license MIT */ -class t{constructor(e,i,s,r,n="div"){this.parent=e,this.object=i,this.property=s,this._disabled=!1,this.initialValue=this.getValue(),this.domElement=document.createElement("div"),this.domElement.classList.add("controller"),this.domElement.classList.add(r),this.$name=document.createElement("div"),this.$name.classList.add("name"),t.nextNameID=t.nextNameID||0,this.$name.id="lil-gui-name-"+ ++t.nextNameID,this.$widget=document.createElement(n),this.$widget.classList.add("widget"),this.$disable=this.$widget,this.domElement.appendChild(this.$name),this.domElement.appendChild(this.$widget),this.parent.children.push(this),this.parent.controllers.push(this),this.parent.$children.appendChild(this.domElement),this._listenCallback=this._listenCallback.bind(this),this.name(s)}name(t){return this._name=t,this.$name.innerHTML=t,this}onChange(t){return this._onChange=t,this}_callOnChange(){this.parent._callOnChange(this),void 0!==this._onChange&&this._onChange.call(this,this.getValue())}onFinishChange(t){return this.onChange(t)}reset(){return this.setValue(this.initialValue),this}enable(t=!0){return this.disable(!t)}disable(t=!0){return t===this._disabled||(this._disabled=t,this.domElement.classList.toggle("disabled",t),t?this.$disable.setAttribute("disabled","disabled"):this.$disable.removeAttribute("disabled")),this}options(t){const e=this.parent.add(this.object,this.property,t);return e.name(this._name),this.destroy(),e}min(t){return this}max(t){return this}step(t){return this}listen(t=!0){return this._listening=t,void 0!==this._listenCallbackID&&(cancelAnimationFrame(this._listenCallbackID),this._listenCallbackID=void 0),this._listening&&this._listenCallback(),this}_listenCallback(){this._listenCallbackID=requestAnimationFrame(this._listenCallback);const t=this.getValue();t===this._listenValuePrev&&Object(t)!==t||this.updateDisplay(),this._listenValuePrev=t}getValue(){return this.object[this.property]}setValue(t){return this.object[this.property]=t,this._callOnChange(),this.updateDisplay(),this}updateDisplay(){return this}load(t){this.setValue(t)}save(){return this.getValue()}destroy(){this.parent.children.splice(this.parent.children.indexOf(this),1),this.parent.controllers.splice(this.parent.controllers.indexOf(this),1),this.parent.$children.removeChild(this.domElement)}}class e extends t{constructor(t,e,i){super(t,e,i,"boolean","label"),this.$input=document.createElement("input"),this.$input.setAttribute("type","checkbox"),this.$widget.appendChild(this.$input),this.$input.addEventListener("change",()=>{this.setValue(this.$input.checked)}),this.$disable=this.$input,this.updateDisplay()}updateDisplay(){return this.$input.checked=this.getValue(),this}}function i(t){let e,i;return(e=t.match(/(#|0x)?([a-f0-9]{6})/i))?i=e[2]:(e=t.match(/rgb\(\s*(\d*)\s*,\s*(\d*)\s*,\s*(\d*)\s*\)/))?i=parseInt(e[1]).toString(16).padStart(2,0)+parseInt(e[2]).toString(16).padStart(2,0)+parseInt(e[3]).toString(16).padStart(2,0):(e=t.match(/^#?([a-f0-9])([a-f0-9])([a-f0-9])$/i))&&(i=e[1]+e[1]+e[2]+e[2]+e[3]+e[3]),!!i&&"#"+i}const s={isPrimitive:!0,match:t=>"string"==typeof t,fromHexString:i,toHexString:i},r={isPrimitive:!0,match:t=>"number"==typeof t,fromHexString:t=>parseInt(t.substring(1),16),toHexString:t=>"#"+t.toString(16).padStart(6,0)},n={isPrimitive:!1,match:Array.isArray,fromHexString(t,e,i=1){const s=r.fromHexString(t);e[0]=(s>>16&255)/255*i,e[1]=(s>>8&255)/255*i,e[2]=(255&s)/255*i},toHexString:([t,e,i],s=1)=>r.toHexString(t*(s=255/s)<<16^e*s<<8^i*s<<0)},l={isPrimitive:!1,match:t=>Object(t)===t,fromHexString(t,e,i=1){const s=r.fromHexString(t);e.r=(s>>16&255)/255*i,e.g=(s>>8&255)/255*i,e.b=(255&s)/255*i},toHexString:({r:t,g:e,b:i},s=1)=>r.toHexString(t*(s=255/s)<<16^e*s<<8^i*s<<0)},o=[s,r,n,l];class a extends t{constructor(t,e,s,r){var n;super(t,e,s,"color"),this.$input=document.createElement("input"),this.$input.setAttribute("type","color"),this.$input.setAttribute("tabindex",-1),this.$input.setAttribute("aria-labelledby",this.$name.id),this.$text=document.createElement("input"),this.$text.setAttribute("type","text"),this.$text.setAttribute("spellcheck","false"),this.$text.setAttribute("aria-labelledby",this.$name.id),this.$display=document.createElement("div"),this.$display.classList.add("display"),this.$display.appendChild(this.$input),this.$widget.appendChild(this.$display),this.$widget.appendChild(this.$text),this._format=(n=this.initialValue,o.find(t=>t.match(n))),this._rgbScale=r,this._initialValueHexString=this.save(),this._textFocused=!1;const l=()=>{this._setValueFromHexString(this.$input.value)};this.$input.addEventListener("change",l),this.$input.addEventListener("input",l),this.$input.addEventListener("focus",()=>{this.$display.classList.add("focus")}),this.$input.addEventListener("blur",()=>{this.$display.classList.remove("focus")}),this.$text.addEventListener("input",()=>{const t=i(this.$text.value);t&&this._setValueFromHexString(t)}),this.$text.addEventListener("focus",()=>{this._textFocused=!0,this.$text.select()}),this.$text.addEventListener("blur",()=>{this._textFocused=!1,this.updateDisplay()}),this.$disable=this.$text,this.updateDisplay()}reset(){return this._setValueFromHexString(this._initialValueHexString),this}_setValueFromHexString(t){if(this._format.isPrimitive){const e=this._format.fromHexString(t);this.setValue(e)}else this._format.fromHexString(t,this.getValue(),this._rgbScale),this._callOnChange(),this.updateDisplay()}save(){return this._format.toHexString(this.getValue(),this._rgbScale)}load(t){this._setValueFromHexString(t)}updateDisplay(){return this.$input.value=this._format.toHexString(this.getValue(),this._rgbScale),this._textFocused||(this.$text.value=this.$input.value.substring(1)),this.$display.style.backgroundColor=this.$input.value,this}}class h extends t{constructor(t,e,i){super(t,e,i,"function"),this.$button=document.createElement("button"),this.$button.appendChild(this.$name),this.$widget.appendChild(this.$button),this.$button.addEventListener("click",t=>{t.preventDefault(),this.getValue().call(this.object)}),this.$button.addEventListener("touchstart",()=>{}),this.$disable=this.$button}}class d extends t{constructor(t,e,i,s,r,n){super(t,e,i,"number"),this._initInput(),this.min(s),this.max(r);const l=void 0!==n;this.step(l?n:this._getImplicitStep(),l),this.updateDisplay()}min(t){return this._min=t,this._onUpdateMinMax(),this}max(t){return this._max=t,this._onUpdateMinMax(),this}step(t,e=!0){return this._step=t,this._stepExplicit=e,this}updateDisplay(){const t=this.getValue();if(this._hasSlider){const e=(t-this._min)/(this._max-this._min);this.$fill.style.setProperty("width",100*e+"%")}return this._inputFocused||(this.$input.value=t),this}_initInput(){this.$input=document.createElement("input"),this.$input.setAttribute("type","text"),this.$input.setAttribute("inputmode","numeric"),this.$input.setAttribute("aria-labelledby",this.$name.id),this.$widget.appendChild(this.$input),this.$disable=this.$input;const t=t=>{const e=parseFloat(this.$input.value);isNaN(e)||(this._snapClampSetValue(e+t),this.$input.value=this.getValue())};this.$input.addEventListener("focus",()=>{this._inputFocused=!0}),this.$input.addEventListener("input",()=>{const t=parseFloat(this.$input.value);isNaN(t)||this.setValue(this._clamp(t))}),this.$input.addEventListener("blur",()=>{this._inputFocused=!1,this.updateDisplay()}),this.$input.addEventListener("keydown",e=>{"Enter"===e.code&&this.$input.blur(),"ArrowUp"===e.code&&(e.preventDefault(),t(this._step*this._arrowKeyMultiplier(e))),"ArrowDown"===e.code&&(e.preventDefault(),t(-1*this._step*this._arrowKeyMultiplier(e)))}),this.$input.addEventListener("wheel",e=>{this._inputFocused&&(e.preventDefault(),t(this._normalizeMouseWheel(e)*this._step))},{passive:!1})}_initSlider(){this._hasSlider=!0,this.$slider=document.createElement("div"),this.$slider.classList.add("slider"),this.$fill=document.createElement("div"),this.$fill.classList.add("fill"),this.$slider.appendChild(this.$fill),this.$widget.insertBefore(this.$slider,this.$input),this.domElement.classList.add("hasSlider");const t=t=>{const e=this.$slider.getBoundingClientRect();let i=(s=t,r=e.left,n=e.right,l=this._min,o=this._max,(s-r)/(n-r)*(o-l)+l);var s,r,n,l,o;this._snapClampSetValue(i)},e=e=>{t(e.clientX)},i=()=>{this._setActiveStyle(!1),window.removeEventListener("mousemove",e),window.removeEventListener("mouseup",i)};this.$slider.addEventListener("mousedown",s=>{t(s.clientX),this._setActiveStyle(!0),window.addEventListener("mousemove",e),window.addEventListener("mouseup",i)});let s,r,n=!1;const l=e=>{if(n){const i=e.touches[0].clientX-s,a=e.touches[0].clientY-r;Math.abs(i)>Math.abs(a)?(e.preventDefault(),t(e.touches[0].clientX),this._setActiveStyle(!0),n=!1):(window.removeEventListener("touchmove",l),window.removeEventListener("touchend",o))}else e.preventDefault(),t(e.touches[0].clientX)},o=()=>{this._setActiveStyle(!1),window.removeEventListener("touchmove",l),window.removeEventListener("touchend",o)};this.$slider.addEventListener("touchstart",e=>{e.touches.length>1||(this._hasScrollBar?(s=e.touches[0].clientX,r=e.touches[0].clientY,n=!0):(e.preventDefault(),t(e.touches[0].clientX),this._setActiveStyle(!0),n=!1),window.addEventListener("touchmove",l,{passive:!1}),window.addEventListener("touchend",o))});this.$slider.addEventListener("wheel",t=>{if(Math.abs(t.deltaX)t.clientHeight}get _hasMin(){return void 0!==this._min}get _hasMax(){return void 0!==this._max}}class c extends t{constructor(t,e,i,s){super(t,e,i,"option"),this.$select=document.createElement("select"),this.$select.setAttribute("aria-labelledby",this.$name.id),this.$display=document.createElement("div"),this.$display.classList.add("display"),this._values=Array.isArray(s)?s:Object.values(s),this._names=Array.isArray(s)?s:Object.keys(s),this._names.forEach(t=>{const e=document.createElement("option");e.innerHTML=t,this.$select.appendChild(e)}),this.$select.addEventListener("change",()=>{this.setValue(this._values[this.$select.selectedIndex])}),this.$select.addEventListener("focus",()=>{this.$display.classList.add("focus")}),this.$select.addEventListener("blur",()=>{this.$display.classList.remove("focus")}),this.$widget.appendChild(this.$select),this.$widget.appendChild(this.$display),this.$disable=this.$select,this.updateDisplay()}updateDisplay(){const t=this.getValue(),e=this._values.indexOf(t);return this.$select.selectedIndex=e,this.$display.innerHTML=-1===e?t:this._names[e],this}}class u extends t{constructor(t,e,i){super(t,e,i,"string"),this.$input=document.createElement("input"),this.$input.setAttribute("type","text"),this.$input.setAttribute("aria-labelledby",this.$name.id),this.$input.addEventListener("input",()=>{this.setValue(this.$input.value)}),this.$input.addEventListener("keydown",t=>{"Enter"===t.code&&this.$input.blur()}),this.$widget.appendChild(this.$input),this.$disable=this.$input,this.updateDisplay()}updateDisplay(){return this.$input.value=this.getValue(),this}}let p=!1;class g{constructor({parent:t,autoPlace:e=void 0===t,touchStyles:i=!0,container:s,injectStyles:r=!0,title:n="Controls",width:l}={}){if(this.parent=t,this.root=t?t.root:this,this.children=[],this.controllers=[],this.folders=[],this._closed=!1,this.domElement=document.createElement("div"),this.domElement.classList.add("lil-gui"),this.$title=document.createElement("div"),this.$title.classList.add("title"),this.$title.setAttribute("role","button"),this.$title.setAttribute("aria-expanded",!0),this.$title.setAttribute("tabindex",0),this.$title.addEventListener("click",()=>this.openAnimated(this._closed)),this.$title.addEventListener("keydown",t=>{"Enter"!==t.code&&"Space"!==t.code||(t.preventDefault(),this.$title.click())}),this.$title.addEventListener("touchstart",()=>{}),this.$children=document.createElement("div"),this.$children.classList.add("children"),this.domElement.appendChild(this.$title),this.domElement.appendChild(this.$children),this.title(n),this.parent)return this.parent.children.push(this),this.parent.folders.push(this),void this.parent.$children.appendChild(this.domElement);this.domElement.classList.add("root"),!p&&r&&(!function(t){const e=document.createElement("style");e.innerHTML=t;const i=document.querySelector("head link[rel=stylesheet], head style");i?document.head.insertBefore(e,i):document.head.appendChild(e)}('.lil-gui{font-family:var(--font-family);font-size:var(--font-size);line-height:1;font-weight:normal;font-style:normal;text-align:left;background-color:var(--background-color);color:var(--text-color);user-select:none;-webkit-user-select:none;touch-action:manipulation;--background-color:#1f1f1f;--text-color:#ebebeb;--title-background-color:#111;--title-text-color:#ebebeb;--widget-color:#424242;--hover-color:#4f4f4f;--focus-color:#595959;--number-color:#2cc9ff;--string-color:#a2db3c;--font-size:11px;--input-font-size:11px;--font-family:-apple-system,BlinkMacSystemFont,"Lucida Grande","Segoe UI",Roboto,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";--font-family-mono:Menlo,Monaco,Consolas,"Droid Sans Mono",monospace,"Droid Sans Fallback";--padding:4px;--spacing:4px;--widget-height:20px;--name-width:45%;--slider-knob-width:2px;--slider-input-width:27%;--color-input-width:27%;--slider-input-min-width:45px;--color-input-min-width:45px;--folder-indent:7px;--widget-padding:0 0 0 3px;--widget-border-radius:2px;--checkbox-size:calc(.75*var(--widget-height));--scrollbar-width: 5px}.lil-gui,.lil-gui *{box-sizing:border-box;margin:0}.lil-gui.root{width:var(--width, 245px);display:flex;flex-direction:column}.lil-gui.root>.title{background:var(--title-background-color);color:var(--title-text-color)}.lil-gui.root>.children{overflow:auto}.lil-gui.root>.children::-webkit-scrollbar{width:var(--scrollbar-width);height:var(--scrollbar-width);background:var(--background-color)}.lil-gui.root>.children::-webkit-scrollbar-thumb{border-radius:var(--scrollbar-width);background:var(--focus-color)}.lil-gui .lil-gui{--background-color:inherit;--text-color:inherit;--title-background-color:inherit;--title-text-color:inherit;--widget-color:inherit;--hover-color:inherit;--focus-color:inherit;--number-color:inherit;--string-color:inherit;--font-size:inherit;--input-font-size:inherit;--font-family:inherit;--font-family-mono:inherit;--padding:inherit;--spacing:inherit;--widget-height:inherit;--name-width:inherit;--slider-knob-width:inherit;--slider-input-width:inherit;--color-input-width:inherit;--slider-input-min-width:inherit;--color-input-min-width:inherit;--folder-indent:inherit;--widget-padding:inherit;--widget-border-radius:inherit;--checkbox-size:inherit}@media(pointer: coarse){.lil-gui.allow-touch-styles{--widget-height: 28px;--padding: 6px;--spacing: 6px;--font-size: 13px;--input-font-size: 16px;--folder-indent: 10px;--widget-padding: 0 0 0 3px;--scrollbar-width: 7px;--slider-input-min-width: 50px;--color-input-min-width: 65px}}.lil-gui.force-touch-styles{--widget-height: 28px;--padding: 6px;--spacing: 6px;--font-size: 13px;--input-font-size: 16px;--folder-indent: 10px;--widget-padding: 0 0 0 3px;--scrollbar-width: 7px;--slider-input-min-width: 50px;--color-input-min-width: 65px}.lil-gui.autoPlace{max-height:100%;position:fixed;top:0;right:15px;z-index:1001}.lil-gui .controller{display:flex;align-items:center;padding:0 var(--padding);margin:var(--spacing) 0}.lil-gui .controller.disabled{opacity:.5}.lil-gui .controller.disabled,.lil-gui .controller.disabled *{pointer-events:none !important}.lil-gui .controller .name{min-width:var(--name-width);flex-shrink:0;white-space:pre;padding-right:var(--spacing);line-height:var(--widget-height)}.lil-gui .controller .widget{position:relative;display:flex;align-items:center;width:100%;min-height:var(--widget-height)}.lil-gui .controller.function .name{line-height:unset;padding:0}.lil-gui .controller.string input{color:var(--string-color)}.lil-gui .controller.boolean .widget{cursor:pointer}.lil-gui .controller.color .display{width:100%;height:var(--widget-height);border-radius:var(--widget-border-radius);position:relative}@media(hover: hover){.lil-gui .controller.color .display:hover:before{content:" ";display:block;position:absolute;border-radius:var(--widget-border-radius);border:1px solid #fff9;left:0;right:0;top:0;bottom:0}}.lil-gui .controller.color input[type=color]{opacity:0;width:100%;height:100%;cursor:pointer}.lil-gui .controller.color input[type=text]{margin-left:var(--spacing);font-family:var(--font-family-mono);min-width:var(--color-input-min-width);width:var(--color-input-width);flex-shrink:0}.lil-gui .controller.option select{opacity:0;position:absolute;width:100%;max-width:100%}.lil-gui .controller.option .display{position:relative;pointer-events:none;border-radius:var(--widget-border-radius);height:var(--widget-height);line-height:var(--widget-height);max-width:100%;overflow:hidden;word-break:break-all;padding-left:.55em;padding-right:1.75em;background:var(--widget-color)}@media(hover: hover){.lil-gui .controller.option .display.focus{background:var(--focus-color)}}.lil-gui .controller.option .display.active{background:var(--focus-color)}.lil-gui .controller.option .display:after{font-family:"lil-gui";content:"↕";position:absolute;top:0;right:0;bottom:0;padding-right:.375em}.lil-gui .controller.option .widget,.lil-gui .controller.option select{cursor:pointer}@media(hover: hover){.lil-gui .controller.option .widget:hover .display{background:var(--hover-color)}}.lil-gui .controller.number input{color:var(--number-color)}.lil-gui .controller.number.hasSlider input{margin-left:var(--spacing);width:var(--slider-input-width);min-width:var(--slider-input-min-width);flex-shrink:0}.lil-gui .controller.number .slider{width:100%;height:var(--widget-height);background-color:var(--widget-color);border-radius:var(--widget-border-radius);padding-right:var(--slider-knob-width);overflow:hidden;cursor:ew-resize;touch-action:pan-y}@media(hover: hover){.lil-gui .controller.number .slider:hover{background-color:var(--hover-color)}}.lil-gui .controller.number .slider.active{background-color:var(--focus-color)}.lil-gui .controller.number .slider.active .fill{opacity:.95}.lil-gui .controller.number .fill{height:100%;border-right:var(--slider-knob-width) solid var(--number-color);box-sizing:content-box}.lil-gui-slider-active .lil-gui{--hover-color: var(--widget-color)}.lil-gui-slider-active *{cursor:ew-resize !important}.lil-gui .title{--title-height: calc(var(--widget-height) + var(--spacing) * 1.25);height:var(--title-height);line-height:calc(var(--title-height) - 4px);font-weight:600;padding:0 var(--padding);-webkit-tap-highlight-color:transparent;cursor:pointer;outline:none;text-decoration-skip:objects}.lil-gui .title:before{font-family:"lil-gui";content:"▾";padding-right:2px;display:inline-block}.lil-gui .title:active{background:var(--title-background-color);opacity:.75}@media(hover: hover){.lil-gui .title:hover{background:var(--title-background-color);opacity:.85}.lil-gui .title:focus{text-decoration:underline var(--focus-color)}}.lil-gui.root>.title:focus{text-decoration:none !important}.lil-gui.closed>.title:before{content:"▸"}.lil-gui.closed>.children{transform:translateY(-7px);opacity:0}.lil-gui.closed:not(.transition)>.children{display:none}.lil-gui.transition>.children{transition-duration:300ms;transition-property:height,opacity,transform;transition-timing-function:cubic-bezier(0.215, 0.61, 0.355, 1);overflow:hidden;pointer-events:none}.lil-gui .children:empty:before{content:"Empty";padding:0 var(--padding);margin:var(--spacing) 0;display:block;height:var(--widget-height);font-style:italic;line-height:var(--widget-height);opacity:.5}.lil-gui.root>.children>.lil-gui>.title{border:0 solid var(--widget-color);border-width:1px 0;transition:border-color 300ms}.lil-gui.root>.children>.lil-gui.closed>.title{border-bottom-color:transparent}.lil-gui+.controller{border-top:1px solid var(--widget-color);margin-top:0;padding-top:var(--spacing)}.lil-gui .lil-gui .lil-gui>.title{border:none}.lil-gui .lil-gui .lil-gui>.children{border:none;margin-left:var(--folder-indent);border-left:2px solid var(--widget-color)}.lil-gui .lil-gui .controller{border:none}.lil-gui input{-webkit-tap-highlight-color:transparent;border:0;outline:none;font-family:var(--font-family);font-size:var(--input-font-size);border-radius:var(--widget-border-radius);height:var(--widget-height);background:var(--widget-color);color:var(--text-color);width:100%}@media(hover: hover){.lil-gui input:hover{background:var(--hover-color)}.lil-gui input:active{background:var(--focus-color)}}.lil-gui input[type=text]{padding:var(--widget-padding)}.lil-gui input[type=text]:focus{background:var(--focus-color)}.lil-gui input[type=checkbox]{appearance:none;-webkit-appearance:none;height:var(--checkbox-size);width:var(--checkbox-size);border-radius:var(--widget-border-radius);text-align:center}.lil-gui input[type=checkbox]:checked:before{font-family:"lil-gui";content:"✓";font-size:var(--checkbox-size);line-height:var(--checkbox-size)}@media(hover: hover){.lil-gui input[type=checkbox]:focus{box-shadow:inset 0 0 0 1px var(--focus-color)}}.lil-gui button{-webkit-tap-highlight-color:transparent;outline:none;cursor:pointer;font-family:var(--font-family);font-size:var(--font-size);color:var(--text-color);width:100%;height:var(--widget-height);text-transform:none;background:var(--widget-color);border-radius:var(--widget-border-radius);border:1px solid var(--widget-color);text-align:center;line-height:calc(var(--widget-height)*.725)}@media(hover: hover){.lil-gui button:hover{background:var(--hover-color);border-color:var(--hover-color)}.lil-gui button:focus{border-color:var(--focus-color)}}.lil-gui button:active{background:var(--focus-color)}@font-face{font-family:"lil-gui";src:url("data:application/font-woff;charset=utf-8;base64,d09GRgABAAAAAAUsAAsAAAAACJwAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAAH4AAADAImwmYE9TLzIAAAGIAAAAPwAAAGBKqH5SY21hcAAAAcgAAAD0AAACrukyyJBnbHlmAAACvAAAAF8AAACEIZ5WI2hlYWQAAAMcAAAAJwAAADZfcj23aGhlYQAAA0QAAAAYAAAAJAC5AHhobXR4AAADXAAAABAAAABMAZAAAGxvY2EAAANsAAAAFAAAACgCEgIybWF4cAAAA4AAAAAeAAAAIAEfABJuYW1lAAADoAAAASIAAAIK9SUU/XBvc3QAAATEAAAAZgAAAJCTcMc2eJxVjbEOgjAURU+hFRBK1dGRL+ALnAiToyMLEzFpnPz/eAshwSa97517c/MwwJmeB9kwPl+0cf5+uGPZXsqPu4nvZabcSZldZ6kfyWnomFY/eScKqZNWupKJO6kXN3K9uCVoL7iInPr1X5baXs3tjuMqCtzEuagm/AAlzQgPAAB4nGNgYRBlnMDAysDAYM/gBiT5oLQBAwuDJAMDEwMrMwNWEJDmmsJwgCFeXZghBcjlZMgFCzOiKOIFAB71Bb8AeJy1kjFuwkAQRZ+DwRAwBtNQRUGKQ8OdKCAWUhAgKLhIuAsVSpWz5Bbkj3dEgYiUIszqWdpZe+Z7/wB1oCYmIoboiwiLT2WjKl/jscrHfGg/pKdMkyklC5Zs2LEfHYpjcRoPzme9MWWmk3dWbK9ObkWkikOetJ554fWyoEsmdSlt+uR0pCJR34b6t/TVg1SY3sYvdf8vuiKrpyaDXDISiegp17p7579Gp3p++y7HPAiY9pmTibljrr85qSidtlg4+l25GLCaS8e6rRxNBmsnERunKbaOObRz7N72ju5vdAjYpBXHgJylOAVsMseDAPEP8LYoUHicY2BiAAEfhjAGJgZWBgZ7RnFRdnVJELCRlBSRlATJMoLV2DK4glSYs6ubq5vbKrJLSbGrgEmovDuDJVhe3VzcXFwNLCOILB/C4IuQ1xTn5FPilBTj5FPmBAB76woyAHicY2BkYGAA4sklsQ/j+W2+MnAzpDBgAyEMYUCSg4EJxAEAvVwFCgB4nGNgZGBgSGFggJMhDIwMqEAYAByHATJ4nGNgAIIUNEwmAABl3AGReJxjYAACIQYlBiMGJ3wQAEcQBEV4nGNgZGBgEGZgY2BiAAEQyQWEDAz/wXwGAAsPATIAAHicXdBNSsNAHAXwl35iA0UQXYnMShfS9GPZA7T7LgIu03SSpkwzYTIt1BN4Ak/gKTyAeCxfw39jZkjymzcvAwmAW/wgwHUEGDb36+jQQ3GXGot79L24jxCP4gHzF/EIr4jEIe7wxhOC3g2TMYy4Q7+Lu/SHuEd/ivt4wJd4wPxbPEKMX3GI5+DJFGaSn4qNzk8mcbKSR6xdXdhSzaOZJGtdapd4vVPbi6rP+cL7TGXOHtXKll4bY1Xl7EGnPtp7Xy2n00zyKLVHfkHBa4IcJ2oD3cgggWvt/V/FbDrUlEUJhTn/0azVWbNTNr0Ens8de1tceK9xZmfB1CPjOmPH4kitmvOubcNpmVTN3oFJyjzCvnmrwhJTzqzVj9jiSX911FjeAAB4nG3HMRKCMBBA0f0giiKi4DU8k0V2GWbIZDOh4PoWWvq6J5V8If9NVNQcaDhyouXMhY4rPTcG7jwYmXhKq8Wz+p762aNaeYXom2n3m2dLTVgsrCgFJ7OTmIkYbwIbC6vIB7WmFfAAAA==") format("woff")}'),p=!0),s?s.appendChild(this.domElement):e&&(this.domElement.classList.add("autoPlace"),document.body.appendChild(this.domElement)),i&&this.domElement.classList.add("allow-touch-styles"),l&&this.domElement.style.setProperty("--width",l+"px")}add(t,i,s,r,n){if(Object(s)===s)return new c(this,t,i,s);const l=t[i];switch(typeof l){case"number":return new d(this,t,i,s,r,n);case"boolean":return new e(this,t,i);case"string":return new u(this,t,i);case"function":return new h(this,t,i)}console.error(`Failed to add controller for "${i}"`,l,t)}addColor(t,e,i=1){return new a(this,t,e,i)}addFolder(t){return new g({parent:this,title:t})}load(t,e=!0){if(!("controllers"in t))throw new Error('Invalid load object. Should contain a "controllers" key.');return this.controllers.forEach(e=>{e instanceof h||e._name in t.controllers&&e.load(t.controllers[e._name])}),e&&t.folders&&this.folders.forEach(e=>{e._title in t.folders&&e.load(t.folders[e._title])}),this}save(t=!0){const e={controllers:{},folders:{}};return this.controllers.forEach(t=>{if(!(t instanceof h)){if(t._name in e.controllers)throw new Error(`Cannot save GUI with duplicate property "${t._name}"`);e.controllers[t._name]=t.save()}}),t&&this.folders.forEach(t=>{if(t._title in e.folders)throw new Error(`Cannot save GUI with duplicate folder "${t._title}"`);e.folders[t._title]=t.save()}),e}open(t=!0){return this._closed=!t,this.$title.setAttribute("aria-expanded",!this._closed),this.domElement.classList.toggle("closed",this._closed),this}close(){return this.open(!1)}openAnimated(t=!0){return this._closed=!t,this.$title.setAttribute("aria-expanded",!this._closed),requestAnimationFrame(()=>{const e=this.$children.clientHeight;this.$children.style.height=e+"px",this.domElement.classList.add("transition");const i=t=>{t.target===this.$children&&(this.$children.style.height="",this.domElement.classList.remove("transition"),this.$children.removeEventListener("transitionend",i))};this.$children.addEventListener("transitionend",i);const s=t?this.$children.scrollHeight:0;this.domElement.classList.toggle("closed",!t),requestAnimationFrame(()=>{this.$children.style.height=s+"px"})}),this}title(t){return this._title=t,this.$title.innerHTML=t,this}reset(t=!0){return(t?this.controllersRecursive():this.controllers).forEach(t=>t.reset()),this}onChange(t){return this._onChange=t,this}_callOnChange(t){this.parent&&this.parent._callOnChange(t),void 0!==this._onChange&&this._onChange.call(this,{object:t.object,property:t.property,value:t.getValue(),controller:t})}destroy(){this.parent&&(this.parent.children.splice(this.parent.children.indexOf(this),1),this.parent.folders.splice(this.parent.folders.indexOf(this),1)),this.domElement.parentElement&&this.domElement.parentElement.removeChild(this.domElement),Array.from(this.children).forEach(t=>t.destroy()),this._onResize&&window.removeEventListener("resize",this._onResize)}controllersRecursive(){let t=Array.from(this.controllers);return this.folders.forEach(e=>{t=t.concat(e.controllersRecursive())}),t}foldersRecursive(){let t=Array.from(this.folders);return this.folders.forEach(e=>{t=t.concat(e.foldersRecursive())}),t}}export default g;export{e as BooleanController,a as ColorController,t as Controller,h as FunctionController,g as GUI,d as NumberController,c as OptionController,u as StringController}; +class t{constructor(i,e,s,n,r="div"){this.parent=i,this.object=e,this.property=s,this._disabled=!1,this.initialValue=this.getValue(),this.domElement=document.createElement("div"),this.domElement.classList.add("controller"),this.domElement.classList.add(n),this.$name=document.createElement("div"),this.$name.classList.add("name"),t.nextNameID=t.nextNameID||0,this.$name.id="lil-gui-name-"+ ++t.nextNameID,this.$widget=document.createElement(r),this.$widget.classList.add("widget"),this.$disable=this.$widget,this.domElement.appendChild(this.$name),this.domElement.appendChild(this.$widget),this.parent.children.push(this),this.parent.controllers.push(this),this.parent.$children.appendChild(this.domElement),this._listenCallback=this._listenCallback.bind(this),this.name(s)}name(t){return this._name=t,this.$name.innerHTML=t,this}onChange(t){return this._onChange=t,this}_callOnChange(){this.parent._callOnChange(this),void 0!==this._onChange&&this._onChange.call(this,this.getValue()),this._changed=!0}onFinishChange(t){return this._onFinishChange=t,this}_callOnFinishChange(){this._changed&&(this.parent._callOnFinishChange(this),void 0!==this._onFinishChange&&this._onFinishChange.call(this,this.getValue())),this._changed=!1}reset(){return this.setValue(this.initialValue),this._callOnFinishChange(),this}enable(t=!0){return this.disable(!t)}disable(t=!0){return t===this._disabled||(this._disabled=t,this.domElement.classList.toggle("disabled",t),this.$disable.toggleAttribute("disabled",t)),this}options(t){const i=this.parent.add(this.object,this.property,t);return i.name(this._name),this.destroy(),i}min(t){return this}max(t){return this}step(t){return this}listen(t=!0){return this._listening=t,void 0!==this._listenCallbackID&&(cancelAnimationFrame(this._listenCallbackID),this._listenCallbackID=void 0),this._listening&&this._listenCallback(),this}_listenCallback(){this._listenCallbackID=requestAnimationFrame(this._listenCallback),this.updateDisplay()}getValue(){return this.object[this.property]}setValue(t){return this.object[this.property]=t,this._callOnChange(),this.updateDisplay(),this}updateDisplay(){return this}load(t){return this.setValue(t),this._callOnFinishChange(),this}save(){return this.getValue()}destroy(){this.parent.children.splice(this.parent.children.indexOf(this),1),this.parent.controllers.splice(this.parent.controllers.indexOf(this),1),this.parent.$children.removeChild(this.domElement)}}class i extends t{constructor(t,i,e){super(t,i,e,"boolean","label"),this.$input=document.createElement("input"),this.$input.setAttribute("type","checkbox"),this.$input.setAttribute("aria-labelledby",this.$name.id),this.$widget.appendChild(this.$input),this.$input.addEventListener("change",()=>{this.setValue(this.$input.checked),this._callOnFinishChange()}),this.$disable=this.$input,this.updateDisplay()}updateDisplay(){return this.$input.checked=this.getValue(),this}}function e(t){let i,e;return(i=t.match(/(#|0x)?([a-f0-9]{6})/i))?e=i[2]:(i=t.match(/rgb\(\s*(\d*)\s*,\s*(\d*)\s*,\s*(\d*)\s*\)/))?e=parseInt(i[1]).toString(16).padStart(2,0)+parseInt(i[2]).toString(16).padStart(2,0)+parseInt(i[3]).toString(16).padStart(2,0):(i=t.match(/^#?([a-f0-9])([a-f0-9])([a-f0-9])$/i))&&(e=i[1]+i[1]+i[2]+i[2]+i[3]+i[3]),!!e&&"#"+e}const s={isPrimitive:!0,match:t=>"string"==typeof t,fromHexString:e,toHexString:e},n={isPrimitive:!0,match:t=>"number"==typeof t,fromHexString:t=>parseInt(t.substring(1),16),toHexString:t=>"#"+t.toString(16).padStart(6,0)},r={isPrimitive:!1,match:Array.isArray,fromHexString(t,i,e=1){const s=n.fromHexString(t);i[0]=(s>>16&255)/255*e,i[1]=(s>>8&255)/255*e,i[2]=(255&s)/255*e},toHexString:([t,i,e],s=1)=>n.toHexString(t*(s=255/s)<<16^i*s<<8^e*s<<0)},l={isPrimitive:!1,match:t=>Object(t)===t,fromHexString(t,i,e=1){const s=n.fromHexString(t);i.r=(s>>16&255)/255*e,i.g=(s>>8&255)/255*e,i.b=(255&s)/255*e},toHexString:({r:t,g:i,b:e},s=1)=>n.toHexString(t*(s=255/s)<<16^i*s<<8^e*s<<0)},o=[s,n,r,l];class a extends t{constructor(t,i,s,n){var r;super(t,i,s,"color"),this.$input=document.createElement("input"),this.$input.setAttribute("type","color"),this.$input.setAttribute("tabindex",-1),this.$input.setAttribute("aria-labelledby",this.$name.id),this.$text=document.createElement("input"),this.$text.setAttribute("type","text"),this.$text.setAttribute("spellcheck","false"),this.$text.setAttribute("aria-labelledby",this.$name.id),this.$display=document.createElement("div"),this.$display.classList.add("display"),this.$display.appendChild(this.$input),this.$widget.appendChild(this.$display),this.$widget.appendChild(this.$text),this._format=(r=this.initialValue,o.find(t=>t.match(r))),this._rgbScale=n,this._initialValueHexString=this.save(),this._textFocused=!1,this.$input.addEventListener("input",()=>{this._setValueFromHexString(this.$input.value)}),this.$input.addEventListener("blur",()=>{this._callOnFinishChange()}),this.$text.addEventListener("input",()=>{const t=e(this.$text.value);t&&this._setValueFromHexString(t)}),this.$text.addEventListener("focus",()=>{this._textFocused=!0,this.$text.select()}),this.$text.addEventListener("blur",()=>{this._textFocused=!1,this.updateDisplay(),this._callOnFinishChange()}),this.$disable=this.$text,this.updateDisplay()}reset(){return this._setValueFromHexString(this._initialValueHexString),this}_setValueFromHexString(t){if(this._format.isPrimitive){const i=this._format.fromHexString(t);this.setValue(i)}else this._format.fromHexString(t,this.getValue(),this._rgbScale),this._callOnChange(),this.updateDisplay()}save(){return this._format.toHexString(this.getValue(),this._rgbScale)}load(t){return this._setValueFromHexString(t),this._callOnFinishChange(),this}updateDisplay(){return this.$input.value=this._format.toHexString(this.getValue(),this._rgbScale),this._textFocused||(this.$text.value=this.$input.value.substring(1)),this.$display.style.backgroundColor=this.$input.value,this}}class h extends t{constructor(t,i,e){super(t,i,e,"function"),this.$button=document.createElement("button"),this.$button.appendChild(this.$name),this.$widget.appendChild(this.$button),this.$button.addEventListener("click",t=>{t.preventDefault(),this.getValue().call(this.object)}),this.$button.addEventListener("touchstart",()=>{}),this.$disable=this.$button}}class d extends t{constructor(t,i,e,s,n,r){super(t,i,e,"number"),this._initInput(),this.min(s),this.max(n);const l=void 0!==r;this.step(l?r:this._getImplicitStep(),l),this.updateDisplay()}min(t){return this._min=t,this._onUpdateMinMax(),this}max(t){return this._max=t,this._onUpdateMinMax(),this}step(t,i=!0){return this._step=t,this._stepExplicit=i,this}updateDisplay(){const t=this.getValue();if(this._hasSlider){let i=(t-this._min)/(this._max-this._min);i=Math.max(0,Math.min(i,1)),this.$fill.style.width=100*i+"%"}return this._inputFocused||(this.$input.value=t),this}_initInput(){this.$input=document.createElement("input"),this.$input.setAttribute("type","number"),this.$input.setAttribute("step","any"),this.$input.setAttribute("aria-labelledby",this.$name.id),this.$widget.appendChild(this.$input),this.$disable=this.$input;const t=t=>{const i=parseFloat(this.$input.value);isNaN(i)||(this._snapClampSetValue(i+t),this.$input.value=this.getValue())};let i,e,s,n,r,l=!1;const o=t=>{if(l){const s=t.clientX-i,n=t.clientY-e;Math.abs(n)>5?(t.preventDefault(),this.$input.blur(),l=!1,this._setDraggingStyle(!0,"vertical")):Math.abs(s)>5&&a()}if(!l){const i=t.clientY-s;r-=i*this._step*this._arrowKeyMultiplier(t),n+r>this._max?r=this._max-n:n+r{this._setDraggingStyle(!1,"vertical"),this._callOnFinishChange(),window.removeEventListener("mousemove",o),window.removeEventListener("mouseup",a)};this.$input.addEventListener("input",()=>{const t=parseFloat(this.$input.value);isNaN(t)||this.setValue(this._clamp(t))}),this.$input.addEventListener("keydown",i=>{"Enter"===i.code&&this.$input.blur(),"ArrowUp"===i.code&&(i.preventDefault(),t(this._step*this._arrowKeyMultiplier(i))),"ArrowDown"===i.code&&(i.preventDefault(),t(this._step*this._arrowKeyMultiplier(i)*-1))}),this.$input.addEventListener("wheel",i=>{this._inputFocused&&(i.preventDefault(),t(this._step*this._normalizeMouseWheel(i)))}),this.$input.addEventListener("mousedown",t=>{i=t.clientX,e=s=t.clientY,l=!0,n=this.getValue(),r=0,window.addEventListener("mousemove",o),window.addEventListener("mouseup",a)}),this.$input.addEventListener("focus",()=>{this._inputFocused=!0}),this.$input.addEventListener("blur",()=>{this._inputFocused=!1,this.updateDisplay(),this._callOnFinishChange()})}_initSlider(){this._hasSlider=!0,this.$slider=document.createElement("div"),this.$slider.classList.add("slider"),this.$fill=document.createElement("div"),this.$fill.classList.add("fill"),this.$slider.appendChild(this.$fill),this.$widget.insertBefore(this.$slider,this.$input),this.domElement.classList.add("hasSlider");const t=t=>{const i=this.$slider.getBoundingClientRect();let e=(s=t,n=i.left,r=i.right,l=this._min,o=this._max,(s-n)/(r-n)*(o-l)+l);var s,n,r,l,o;this._snapClampSetValue(e)},i=i=>{t(i.clientX)},e=()=>{this._callOnFinishChange(),this._setDraggingStyle(!1),window.removeEventListener("mousemove",i),window.removeEventListener("mouseup",e)};let s,n,r=!1;const l=i=>{i.preventDefault(),this._setDraggingStyle(!0),t(i.touches[0].clientX),r=!1},o=i=>{if(r){const t=i.touches[0].clientX-s,e=i.touches[0].clientY-n;Math.abs(t)>Math.abs(e)?l(i):(window.removeEventListener("touchmove",o),window.removeEventListener("touchend",a))}else i.preventDefault(),t(i.touches[0].clientX)},a=()=>{this._callOnFinishChange(),this._setDraggingStyle(!1),window.removeEventListener("touchmove",o),window.removeEventListener("touchend",a)},h=this._callOnFinishChange.bind(this);let d;this.$slider.addEventListener("mousedown",s=>{this._setDraggingStyle(!0),t(s.clientX),window.addEventListener("mousemove",i),window.addEventListener("mouseup",e)}),this.$slider.addEventListener("touchstart",t=>{t.touches.length>1||(this._hasScrollBar?(s=t.touches[0].clientX,n=t.touches[0].clientY,r=!0):l(t),window.addEventListener("touchmove",o),window.addEventListener("touchend",a))}),this.$slider.addEventListener("wheel",t=>{if(Math.abs(t.deltaX)this._max&&(t=this._max),t}_snapClampSetValue(t){this.setValue(this._clamp(this._snap(t)))}get _hasScrollBar(){const t=this.parent.root.$children;return t.scrollHeight>t.clientHeight}get _hasMin(){return void 0!==this._min}get _hasMax(){return void 0!==this._max}}class c extends t{constructor(t,i,e,s){super(t,i,e,"option"),this.$select=document.createElement("select"),this.$select.setAttribute("aria-labelledby",this.$name.id),this.$display=document.createElement("div"),this.$display.classList.add("display"),this._values=Array.isArray(s)?s:Object.values(s),this._names=Array.isArray(s)?s:Object.keys(s),this._names.forEach(t=>{const i=document.createElement("option");i.innerHTML=t,this.$select.appendChild(i)}),this.$select.addEventListener("change",()=>{this.setValue(this._values[this.$select.selectedIndex]),this._callOnFinishChange()}),this.$select.addEventListener("focus",()=>{this.$display.classList.add("focus")}),this.$select.addEventListener("blur",()=>{this.$display.classList.remove("focus")}),this.$widget.appendChild(this.$select),this.$widget.appendChild(this.$display),this.$disable=this.$select,this.updateDisplay()}updateDisplay(){const t=this.getValue(),i=this._values.indexOf(t);return this.$select.selectedIndex=i,this.$display.innerHTML=-1===i?t:this._names[i],this}}class u extends t{constructor(t,i,e){super(t,i,e,"string"),this.$input=document.createElement("input"),this.$input.setAttribute("type","text"),this.$input.setAttribute("aria-labelledby",this.$name.id),this.$input.addEventListener("input",()=>{this.setValue(this.$input.value)}),this.$input.addEventListener("keydown",t=>{"Enter"===t.code&&this.$input.blur()}),this.$input.addEventListener("blur",()=>{this._callOnFinishChange()}),this.$widget.appendChild(this.$input),this.$disable=this.$input,this.updateDisplay()}updateDisplay(){return this.$input.value=this.getValue(),this}}let p=!1;class g{constructor({parent:t,autoPlace:i=void 0===t,container:e,width:s,title:n="Controls",injectStyles:r=!0,touchStyles:l=!0}={}){if(this.parent=t,this.root=t?t.root:this,this.children=[],this.controllers=[],this.folders=[],this._closed=!1,this._hidden=!1,this.domElement=document.createElement("div"),this.domElement.classList.add("lil-gui"),this.$title=document.createElement("div"),this.$title.classList.add("title"),this.$title.setAttribute("role","button"),this.$title.setAttribute("aria-expanded",!0),this.$title.setAttribute("tabindex",0),this.$title.addEventListener("click",()=>this.openAnimated(this._closed)),this.$title.addEventListener("keydown",t=>{"Enter"!==t.code&&"Space"!==t.code||(t.preventDefault(),this.$title.click())}),this.$title.addEventListener("touchstart",()=>{}),this.$children=document.createElement("div"),this.$children.classList.add("children"),this.domElement.appendChild(this.$title),this.domElement.appendChild(this.$children),this.title(n),l&&this.domElement.classList.add("allow-touch-styles"),this.parent)return this.parent.children.push(this),this.parent.folders.push(this),void this.parent.$children.appendChild(this.domElement);this.domElement.classList.add("root"),!p&&r&&(!function(t){const i=document.createElement("style");i.innerHTML=t;const e=document.querySelector("head link[rel=stylesheet], head style");e?document.head.insertBefore(i,e):document.head.appendChild(i)}('.lil-gui{--background-color:#1f1f1f;--text-color:#ebebeb;--title-background-color:#111;--title-text-color:#ebebeb;--widget-color:#424242;--hover-color:#4f4f4f;--focus-color:#595959;--number-color:#2cc9ff;--string-color:#a2db3c;--font-size:11px;--input-font-size:11px;--font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Arial,sans-serif;--font-family-mono:Menlo,Monaco,Consolas,"Droid Sans Mono",monospace;--padding:4px;--spacing:4px;--widget-height:20px;--name-width:45%;--slider-knob-width:2px;--slider-input-width:27%;--color-input-width:27%;--slider-input-min-width:45px;--color-input-min-width:45px;--folder-indent:7px;--widget-padding:0 0 0 3px;--widget-border-radius:2px;--checkbox-size:calc(var(--widget-height)*0.75);--scrollbar-width:5px;background-color:var(--background-color);color:var(--text-color);font-family:var(--font-family);font-size:var(--font-size);font-style:normal;font-weight:400;line-height:1;text-align:left;touch-action:manipulation;user-select:none;-webkit-user-select:none}.lil-gui,.lil-gui *{box-sizing:border-box;margin:0;padding:0}.lil-gui.root{display:flex;flex-direction:column;width:var(--width,245px)}.lil-gui.root>.title{background:var(--title-background-color);color:var(--title-text-color)}.lil-gui.root>.children{overflow-x:hidden;overflow-y:auto}.lil-gui.root>.children::-webkit-scrollbar{background:var(--background-color);height:var(--scrollbar-width);width:var(--scrollbar-width)}.lil-gui.root>.children::-webkit-scrollbar-thumb{background:var(--focus-color);border-radius:var(--scrollbar-width)}.lil-gui.force-touch-styles{--widget-height:28px;--padding:6px;--spacing:6px;--font-size:13px;--input-font-size:16px;--folder-indent:10px;--scrollbar-width:7px;--slider-input-min-width:50px;--color-input-min-width:65px}.lil-gui.autoPlace{max-height:100%;position:fixed;right:15px;top:0;z-index:1001}.lil-gui .controller{align-items:center;display:flex;margin:var(--spacing) 0;padding:0 var(--padding)}.lil-gui .controller.disabled{opacity:.5}.lil-gui .controller.disabled,.lil-gui .controller.disabled *{pointer-events:none!important}.lil-gui .controller>.name{flex-shrink:0;line-height:var(--widget-height);min-width:var(--name-width);padding-right:var(--spacing);white-space:pre}.lil-gui .controller .widget{align-items:center;display:flex;min-height:var(--widget-height);position:relative;width:100%}.lil-gui .controller.string input{color:var(--string-color)}.lil-gui .controller.boolean .widget{cursor:pointer}.lil-gui .controller.color .display{border-radius:var(--widget-border-radius);height:var(--widget-height);position:relative;width:100%}.lil-gui .controller.color input[type=color]{cursor:pointer;height:100%;opacity:0;width:100%}.lil-gui .controller.color input[type=text]{flex-shrink:0;font-family:var(--font-family-mono);margin-left:var(--spacing);min-width:var(--color-input-min-width);width:var(--color-input-width)}.lil-gui .controller.option select{max-width:100%;opacity:0;position:absolute;width:100%}.lil-gui .controller.option .display{background:var(--widget-color);border-radius:var(--widget-border-radius);height:var(--widget-height);line-height:var(--widget-height);max-width:100%;overflow:hidden;padding-left:.55em;padding-right:1.75em;pointer-events:none;position:relative;word-break:break-all}.lil-gui .controller.option .display.active{background:var(--focus-color)}.lil-gui .controller.option .display:after{bottom:0;content:"↕";font-family:lil-gui;padding-right:.375em;position:absolute;right:0;top:0}.lil-gui .controller.option .widget,.lil-gui .controller.option select{cursor:pointer}.lil-gui .controller.number input{color:var(--number-color)}.lil-gui .controller.number.hasSlider input{flex-shrink:0;margin-left:var(--spacing);min-width:var(--slider-input-min-width);width:var(--slider-input-width)}.lil-gui .controller.number .slider{background-color:var(--widget-color);border-radius:var(--widget-border-radius);cursor:ew-resize;height:var(--widget-height);overflow:hidden;padding-right:var(--slider-knob-width);touch-action:pan-y;width:100%}.lil-gui .controller.number .slider.active{background-color:var(--focus-color)}.lil-gui .controller.number .slider.active .fill{opacity:.95}.lil-gui .controller.number .fill{border-right:var(--slider-knob-width) solid var(--number-color);box-sizing:content-box;height:100%}.lil-gui-dragging .lil-gui{--hover-color:var(--widget-color)}.lil-gui-dragging *{cursor:ew-resize!important}.lil-gui-dragging.lil-gui-vertical *{cursor:ns-resize!important}.lil-gui .title{--title-height:calc(var(--widget-height) + var(--spacing)*1.25);-webkit-tap-highlight-color:transparent;text-decoration-skip:objects;cursor:pointer;font-weight:600;height:var(--title-height);line-height:calc(var(--title-height) - 4px);outline:none;padding:0 var(--padding)}.lil-gui .title:before{content:"▾";display:inline-block;font-family:lil-gui;padding-right:2px}.lil-gui .title:active{background:var(--title-background-color);opacity:.75}.lil-gui.root>.title:focus{text-decoration:none!important}.lil-gui.closed>.title:before{content:"▸"}.lil-gui.closed>.children{opacity:0;transform:translateY(-7px)}.lil-gui.closed:not(.transition)>.children{display:none}.lil-gui.transition>.children{overflow:hidden;pointer-events:none;transition-duration:.3s;transition-property:height,opacity,transform;transition-timing-function:cubic-bezier(.2,.6,.35,1)}.lil-gui .children:empty:before{content:"Empty";display:block;font-style:italic;height:var(--widget-height);line-height:var(--widget-height);margin:var(--spacing) 0;opacity:.5;padding:0 var(--padding)}.lil-gui.root>.children>.lil-gui>.title{border-width:0;border-bottom:1px solid var(--widget-color);border-left:0 solid var(--widget-color);border-right:0 solid var(--widget-color);border-top:1px solid var(--widget-color);transition:border-color .3s}.lil-gui.root>.children>.lil-gui.closed>.title{border-bottom-color:transparent}.lil-gui+.controller{border-top:1px solid var(--widget-color);margin-top:0;padding-top:var(--spacing)}.lil-gui .lil-gui .lil-gui>.title{border:none}.lil-gui .lil-gui .lil-gui>.children{border:none;border-left:2px solid var(--widget-color);margin-left:var(--folder-indent)}.lil-gui .lil-gui .controller{border:none}.lil-gui input{-webkit-tap-highlight-color:transparent;background:var(--widget-color);border:0;border-radius:var(--widget-border-radius);color:var(--text-color);font-family:var(--font-family);font-size:var(--input-font-size);height:var(--widget-height);outline:none;width:100%}.lil-gui input:disabled{opacity:1}.lil-gui input[type=number],.lil-gui input[type=text]{padding:var(--widget-padding)}.lil-gui input[type=number]:focus,.lil-gui input[type=text]:focus{background:var(--focus-color)}.lil-gui input::-webkit-inner-spin-button,.lil-gui input::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.lil-gui input[type=number]{-moz-appearance:textfield}.lil-gui input[type=checkbox]{appearance:none;-webkit-appearance:none;border-radius:var(--widget-border-radius);cursor:pointer;height:var(--checkbox-size);text-align:center;width:var(--checkbox-size)}.lil-gui input[type=checkbox]:checked:before{content:"✓";font-family:lil-gui;font-size:var(--checkbox-size);line-height:var(--checkbox-size)}.lil-gui button{-webkit-tap-highlight-color:transparent;background:var(--widget-color);border:1px solid var(--widget-color);border-radius:var(--widget-border-radius);color:var(--text-color);cursor:pointer;font-family:var(--font-family);font-size:var(--font-size);height:var(--widget-height);line-height:calc(var(--widget-height) - 4px);outline:none;text-align:center;text-transform:none;width:100%}.lil-gui button:active{background:var(--focus-color)}@font-face{font-family:lil-gui;src:url("data:application/font-woff;charset=utf-8;base64,d09GRgABAAAAAAUsAAsAAAAACJwAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAAH4AAADAImwmYE9TLzIAAAGIAAAAPwAAAGBKqH5SY21hcAAAAcgAAAD0AAACrukyyJBnbHlmAAACvAAAAF8AAACEIZpWH2hlYWQAAAMcAAAAJwAAADZfcj2zaGhlYQAAA0QAAAAYAAAAJAC5AHhobXR4AAADXAAAABAAAABMAZAAAGxvY2EAAANsAAAAFAAAACgCEgIybWF4cAAAA4AAAAAeAAAAIAEfABJuYW1lAAADoAAAASIAAAIK9SUU/XBvc3QAAATEAAAAZgAAAJCTcMc2eJxVjbEOgjAURU+hFRBK1dGRL+ALnAiToyMLEzFpnPz/eAshwSa97517c/MwwJmeB9kwPl+0cf5+uGPZXsqPu4nvZabcSZldZ6kfyWnomFY/eScKqZNWupKJO6kXN3K9uCVoL7iInPr1X5baXs3tjuMqCtzEuagm/AAlzQgPAAB4nGNgYRBlnMDAysDAYM/gBiT5oLQBAwuDJAMDEwMrMwNWEJDmmsJwgCFeXZghBcjlZMgFCzOiKOIFAB71Bb8AeJy1kjFuwkAQRZ+DwRAwBtNQRUGKQ8OdKCAWUhAgKLhIuAsVSpWz5Bbkj3dEgYiUIszqWdpZe+Z7/wB1oCYmIoboiwiLT2WjKl/jscrHfGg/pKdMkyklC5Zs2LEfHYpjcRoPzme9MWWmk3dWbK9ObkWkikOetJ554fWyoEsmdSlt+uR0pCJR34b6t/TVg1SY3sYvdf8vuiKrpyaDXDISiegp17p7579Gp3p++y7HPAiY9pmTibljrr85qSidtlg4+l25GLCaS8e6rRxNBmsnERunKbaOObRz7N72ju5vdAjYpBXHgJylOAVsMseDAPEP8LYoUHicY2BiAAEfhiAGJgZWBgZ7RnFRdnVJELCQlBSRlATJMoLV2DK4glSYs6ubq5vbKrJLSbGrgEmovDuDJVhe3VzcXFwNLCOILB/C4IuQ1xTn5FPilBTj5FPmBAB4WwoqAHicY2BkYGAA4sk1sR/j+W2+MnAzpDBgAyEMQUCSg4EJxAEAwUgFHgB4nGNgZGBgSGFggJMhDIwMqEAYAByHATJ4nGNgAIIUNEwmAABl3AGReJxjYAACIQYlBiMGJ3wQAEcQBEV4nGNgZGBgEGZgY2BiAAEQyQWEDAz/wXwGAAsPATIAAHicXdBNSsNAHAXwl35iA0UQXYnMShfS9GPZA7T7LgIu03SSpkwzYTIt1BN4Ak/gKTyAeCxfw39jZkjymzcvAwmAW/wgwHUEGDb36+jQQ3GXGot79L24jxCP4gHzF/EIr4jEIe7wxhOC3g2TMYy4Q7+Lu/SHuEd/ivt4wJd4wPxbPEKMX3GI5+DJFGaSn4qNzk8mcbKSR6xdXdhSzaOZJGtdapd4vVPbi6rP+cL7TGXOHtXKll4bY1Xl7EGnPtp7Xy2n00zyKLVHfkHBa4IcJ2oD3cgggWvt/V/FbDrUlEUJhTn/0azVWbNTNr0Ens8de1tceK9xZmfB1CPjOmPH4kitmvOubcNpmVTN3oFJyjzCvnmrwhJTzqzVj9jiSX911FjeAAB4nG3HMRKCMBBA0f0giiKi4DU8k0V2GWbIZDOh4PoWWvq6J5V8If9NVNQcaDhyouXMhY4rPTcG7jwYmXhKq8Wz+p762aNaeYXom2n3m2dLTVgsrCgFJ7OTmIkYbwIbC6vIB7WmFfAAAA==") format("woff")}@media (pointer:coarse){.lil-gui.allow-touch-styles{--widget-height:28px;--padding:6px;--spacing:6px;--font-size:13px;--input-font-size:16px;--folder-indent:10px;--scrollbar-width:7px;--slider-input-min-width:50px;--color-input-min-width:65px}}@media (hover:hover){.lil-gui .controller.color .display:hover:before{border:1px solid #fff9;border-radius:var(--widget-border-radius);bottom:0;content:" ";display:block;left:0;position:absolute;right:0;top:0}.lil-gui .controller.option .display.focus{background:var(--focus-color)}.lil-gui .controller.option .widget:hover .display{background:var(--hover-color)}.lil-gui .controller.number .slider:hover{background-color:var(--hover-color)}body:not(.lil-gui-dragging) .lil-gui .title:hover{background:var(--title-background-color);opacity:.85}.lil-gui .title:focus{text-decoration:underline var(--focus-color)}.lil-gui input:hover{background:var(--hover-color)}.lil-gui input:active{background:var(--focus-color)}.lil-gui input[type=checkbox]:focus{box-shadow:inset 0 0 0 1px var(--focus-color)}.lil-gui button:hover{background:var(--hover-color);border-color:var(--hover-color)}.lil-gui button:focus{border-color:var(--focus-color)}}'),p=!0),e?e.appendChild(this.domElement):i&&(this.domElement.classList.add("autoPlace"),document.body.appendChild(this.domElement)),s&&this.domElement.style.setProperty("--width",s+"px"),this.domElement.addEventListener("keydown",t=>t.stopPropagation()),this.domElement.addEventListener("keyup",t=>t.stopPropagation())}add(t,e,s,n,r){if(Object(s)===s)return new c(this,t,e,s);const l=t[e];switch(typeof l){case"number":return new d(this,t,e,s,n,r);case"boolean":return new i(this,t,e);case"string":return new u(this,t,e);case"function":return new h(this,t,e)}console.error("gui.add failed\n\tproperty:",e,"\n\tobject:",t,"\n\tvalue:",l)}addColor(t,i,e=1){return new a(this,t,i,e)}addFolder(t){return new g({parent:this,title:t})}load(t,i=!0){return t.controllers&&this.controllers.forEach(i=>{i instanceof h||i._name in t.controllers&&i.load(t.controllers[i._name])}),i&&t.folders&&this.folders.forEach(i=>{i._title in t.folders&&i.load(t.folders[i._title])}),this}save(t=!0){const i={controllers:{},folders:{}};return this.controllers.forEach(t=>{if(!(t instanceof h)){if(t._name in i.controllers)throw new Error(`Cannot save GUI with duplicate property "${t._name}"`);i.controllers[t._name]=t.save()}}),t&&this.folders.forEach(t=>{if(t._title in i.folders)throw new Error(`Cannot save GUI with duplicate folder "${t._title}"`);i.folders[t._title]=t.save()}),i}open(t=!0){return this._closed=!t,this.$title.setAttribute("aria-expanded",!this._closed),this.domElement.classList.toggle("closed",this._closed),this}close(){return this.open(!1)}show(t=!0){return this._hidden=!t,this.domElement.style.display=this._hidden?"none":"",this}hide(){return this.show(!1)}openAnimated(t=!0){return this._closed=!t,this.$title.setAttribute("aria-expanded",!this._closed),requestAnimationFrame(()=>{const i=this.$children.clientHeight;this.$children.style.height=i+"px",this.domElement.classList.add("transition");const e=t=>{t.target===this.$children&&(this.$children.style.height="",this.domElement.classList.remove("transition"),this.$children.removeEventListener("transitionend",e))};this.$children.addEventListener("transitionend",e);const s=t?this.$children.scrollHeight:0;this.domElement.classList.toggle("closed",!t),requestAnimationFrame(()=>{this.$children.style.height=s+"px"})}),this}title(t){return this._title=t,this.$title.innerHTML=t,this}reset(t=!0){return(t?this.controllersRecursive():this.controllers).forEach(t=>t.reset()),this}onChange(t){return this._onChange=t,this}_callOnChange(t){this.parent&&this.parent._callOnChange(t),void 0!==this._onChange&&this._onChange.call(this,{object:t.object,property:t.property,value:t.getValue(),controller:t})}onFinishChange(t){return this._onFinishChange=t,this}_callOnFinishChange(t){this.parent&&this.parent._callOnFinishChange(t),void 0!==this._onFinishChange&&this._onFinishChange.call(this,{object:t.object,property:t.property,value:t.getValue(),controller:t})}destroy(){this.parent&&(this.parent.children.splice(this.parent.children.indexOf(this),1),this.parent.folders.splice(this.parent.folders.indexOf(this),1)),this.domElement.parentElement&&this.domElement.parentElement.removeChild(this.domElement),Array.from(this.children).forEach(t=>t.destroy())}controllersRecursive(){let t=Array.from(this.controllers);return this.folders.forEach(i=>{t=t.concat(i.controllersRecursive())}),t}foldersRecursive(){let t=Array.from(this.folders);return this.folders.forEach(i=>{t=t.concat(i.foldersRecursive())}),t}}export default g;export{i as BooleanController,a as ColorController,t as Controller,h as FunctionController,g as GUI,d as NumberController,c as OptionController,u as StringController}; diff --git a/examples/jsm/loaders/AMFLoader.js b/examples/jsm/loaders/AMFLoader.js index 19379fb94314df..a8ac15e090e4ed 100644 --- a/examples/jsm/loaders/AMFLoader.js +++ b/examples/jsm/loaders/AMFLoader.js @@ -15,8 +15,6 @@ import * as fflate from '../libs/fflate.module.js'; * Description: Early release of an AMF Loader following the pattern of the * example loaders in the three.js project. * - * More information about the AMF format: http://amf.wikispaces.com - * * Usage: * const loader = new AMFLoader(); * loader.load('/path/to/project.amf', function(objecttree) { diff --git a/examples/jsm/loaders/BasisTextureLoader.js b/examples/jsm/loaders/BasisTextureLoader.js index 65e7f67278acf5..e71a7210c483eb 100644 --- a/examples/jsm/loaders/BasisTextureLoader.js +++ b/examples/jsm/loaders/BasisTextureLoader.js @@ -48,6 +48,13 @@ class BasisTextureLoader extends Loader { this.workerSourceURL = ''; this.workerConfig = null; + console.warn( + + 'THREE.BasisTextureLoader: This loader is deprecated, and will be removed in a future release. ' + + 'Instead, use Basis Universal compression in KTX2 (.ktx2) files with THREE.KTX2Loader.' + + ); + } setTranscoderPath( path ) { diff --git a/examples/jsm/loaders/EXRLoader.js b/examples/jsm/loaders/EXRLoader.js index 86513e3d8e43e6..625bae70e04042 100644 --- a/examples/jsm/loaders/EXRLoader.js +++ b/examples/jsm/loaders/EXRLoader.js @@ -5,12 +5,8 @@ import { HalfFloatType, LinearEncoding, LinearFilter, - NearestFilter, - RGBAFormat, - RGBEEncoding, - RGBEFormat, - RGBFormat, - UnsignedByteType + RedFormat, + RGBAFormat } from '../../../build/three.module.js'; import * as fflate from '../libs/fflate.module.js'; @@ -132,41 +128,6 @@ class EXRLoader extends DataTextureLoader { const logBase = Math.pow( 2.7182818, 2.2 ); - var tmpDataView = new DataView( new ArrayBuffer( 8 ) ); - - function frexp( value ) { - - if ( value === 0 ) return [ value, 0 ]; - - tmpDataView.setFloat64( 0, value ); - - var bits = ( tmpDataView.getUint32( 0 ) >>> 20 ) & 0x7FF; - if ( bits === 0 ) { // denormal - - tmpDataView.setFloat64( 0, value * Math.pow( 2, 64 ) ); // exp + 64 - bits = ( ( tmpDataView.getUint32( 0 ) >>> 20 ) & 0x7FF ) - 64; - - } - - var exponent = bits - 1022; - var mantissa = ldexp( value, - exponent ); - - return [ mantissa, exponent ]; - - } - - function ldexp( mantissa, exponent ) { - - var steps = Math.min( 3, Math.ceil( Math.abs( exponent ) / 1023 ) ); - var result = mantissa; - - for ( var i = 0; i < steps; i ++ ) - result *= Math.pow( 2, Math.floor( ( exponent + i ) / steps ) ); - - return result; - - } - function reverseLutFromBitmap( bitmap, lut ) { var k = 0; @@ -269,7 +230,7 @@ class EXRLoader extends DataTextureLoader { if ( p.value - inOffset.value > ni ) { - throw 'Something wrong with hufUnpackEncTable'; + throw new Error( 'Something wrong with hufUnpackEncTable' ); } @@ -281,7 +242,7 @@ class EXRLoader extends DataTextureLoader { if ( im + zerun > iM + 1 ) { - throw 'Something wrong with hufUnpackEncTable'; + throw new Error( 'Something wrong with hufUnpackEncTable' ); } @@ -295,7 +256,7 @@ class EXRLoader extends DataTextureLoader { if ( im + zerun > iM + 1 ) { - throw 'Something wrong with hufUnpackEncTable'; + throw new Error( 'Something wrong with hufUnpackEncTable' ); } @@ -332,7 +293,7 @@ class EXRLoader extends DataTextureLoader { if ( c >> l ) { - throw 'Invalid table entry'; + throw new Error( 'Invalid table entry' ); } @@ -342,7 +303,7 @@ class EXRLoader extends DataTextureLoader { if ( pl.len ) { - throw 'Invalid table entry'; + throw new Error( 'Invalid table entry' ); } @@ -377,7 +338,7 @@ class EXRLoader extends DataTextureLoader { if ( pl.len || pl.p ) { - throw 'Invalid table entry'; + throw new Error( 'Invalid table entry' ); } @@ -665,7 +626,7 @@ class EXRLoader extends DataTextureLoader { if ( ! pl.p ) { - throw 'hufDecode issues'; + throw new Error( 'hufDecode issues' ); } @@ -705,7 +666,7 @@ class EXRLoader extends DataTextureLoader { if ( j == pl.lit ) { - throw 'hufDecode issues'; + throw new Error( 'hufDecode issues' ); } @@ -735,7 +696,7 @@ class EXRLoader extends DataTextureLoader { } else { - throw 'hufDecode issues'; + throw new Error( 'hufDecode issues' ); } @@ -761,7 +722,7 @@ class EXRLoader extends DataTextureLoader { if ( im < 0 || im >= HUF_ENCSIZE || iM < 0 || iM >= HUF_ENCSIZE ) { - throw 'Something wrong with HUF_ENCSIZE'; + throw new Error( 'Something wrong with HUF_ENCSIZE' ); } @@ -776,7 +737,7 @@ class EXRLoader extends DataTextureLoader { if ( nBits > 8 * ( nCompressed - ( inOffset.value - initialInOffset ) ) ) { - throw 'Something wrong with hufUncompress'; + throw new Error( 'Something wrong with hufUncompress' ); } @@ -1312,8 +1273,7 @@ class EXRLoader extends DataTextureLoader { var inDataView = info.viewer; var inOffset = { value: info.offset.value }; - var tmpBufSize = info.width * scanlineBlockSize * ( EXRHeader.channels.length * info.type ); - var outBuffer = new Uint16Array( tmpBufSize ); + var outBuffer = new Uint16Array( info.width * info.scanlineBlockSize * ( info.channels * info.type ) ); var bitmap = new Uint8Array( BITMAP_SIZE ); // Setup channel info @@ -1333,12 +1293,13 @@ class EXRLoader extends DataTextureLoader { } // Read range compression data + var minNonZero = parseUint16( inDataView, inOffset ); var maxNonZero = parseUint16( inDataView, inOffset ); if ( maxNonZero >= BITMAP_SIZE ) { - throw 'Something is wrong with PIZ_COMPRESSION BITMAP_SIZE'; + throw new Error( 'Something is wrong with PIZ_COMPRESSION BITMAP_SIZE' ); } @@ -1489,7 +1450,7 @@ class EXRLoader extends DataTextureLoader { var inDataView = info.viewer; var inOffset = { value: info.offset.value }; - var outBuffer = new Uint8Array( info.width * info.lines * ( EXRHeader.channels.length * info.type * INT16_SIZE ) ); + var outBuffer = new Uint8Array( info.width * info.lines * ( info.channels * info.type * INT16_SIZE ) ); // Read compression header information var dwaHeader = { @@ -1509,7 +1470,7 @@ class EXRLoader extends DataTextureLoader { }; if ( dwaHeader.version < 2 ) - throw 'EXRLoader.parse: ' + EXRHeader.compression + ' version ' + dwaHeader.version + ' is unsupported'; + throw new Error( 'EXRLoader.parse: ' + EXRHeader.compression + ' version ' + dwaHeader.version + ' is unsupported' ); // Read channel ruleset information var channelRules = new Array(); @@ -1694,7 +1655,7 @@ class EXRLoader extends DataTextureLoader { case LOSSY_DCT: // skip default: - throw 'EXRLoader.parse: unsupported channel compression'; + throw new Error( 'EXRLoader.parse: unsupported channel compression' ); } @@ -1737,16 +1698,6 @@ class EXRLoader extends DataTextureLoader { } - function parseUlong( dataView, offset ) { - - var uLong = dataView.getUint32( 0, true ); - - offset.value = offset.value + ULONG_SIZE; - - return uLong; - - } - function parseRational( dataView, offset ) { var x = parseInt32( dataView, offset ); @@ -2037,311 +1988,274 @@ class EXRLoader extends DataTextureLoader { } - var bufferDataView = new DataView( buffer ); - var uInt8Array = new Uint8Array( buffer ); - - var EXRHeader = {}; - - bufferDataView.getUint32( 0, true ); // magic - bufferDataView.getUint8( 4, true ); // versionByteZero - bufferDataView.getUint8( 5, true ); // fullMask - - // start of header + function parseHeader( dataView, buffer, offset ) { - var offset = { value: 8 }; // start at 8, after magic stuff + const EXRHeader = {}; - var keepReading = true; + if ( dataView.getUint32( 0, true ) != 20000630 ) { // magic - while ( keepReading ) { - - var attributeName = parseNullTerminatedString( buffer, offset ); - - if ( attributeName == 0 ) { - - keepReading = false; - - } else { - - var attributeType = parseNullTerminatedString( buffer, offset ); - var attributeSize = parseUint32( bufferDataView, offset ); - var attributeValue = parseValue( bufferDataView, buffer, offset, attributeType, attributeSize ); - - if ( attributeValue === undefined ) { - - console.warn( `EXRLoader.parse: skipped unknown header attribute type \'${ attributeType }\'.` ); - - } else { - - EXRHeader[ attributeName ] = attributeValue; - - } + throw new Error( 'THREE.EXRLoader: provided file doesn\'t appear to be in OpenEXR format.' ); } - } - - // offsets - var dataWindowHeight = EXRHeader.dataWindow.yMax + 1; + EXRHeader.version = dataView.getUint8( 4, true ); - var uncompress; - var scanlineBlockSize; + const spec = dataView.getUint8( 5, true ); // fullMask - switch ( EXRHeader.compression ) { + EXRHeader.spec = { + singleTile: !! ( spec & 1 ), + longName: !! ( spec & 2 ), + deepFormat: !! ( spec & 4 ), + multiPart: !! ( spec & 8 ), + }; - case 'NO_COMPRESSION': + // start of header - scanlineBlockSize = 1; - uncompress = uncompressRAW; - break; + offset.value = 8; // start at 8 - after pre-amble - case 'RLE_COMPRESSION': + var keepReading = true; - scanlineBlockSize = 1; - uncompress = uncompressRLE; - break; + while ( keepReading ) { - case 'ZIPS_COMPRESSION': + var attributeName = parseNullTerminatedString( buffer, offset ); - scanlineBlockSize = 1; - uncompress = uncompressZIP; - break; + if ( attributeName == 0 ) { - case 'ZIP_COMPRESSION': + keepReading = false; - scanlineBlockSize = 16; - uncompress = uncompressZIP; - break; + } else { - case 'PIZ_COMPRESSION': + var attributeType = parseNullTerminatedString( buffer, offset ); + var attributeSize = parseUint32( dataView, offset ); + var attributeValue = parseValue( dataView, buffer, offset, attributeType, attributeSize ); - scanlineBlockSize = 32; - uncompress = uncompressPIZ; - break; + if ( attributeValue === undefined ) { - case 'PXR24_COMPRESSION': + console.warn( `EXRLoader.parse: skipped unknown header attribute type \'${attributeType}\'.` ); - scanlineBlockSize = 16; - uncompress = uncompressPXR; - break; + } else { - case 'DWAA_COMPRESSION': + EXRHeader[ attributeName ] = attributeValue; - scanlineBlockSize = 32; - uncompress = uncompressDWA; - break; + } - case 'DWAB_COMPRESSION': + } - scanlineBlockSize = 256; - uncompress = uncompressDWA; - break; + } - default: + if ( spec != 0 ) { - throw 'EXRLoader.parse: ' + EXRHeader.compression + ' is unsupported'; + console.error( 'EXRHeader:', EXRHeader ); + throw new Error( 'THREE.EXRLoader: provided file is currently unsupported.' ); - } + } - var size_t; - var getValue; + return EXRHeader; - // mixed pixelType not supported - var pixelType = EXRHeader.channels[ 0 ].pixelType; + } - if ( pixelType === 1 ) { // half + function setupDecoder( EXRHeader, dataView, uInt8Array, offset, outputType ) { - switch ( this.type ) { + const EXRDecoder = { + size: 0, + viewer: dataView, + array: uInt8Array, + offset: offset, + width: EXRHeader.dataWindow.xMax - EXRHeader.dataWindow.xMin + 1, + height: EXRHeader.dataWindow.yMax - EXRHeader.dataWindow.yMin + 1, + channels: EXRHeader.channels.length, + bytesPerLine: null, + lines: null, + inputSize: null, + type: EXRHeader.channels[ 0 ].pixelType, + uncompress: null, + getter: null, + format: null, + encoding: null, + }; - case UnsignedByteType: - case FloatType: + switch ( EXRHeader.compression ) { - getValue = parseFloat16; - size_t = INT16_SIZE; + case 'NO_COMPRESSION': + EXRDecoder.lines = 1; + EXRDecoder.uncompress = uncompressRAW; break; - case HalfFloatType: - - getValue = parseUint16; - size_t = INT16_SIZE; + case 'RLE_COMPRESSION': + EXRDecoder.lines = 1; + EXRDecoder.uncompress = uncompressRLE; break; - } + case 'ZIPS_COMPRESSION': + EXRDecoder.lines = 1; + EXRDecoder.uncompress = uncompressZIP; + break; - } else if ( pixelType === 2 ) { // float + case 'ZIP_COMPRESSION': + EXRDecoder.lines = 16; + EXRDecoder.uncompress = uncompressZIP; + break; - switch ( this.type ) { + case 'PIZ_COMPRESSION': + EXRDecoder.lines = 32; + EXRDecoder.uncompress = uncompressPIZ; + break; - case UnsignedByteType: - case FloatType: + case 'PXR24_COMPRESSION': + EXRDecoder.lines = 16; + EXRDecoder.uncompress = uncompressPXR; + break; - getValue = parseFloat32; - size_t = FLOAT32_SIZE; + case 'DWAA_COMPRESSION': + EXRDecoder.lines = 32; + EXRDecoder.uncompress = uncompressDWA; break; - case HalfFloatType: + case 'DWAB_COMPRESSION': + EXRDecoder.lines = 256; + EXRDecoder.uncompress = uncompressDWA; + break; - getValue = decodeFloat32; - size_t = FLOAT32_SIZE; + default: + throw new Error( 'EXRLoader.parse: ' + EXRHeader.compression + ' is unsupported' ); } - } else { - - throw 'EXRLoader.parse: unsupported pixelType ' + pixelType + ' for ' + EXRHeader.compression + '.'; - - } - - var numBlocks = dataWindowHeight / scanlineBlockSize; - - for ( var i = 0; i < numBlocks; i ++ ) { - - parseUlong( bufferDataView, offset ); // scanlineOffset + EXRDecoder.scanlineBlockSize = EXRDecoder.lines; - } - - // we should be passed the scanline offset table, start reading pixel data - - var width = EXRHeader.dataWindow.xMax - EXRHeader.dataWindow.xMin + 1; - var height = EXRHeader.dataWindow.yMax - EXRHeader.dataWindow.yMin + 1; - // Firefox only supports RGBA (half) float textures - // var numChannels = EXRHeader.channels.length; - var numChannels = 4; - var size = width * height * numChannels; - - // Fill initially with 1s for the alpha value if the texture is not RGBA, RGB values will be overwritten - switch ( this.type ) { + if ( EXRDecoder.type == 1 ) { - case UnsignedByteType: - case FloatType: + // half + switch ( outputType ) { - var byteArray = new Float32Array( size ); - - if ( EXRHeader.channels.length < numChannels ) { + case FloatType: + EXRDecoder.getter = parseFloat16; + EXRDecoder.inputSize = INT16_SIZE; + break; - byteArray.fill( 1, 0, size ); + case HalfFloatType: + EXRDecoder.getter = parseUint16; + EXRDecoder.inputSize = INT16_SIZE; + break; } - break; + } else if ( EXRDecoder.type == 2 ) { - case HalfFloatType: + // float + switch ( outputType ) { - var byteArray = new Uint16Array( size ); - - if ( EXRHeader.channels.length < numChannels ) { + case FloatType: + EXRDecoder.getter = parseFloat32; + EXRDecoder.inputSize = FLOAT32_SIZE; + break; - byteArray.fill( 0x3C00, 0, size ); // Uint16Array holds half float data, 0x3C00 is 1 + case HalfFloatType: + EXRDecoder.getter = decodeFloat32; + EXRDecoder.inputSize = FLOAT32_SIZE; } - break; - - default: - - console.error( 'THREE.EXRLoader: unsupported type: ', this.type ); - break; + } else { - } + throw new Error( 'EXRLoader.parse: unsupported pixelType ' + EXRDecoder.type + ' for ' + EXRHeader.compression + '.' ); - var channelOffsets = { - R: 0, - G: 1, - B: 2, - A: 3 - }; + } - var compressionInfo = { + EXRDecoder.blockCount = ( EXRHeader.dataWindow.yMax + 1 ) / EXRDecoder.scanlineBlockSize; - size: 0, - width: width, - lines: scanlineBlockSize, + for ( var i = 0; i < EXRDecoder.blockCount; i ++ ) + parseInt64( dataView, offset ); // scanlineOffset - offset: offset, - array: uInt8Array, - viewer: bufferDataView, + // we should be passed the scanline offset table, ready to start reading pixel data. - type: pixelType, - channels: EXRHeader.channels.length, + // RGB images will be converted to RGBA format, preventing software emulation in select devices. + EXRDecoder.outputChannels = ( ( EXRDecoder.channels == 3 ) ? 4 : EXRDecoder.channels ); + const size = EXRDecoder.width * EXRDecoder.height * EXRDecoder.outputChannels; - }; + switch ( outputType ) { - var line; - var size; - var viewer; - var tmpOffset = { value: 0 }; + case FloatType: + EXRDecoder.byteArray = new Float32Array( size ); - for ( var scanlineBlockIdx = 0; scanlineBlockIdx < height / scanlineBlockSize; scanlineBlockIdx ++ ) { + // Fill initially with 1s for the alpha value if the texture is not RGBA, RGB values will be overwritten + if ( EXRDecoder.channels < EXRDecoder.outputChannels ) + EXRDecoder.byteArray.fill( 1, 0, size ); - line = parseUint32( bufferDataView, offset ); // line_no - size = parseUint32( bufferDataView, offset ); // data_len + break; - compressionInfo.lines = ( line + scanlineBlockSize > height ) ? height - line : scanlineBlockSize; - compressionInfo.offset = offset; - compressionInfo.size = size; + case HalfFloatType: + EXRDecoder.byteArray = new Uint16Array( size ); - viewer = uncompress( compressionInfo ); + if ( EXRDecoder.channels < EXRDecoder.outputChannels ) + EXRDecoder.byteArray.fill( 0x3C00, 0, size ); // Uint16Array holds half float data, 0x3C00 is 1 - offset.value += size; + break; - for ( var line_y = 0; line_y < scanlineBlockSize; line_y ++ ) { + default: + console.error( 'THREE.EXRLoader: unsupported type: ', outputType ); + break; - var true_y = line_y + ( scanlineBlockIdx * scanlineBlockSize ); + } - if ( true_y >= height ) break; + EXRDecoder.bytesPerLine = EXRDecoder.width * EXRDecoder.inputSize * EXRDecoder.channels; - for ( var channelID = 0; channelID < EXRHeader.channels.length; channelID ++ ) { + if ( EXRDecoder.outputChannels == 4 ) { - var cOff = channelOffsets[ EXRHeader.channels[ channelID ].name ]; + EXRDecoder.format = RGBAFormat; + EXRDecoder.encoding = LinearEncoding; - for ( var x = 0; x < width; x ++ ) { + } else { - var idx = ( line_y * ( EXRHeader.channels.length * width ) ) + ( channelID * width ) + x; - tmpOffset.value = idx * size_t; + EXRDecoder.format = RedFormat; + EXRDecoder.encoding = LinearEncoding; - var val = getValue( viewer, tmpOffset ); + } - byteArray[ ( ( ( height - 1 - true_y ) * ( width * numChannels ) ) + ( x * numChannels ) ) + cOff ] = val; + return EXRDecoder; - } + } - } + // start parsing file [START] - } + const bufferDataView = new DataView( buffer ); + const uInt8Array = new Uint8Array( buffer ); + const offset = { value: 0 }; - } + // get header information and validate format. + const EXRHeader = parseHeader( bufferDataView, buffer, offset ); - if ( this.type === UnsignedByteType ) { + // get input compression information and prepare decoding. + const EXRDecoder = setupDecoder( EXRHeader, bufferDataView, uInt8Array, offset, this.type ); - let v, i; - const size = byteArray.length; - const RGBEArray = new Uint8Array( size ); + const tmpOffset = { value: 0 }; + const channelOffsets = { R: 0, G: 1, B: 2, A: 3, Y: 0 }; - for ( let h = 0; h < height; ++ h ) { + for ( let scanlineBlockIdx = 0; scanlineBlockIdx < EXRDecoder.height / EXRDecoder.scanlineBlockSize; scanlineBlockIdx ++ ) { - for ( let w = 0; w < width; ++ w ) { + const line = parseUint32( bufferDataView, offset ); // line_no + EXRDecoder.size = parseUint32( bufferDataView, offset ); // data_len + EXRDecoder.lines = ( ( line + EXRDecoder.scanlineBlockSize > EXRDecoder.height ) ? ( EXRDecoder.height - line ) : EXRDecoder.scanlineBlockSize ); - i = h * width * 4 + w * 4; + const isCompressed = EXRDecoder.size < EXRDecoder.lines * EXRDecoder.bytesPerLine; + const viewer = isCompressed ? EXRDecoder.uncompress( EXRDecoder ) : uncompressRAW( EXRDecoder ); - const red = byteArray[ i ]; - const green = byteArray[ i + 1 ]; - const blue = byteArray[ i + 2 ]; + offset.value += EXRDecoder.size; - v = ( red > green ) ? red : green; - v = ( blue > v ) ? blue : v; + for ( let line_y = 0; line_y < EXRDecoder.scanlineBlockSize; line_y ++ ) { - if ( v < 1e-32 ) { + const true_y = line_y + scanlineBlockIdx * EXRDecoder.scanlineBlockSize; + if ( true_y >= EXRDecoder.height ) break; - RGBEArray[ i ] = RGBEArray[ i + 1 ] = RGBEArray[ i + 2 ] = RGBEArray[ i + 3 ] = 0; + for ( let channelID = 0; channelID < EXRDecoder.channels; channelID ++ ) { - } else { + const cOff = channelOffsets[ EXRHeader.channels[ channelID ].name ]; - const res = frexp( v ); - v = res[ 0 ] * 256 / v; + for ( let x = 0; x < EXRDecoder.width; x ++ ) { - RGBEArray[ i ] = red * v; - RGBEArray[ i + 1 ] = green * v; - RGBEArray[ i + 2 ] = blue * v; - RGBEArray[ i + 3 ] = res[ 1 ] + 128; + tmpOffset.value = ( line_y * ( EXRDecoder.channels * EXRDecoder.width ) + channelID * EXRDecoder.width + x ) * EXRDecoder.inputSize; + const outIndex = ( EXRDecoder.height - 1 - true_y ) * ( EXRDecoder.width * EXRDecoder.outputChannels ) + x * EXRDecoder.outputChannels + cOff; + EXRDecoder.byteArray[ outIndex ] = EXRDecoder.getter( viewer, tmpOffset ); } @@ -2349,19 +2263,16 @@ class EXRLoader extends DataTextureLoader { } - byteArray = RGBEArray; - } - const format = ( this.type === UnsignedByteType ) ? RGBEFormat : ( numChannels === 4 ) ? RGBAFormat : RGBFormat; - return { header: EXRHeader, - width: width, - height: height, - data: byteArray, - format: format, - type: this.type + width: EXRDecoder.width, + height: EXRDecoder.height, + data: EXRDecoder.byteArray, + format: EXRDecoder.format, + encoding: EXRDecoder.encoding, + type: this.type, }; } @@ -2377,28 +2288,11 @@ class EXRLoader extends DataTextureLoader { function onLoadCallback( texture, texData ) { - switch ( texture.type ) { - - case UnsignedByteType: - - texture.encoding = RGBEEncoding; - texture.minFilter = NearestFilter; - texture.magFilter = NearestFilter; - texture.generateMipmaps = false; - texture.flipY = false; - break; - - case FloatType: - case HalfFloatType: - - texture.encoding = LinearEncoding; - texture.minFilter = LinearFilter; - texture.magFilter = LinearFilter; - texture.generateMipmaps = false; - texture.flipY = false; - break; - - } + texture.encoding = texData.encoding; + texture.minFilter = LinearFilter; + texture.magFilter = LinearFilter; + texture.generateMipmaps = false; + texture.flipY = false; if ( onLoad ) onLoad( texture, texData ); diff --git a/examples/jsm/loaders/FBXLoader.js b/examples/jsm/loaders/FBXLoader.js index 878f5d4361f1cf..5cd7c8b10466be 100644 --- a/examples/jsm/loaders/FBXLoader.js +++ b/examples/jsm/loaders/FBXLoader.js @@ -53,11 +53,10 @@ import { NURBSCurve } from '../curves/NURBSCurve.js'; * Morph normals / blend shape normals * * FBX format references: - * https://wiki.blender.org/index.php/User:Mont29/Foundation/FBX_File_Structure - * http://help.autodesk.com/view/FBX/2017/ENU/?guid=__cpp_ref_index_html (C++ SDK reference) + * https://help.autodesk.com/view/FBX/2017/ENU/?guid=__cpp_ref_index_html (C++ SDK reference) * - * Binary format specification: - * https://code.blender.org/2013/08/fbx-binary-file-format-specification/ + * Binary format specification: + * https://code.blender.org/2013/08/fbx-binary-file-format-specification/ */ diff --git a/examples/jsm/loaders/GLTFLoader.js b/examples/jsm/loaders/GLTFLoader.js index a6e0065aa474dd..82e7b012bff6c0 100644 --- a/examples/jsm/loaders/GLTFLoader.js +++ b/examples/jsm/loaders/GLTFLoader.js @@ -1445,7 +1445,7 @@ class GLTFTextureTransformExtension { /** * Specular-Glossiness Extension * - * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness + * Specification: https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Archived/KHR_materials_pbrSpecularGlossiness */ /** @@ -1478,7 +1478,6 @@ class GLTFMeshStandardSGMaterial extends MeshStandardMaterial { 'vec3 specularFactor = specular;', '#ifdef USE_SPECULARMAP', ' vec4 texelSpecular = texture2D( specularMap, vUv );', - ' texelSpecular = sRGBToLinear( texelSpecular );', ' // reads channel RGB, compatible with a glTF Specular-Glossiness (RGBA) texture', ' specularFactor *= texelSpecular.rgb;', '#endif' @@ -2253,7 +2252,7 @@ class GLTFParser { // Use an ImageBitmapLoader if imageBitmaps are supported. Moves much of the // expensive work of uploading a texture to the GPU off the main thread. - if ( typeof createImageBitmap !== 'undefined' && /Firefox/.test( navigator.userAgent ) === false ) { + if ( typeof createImageBitmap !== 'undefined' && /Firefox|Safari/.test( navigator.userAgent ) === false ) { this.textureLoader = new ImageBitmapLoader( this.options.manager ); diff --git a/examples/jsm/loaders/HDRCubeTextureLoader.js b/examples/jsm/loaders/HDRCubeTextureLoader.js index 84458ae3ebbfdc..d55fec78987d5d 100644 --- a/examples/jsm/loaders/HDRCubeTextureLoader.js +++ b/examples/jsm/loaders/HDRCubeTextureLoader.js @@ -7,11 +7,7 @@ import { LinearEncoding, LinearFilter, Loader, - NearestFilter, - RGBAFormat, - RGBEEncoding, - RGBFormat, - UnsignedByteType + RGBFormat } from '../../../build/three.module.js'; import { RGBELoader } from '../loaders/RGBELoader.js'; @@ -47,15 +43,6 @@ class HDRCubeTextureLoader extends Loader { switch ( texture.type ) { - case UnsignedByteType: - - texture.encoding = RGBEEncoding; - texture.format = RGBAFormat; - texture.minFilter = NearestFilter; - texture.magFilter = NearestFilter; - texture.generateMipmaps = false; - break; - case FloatType: texture.encoding = LinearEncoding; diff --git a/examples/jsm/loaders/LDrawLoader.js b/examples/jsm/loaders/LDrawLoader.js index 27b2eb8660b606..08866408d4f935 100644 --- a/examples/jsm/loaders/LDrawLoader.js +++ b/examples/jsm/loaders/LDrawLoader.js @@ -13,7 +13,8 @@ import { ShaderMaterial, UniformsLib, UniformsUtils, - Vector3 + Vector3, + Ray } from '../../../build/three.module.js'; // Special surface finish tag types. @@ -167,7 +168,28 @@ class LDrawConditionalLineMaterial extends ShaderMaterial { } -function smoothNormals( faces, lineSegments ) { +function generateFaceNormals( faces ) { + + for ( let i = 0, l = faces.length; i < l; i ++ ) { + + const face = faces[ i ]; + const vertices = face.vertices; + const v0 = vertices[ 0 ]; + const v1 = vertices[ 1 ]; + const v2 = vertices[ 2 ]; + + _tempVec0.subVectors( v1, v0 ); + _tempVec1.subVectors( v2, v1 ); + face.faceNormal = new Vector3() + .crossVectors( _tempVec0, _tempVec1 ) + .normalize(); + + } + +} + +const _ray = new Ray(); +function smoothNormals( faces, lineSegments, checkSubSegments = false ) { function hashVertex( v ) { @@ -187,7 +209,27 @@ function smoothNormals( faces, lineSegments ) { } + // converts the two vertices to a ray with a normalized direction and origin of 0, 0, 0 projected + // onto the original line. + function toNormalizedRay( v0, v1, targetRay ) { + + targetRay.direction.subVectors( v1, v0 ).normalize(); + + const scalar = v0.dot( targetRay.direction ); + targetRay.origin.copy( v0 ).addScaledVector( targetRay.direction, - scalar ); + + return targetRay; + + } + + function hashRay( ray ) { + + return hashEdge( ray.origin, ray.direction ); + + } + const hardEdges = new Set(); + const hardEdgeRays = new Map(); const halfEdgeList = {}; const normals = []; @@ -201,6 +243,43 @@ function smoothNormals( faces, lineSegments ) { hardEdges.add( hashEdge( v0, v1 ) ); hardEdges.add( hashEdge( v1, v0 ) ); + // only generate the hard edge ray map if we're checking subsegments because it's more expensive to check + // and requires more memory. + if ( checkSubSegments ) { + + // add both ray directions to the map + const ray = toNormalizedRay( v0, v1, new Ray() ); + const rh1 = hashRay( ray ); + if ( ! hardEdgeRays.has( rh1 ) ) { + + toNormalizedRay( v1, v0, ray ); + const rh2 = hashRay( ray ); + + const info = { + ray, + distances: [], + }; + + hardEdgeRays.set( rh1, info ); + hardEdgeRays.set( rh2, info ); + + } + + // store both segments ends in min, max order in the distances array to check if a face edge is a + // subsegment later. + const info = hardEdgeRays.get( rh1 ); + let d0 = info.ray.direction.dot( v0 ); + let d1 = info.ray.direction.dot( v1 ); + if ( d0 > d1 ) { + + [ d0, d1 ] = [ d1, d0 ]; + + } + + info.distances.push( d0, d1 ); + + } + } // track the half edges associated with each triangle @@ -218,7 +297,53 @@ function smoothNormals( faces, lineSegments ) { const hash = hashEdge( v0, v1 ); // don't add the triangle if the edge is supposed to be hard - if ( hardEdges.has( hash ) ) continue; + if ( hardEdges.has( hash ) ) { + + continue; + + } + + // if checking subsegments then check to see if this edge lies on a hard edge ray and whether its within any ray bounds + if ( checkSubSegments ) { + + toNormalizedRay( v0, v1, _ray ); + + const rayHash = hashRay( _ray ); + if ( hardEdgeRays.has( rayHash ) ) { + + const info = hardEdgeRays.get( rayHash ); + const { ray, distances } = info; + let d0 = ray.direction.dot( v0 ); + let d1 = ray.direction.dot( v1 ); + + if ( d0 > d1 ) { + + [ d0, d1 ] = [ d1, d0 ]; + + } + + // return early if the face edge is found to be a subsegment of a line edge meaning the edge will have "hard" normals + let found = false; + for ( let i = 0, l = distances.length; i < l; i += 2 ) { + + if ( d0 >= distances[ i ] && d1 <= distances[ i + 1 ] ) { + + found = true; + break; + + } + + } + + if ( found ) { + + continue; + + } + + } + + } const info = { index: index, @@ -462,6 +587,12 @@ class LineParser { } + getVector() { + + return new Vector3( parseFloat( this.getToken() ), parseFloat( this.getToken() ), parseFloat( this.getToken() ) ); + + } + getRemainingString() { return this.line.substring( this.currentCharIndex, this.lineLength ); @@ -666,8 +797,22 @@ function createObject( elements, elementSize, isConditionalSegments = false, tot } + // create the normals array if this is a set of faces if ( elementSize === 3 ) { + if ( ! elem.faceNormal ) { + + const v0 = vertices[ 0 ]; + const v1 = vertices[ 1 ]; + const v2 = vertices[ 2 ]; + _tempVec0.subVectors( v1, v0 ); + _tempVec1.subVectors( v2, v1 ); + elem.faceNormal = new Vector3() + .crossVectors( _tempVec0, _tempVec1 ) + .normalize(); + + } + let elemNormals = elem.normals; if ( elemNormals.length === 4 ) { @@ -683,6 +828,7 @@ function createObject( elements, elementSize, isConditionalSegments = false, tot for ( let j = 0, l = elemNormals.length; j < l; j ++ ) { + // use face normal if a vertex normal is not provided let n = elem.faceNormal; if ( elemNormals[ j ] ) { @@ -815,7 +961,7 @@ class LDrawLoader extends Loader { this.cache = new LDrawFileCache( this ); // This object is a map from file names to paths. It agilizes the paths search. If it is not set then files will be searched by trial and error. - this.fileMap = null; + this.fileMap = {}; this.rootParseScope = this.newParseScopeLevel(); @@ -825,10 +971,6 @@ class LDrawLoader extends Loader { this.parseColourMetaDirective( new LineParser( 'Edge_Colour CODE 24 VALUE #A0A0A0 EDGE #333333' ) ) ] ); - // If this flag is set to true, each subobject will be a Object. - // If not (the default), only one object which contains all the merged primitives will be created. - this.separateObjects = false; - // If this flag is set to true the vertex normals will be smoothed. this.smoothNormals = true; @@ -874,12 +1016,6 @@ class LDrawLoader extends Loader { load( url, onLoad, onProgress, onError ) { - if ( ! this.fileMap ) { - - this.fileMap = {}; - - } - const fileLoader = new FileLoader( this.manager ); fileLoader.setPath( this.path ); fileLoader.setRequestHeader( this.requestHeader ); @@ -964,9 +1100,9 @@ class LDrawLoader extends Loader { currentFileName: null, mainColourCode: parentScope ? parentScope.mainColourCode : '16', mainEdgeColourCode: parentScope ? parentScope.mainEdgeColourCode : '24', - currentMatrix: new Matrix4(), matrix: new Matrix4(), type: 'Model', + groupObject: null, // If false, it is a root material scope previous to parse isFromParse: true, @@ -975,6 +1111,7 @@ class LDrawLoader extends Loader { lineSegments: [], conditionalSegments: [], totalFaces: 0, + faceMaterials: new Set(), // If true, this object is the start of a construction step startingConstructionStep: false @@ -1060,7 +1197,7 @@ class LDrawLoader extends Loader { const name = lineParser.getToken(); if ( ! name ) { - throw 'LDrawLoader: Material name was expected after "!COLOUR tag' + lineParser.getLineNumberString() + '.'; + throw new Error( 'LDrawLoader: Material name was expected after "!COLOUR tag' + lineParser.getLineNumberString() + '.' ); } @@ -1092,7 +1229,7 @@ class LDrawLoader extends Loader { } else if ( ! colour.startsWith( '#' ) ) { - throw 'LDrawLoader: Invalid colour while parsing material' + lineParser.getLineNumberString() + '.'; + throw new Error( 'LDrawLoader: Invalid colour while parsing material' + lineParser.getLineNumberString() + '.' ); } @@ -1111,7 +1248,7 @@ class LDrawLoader extends Loader { edgeMaterial = this.getMaterial( edgeColour ); if ( ! edgeMaterial ) { - throw 'LDrawLoader: Invalid edge colour while parsing material' + lineParser.getLineNumberString() + '.'; + throw new Error( 'LDrawLoader: Invalid edge colour while parsing material' + lineParser.getLineNumberString() + '.' ); } @@ -1128,7 +1265,7 @@ class LDrawLoader extends Loader { if ( isNaN( alpha ) ) { - throw 'LDrawLoader: Invalid alpha value in material definition' + lineParser.getLineNumberString() + '.'; + throw new Error( 'LDrawLoader: Invalid alpha value in material definition' + lineParser.getLineNumberString() + '.' ); } @@ -1148,7 +1285,7 @@ class LDrawLoader extends Loader { if ( isNaN( luminance ) ) { - throw 'LDrawLoader: Invalid luminance value in material definition' + LineParser.getLineNumberString() + '.'; + throw new Error( 'LDrawLoader: Invalid luminance value in material definition' + LineParser.getLineNumberString() + '.' ); } @@ -1182,8 +1319,7 @@ class LDrawLoader extends Loader { break; default: - throw 'LDrawLoader: Unknown token "' + token + '" while parsing material' + lineParser.getLineNumberString() + '.'; - break; + throw new Error( 'LDrawLoader: Unknown token "' + token + '" while parsing material' + lineParser.getLineNumberString() + '.' ); } @@ -1327,8 +1463,7 @@ class LDrawLoader extends Loader { let startingConstructionStep = false; - const scope = this; - function parseColourCode( lineParser, forEdge ) { + const parseColourCode = ( lineParser, forEdge ) => { // Parses next colour code and returns a THREE.Material @@ -1346,31 +1481,17 @@ class LDrawLoader extends Loader { } - const material = scope.getMaterial( colourCode, currentParseScope ); + const material = this.getMaterial( colourCode, currentParseScope ); if ( ! material ) { - throw 'LDrawLoader: Unknown colour code "' + colourCode + '" is used' + lineParser.getLineNumberString() + ' but it was not defined previously.'; + throw new Error( 'LDrawLoader: Unknown colour code "' + colourCode + '" is used' + lineParser.getLineNumberString() + ' but it was not defined previously.' ); } return material; - } - - function parseVector( lp ) { - - const v = new Vector3( parseFloat( lp.getToken() ), parseFloat( lp.getToken() ), parseFloat( lp.getToken() ) ); - - if ( ! scope.separateObjects ) { - - v.applyMatrix4( currentParseScope.currentMatrix ); - - } - - return v; - - } + }; // Parse all line commands for ( let lineIndex = 0; lineIndex < numLines; lineIndex ++ ) { @@ -1419,7 +1540,7 @@ class LDrawLoader extends Loader { let inverted; let ccw; let doubleSided; - let v0, v1, v2, v3, c0, c1, faceNormal; + let v0, v1, v2, v3, c0, c1; switch ( lineType ) { @@ -1439,27 +1560,6 @@ class LDrawLoader extends Loader { currentParseScope.type = type; - const isRoot = ! parentParseScope.isFromParse; - if ( isRoot || scope.separateObjects && ! isPrimitiveType( type ) ) { - - currentParseScope.groupObject = new Group(); - - currentParseScope.groupObject.userData.startingConstructionStep = currentParseScope.startingConstructionStep; - - } - - // If the scale of the object is negated then the triangle winding order - // needs to be flipped. - if ( - currentParseScope.matrix.determinant() < 0 && ( - scope.separateObjects && isPrimitiveType( type ) || - ! scope.separateObjects - ) ) { - - currentParseScope.inverted = ! currentParseScope.inverted; - - } - faces = currentParseScope.faces; lineSegments = currentParseScope.lineSegments; conditionalSegments = currentParseScope.conditionalSegments; @@ -1615,10 +1715,10 @@ class LDrawLoader extends Loader { let fileName = lp.getRemainingString().trim().replace( /\\/g, '/' ); - if ( scope.fileMap[ fileName ] ) { + if ( this.fileMap[ fileName ] ) { // Found the subobject path in the preloaded file path map - fileName = scope.fileMap[ fileName ]; + fileName = this.fileMap[ fileName ]; } else { @@ -1651,8 +1751,8 @@ class LDrawLoader extends Loader { case '2': material = parseColourCode( lp, true ); - v0 = parseVector( lp ); - v1 = parseVector( lp ); + v0 = lp.getVector(); + v1 = lp.getVector(); segment = { material: material.userData.edgeMaterial, @@ -1671,10 +1771,10 @@ class LDrawLoader extends Loader { case '5': material = parseColourCode( lp, true ); - v0 = parseVector( lp ); - v1 = parseVector( lp ); - c0 = parseVector( lp ); - c1 = parseVector( lp ); + v0 = lp.getVector(); + v1 = lp.getVector(); + c0 = lp.getVector(); + c1 = lp.getVector(); segment = { material: material.userData.edgeMaterial.userData.conditionalEdgeMaterial, @@ -1698,28 +1798,22 @@ class LDrawLoader extends Loader { if ( ccw === true ) { - v0 = parseVector( lp ); - v1 = parseVector( lp ); - v2 = parseVector( lp ); + v0 = lp.getVector(); + v1 = lp.getVector(); + v2 = lp.getVector(); } else { - v2 = parseVector( lp ); - v1 = parseVector( lp ); - v0 = parseVector( lp ); + v2 = lp.getVector(); + v1 = lp.getVector(); + v0 = lp.getVector(); } - _tempVec0.subVectors( v1, v0 ); - _tempVec1.subVectors( v2, v1 ); - faceNormal = new Vector3() - .crossVectors( _tempVec0, _tempVec1 ) - .normalize(); - faces.push( { material: material, colourCode: material.userData.code, - faceNormal: faceNormal, + faceNormal: null, vertices: [ v0, v1, v2 ], normals: [ null, null, null ], } ); @@ -1730,7 +1824,7 @@ class LDrawLoader extends Loader { faces.push( { material: material, colourCode: material.userData.code, - faceNormal: faceNormal, + faceNormal: null, vertices: [ v2, v1, v0 ], normals: [ null, null, null ], } ); @@ -1738,6 +1832,8 @@ class LDrawLoader extends Loader { } + currentParseScope.faceMaterials.add( material ); + break; // Line type 4: Quadrilateral @@ -1751,32 +1847,26 @@ class LDrawLoader extends Loader { if ( ccw === true ) { - v0 = parseVector( lp ); - v1 = parseVector( lp ); - v2 = parseVector( lp ); - v3 = parseVector( lp ); + v0 = lp.getVector(); + v1 = lp.getVector(); + v2 = lp.getVector(); + v3 = lp.getVector(); } else { - v3 = parseVector( lp ); - v2 = parseVector( lp ); - v1 = parseVector( lp ); - v0 = parseVector( lp ); + v3 = lp.getVector(); + v2 = lp.getVector(); + v1 = lp.getVector(); + v0 = lp.getVector(); } - _tempVec0.subVectors( v1, v0 ); - _tempVec1.subVectors( v2, v1 ); - faceNormal = new Vector3() - .crossVectors( _tempVec0, _tempVec1 ) - .normalize(); - // specifically place the triangle diagonal in the v0 and v1 slots so we can // account for the doubling of vertices later when smoothing normals. faces.push( { material: material, colourCode: material.userData.code, - faceNormal: faceNormal, + faceNormal: null, vertices: [ v0, v1, v2, v3 ], normals: [ null, null, null, null ], } ); @@ -1787,7 +1877,7 @@ class LDrawLoader extends Loader { faces.push( { material: material, colourCode: material.userData.code, - faceNormal: faceNormal, + faceNormal: null, vertices: [ v3, v2, v1, v0 ], normals: [ null, null, null, null ], } ); @@ -1798,8 +1888,7 @@ class LDrawLoader extends Loader { break; default: - throw 'LDrawLoader: Unknown line type "' + lineType + '"' + lp.getLineNumberString() + '.'; - break; + throw new Error( 'LDrawLoader: Unknown line type "' + lineType + '"' + lp.getLineNumberString() + '.' ); } @@ -1817,6 +1906,14 @@ class LDrawLoader extends Loader { currentParseScope.numSubobjects = subobjects.length; currentParseScope.subobjectIndex = 0; + const isRoot = ! parentParseScope.isFromParse; + if ( isRoot || ! isPrimitiveType( type ) ) { + + currentParseScope.groupObject = new Group(); + currentParseScope.groupObject.userData.startingConstructionStep = currentParseScope.startingConstructionStep; + + } + } computeConstructionSteps( model ) { @@ -1862,19 +1959,23 @@ class LDrawLoader extends Loader { const doSmooth = isPartType( subobjectParseScope.type ) || ( - ! isPartType( subobjectParseScope.type ) && - ! isModelType( subobjectParseScope.type ) && + isPrimitiveType( subobjectParseScope.type ) && isModelType( subobjectParseScope.parentScope.type ) ); if ( this.smoothNormals && doSmooth ) { - smoothNormals( subobjectParseScope.faces, subobjectParseScope.lineSegments ); + generateFaceNormals( subobjectParseScope.faces ); + + // only check subsetgments if we have multiple materials in a single part because this seems to be the case where it's needed most -- + // there may be cases where a single edge line crosses over polygon edges that are broken up by multiple materials. + const checkSubSegments = subobjectParseScope.faceMaterials.size > 1; + smoothNormals( subobjectParseScope.faces, subobjectParseScope.lineSegments, checkSubSegments ); } const isRoot = ! parentParseScope.isFromParse; - if ( this.separateObjects && ! isPrimitiveType( subobjectParseScope.type ) || isRoot ) { + if ( ! isPrimitiveType( subobjectParseScope.type ) || isRoot ) { const objGroup = subobjectParseScope.groupObject; @@ -1909,26 +2010,24 @@ class LDrawLoader extends Loader { } else { - const separateObjects = this.separateObjects; const parentLineSegments = parentParseScope.lineSegments; const parentConditionalSegments = parentParseScope.conditionalSegments; const parentFaces = parentParseScope.faces; + const parentFaceMaterials = parentParseScope.faceMaterials; const lineSegments = subobjectParseScope.lineSegments; const conditionalSegments = subobjectParseScope.conditionalSegments; const faces = subobjectParseScope.faces; + const faceMaterials = subobjectParseScope.faceMaterials; + const matrix = subobjectParseScope.matrix; + const matrixScaleInverted = matrix.determinant() < 0; for ( let i = 0, l = lineSegments.length; i < l; i ++ ) { const ls = lineSegments[ i ]; - - if ( separateObjects ) { - - const vertices = ls.vertices; - vertices[ 0 ].applyMatrix4( subobjectParseScope.matrix ); - vertices[ 1 ].applyMatrix4( subobjectParseScope.matrix ); - - } + const vertices = ls.vertices; + vertices[ 0 ].applyMatrix4( matrix ); + vertices[ 1 ].applyMatrix4( matrix ); parentLineSegments.push( ls ); @@ -1937,17 +2036,12 @@ class LDrawLoader extends Loader { for ( let i = 0, l = conditionalSegments.length; i < l; i ++ ) { const os = conditionalSegments[ i ]; - - if ( separateObjects ) { - - const vertices = os.vertices; - const controlPoints = os.controlPoints; - vertices[ 0 ].applyMatrix4( subobjectParseScope.matrix ); - vertices[ 1 ].applyMatrix4( subobjectParseScope.matrix ); - controlPoints[ 0 ].applyMatrix4( subobjectParseScope.matrix ); - controlPoints[ 1 ].applyMatrix4( subobjectParseScope.matrix ); - - } + const vertices = os.vertices; + const controlPoints = os.controlPoints; + vertices[ 0 ].applyMatrix4( matrix ); + vertices[ 1 ].applyMatrix4( matrix ); + controlPoints[ 0 ].applyMatrix4( matrix ); + controlPoints[ 1 ].applyMatrix4( matrix ); parentConditionalSegments.push( os ); @@ -1956,19 +2050,18 @@ class LDrawLoader extends Loader { for ( let i = 0, l = faces.length; i < l; i ++ ) { const tri = faces[ i ]; + const vertices = tri.vertices; + for ( let i = 0, l = vertices.length; i < l; i ++ ) { - if ( separateObjects ) { + vertices[ i ].applyMatrix4( matrix ); - const vertices = tri.vertices; - for ( let i = 0, l = vertices.length; i < l; i ++ ) { - - vertices[ i ] = vertices[ i ].clone().applyMatrix4( subobjectParseScope.matrix ); + } - } + // If the scale of the object is negated then the triangle winding order + // needs to be flipped. + if ( matrixScaleInverted ) { - _tempVec0.subVectors( vertices[ 1 ], vertices[ 0 ] ); - _tempVec1.subVectors( vertices[ 2 ], vertices[ 1 ] ); - tri.faceNormal.crossVectors( _tempVec0, _tempVec1 ).normalize(); + vertices.reverse(); } @@ -1977,6 +2070,7 @@ class LDrawLoader extends Loader { } parentParseScope.totalFaces += subobjectParseScope.totalFaces; + faceMaterials.forEach( material => parentFaceMaterials.add( material ) ); } @@ -1994,7 +2088,6 @@ class LDrawLoader extends Loader { // Set current matrix if ( subobject ) { - parseScope.currentMatrix.multiplyMatrices( parentParseScope.currentMatrix, subobject.matrix ); parseScope.matrix.copy( subobject.matrix ); parseScope.inverted = subobject.inverted; parseScope.startingConstructionStep = subobject.startingConstructionStep; @@ -2040,9 +2133,10 @@ class LDrawLoader extends Loader { return scope.processObject( text, subobject, url, parseScope ); - } ).catch( function () { + } ).catch( function ( err ) { - console.warn( 'LDrawLoader: Subobject "' + subobject.fileName + '" could not be found.' ); + console.warn( 'LDrawLoader: Subobject "' + subobject.fileName + '" could not be loaded.' ); + console.warn( err ); return null; } ); diff --git a/examples/jsm/loaders/MMDLoader.js b/examples/jsm/loaders/MMDLoader.js index 1675be0f12c626..9e00f5bedc12ba 100644 --- a/examples/jsm/loaders/MMDLoader.js +++ b/examples/jsm/loaders/MMDLoader.js @@ -357,7 +357,6 @@ class MMDLoader extends Loader { /* * base64 encoded defalut toon textures toon00.bmp - toon10.bmp. * We don't need to request external toon image files. - * This idea is from http://www20.atpages.jp/katwat/three.js_r58/examples/mytest37/mmd.three.js */ const DEFAULT_TOON_TEXTURES = [ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=', diff --git a/examples/jsm/loaders/NRRDLoader.js b/examples/jsm/loaders/NRRDLoader.js index 8ffb3135c7afaf..512d6d11a0ea56 100644 --- a/examples/jsm/loaders/NRRDLoader.js +++ b/examples/jsm/loaders/NRRDLoader.js @@ -208,7 +208,11 @@ class NRRDLoader extends Loader { if ( ! headerObject.vectors ) { //if no space direction is set, let's use the identity - headerObject.vectors = [ new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ) ]; + headerObject.vectors = [ ]; + headerObject.vectors.push( [ 1, 0, 0 ] ); + headerObject.vectors.push( [ 0, 1, 0 ] ); + headerObject.vectors.push( [ 0, 0, 1 ] ); + //apply spacing if defined if ( headerObject.spacings ) { @@ -216,7 +220,11 @@ class NRRDLoader extends Loader { if ( ! isNaN( headerObject.spacings[ i ] ) ) { - headerObject.vectors[ i ].multiplyScalar( headerObject.spacings[ i ] ); + for ( let j = 0; j <= 2; j ++ ) { + + headerObject.vectors[ i ][ j ] *= headerObject.spacings[ i ]; + + } } diff --git a/examples/jsm/loaders/OBJLoader.js b/examples/jsm/loaders/OBJLoader.js index 745ae0e315f114..883bd194cd74a9 100644 --- a/examples/jsm/loaders/OBJLoader.js +++ b/examples/jsm/loaders/OBJLoader.js @@ -684,8 +684,6 @@ class OBJLoader extends Loader { /* * http://paulbourke.net/dataformats/obj/ - * or - * http://www.cs.utah.edu/~boulos/cs3505/obj_spec.pdf * * From chapter "Grouping" Syntax explanation "s group_number": * "group_number is the smoothing group number. To turn off smoothing groups, use a value of 0 or off. diff --git a/examples/jsm/loaders/PLYLoader.js b/examples/jsm/loaders/PLYLoader.js index 8f12d8ca987090..759652e1dc3d94 100644 --- a/examples/jsm/loaders/PLYLoader.js +++ b/examples/jsm/loaders/PLYLoader.js @@ -88,7 +88,7 @@ class PLYLoader extends Loader { function parseHeader( data ) { - const patternHeader = /ply([\s\S]*)end_header\r?\n/; + const patternHeader = /^ply([\s\S]*)end_header\r?\n/; let headerText = ''; let headerLength = 0; const result = patternHeader.exec( data ); diff --git a/examples/jsm/loaders/RGBELoader.js b/examples/jsm/loaders/RGBELoader.js index 9edd8a48dbf5ea..b3df5301074ca7 100644 --- a/examples/jsm/loaders/RGBELoader.js +++ b/examples/jsm/loaders/RGBELoader.js @@ -5,11 +5,7 @@ import { HalfFloatType, LinearEncoding, LinearFilter, - NearestFilter, - RGBEEncoding, - RGBEFormat, RGBFormat, - UnsignedByteType } from '../../../build/three.module.js'; // https://github.com/mrdoob/three.js/issues/5552 @@ -378,13 +374,6 @@ class RGBELoader extends DataTextureLoader { switch ( this.type ) { - case UnsignedByteType: - - data = image_rgba_data; - format = RGBEFormat; // handled as THREE.RGBAFormat in shaders - type = UnsignedByteType; - break; - case FloatType: numElements = image_rgba_data.length / 4; @@ -455,15 +444,6 @@ class RGBELoader extends DataTextureLoader { switch ( texture.type ) { - case UnsignedByteType: - - texture.encoding = RGBEEncoding; - texture.minFilter = NearestFilter; - texture.magFilter = NearestFilter; - texture.generateMipmaps = false; - texture.flipY = true; - break; - case FloatType: texture.encoding = LinearEncoding; diff --git a/examples/jsm/loaders/RGBMLoader.js b/examples/jsm/loaders/RGBMLoader.js index a1e87cd8e842e3..8047fda2fc06dd 100644 --- a/examples/jsm/loaders/RGBMLoader.js +++ b/examples/jsm/loaders/RGBMLoader.js @@ -1,14 +1,37 @@ import { DataTextureLoader, - UnsignedByteType, RGBAFormat, LinearFilter, CubeTexture, - RGBM7Encoding + HalfFloatType, + DataUtils } from '../../../build/three.module.js'; class RGBMLoader extends DataTextureLoader { + constructor( manager ) { + + super( manager ); + + this.type = HalfFloatType; + this.maxRange = 7; // more information about this property at https://iwasbeingirony.blogspot.com/2010/06/difference-between-rgbm-and-rgbd.html + + } + + setDataType( value ) { + + this.type = value; + return this; + + } + + setMaxRange( value ) { + + this.maxRange = value; + return this; + + } + loadCubemap( urls, onLoad, onProgress, onError ) { const texture = new CubeTexture(); @@ -43,7 +66,7 @@ class RGBMLoader extends DataTextureLoader { } - texture.encoding = RGBM7Encoding; + texture.type = this.type; texture.format = RGBAFormat; texture.minFilter = LinearFilter; texture.generateMipmaps = false; @@ -57,14 +80,45 @@ class RGBMLoader extends DataTextureLoader { const img = UPNG.decode( buffer ); const rgba = UPNG.toRGBA8( img )[ 0 ]; + const data = new Uint8Array( rgba ); + const size = img.width * img.height * 4; + + const output = ( this.type === HalfFloatType ) ? new Uint16Array( size ) : new Float32Array( size ); + + // decode RGBM + + for ( let i = 0; i < data.length; i += 4 ) { + + const r = data[ i + 0 ] / 255; + const g = data[ i + 1 ] / 255; + const b = data[ i + 2 ] / 255; + const a = data[ i + 3 ] / 255; + + if ( this.type === HalfFloatType ) { + + output[ i + 0 ] = DataUtils.toHalfFloat( Math.min( r * a * this.maxRange, 65504 ) ); + output[ i + 1 ] = DataUtils.toHalfFloat( Math.min( g * a * this.maxRange, 65504 ) ); + output[ i + 2 ] = DataUtils.toHalfFloat( Math.min( b * a * this.maxRange, 65504 ) ); + output[ i + 3 ] = DataUtils.toHalfFloat( 1 ); + + } else { + + output[ i + 0 ] = r * a * this.maxRange; + output[ i + 1 ] = g * a * this.maxRange; + output[ i + 2 ] = b * a * this.maxRange; + output[ i + 3 ] = 1; + + } + + } + return { width: img.width, height: img.height, - data: new Uint8Array( rgba ), + data: output, format: RGBAFormat, - type: UnsignedByteType, - flipY: true, - encoding: RGBM7Encoding + type: this.type, + flipY: true }; } @@ -274,7 +328,7 @@ UPNG.decode = function ( buff ) { var fd, foff = 0; // frames var mgck = [ 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a ]; - for ( var i = 0; i < 8; i ++ ) if ( data[ i ] != mgck[ i ] ) throw 'The input is not a PNG file!'; + for ( var i = 0; i < 8; i ++ ) if ( data[ i ] != mgck[ i ] ) throw new Error( 'The input is not a PNG file!' ); while ( offset < data.length ) { diff --git a/examples/jsm/loaders/VRMLLoader.js b/examples/jsm/loaders/VRMLLoader.js index d31ec9ba344508..e31b898db55d13 100644 --- a/examples/jsm/loaders/VRMLLoader.js +++ b/examples/jsm/loaders/VRMLLoader.js @@ -192,7 +192,7 @@ class VRMLLoader extends Loader { // - const StringLiteral = createToken( { name: 'StringLiteral', pattern: /"(:?[^\\"\n\r]+|\\(:?[bfnrtv"\\/]|u[0-9a-fA-F]{4}))*"/ } ); + const StringLiteral = createToken( { name: 'StringLiteral', pattern: /"(?:[^\\"\n\r]|\\[bfnrtv"\\/]|\\u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])*"/ } ); const HexLiteral = createToken( { name: 'HexLiteral', pattern: /0[xX][0-9a-fA-F]+/ } ); const NumberLiteral = createToken( { name: 'NumberLiteral', pattern: /[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?/ } ); const TrueLiteral = createToken( { name: 'TrueLiteral', pattern: /TRUE/ } ); diff --git a/examples/jsm/math/ImprovedNoise.js b/examples/jsm/math/ImprovedNoise.js index 8e197e5f375128..5647d1b208d9e4 100644 --- a/examples/jsm/math/ImprovedNoise.js +++ b/examples/jsm/math/ImprovedNoise.js @@ -1,4 +1,4 @@ -// http://mrl.nyu.edu/~perlin/noise/ +// https://cs.nyu.edu/~perlin/noise/ const _p = [ 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, diff --git a/examples/jsm/misc/Volume.js b/examples/jsm/misc/Volume.js index 8b85c3fc057e67..ccbdfb3248f9f9 100644 --- a/examples/jsm/misc/Volume.js +++ b/examples/jsm/misc/Volume.js @@ -99,7 +99,7 @@ function Volume( xLength, yLength, zLength, type, arrayBuffer ) { case 'unsigned long long int' : case 'uint64' : case 'uint64_t' : - throw 'Error in Volume constructor : this type is not supported in JavaScript'; + throw new Error( 'Error in Volume constructor : this type is not supported in JavaScript' ); break; case 'Float32' : case 'float32' : @@ -118,7 +118,7 @@ function Volume( xLength, yLength, zLength, type, arrayBuffer ) { if ( this.data.length !== this.xLength * this.yLength * this.zLength ) { - throw 'Error in Volume constructor, lengths are not matching arrayBuffer size'; + throw new Error( 'Error in Volume constructor, lengths are not matching arrayBuffer size' ); } diff --git a/examples/jsm/modifiers/EdgeSplitModifier.js b/examples/jsm/modifiers/EdgeSplitModifier.js index 3b9eb9edbea8df..c0a129c21ab3d6 100644 --- a/examples/jsm/modifiers/EdgeSplitModifier.js +++ b/examples/jsm/modifiers/EdgeSplitModifier.js @@ -183,7 +183,7 @@ class EdgeSplitModifier { if ( BufferGeometryUtils === undefined ) { - throw 'THREE.EdgeSplitModifier relies on BufferGeometryUtils'; + throw new Error( 'THREE.EdgeSplitModifier relies on BufferGeometryUtils' ); } diff --git a/examples/jsm/modifiers/SimplifyModifier.js b/examples/jsm/modifiers/SimplifyModifier.js index 6c1f8d1631304e..4483c24d805800 100644 --- a/examples/jsm/modifiers/SimplifyModifier.js +++ b/examples/jsm/modifiers/SimplifyModifier.js @@ -21,7 +21,7 @@ class SimplifyModifier { if ( BufferGeometryUtils === undefined ) { - throw 'THREE.SimplifyModifier relies on BufferGeometryUtils'; + throw new Error( 'THREE.SimplifyModifier relies on BufferGeometryUtils' ); } diff --git a/examples/jsm/nodes/core/NodeBuilder.js b/examples/jsm/nodes/core/NodeBuilder.js index f3f875d6fc7429..6856b5aa6b74ed 100644 --- a/examples/jsm/nodes/core/NodeBuilder.js +++ b/examples/jsm/nodes/core/NodeBuilder.js @@ -4,7 +4,7 @@ import { CubeUVReflectionMapping, CubeUVRefractionMapping, LinearEncoding, - GammaEncoding + sRGBEncoding } from '../../../../build/three.module.js'; import { NodeUniform } from './NodeUniform.js'; @@ -951,7 +951,7 @@ class NodeBuilder { if ( encoding === LinearEncoding && this.context.gamma ) { - encoding = GammaEncoding; + encoding = sRGBEncoding; } diff --git a/examples/jsm/nodes/materials/nodes/StandardNode.js b/examples/jsm/nodes/materials/nodes/StandardNode.js index 3990413e7faaf2..0c8ffe626d17eb 100644 --- a/examples/jsm/nodes/materials/nodes/StandardNode.js +++ b/examples/jsm/nodes/materials/nodes/StandardNode.js @@ -32,6 +32,7 @@ class StandardNode extends Node { if ( useClearcoat ) { builder.define( 'CLEARCOAT' ); + builder.define( 'USE_CLEARCOAT' ); } diff --git a/examples/jsm/nodes/math/MathNode.js b/examples/jsm/nodes/math/MathNode.js index 8cc7e0d2192c4e..8237f410cf2452 100644 --- a/examples/jsm/nodes/math/MathNode.js +++ b/examples/jsm/nodes/math/MathNode.js @@ -18,6 +18,14 @@ class MathNode extends TempNode { switch ( this.method ) { + // variable + + case MathNode.ARCTAN: + + return this.b ? 2 : 1; + + // 3 + case MathNode.MIX: case MathNode.CLAMP: case MathNode.REFRACT: @@ -26,6 +34,8 @@ class MathNode extends TempNode { return 3; + // 2 + case MathNode.MIN: case MathNode.MAX: case MathNode.MOD: @@ -38,6 +48,8 @@ class MathNode extends TempNode { return 2; + // 1 + default: return 1; diff --git a/examples/jsm/nodes/misc/BumpMapNode.js b/examples/jsm/nodes/misc/BumpMapNode.js index 2e65c345868dbc..83e5c27150199a 100644 --- a/examples/jsm/nodes/misc/BumpMapNode.js +++ b/examples/jsm/nodes/misc/BumpMapNode.js @@ -90,7 +90,7 @@ class BumpMapNode extends TempNode { BumpMapNode.Nodes = ( function () { // Bump Mapping Unparametrized Surfaces on the GPU by Morten S. Mikkelsen - // http://api.unrealengine.com/attachments/Engine/Rendering/LightingAndShadows/BumpMappingWithoutTangentSpace/mm_sfgrad_bump.pdf + // https://mmikk.github.io/papers3d/mm_sfgrad_bump.pdf // Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2) diff --git a/examples/jsm/nodes/misc/TextureCubeUVNode.js b/examples/jsm/nodes/misc/TextureCubeUVNode.js index 6662afb734e9ba..ed2962f4f919c8 100644 --- a/examples/jsm/nodes/misc/TextureCubeUVNode.js +++ b/examples/jsm/nodes/misc/TextureCubeUVNode.js @@ -26,19 +26,15 @@ class TextureCubeUVNode extends TempNode { const bilinearCubeUV = new FunctionCallNode( TextureCubeUVNode.Nodes.bilinearCubeUV, [ texture, uv, mipInt ] ); this.colorSpaceTL = this.colorSpaceTL || new ColorSpaceNode( new ExpressionNode( '', 'v4' ) ); - this.colorSpaceTL.fromDecoding( builder.getTextureEncodingFromMap( this.value.value ) ); this.colorSpaceTL.input.parse( bilinearCubeUV.build( builder ) + '.tl' ); this.colorSpaceTR = this.colorSpaceTR || new ColorSpaceNode( new ExpressionNode( '', 'v4' ) ); - this.colorSpaceTR.fromDecoding( builder.getTextureEncodingFromMap( this.value.value ) ); this.colorSpaceTR.input.parse( bilinearCubeUV.build( builder ) + '.tr' ); this.colorSpaceBL = this.colorSpaceBL || new ColorSpaceNode( new ExpressionNode( '', 'v4' ) ); - this.colorSpaceBL.fromDecoding( builder.getTextureEncodingFromMap( this.value.value ) ); this.colorSpaceBL.input.parse( bilinearCubeUV.build( builder ) + '.bl' ); this.colorSpaceBR = this.colorSpaceBR || new ColorSpaceNode( new ExpressionNode( '', 'v4' ) ); - this.colorSpaceBR.fromDecoding( builder.getTextureEncodingFromMap( this.value.value ) ); this.colorSpaceBR.input.parse( bilinearCubeUV.build( builder ) + '.br' ); // add a custom context for fix incompatibility with the core @@ -230,6 +226,7 @@ TextureCubeUVNode.Nodes = ( function () { return TextureCubeUVData( tl, tr, br, bl, f ); }`, [ TextureCubeUVData, getFace, getUV, cubeUV_maxMipLevel, cubeUV_minMipLevel, cubeUV_maxTileSize, cubeUV_minTileSize ] ); + bilinearCubeUV.useKeywords = false; // These defines must match with PMREMGenerator diff --git a/examples/jsm/nodes/utils/ColorSpaceNode.js b/examples/jsm/nodes/utils/ColorSpaceNode.js index f0ea993465f5ac..d9cea7de466359 100644 --- a/examples/jsm/nodes/utils/ColorSpaceNode.js +++ b/examples/jsm/nodes/utils/ColorSpaceNode.js @@ -1,17 +1,10 @@ import { - GammaEncoding, LinearEncoding, - RGBEEncoding, - RGBM7Encoding, - RGBM16Encoding, - RGBDEncoding, sRGBEncoding } from '../../../../build/three.module.js'; import { TempNode } from '../core/TempNode.js'; -import { FloatNode } from '../inputs/FloatNode.js'; import { FunctionNode } from '../core/FunctionNode.js'; -import { ExpressionNode } from '../core/ExpressionNode.js'; class ColorSpaceNode extends TempNode { @@ -64,9 +57,11 @@ class ColorSpaceNode extends TempNode { } - fromDecoding( encoding ) { + fromDecoding() { - const components = ColorSpaceNode.getEncodingComponents( encoding ); + // TODO: Remove fromDecoding() + + const components = ColorSpaceNode.getEncodingComponents( LinearEncoding ); this.method = components[ 0 ] + 'ToLinear'; this.factor = components[ 1 ]; @@ -105,8 +100,6 @@ class ColorSpaceNode extends TempNode { ColorSpaceNode.Nodes = ( function () { - // For a discussion of what this is, please read this: http://lousodrome.net/blog/light/2013/05/26/gamma-correct-and-hdr-rendering-in-a-32-bits-buffer/ - const LinearToLinear = new FunctionNode( /* glsl */` vec4 LinearToLinear( in vec4 value ) { @@ -115,30 +108,6 @@ ColorSpaceNode.Nodes = ( function () { }` ); - const GammaToLinear = new FunctionNode( /* glsl */` - vec4 GammaToLinear( in vec4 value, in float gammaFactor ) { - - return vec4( pow( value.xyz, vec3( gammaFactor ) ), value.w ); - - }` - ); - - const LinearToGamma = new FunctionNode( /* glsl */` - vec4 LinearToGamma( in vec4 value, in float gammaFactor ) { - - return vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w ); - - }` - ); - - const sRGBToLinear = new FunctionNode( /* glsl */` - vec4 sRGBToLinear( in vec4 value ) { - - return vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.w ); - - }` - ); - const LinearTosRGB = new FunctionNode( /* glsl */` vec4 LinearTosRGB( in vec4 value ) { @@ -147,99 +116,16 @@ ColorSpaceNode.Nodes = ( function () { }` ); - const RGBEToLinear = new FunctionNode( /* glsl */` - vec4 RGBEToLinear( in vec4 value ) { - - return vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 ); - - }` - ); - - const LinearToRGBE = new FunctionNode( /* glsl */` - vec4 LinearToRGBE( in vec4 value ) { - - float maxComponent = max( max( value.r, value.g ), value.b ); - float fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 ); - return vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 ); - - }` - ); - - // reference: http://iwasbeingirony.blogspot.ca/2010/06/difference-between-rgbm-and-rgbd.html - - const RGBMToLinear = new FunctionNode( /* glsl */` - vec3 RGBMToLinear( in vec4 value, in float maxRange ) { - - return vec4( value.xyz * value.w * maxRange, 1.0 ); - - }` - ); - - const LinearToRGBM = new FunctionNode( /* glsl */` - vec3 LinearToRGBM( in vec4 value, in float maxRange ) { - - float maxRGB = max( value.x, max( value.g, value.b ) ); - float M = clamp( maxRGB / maxRange, 0.0, 1.0 ); - M = ceil( M * 255.0 ) / 255.0; - return vec4( value.rgb / ( M * maxRange ), M ); - - }` - ); - - // reference: http://iwasbeingirony.blogspot.ca/2010/06/difference-between-rgbm-and-rgbd.html - - const RGBDToLinear = new FunctionNode( /* glsl */` - vec3 RGBDToLinear( in vec4 value, in float maxRange ) { - - return vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 ); - - }` - ); - - const LinearToRGBD = new FunctionNode( /* glsl */` - vec3 LinearToRGBD( in vec4 value, in float maxRange ) { - - float maxRGB = max( value.x, max( value.g, value.b ) ); - float D = max( maxRange / maxRGB, 1.0 ); - D = clamp( floor( D ) / 255.0, 0.0, 1.0 ); - return vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D ); - - }` - ); - return { LinearToLinear: LinearToLinear, - GammaToLinear: GammaToLinear, - LinearToGamma: LinearToGamma, - sRGBToLinear: sRGBToLinear, - LinearTosRGB: LinearTosRGB, - RGBEToLinear: RGBEToLinear, - LinearToRGBE: LinearToRGBE, - RGBMToLinear: RGBMToLinear, - LinearToRGBM: LinearToRGBM, - RGBDToLinear: RGBDToLinear, - LinearToRGBD: LinearToRGBD + LinearTosRGB: LinearTosRGB }; } )(); ColorSpaceNode.LINEAR_TO_LINEAR = 'LinearToLinear'; - -ColorSpaceNode.GAMMA_TO_LINEAR = 'GammaToLinear'; -ColorSpaceNode.LINEAR_TO_GAMMA = 'LinearToGamma'; - -ColorSpaceNode.SRGB_TO_LINEAR = 'sRGBToLinear'; ColorSpaceNode.LINEAR_TO_SRGB = 'LinearTosRGB'; -ColorSpaceNode.RGBE_TO_LINEAR = 'RGBEToLinear'; -ColorSpaceNode.LINEAR_TO_RGBE = 'LinearToRGBE'; - -ColorSpaceNode.RGBM_TO_LINEAR = 'RGBMToLinear'; -ColorSpaceNode.LINEAR_TO_RGBM = 'LinearToRGBM'; - -ColorSpaceNode.RGBD_TO_LINEAR = 'RGBDToLinear'; -ColorSpaceNode.LINEAR_TO_RGBD = 'LinearToRGBD'; - ColorSpaceNode.getEncodingComponents = function ( encoding ) { switch ( encoding ) { @@ -248,16 +134,6 @@ ColorSpaceNode.getEncodingComponents = function ( encoding ) { return [ 'Linear' ]; case sRGBEncoding: return [ 'sRGB' ]; - case RGBEEncoding: - return [ 'RGBE' ]; - case RGBM7Encoding: - return [ 'RGBM', new FloatNode( 7.0 ).setReadonly( true ) ]; - case RGBM16Encoding: - return [ 'RGBM', new FloatNode( 16.0 ).setReadonly( true ) ]; - case RGBDEncoding: - return [ 'RGBD', new FloatNode( 256.0 ).setReadonly( true ) ]; - case GammaEncoding: - return [ 'Gamma', new ExpressionNode( 'float( GAMMA_FACTOR )', 'f' ) ]; } diff --git a/examples/jsm/objects/Sky.js b/examples/jsm/objects/Sky.js index 0c8c708fa2f99c..92b8358d477828 100644 --- a/examples/jsm/objects/Sky.js +++ b/examples/jsm/objects/Sky.js @@ -13,7 +13,7 @@ import { * https://www.researchgate.net/publication/220720443_A_Practical_Analytic_Model_for_Daylight * * First implemented by Simon Wallner - * http://www.simonwallner.at/projects/atmospheric-scattering + * http://simonwallner.at/project/atmospheric-scattering/ * * Improved by Martin Upitis * http://blenderartists.org/forum/showthread.php?245954-preethams-sky-impementation-HDR diff --git a/examples/jsm/objects/Water.js b/examples/jsm/objects/Water.js index 1c72a0373b8ad6..d619d69c9ce21e 100644 --- a/examples/jsm/objects/Water.js +++ b/examples/jsm/objects/Water.js @@ -18,8 +18,8 @@ import { /** * Work based on : - * http://slayvin.net : Flat mirror for three.js - * http://www.adelphi.edu/~stemkoski : An implementation of water shader based on the flat mirror + * https://github.com/Slayvin: Flat mirror for three.js + * https://home.adelphi.edu/~stemkoski/ : An implementation of water shader based on the flat mirror * http://29a.ch/ && http://29a.ch/slides/2012/webglwater/ : Water shader explanations in WebGL */ diff --git a/examples/jsm/objects/Water2.js b/examples/jsm/objects/Water2.js index d56c77e6080274..b909c30cfcba5c 100644 --- a/examples/jsm/objects/Water2.js +++ b/examples/jsm/objects/Water2.js @@ -16,8 +16,8 @@ import { Refractor } from '../objects/Refractor.js'; /** * References: - * http://www.valvesoftware.com/publications/2010/siggraph2010_vlachos_waterflow.pdf - * http://graphicsrunner.blogspot.de/2010/08/water-using-flow-maps.html + * https://alex.vlachos.com/graphics/Vlachos-SIGGRAPH10-WaterFlow.pdf + * http://graphicsrunner.blogspot.de/2010/08/water-using-flow-maps.html * */ diff --git a/examples/jsm/renderers/nodes/display/ColorSpaceNode.js b/examples/jsm/renderers/nodes/display/ColorSpaceNode.js index b94b94d822b8d6..adc07d87963741 100644 --- a/examples/jsm/renderers/nodes/display/ColorSpaceNode.js +++ b/examples/jsm/renderers/nodes/display/ColorSpaceNode.js @@ -1,12 +1,10 @@ import TempNode from '../core/Node.js'; import { ShaderNode, vec3, - pow, mul, add, sub, mix, join, + pow, mul, sub, mix, join, lessThanEqual } from '../ShaderNode.js'; -import { LinearEncoding, - sRGBEncoding/*, RGBEEncoding, RGBM7Encoding, RGBM16Encoding, - RGBDEncoding, GammaEncoding*/ } from '../../../../../build/three.module.js'; +import { LinearEncoding, sRGBEncoding } from '../../../../../build/three.module.js'; export const LinearToLinear = new ShaderNode( ( inputs ) => { @@ -14,22 +12,6 @@ export const LinearToLinear = new ShaderNode( ( inputs ) => { } ); -export const sRGBToLinear = new ShaderNode( ( inputs ) => { - - const { value } = inputs; - - const rgb = value.rgb; - - const a = pow( add( mul( rgb, 0.9478672986 ), vec3( 0.0521327014 ) ), vec3( 2.4 ) ); - const b = mul( rgb, 0.0773993808 ); - const factor = vec3( lessThanEqual( rgb, vec3( 0.04045 ) ) ); - - const rgbResult = mix( a, b, factor ); - - return join( rgbResult.r, rgbResult.g, rgbResult.b, value.a ); - -} ); - export const LinearTosRGB = new ShaderNode( ( inputs ) => { const { value } = inputs; @@ -48,7 +30,6 @@ export const LinearTosRGB = new ShaderNode( ( inputs ) => { const EncodingLib = { LinearToLinear, - sRGBToLinear, LinearTosRGB }; @@ -60,18 +41,6 @@ function getEncodingComponents( encoding ) { return [ 'Linear' ]; case sRGBEncoding: return [ 'sRGB' ]; -/* - case RGBEEncoding: - return [ 'RGBE' ]; - case RGBM7Encoding: - return [ 'RGBM', new FloatNode( 7.0 ).setConst( true ) ]; - case RGBM16Encoding: - return [ 'RGBM', new FloatNode( 16.0 ).setConst( true ) ]; - case RGBDEncoding: - return [ 'RGBD', new FloatNode( 256.0 ).setConst( true ) ]; - case GammaEncoding: - return [ 'Gamma', new CodeNode( 'float( GAMMA_FACTOR )' ) ]; -*/ } @@ -80,22 +49,8 @@ function getEncodingComponents( encoding ) { class ColorSpaceNode extends TempNode { static LINEAR_TO_LINEAR = 'LinearToLinear'; - - static SRGB_TO_LINEAR = 'sRGBToLinear'; static LINEAR_TO_SRGB = 'LinearTosRGB'; - /* - static GAMMA_TO_LINEAR = 'GammaToLinear'; - static LINEAR_TO_GAMMA = 'LinearToGamma'; - static RGBE_TO_LINEAR = 'RGBEToLinear'; - static LINEAR_TO_RGBE = 'LinearToRGBE'; - - static RGBM_TO_LINEAR = 'RGBMToLinear'; - static LINEAR_TO_RGBM = 'LinearToRGBM'; - - static RGBD_TO_LINEAR = 'RGBDToLinear'; - static LINEAR_TO_RGBD = 'LinearToRGBD'; -*/ constructor( method, node ) { super( 'vec4' ); @@ -118,9 +73,11 @@ class ColorSpaceNode extends TempNode { } - fromDecoding( encoding ) { + fromDecoding() { - const components = getEncodingComponents( encoding ); + // TODO: Remove fromDecoding() + + const components = getEncodingComponents( LinearEncoding ); this.method = components[ 0 ] + 'ToLinear'; this.factor = components[ 1 ]; diff --git a/examples/jsm/renderers/nodes/math/MathNode.js b/examples/jsm/renderers/nodes/math/MathNode.js index 40d76b374e4f05..eaf57f9fb39d8b 100644 --- a/examples/jsm/renderers/nodes/math/MathNode.js +++ b/examples/jsm/renderers/nodes/math/MathNode.js @@ -187,7 +187,7 @@ class MathNode extends TempNode { } else if ( method === MathNode.STEP ) { params.push( - b.build( builder, builder.getTypeLength( a.getNodeType( builder ) ) === 1 ? 'float' : inputType ), + a.build( builder, builder.getTypeLength( a.getNodeType( builder ) ) === 1 ? 'float' : inputType ), b.build( builder, inputType ) ); diff --git a/examples/jsm/renderers/webgl/nodes/WebGLNodeBuilder.js b/examples/jsm/renderers/webgl/nodes/WebGLNodeBuilder.js index e0b9a27a12a5d7..ea6c5d08136e7b 100644 --- a/examples/jsm/renderers/webgl/nodes/WebGLNodeBuilder.js +++ b/examples/jsm/renderers/webgl/nodes/WebGLNodeBuilder.js @@ -116,15 +116,15 @@ class WebGLNodeBuilder extends NodeBuilder { } - if ( material.sizeNode && material.sizeNode.isNode ) { + if ( material.positionNode && material.positionNode.isNode ) { - this.addSlot( 'vertex', new SlotNode( material.sizeNode, 'SIZE', 'float' ) ); + this.addSlot( 'vertex', new SlotNode( material.positionNode, 'POSITION', 'vec3' ) ); } - if ( material.positionNode && material.positionNode.isNode ) { + if ( material.sizeNode && material.sizeNode.isNode ) { - this.addSlot( 'vertex', new SlotNode( material.positionNode, 'POSITION', 'vec3' ) ); + this.addSlot( 'vertex', new SlotNode( material.sizeNode, 'SIZE', 'float' ) ); } @@ -376,8 +376,8 @@ ${this.shader[ getShaderStageProperty( shaderStage ) ]} this.parseInclude( 'fragment', 'lights_physical_fragment' ); const colorSlot = this.getSlot( 'fragment', 'COLOR' ); - const normalSlot = this.getSlot( 'fragment', 'NORMAL' ); const opacityNode = this.getSlot( 'fragment', 'OPACITY' ); + const normalSlot = this.getSlot( 'fragment', 'NORMAL' ); const emissiveNode = this.getSlot( 'fragment', 'EMISSIVE' ); const roughnessNode = this.getSlot( 'fragment', 'ROUGHNESS' ); const metalnessNode = this.getSlot( 'fragment', 'METALNESS' ); @@ -397,22 +397,22 @@ ${this.shader[ getShaderStageProperty( shaderStage ) ]} } - if ( normalSlot !== undefined ) { + if ( opacityNode !== undefined ) { this.addCodeAfterInclude( 'fragment', - 'normal_fragment_begin', - `${normalSlot.code}\n\tnormal = ${normalSlot.result};` + 'alphatest_fragment', + `${opacityNode.code}\n\tdiffuseColor.a = ${opacityNode.result};` ); } - if ( opacityNode !== undefined ) { + if ( normalSlot !== undefined ) { this.addCodeAfterInclude( 'fragment', - 'alphamap_fragment', - `${opacityNode.code}\n\tdiffuseColor.a = ${opacityNode.result};` + 'normal_fragment_begin', + `${normalSlot.code}\n\tnormal = ${normalSlot.result};` ); } diff --git a/examples/jsm/renderers/webgpu/WebGPUObjects.js b/examples/jsm/renderers/webgpu/WebGPUObjects.js index 2c732eed126ba0..06a42fbbe81777 100644 --- a/examples/jsm/renderers/webgpu/WebGPUObjects.js +++ b/examples/jsm/renderers/webgpu/WebGPUObjects.js @@ -17,7 +17,7 @@ class WebGPUObjects { if ( geometry.isBufferGeometry !== true ) { - throw 'THREE.WebGPURenderer: This renderer only supports THREE.BufferGeometry for geometries.'; + throw new Error( 'THREE.WebGPURenderer: This renderer only supports THREE.BufferGeometry for geometries.' ); } diff --git a/examples/jsm/shaders/GammaCorrectionShader.js b/examples/jsm/shaders/GammaCorrectionShader.js index e2f9546e2a53fd..7108187c2067e2 100644 --- a/examples/jsm/shaders/GammaCorrectionShader.js +++ b/examples/jsm/shaders/GammaCorrectionShader.js @@ -32,7 +32,7 @@ const GammaCorrectionShader = { vec4 tex = texture2D( tDiffuse, vUv ); - gl_FragColor = LinearTosRGB( tex ); // optional: LinearToGamma( tex, float( GAMMA_FACTOR ) ); + gl_FragColor = LinearTosRGB( tex ); }` diff --git a/examples/jsm/shaders/SSRShader.js b/examples/jsm/shaders/SSRShader.js index 74d1441d8e7f88..0169e45163bdbe 100644 --- a/examples/jsm/shaders/SSRShader.js +++ b/examples/jsm/shaders/SSRShader.js @@ -175,7 +175,7 @@ var SSRShader = { vec3 vP=getViewPosition( uv, d, cW ); #ifdef PERSPECTIVE_CAMERA - // https://www.comp.nus.edu.sg/~lowkl/publications/lowk_persp_interp_techrep.pdf + // https://comp.nus.edu.sg/~lowkl/publications/lowk_persp_interp_techrep.pdf float recipVPZ=1./viewPosition.z; float viewReflectRayZ=1./(recipVPZ+s*(1./d1viewPosition.z-recipVPZ)); #else diff --git a/examples/jsm/shaders/SSRrShader.js b/examples/jsm/shaders/SSRrShader.js index b6b0a847b9b5b9..8357ab55d498a3 100644 --- a/examples/jsm/shaders/SSRrShader.js +++ b/examples/jsm/shaders/SSRrShader.js @@ -190,7 +190,7 @@ const SSRrShader = { vec3 vP=getViewPosition( uv, d, cW ); #ifdef PERSPECTIVE_CAMERA - // https://www.comp.nus.edu.sg/~lowkl/publications/lowk_persp_interp_techrep.pdf + // https://comp.nus.edu.sg/~lowkl/publications/lowk_persp_interp_techrep.pdf float recipVPZ=1./viewPosition.z; float viewRefractRayZ=1./(recipVPZ+s*(1./d1viewPosition.z-recipVPZ)); float sD=surfDist*cW; diff --git a/examples/jsm/utils/GeometryUtils.js b/examples/jsm/utils/GeometryUtils.js index dc2a23367969c2..d1b4504e51a200 100644 --- a/examples/jsm/utils/GeometryUtils.js +++ b/examples/jsm/utils/GeometryUtils.js @@ -59,7 +59,7 @@ function hilbert2D( center = new Vector3( 0, 0, 0 ), size = 10, iterations = 1, * Generates 3D-Coordinates in a very fast way. * * Based on work by: - * @link http://www.openprocessing.org/visuals/?visualID=15599 + * @link https://openprocessing.org/user/5654 * * @param center Center of Hilbert curve. * @param size Total width of Hilbert curve. diff --git a/examples/jsm/utils/RoughnessMipmapper.js b/examples/jsm/utils/RoughnessMipmapper.js deleted file mode 100644 index 9fc441f655419a..00000000000000 --- a/examples/jsm/utils/RoughnessMipmapper.js +++ /dev/null @@ -1,288 +0,0 @@ -/** - * This class generates custom mipmaps for a roughness map by encoding the lost variation in the - * normal map mip levels as increased roughness in the corresponding roughness mip levels. This - * helps with rendering accuracy for MeshStandardMaterial, and also helps with anti-aliasing when - * using PMREM. If the normal map is larger than the roughness map, the roughness map will be - * enlarged to match the dimensions of the normal map. - */ - -import { - MathUtils, - Mesh, - NoBlending, - OrthographicCamera, - PlaneGeometry, - RawShaderMaterial, - Vector2, - WebGLRenderTarget, - FramebufferTexture -} from '../../../build/three.module.js'; - -const _mipmapMaterial = _getMipmapMaterial(); - -const _mesh = new Mesh( new PlaneGeometry( 2, 2 ), _mipmapMaterial ); - -const _flatCamera = new OrthographicCamera( 0, 1, 0, 1, 0, 1 ); - -let _tempTarget = null; - -let _renderer = null; - -class RoughnessMipmapper { - - constructor( renderer ) { - - _renderer = renderer; - - _renderer.compile( _mesh, _flatCamera ); - - } - - generateMipmaps( material ) { - - if ( 'roughnessMap' in material === false ) return; - - const { roughnessMap, normalMap } = material; - - if ( roughnessMap === null || normalMap === null || ! roughnessMap.generateMipmaps || material.userData.roughnessUpdated ) return; - - material.userData.roughnessUpdated = true; - - let width = Math.max( roughnessMap.image.width, normalMap.image.width ); - let height = Math.max( roughnessMap.image.height, normalMap.image.height ); - - if ( ! MathUtils.isPowerOfTwo( width ) || ! MathUtils.isPowerOfTwo( height ) ) return; - - const oldTarget = _renderer.getRenderTarget(); - - const autoClear = _renderer.autoClear; - - _renderer.autoClear = false; - - if ( _tempTarget === null || _tempTarget.width !== width || _tempTarget.height !== height ) { - - if ( _tempTarget !== null ) _tempTarget.dispose(); - - _tempTarget = new WebGLRenderTarget( width, height, { depthBuffer: false } ); - - _tempTarget.scissorTest = true; - - } - - const newRoughnessTexture = new FramebufferTexture( width, height, roughnessMap.format ); - newRoughnessTexture.wrapS = roughnessMap.wrapS; - newRoughnessTexture.wrapT = roughnessMap.wrapT; - newRoughnessTexture.minFilter = roughnessMap.minFilter; - newRoughnessTexture.magFilter = roughnessMap.magFilter; - - material.roughnessMap = newRoughnessTexture; - - if ( material.metalnessMap == roughnessMap ) material.metalnessMap = material.roughnessMap; - - if ( material.aoMap == roughnessMap ) material.aoMap = material.roughnessMap; - - // Copy UV transform parameters - - material.roughnessMap.offset.copy( roughnessMap.offset ); - material.roughnessMap.repeat.copy( roughnessMap.repeat ); - material.roughnessMap.center.copy( roughnessMap.center ); - material.roughnessMap.rotation = roughnessMap.rotation; - material.roughnessMap.image = roughnessMap.image; // required for USDZExporter, see #22741 - - material.roughnessMap.matrixAutoUpdate = roughnessMap.matrixAutoUpdate; - material.roughnessMap.matrix.copy( roughnessMap.matrix ); - - _mipmapMaterial.uniforms.roughnessMap.value = roughnessMap; - - _mipmapMaterial.uniforms.normalMap.value = normalMap; - - const position = new Vector2( 0, 0 ); - - const texelSize = _mipmapMaterial.uniforms.texelSize.value; - - for ( let mip = 0; width >= 1 && height >= 1; ++ mip, width /= 2, height /= 2 ) { - - // Rendering to a mip level is not allowed in webGL1. Instead we must set - // up a secondary texture to write the result to, then copy it back to the - // proper mipmap level. - - texelSize.set( 1.0 / width, 1.0 / height ); - - if ( mip == 0 ) texelSize.set( 0.0, 0.0 ); - - _tempTarget.viewport.set( position.x, position.y, width, height ); - - _tempTarget.scissor.set( position.x, position.y, width, height ); - - _renderer.setRenderTarget( _tempTarget ); - - _renderer.render( _mesh, _flatCamera ); - - _renderer.copyFramebufferToTexture( position, material.roughnessMap, mip ); - - _mipmapMaterial.uniforms.roughnessMap.value = material.roughnessMap; - - } - - roughnessMap.dispose(); - - _renderer.setRenderTarget( oldTarget ); - - _renderer.autoClear = autoClear; - - } - - dispose() { - - _mipmapMaterial.dispose(); - - _mesh.geometry.dispose(); - - if ( _tempTarget != null ) _tempTarget.dispose(); - - } - -} - -function _getMipmapMaterial() { - - const shaderMaterial = new RawShaderMaterial( { - - uniforms: { - roughnessMap: { value: null }, - normalMap: { value: null }, - texelSize: { value: new Vector2( 1, 1 ) } - }, - - vertexShader: /* glsl */` - precision mediump float; - precision mediump int; - - attribute vec3 position; - attribute vec2 uv; - - varying vec2 vUv; - - void main() { - - vUv = uv; - - gl_Position = vec4( position, 1.0 ); - - } - `, - - fragmentShader: /* glsl */` - precision mediump float; - precision mediump int; - - varying vec2 vUv; - - uniform sampler2D roughnessMap; - uniform sampler2D normalMap; - uniform vec2 texelSize; - - #define ENVMAP_TYPE_CUBE_UV - - vec4 envMapTexelToLinear( vec4 a ) { return a; } - - #include - - float roughnessToVariance( float roughness ) { - - float variance = 0.0; - - if ( roughness >= r1 ) { - - variance = ( r0 - roughness ) * ( v1 - v0 ) / ( r0 - r1 ) + v0; - - } else if ( roughness >= r4 ) { - - variance = ( r1 - roughness ) * ( v4 - v1 ) / ( r1 - r4 ) + v1; - - } else if ( roughness >= r5 ) { - - variance = ( r4 - roughness ) * ( v5 - v4 ) / ( r4 - r5 ) + v4; - - } else { - - float roughness2 = roughness * roughness; - - variance = 1.79 * roughness2 * roughness2; - - } - - return variance; - - } - - float varianceToRoughness( float variance ) { - - float roughness = 0.0; - - if ( variance >= v1 ) { - - roughness = ( v0 - variance ) * ( r1 - r0 ) / ( v0 - v1 ) + r0; - - } else if ( variance >= v4 ) { - - roughness = ( v1 - variance ) * ( r4 - r1 ) / ( v1 - v4 ) + r1; - - } else if ( variance >= v5 ) { - - roughness = ( v4 - variance ) * ( r5 - r4 ) / ( v4 - v5 ) + r4; - - } else { - - roughness = pow( 0.559 * variance, 0.25 ); // 0.559 = 1.0 / 1.79 - - } - - return roughness; - - } - - void main() { - - gl_FragColor = texture2D( roughnessMap, vUv, - 1.0 ); - - if ( texelSize.x == 0.0 ) return; - - float roughness = gl_FragColor.g; - - float variance = roughnessToVariance( roughness ); - - vec3 avgNormal; - - for ( float x = - 1.0; x < 2.0; x += 2.0 ) { - - for ( float y = - 1.0; y < 2.0; y += 2.0 ) { - - vec2 uv = vUv + vec2( x, y ) * 0.25 * texelSize; - - avgNormal += normalize( texture2D( normalMap, uv, - 1.0 ).xyz - 0.5 ); - - } - - } - - variance += 1.0 - 0.25 * length( avgNormal ); - - gl_FragColor.g = varianceToRoughness( variance ); - - } - `, - - blending: NoBlending, - depthTest: false, - depthWrite: false - - } ); - - shaderMaterial.type = 'RoughnessMipmapper'; - - return shaderMaterial; - -} - -export { RoughnessMipmapper }; diff --git a/examples/jsm/webxr/VRButton.js b/examples/jsm/webxr/VRButton.js index 20687329b6f110..405e2ac31fb8dc 100644 --- a/examples/jsm/webxr/VRButton.js +++ b/examples/jsm/webxr/VRButton.js @@ -132,6 +132,12 @@ class VRButton { supported ? showEnterVR() : showWebXRNotFound(); + if ( supported && VRButton.xrSessionIsGranted ) { + + button.click(); + + } + } ); return button; @@ -164,6 +170,24 @@ class VRButton { } + static xrSessionIsGranted = false; + + static registerSessionGrantedListener() { + + if ( 'xr' in navigator ) { + + navigator.xr.addEventListener( 'sessiongranted', () => { + + VRButton.xrSessionIsGranted = true; + + } ); + + } + + } + } +VRButton.registerSessionGrantedListener(); + export { VRButton }; diff --git a/examples/misc_controls_arcball.html b/examples/misc_controls_arcball.html index 96c3caa28e5942..0446d7e853104a 100644 --- a/examples/misc_controls_arcball.html +++ b/examples/misc_controls_arcball.html @@ -143,7 +143,6 @@ render(); new RGBELoader() - .setDataType( THREE.UnsignedByteType ) .setPath( 'textures/equirectangular/' ) .load( 'venice_sunset_1k.hdr', function ( hdrEquirect ) { @@ -156,6 +155,7 @@ } ); + window.addEventListener( 'keydown', onKeyDown ); window.addEventListener( 'resize', onWindowResize ); // @@ -238,6 +238,28 @@ } + function onKeyDown( event ) { + + if ( event.key === 'c' ) { + + if ( event.ctrlKey || event.metaKey ) { + + controls.copyState(); + + } + + } else if ( event.key === 'v' ) { + + if ( event.ctrlKey || event.metaKey ) { + + controls.pasteState(); + + } + + } + + } + function setCamera( type ) { if ( type == 'Orthographic' ) { diff --git a/examples/models/3mf/README.md b/examples/models/3mf/README.md new file mode 100644 index 00000000000000..50cd1e02c4e9b4 --- /dev/null +++ b/examples/models/3mf/README.md @@ -0,0 +1,25 @@ +## License of the files in this directory + +### cube_gears.3mf + +Source: https://github.com/3MFConsortium/3mf-samples + +License: BSD 2-Clause "Simplified" License + +### facecolors.3mf + +Source: https://github.com/3MFConsortium/3mf-samples (original name `rhombicuboctahedron_color.3mf`) + +License: BSD 2-Clause "Simplified" License + +### multipletextures.3mf + +Source: https://github.com/3MFConsortium/3mf-samples + +License: BSD 2-Clause "Simplified" License + +### vertexcolors.3mf + +Source: https://github.com/3MFConsortium/3mf-samples (original name `pyramid_vertexcolor.3mf`) + +License: BSD 2-Clause "Simplified" License diff --git a/examples/models/nrrd/README.txt b/examples/models/nrrd/README.txt index 5f1ded491fe336..abc40e8533fdbd 100644 --- a/examples/models/nrrd/README.txt +++ b/examples/models/nrrd/README.txt @@ -4,7 +4,7 @@ ## stent.nrrd A 3D volume converted from stent.npz from the imageio project. -https://imageio.readthedocs.io/en/latest/standardimages.html +https://imageio.readthedocs.io/en/stable/getting_started/standardimages.html It is in the public domain. diff --git a/examples/screenshots/webgl_animation_multiple.jpg b/examples/screenshots/webgl_animation_multiple.jpg index ff96ca80595df2..9b7817ef7e5c7a 100644 Binary files a/examples/screenshots/webgl_animation_multiple.jpg and b/examples/screenshots/webgl_animation_multiple.jpg differ diff --git a/examples/screenshots/webgl_geometry_teapot.jpg b/examples/screenshots/webgl_geometry_teapot.jpg index 80b7355753fd29..c28cfaef19a6a6 100644 Binary files a/examples/screenshots/webgl_geometry_teapot.jpg and b/examples/screenshots/webgl_geometry_teapot.jpg differ diff --git a/examples/screenshots/webgl_instancing_raycast.jpg b/examples/screenshots/webgl_instancing_raycast.jpg index e705fba64f3843..807d49d51f285e 100644 Binary files a/examples/screenshots/webgl_instancing_raycast.jpg and b/examples/screenshots/webgl_instancing_raycast.jpg differ diff --git a/examples/screenshots/webgl_loader_gltf.jpg b/examples/screenshots/webgl_loader_gltf.jpg index aca651abb2c13c..3eedd841e2d8f1 100644 Binary files a/examples/screenshots/webgl_loader_gltf.jpg and b/examples/screenshots/webgl_loader_gltf.jpg differ diff --git a/examples/screenshots/webgl_loader_gltf_sheen.jpg b/examples/screenshots/webgl_loader_gltf_sheen.jpg index bbfa0e1b341a53..0695bc6b6ffb46 100644 Binary files a/examples/screenshots/webgl_loader_gltf_sheen.jpg and b/examples/screenshots/webgl_loader_gltf_sheen.jpg differ diff --git a/examples/screenshots/webgl_loader_texture_basis.jpg b/examples/screenshots/webgl_loader_texture_basis.jpg deleted file mode 100644 index 055b1882a438a7..00000000000000 Binary files a/examples/screenshots/webgl_loader_texture_basis.jpg and /dev/null differ diff --git a/examples/screenshots/webgl_materials_envmaps_hdr_nodes.jpg b/examples/screenshots/webgl_materials_envmaps_hdr_nodes.jpg index 26dd598c870cb7..74687157fa0f77 100644 Binary files a/examples/screenshots/webgl_materials_envmaps_hdr_nodes.jpg and b/examples/screenshots/webgl_materials_envmaps_hdr_nodes.jpg differ diff --git a/examples/screenshots/webgl_materials_envmaps_pmrem_nodes.jpg b/examples/screenshots/webgl_materials_envmaps_pmrem_nodes.jpg index 26dd598c870cb7..74687157fa0f77 100644 Binary files a/examples/screenshots/webgl_materials_envmaps_pmrem_nodes.jpg and b/examples/screenshots/webgl_materials_envmaps_pmrem_nodes.jpg differ diff --git a/examples/textures/matcaps/matcap-porcelain-white.txt b/examples/textures/matcaps/matcap-porcelain-white.txt index 858ffeb6bc345a..2caee86100c73d 100644 --- a/examples/textures/matcaps/matcap-porcelain-white.txt +++ b/examples/textures/matcaps/matcap-porcelain-white.txt @@ -1,5 +1,4 @@ matcap-porcelain-white.jpg courtesy of Milos Paripovic -https://milosparipovic.com/blog/matcaps-collection - +https://web.archive.org/web/20160917232238/http://milosparipovic.com/blog/matcaps-collection/ diff --git a/examples/webgl2_buffergeometry_attributes_integer.html b/examples/webgl2_buffergeometry_attributes_integer.html index 1044a4d33b8021..8b1a8dc1a903fa 100644 --- a/examples/webgl2_buffergeometry_attributes_integer.html +++ b/examples/webgl2_buffergeometry_attributes_integer.html @@ -48,11 +48,11 @@ import * as THREE from '../build/three.module.js'; - import { WEBGL } from './jsm/WebGL.js'; + import WebGL from './jsm/capabilities/WebGL.js'; - if ( WEBGL.isWebGL2Available() === false ) { + if ( WebGL.isWebGL2Available() === false ) { - document.body.appendChild( WEBGL.getWebGL2ErrorMessage() ); + document.body.appendChild( WebGL.getWebGL2ErrorMessage() ); } diff --git a/examples/webgl2_materials_texture2darray.html b/examples/webgl2_materials_texture2darray.html index 4cae2742646104..b167da971c2032 100644 --- a/examples/webgl2_materials_texture2darray.html +++ b/examples/webgl2_materials_texture2darray.html @@ -58,11 +58,11 @@ import Stats from './jsm/libs/stats.module.js'; import { unzipSync } from './jsm/libs/fflate.module.js'; - import { WEBGL } from './jsm/WebGL.js'; + import WebGL from './jsm/capabilities/WebGL.js'; - if ( WEBGL.isWebGL2Available() === false ) { + if ( WebGL.isWebGL2Available() === false ) { - document.body.appendChild( WEBGL.getWebGL2ErrorMessage() ); + document.body.appendChild( WebGL.getWebGL2ErrorMessage() ); } diff --git a/examples/webgl2_materials_texture3d.html b/examples/webgl2_materials_texture3d.html index ad8d56be894984..58e5c9bc9cd837 100644 --- a/examples/webgl2_materials_texture3d.html +++ b/examples/webgl2_materials_texture3d.html @@ -20,11 +20,11 @@ import { OrbitControls } from './jsm/controls/OrbitControls.js'; import { NRRDLoader } from './jsm/loaders/NRRDLoader.js'; import { VolumeRenderShader1 } from './jsm/shaders/VolumeShader.js'; - import { WEBGL } from './jsm/WebGL.js'; + import WebGL from './jsm/capabilities/WebGL.js'; - if ( WEBGL.isWebGL2Available() === false ) { + if ( WebGL.isWebGL2Available() === false ) { - document.body.appendChild( WEBGL.getWebGL2ErrorMessage() ); + document.body.appendChild( WebGL.getWebGL2ErrorMessage() ); } diff --git a/examples/webgl2_materials_texture3d_partialupdate.html b/examples/webgl2_materials_texture3d_partialupdate.html index d84a21cefdb4c7..253bc213420952 100644 --- a/examples/webgl2_materials_texture3d_partialupdate.html +++ b/examples/webgl2_materials_texture3d_partialupdate.html @@ -18,11 +18,11 @@ import { ImprovedNoise } from './jsm/math/ImprovedNoise.js'; import { GUI } from './jsm/libs/lil-gui.module.min.js'; - import { WEBGL } from './jsm/WebGL.js'; + import WebGL from './jsm/capabilities/WebGL.js'; - if ( WEBGL.isWebGL2Available() === false ) { + if ( WebGL.isWebGL2Available() === false ) { - document.body.appendChild( WEBGL.getWebGL2ErrorMessage() ); + document.body.appendChild( WebGL.getWebGL2ErrorMessage() ); } diff --git a/examples/webgl2_multiple_rendertargets.html b/examples/webgl2_multiple_rendertargets.html index 6c63d0301112e6..0a86adbec8ae10 100644 --- a/examples/webgl2_multiple_rendertargets.html +++ b/examples/webgl2_multiple_rendertargets.html @@ -109,7 +109,7 @@ import * as THREE from '../build/three.module.js'; - import { WEBGL } from './jsm/WebGL.js'; + import WebGL from './jsm/capabilities/WebGL.js'; import { OrbitControls } from './jsm/controls/OrbitControls.js'; let camera, scene, renderer, controls; @@ -120,9 +120,9 @@ function init() { - if ( WEBGL.isWebGL2Available() === false ) { + if ( WebGL.isWebGL2Available() === false ) { - document.body.appendChild( WEBGL.getWebGL2ErrorMessage() ); + document.body.appendChild( WebGL.getWebGL2ErrorMessage() ); return; } diff --git a/examples/webgl2_multisampled_renderbuffers.html b/examples/webgl2_multisampled_renderbuffers.html index 08f57e7e0ee409..d7d1e3be3c6ed3 100644 --- a/examples/webgl2_multisampled_renderbuffers.html +++ b/examples/webgl2_multisampled_renderbuffers.html @@ -41,7 +41,7 @@ import { RenderPass } from './jsm/postprocessing/RenderPass.js'; import { ShaderPass } from './jsm/postprocessing/ShaderPass.js'; import { CopyShader } from './jsm/shaders/CopyShader.js'; - import { WEBGL } from './jsm/WebGL.js'; + import WebGL from './jsm/capabilities/WebGL.js'; let camera, renderer, clock, group, container; @@ -51,9 +51,9 @@ function init() { - if ( WEBGL.isWebGL2Available() === false ) { + if ( WebGL.isWebGL2Available() === false ) { - document.body.appendChild( WEBGL.getWebGL2ErrorMessage() ); + document.body.appendChild( WebGL.getWebGL2ErrorMessage() ); return; } diff --git a/examples/webgl2_rendertarget_texture2darray.html b/examples/webgl2_rendertarget_texture2darray.html index 0c878b00c86e29..0ff4b0f560a421 100644 --- a/examples/webgl2_rendertarget_texture2darray.html +++ b/examples/webgl2_rendertarget_texture2darray.html @@ -103,11 +103,11 @@ import { unzipSync } from './jsm/libs/fflate.module.js'; import { GUI } from './jsm/libs/lil-gui.module.min.js'; - import { WEBGL } from './jsm/WebGL.js'; + import WebGL from './jsm/capabilities/WebGL.js'; - if ( WEBGL.isWebGL2Available() === false ) { + if ( WebGL.isWebGL2Available() === false ) { - document.body.appendChild( WEBGL.getWebGL2ErrorMessage() ); + document.body.appendChild( WebGL.getWebGL2ErrorMessage() ); } diff --git a/examples/webgl2_volume_cloud.html b/examples/webgl2_volume_cloud.html index 2a66dcaec761db..08198762f3eb8f 100644 --- a/examples/webgl2_volume_cloud.html +++ b/examples/webgl2_volume_cloud.html @@ -18,11 +18,11 @@ import { ImprovedNoise } from './jsm/math/ImprovedNoise.js'; import { GUI } from './jsm/libs/lil-gui.module.min.js'; - import { WEBGL } from './jsm/WebGL.js'; + import WebGL from './jsm/capabilities/WebGL.js'; - if ( WEBGL.isWebGL2Available() === false ) { + if ( WebGL.isWebGL2Available() === false ) { - document.body.appendChild( WEBGL.getWebGL2ErrorMessage() ); + document.body.appendChild( WebGL.getWebGL2ErrorMessage() ); } diff --git a/examples/webgl2_volume_instancing.html b/examples/webgl2_volume_instancing.html index 25c38999d8b227..22a272c024f180 100644 --- a/examples/webgl2_volume_instancing.html +++ b/examples/webgl2_volume_instancing.html @@ -17,11 +17,11 @@ import { OrbitControls } from './jsm/controls/OrbitControls.js'; import { VOXLoader, VOXDataTexture3D } from './jsm/loaders/VOXLoader.js'; - import { WEBGL } from './jsm/WebGL.js'; + import WebGL from './jsm/capabilities/WebGL.js'; - if ( WEBGL.isWebGL2Available() === false ) { + if ( WebGL.isWebGL2Available() === false ) { - document.body.appendChild( WEBGL.getWebGL2ErrorMessage() ); + document.body.appendChild( WebGL.getWebGL2ErrorMessage() ); } diff --git a/examples/webgl2_volume_perlin.html b/examples/webgl2_volume_perlin.html index 2434dc3b1363ba..0ddfc7cab87b81 100644 --- a/examples/webgl2_volume_perlin.html +++ b/examples/webgl2_volume_perlin.html @@ -18,11 +18,11 @@ import { ImprovedNoise } from './jsm/math/ImprovedNoise.js'; import { GUI } from './jsm/libs/lil-gui.module.min.js'; - import { WEBGL } from './jsm/WebGL.js'; + import WebGL from './jsm/capabilities/WebGL.js'; - if ( WEBGL.isWebGL2Available() === false ) { + if ( WebGL.isWebGL2Available() === false ) { - document.body.appendChild( WEBGL.getWebGL2ErrorMessage() ); + document.body.appendChild( WebGL.getWebGL2ErrorMessage() ); } diff --git a/examples/webgl_animation_keyframes.html b/examples/webgl_animation_keyframes.html index 9792e5300d78a2..ace1cb865942d5 100644 --- a/examples/webgl_animation_keyframes.html +++ b/examples/webgl_animation_keyframes.html @@ -23,8 +23,8 @@
    three.js webgl - animation - keyframes
    - Model: Littlest Tokyo by - Glen Fox, CC Attribution. + Model: Littlest Tokyo by + Glen Fox, CC Attribution.
    diff --git a/examples/webgl_interactive_voxelpainter.html b/examples/webgl_interactive_voxelpainter.html index 6ff8b6cf4a2541..151b6ffe62c9db 100644 --- a/examples/webgl_interactive_voxelpainter.html +++ b/examples/webgl_interactive_voxelpainter.html @@ -128,9 +128,9 @@ rollOverMesh.position.copy( intersect.point ).add( intersect.face.normal ); rollOverMesh.position.divideScalar( 50 ).floor().multiplyScalar( 50 ).addScalar( 25 ); - } + render(); - render(); + } } diff --git a/examples/webgl_lightprobe_cubecamera.html b/examples/webgl_lightprobe_cubecamera.html index b6d9dd8344fa0c..4de9d5a61cff75 100644 --- a/examples/webgl_lightprobe_cubecamera.html +++ b/examples/webgl_lightprobe_cubecamera.html @@ -43,7 +43,6 @@ camera.position.set( 0, 0, 30 ); const cubeRenderTarget = new THREE.WebGLCubeRenderTarget( 256, { - encoding: THREE.sRGBEncoding, // since gamma is applied during rendering, the cubeCamera renderTarget texture encoding must be sRGBEncoding format: THREE.RGBAFormat } ); diff --git a/examples/webgl_lights_pointlights.html b/examples/webgl_lights_pointlights.html index 4c9df84741665b..60f88d51769e44 100644 --- a/examples/webgl_lights_pointlights.html +++ b/examples/webgl_lights_pointlights.html @@ -10,7 +10,7 @@
    three.js - point lights WebGL demo.
    - Walt Disney head by David OReilly + Walt Disney head by David OReilly
    - - - diff --git a/examples/webgl_loader_texture_hdr.html b/examples/webgl_loader_texture_hdr.html index 914336ddf50a91..bc76fe8a40d502 100644 --- a/examples/webgl_loader_texture_hdr.html +++ b/examples/webgl_loader_texture_hdr.html @@ -48,7 +48,6 @@ camera = new THREE.OrthographicCamera( - aspect, aspect, 1, - 1, 0, 1 ); new RGBELoader() - .setDataType( THREE.UnsignedByteType ) // alt: FloatType, HalfFloatType .load( 'textures/memorial.hdr', function ( texture, textureData ) { //console.log( textureData ); diff --git a/examples/webgl_loader_texture_rgbm.html b/examples/webgl_loader_texture_rgbm.html index 95bc961c8caef0..9def9d182472d3 100644 --- a/examples/webgl_loader_texture_rgbm.html +++ b/examples/webgl_loader_texture_rgbm.html @@ -46,9 +46,7 @@ camera = new THREE.OrthographicCamera( - aspect, aspect, 1, - 1, 0, 1 ); - new RGBMLoader().load( 'textures/memorial.png', function ( texture ) { - - texture.encoding = THREE.RGBM16Encoding; + new RGBMLoader().setMaxRange( 16 ).load( 'textures/memorial.png', function ( texture ) { const material = new THREE.MeshBasicMaterial( { map: texture } ); diff --git a/examples/webgl_materials_cubemap.html b/examples/webgl_materials_cubemap.html index aa5ecaaf55c8d0..db434ecc6d36ff 100644 --- a/examples/webgl_materials_cubemap.html +++ b/examples/webgl_materials_cubemap.html @@ -11,7 +11,7 @@
    three.js - cube mapping demo.
    - Texture by Humus, Walt Disney head by David OReilly + Texture by Humus, Walt Disney head by David OReilly
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + diff --git a/manual/examples/resources/lessons-helper.js b/manual/examples/resources/lessons-helper.js index f5e25d430bdb31..caf0e3f2944512 100644 --- a/manual/examples/resources/lessons-helper.js +++ b/manual/examples/resources/lessons-helper.js @@ -252,7 +252,7 @@ if ((/chrome|opera/i).test(browser.name)) { lineNdx = 3; matcher = function(line) { - const m = /at ([^(]+)*?\(*(.*?):(\d+):(\d+)/.exec(line); + const m = /at ([^(]*?)\(*(.*?):(\d+):(\d+)/.exec(line); if (m) { let userFnName = m[1]; let url = m[2]; diff --git a/manual/examples/voxel-geometry-culled-faces-ui.html b/manual/examples/voxel-geometry-culled-faces-ui.html index 727822db33f0f2..135011dcc39a8a 100644 --- a/manual/examples/voxel-geometry-culled-faces-ui.html +++ b/manual/examples/voxel-geometry-culled-faces-ui.html @@ -189,7 +189,7 @@ } // from - // http://www.cse.chalmers.se/edu/year/2010/course/TDA361/grid.pdf + // https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.42.3443&rep=rep1&type=pdf intersectRay(start, end) { let dx = end.x - start.x; let dy = end.y - start.y; @@ -584,4 +584,3 @@ main(); - diff --git a/manual/fr/fundamentals.html b/manual/fr/fundamentals.html index cb96b6b3a6d589..d5f486fdfe565e 100644 --- a/manual/fr/fundamentals.html +++ b/manual/fr/fundamentals.html @@ -35,7 +35,7 @@

    principes de base

    La plupart des navigateurs qui supportent three.js se mettent à jour automatiquement donc la plupart des utilisateurs devraient être capables d'exécuter ce code. Si vous souhaitez exécuter ce code sur un très vieux navigateur, nous vous recommandons -un transpileur tel que Babel. +un transpileur tel que Babel. Bien sûr, les utilisateurs exécutant de très vieux navigateurs ont probablement des machines incapables de faire tourner Three.js.

    Lors de l'apprentissage de la plupart des langages de programmation, @@ -429,4 +429,4 @@

    es6 modules, Three.js et structure de dossiers

    - \ No newline at end of file + diff --git a/manual/index.html b/manual/index.html index 2d730a6e943caa..1c70602b9b6c42 100644 --- a/manual/index.html +++ b/manual/index.html @@ -151,7 +151,12 @@

    three.js

    // Activate content and title change on browser navigation - window.onpopstate = createNewIframe; + window.onpopstate = function() { + + updateNavigation(); + createNewIframe(); + + } // Create the navigation panel and configure the iframe @@ -189,14 +194,7 @@

    three.js

    window.location.hash = pageURL; panel.classList.remove( 'open' ); - - content.querySelectorAll( 'a' ).forEach( function ( item ) { - - item.classList.remove( 'selected' ); - - } ); - - link.classList.add( 'selected' ); + updateNavigation(); } ); @@ -224,7 +222,7 @@

    three.js

    } const categories = list[ language ]; - const selectedPage = window.location.hash.substring( 1 ); + const selectedPage = window.location.hash.substring( 1 ).replace( /\.html$/, '' ); for ( const category in categories ) { @@ -286,6 +284,26 @@

    three.js

    } + function updateNavigation() { + + const selectedPage = window.location.hash.substring( 1 ).replace( /\.html$/, '' ); + + content.querySelectorAll( 'a' ).forEach( function ( item ) { + + if ( item.href.includes( selectedPage ) ) { + + item.classList.add( 'selected' ); + + } else { + + item.classList.remove( 'selected' ); + + } + + } ); + + } + // Auto change language url. If a reader open a document in English, when he click "zh", the document he read will auto change into Chinese version function autoChangeUrlLanguage( language ) { @@ -430,6 +448,7 @@

    three.js

    } else { window.location.hash = newHash; + updateNavigation(); createNewIframe(); } diff --git a/manual/ja/fundamentals.html b/manual/ja/fundamentals.html index 6c42f3e9d9c25a..f92104796e369c 100644 --- a/manual/ja/fundamentals.html +++ b/manual/ja/fundamentals.html @@ -29,7 +29,7 @@

    の基礎知識

    これらのチュートリアルはJavaScriptを知っている事を前提としており、ほとんどの部分でES6スタイルを使用します。 あなたがすでに知っている事が期待される簡潔なリストはこちらをご覧下さい。 three.jsがサポートするほとんどのブラウザは自動更新されるため、ほとんどのユーザーはこのコードを実行できます。 -古いブラウザーで実行したい場合は、Babel のようなトランスパイラーを調べて下さい。 +古いブラウザーで実行したい場合は、Babel のようなトランスパイラーを調べて下さい。 もちろん、本当に古いブラウザを実行しているユーザーはthree.jsを実行できないマシンを持っている可能性があります。

    ほとんどのプログラミング言語を学ぶ時、最初にする事は "Hello World!" を表示する事です。 3Dで最初に行う最も一般的な事の1つは、3Dキューブを作成する事です。 @@ -310,4 +310,4 @@

    es6モジュール、three.js、およびフォルダー構造

    - \ No newline at end of file + diff --git a/manual/ko/multiple-scenes.html b/manual/ko/multiple-scenes.html index b753a947b0813a..ff3653f878d7af 100644 --- a/manual/ko/multiple-scenes.html +++ b/manual/ko/multiple-scenes.html @@ -335,7 +335,7 @@

    확장하기 쉽게 만들기

    HTML Dataset 사용하기

    -

    HTML의 dataset을 +

    HTML의 dataset을 이용하면 좀 더 확장하기 쉬운 환경을 만들 수 있습니다. id="..." 대신 data-diagram="..."을 이용해 데이터를 직접 HTML 요소에 지정하는 거죠.

    <canvas id="c"></canvas>
    diff --git a/manual/ko/tips.html b/manual/ko/tips.html
    index 3b3c7a7651304d..bbb489685f6316 100644
    --- a/manual/ko/tips.html
    +++ b/manual/ko/tips.html
    @@ -24,7 +24,7 @@ 


    캔버스의 스크린샷 찍기

    -

    브라우저에서 스크린샷을 찍을 수 있는 방법은 2가지 정도가 있습니다. 예전부터 사용하던 canvas.toDataURL과, 새로 등장한 canvas.toBlob이 있죠.

    +

    브라우저에서 스크린샷을 찍을 수 있는 방법은 2가지 정도가 있습니다. 예전부터 사용하던 canvas.toDataURL과, 새로 등장한 canvas.toBlob이 있죠.

    그냥 메서드만 호출하면 되는 거라니, 얼핏 쉬워 보입니다. 아래 정도의 코드면 손쉽게 스크린샷을 찍을 수 있을 것 같네요.

    <canvas id="c"></canvas>
     +<button id="screenshot" type="button">Save...</button>
    diff --git a/manual/ko/voxel-geometry.html b/manual/ko/voxel-geometry.html
    index 02d71bb800a573..85ef61247cd514 100644
    --- a/manual/ko/voxel-geometry.html
    +++ b/manual/ko/voxel-geometry.html
    @@ -983,7 +983,7 @@ 

    복셀 Geometry

    참고:

    -

    예제의 방법 대신 RayCaster를 써도 괜찮은 결과가 나올 수 있습니다. 따로 테스트를 해보진 않았지만, 대신 복셀에 최적화된 raycaster를 찾아 이걸 적용했습니다.

    +

    예제의 방법 대신 RayCaster를 써도 괜찮은 결과가 나올 수 있습니다. 따로 테스트를 해보진 않았지만, 대신 복셀에 최적화된 raycaster를 찾아 이걸 적용했습니다.

    intersectRay를 VoxelWorld의 메서드로 만든 건 성능 때문입니다. 복셀 단위로 체크하는 게 너무 느릴 경우 cell 단위로 먼저 체크해 성능을 좀 더 높혀보려는 계획이었죠.

    현재 raycaster의 길이는 z-far까지인데, 이 값을 바꿔도 됩니다. 이건 제가 예제를 만들 때 1-2픽셀 정도로 보이는 먼 곳에는 복셀을 만들 일이 없다고 생각했기 때문이니까요.

    geometry.computeBoundingSphere 메서드의 성능은 다소 느릴 수 있습니다. 이 경우 cell을 전부 포함하는 경계 구체를 직접 만들 수 있죠.

    @@ -998,11 +998,11 @@

    복셀 Geometry

    - + - \ No newline at end of file + diff --git a/manual/list.json b/manual/list.json index 9fb34680a0a7e9..56b57dfe714c6e 100644 --- a/manual/list.json +++ b/manual/list.json @@ -319,7 +319,7 @@ }, "技巧": { "按需渲染": "zh/rendering-on-demand", - "Debugging JavaScript": "zh/debugging-javascript", + "调试JavaScript": "zh/debugging-javascript", "调试着色器": "zh/debugging-glsl", "Taking a screenshot": "zh/tips#screenshot", "Prevent the Canvas Being Cleared": "zh/tips#preservedrawingbuffer", @@ -359,4 +359,4 @@ "Material Table": "zh/material-table" } } -} +} \ No newline at end of file diff --git a/manual/resources/lang.css b/manual/resources/lang.css index 08dfba03b3d729..8ba5b24a7f77a1 100644 --- a/manual/resources/lang.css +++ b/manual/resources/lang.css @@ -28,11 +28,23 @@ pre.prettyprint ul.modifiedlines li.linedeleted { background-color: #ffebe9; } +pre.prettyprint ul.modifiedlines li.linedeleted:before { + content: '-'; + background-color: #ffebe9; + padding-right: 8px; +} + pre.prettyprint ul.modifiedlines li.lineadded { list-style-type: none; background-color: #e6ffec; } +pre.prettyprint ul.modifiedlines li.lineadded:before { + content: '+'; + background-color: #e6ffec; + padding-right: 8px; +} + pre.prettyprint, code.prettyprint, .dos { background: #f5f5f5; font-family: 'Roboto Mono', monospace; @@ -70,10 +82,18 @@ pre.prettyprint, code.prettyprint, .dos { background-color: #412e32; } + pre.prettyprint ul.modifiedlines li.linedeleted:before { + background-color: #412e32; + } + pre.prettyprint ul.modifiedlines li.lineadded { background-color: #293832; } + pre.prettyprint ul.modifiedlines li.lineadded:before { + background-color: #293832; + } + pre.prettyprint, code.prettyprint, .dos { background: #333333; } diff --git a/manual/ru/materials.html b/manual/ru/materials.html index c6dcee3840eec6..21f6b6ab930b8a 100644 --- a/manual/ru/materials.html +++ b/manual/ru/materials.html @@ -55,7 +55,7 @@

    Материалы

    прим. переводчика: Блик - световое пятно на ярко освещённой выпуклой или плоской глянцевой поверхности. -Зеркальное отражение я часто буду называть бликом, +Зеркальное отражение я часто буду называть бликом, хотя это скорее частный случай.

    Итак, давайте рассмотрим набор материалов Three.js.

    MeshBasicMaterial не зависит от света. @@ -308,4 +308,4 @@

    material.needsUpdate

    - \ No newline at end of file + diff --git a/manual/zh/debugging-javascript.html b/manual/zh/debugging-javascript.html index 274ec3ab63196b..0ae59c358e4351 100644 --- a/manual/zh/debugging-javascript.html +++ b/manual/zh/debugging-javascript.html @@ -1,36 +1,523 @@ - - - Debugging JavaScript - - - - - - - - - - - - - -
    -
    -

    Debugging JavaScript

    -
    -
    -
    -

    抱歉,还没有中文翻译哦。 欢迎加入翻译! 😄

    -

    英文原文链接.

    - -
    -
    -
    - - - - - - - - \ No newline at end of file + + + + + + 调试 JavaScript + + + + + + + + + + + + + +
    +
    +

    调试 JavaScript

    +
    +
    +
    +

    + 总的来说这篇文章的大部分是关于如何调试JavaScript的,而不是直接关于THREE.js的。这似乎很重要,因为很多刚开始学习THREE.js的人同时也刚开始学JavaScript,所以我希望这可以帮助他们更轻松地解决遇到的任何问题。 +

    +

    调试是一个大话题,我可能无法介绍出所有需要了解的内容,但如果您是JavaScript新手,我在这里会尝试给您一些建议。我强烈建议你花点时间来学习它们。它们会对你的学习有很大帮助。

    +

    了解你的浏览器开发者工具

    +

    所有的浏览器都有开发者工具。 + Chrome, + Firefox, + Safari, + Edge. +

    +

    在Chrome浏览器中你可以点击标志, 选择 More + Tools->Developer Tools + 来打开开发者工具。快捷键也显示在了上面。

    +
    + +

    在Firefox中你可以点击 标志, 选择 "Web Developer", 接着选择 + "Toggle Tools"

    +
    + +

    在Safari中你首先要从Advanced Safari Preferences中打开 Develop menu。

    +
    + +

    接着在Develop菜单你可以选择"Show/Connect Web Inspector"。

    +
    + +

    在Chrome中你也可以使用电脑端的开发者工具来调试运行在安卓手机或者平板的chrome浏览器上的网页. + 同样的在Safari中你可以 + 使用电脑端调试iPhones和iPads的Safari上的网页. +

    +

    我对Chrome最为熟悉,因此本指南在提到开发者工具时将以Chrome为例,但大多数浏览器都有类似的功能,因此应该很容易将此处的任何内容应用于所有浏览器。

    +

    关闭缓存

    +

    浏览器试图重用他们已经下载的数据。这对用户来说非常好,因此,如果您再次访问网站,许多用于显示网站的文件将不会被再次下载。

    +

    但是这可能不利于web开发。如果您改变了加载的资源,并重新加载了页面,但由于浏览器使用了上次缓存的版本,因此可能会看不到变动。

    +

    在开发过程中一个解决方案是关闭缓存。这样,浏览器将始终获取文件的最新版本。

    +

    首先在右上角点击设置按钮

    +
    + +

    接着选择"Disable Cache (while DevTools is open)".

    +
    + +

    使用JavaScript控制台

    +

    在所有开发者工具中都有 控制台。 它显示了警告和错误信息。

    +

    读这些信息!!

    +

    通常应该只有 1 或 2 条信息。

    +
    + +

    如果你看到有其他的消息,请务必 读它们。 例如:

    +
    + +

    我把 "three" 错拼成了 "threee"

    +

    通过console.log 方法,你也可以打印你自己信息到控制台,比如

    +
    console.log(someObject.position.x, someObject.position.y, someObject.position.z);
    +
    +

    更酷的是,如果你打印了一个object你可以检查它。 例如,如果从加载gLTF这篇文章中打印了一个根场景object

    +
      {
    +  const gltfLoader = new GLTFLoader();
    +  gltfLoader.load('resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf', (gltf) => {
    +    const root = gltf.scene;
    +    scene.add(root);
    ++      console.log(root);
    +
    +

    我们接着就可以在JavaScript控制台中展开那个object

    +
    +
    + +

    你也可以使用 console.error 来输出错误信息,该方法会打印一条红色的信息并附上错误栈

    +

    在屏幕上显示数据

    +

    另一个直观的但是经常被忽视的方式是通过添加<div><pre> 标签 + 并将要显示的数据放在标签内。

    +

    最简单的方法就是写一些HTML元素

    +
    <canvas id="c"></canvas>
    ++<div id="debug">
    ++  <div>x:<span id="x"></span></div>
    ++  <div>y:<span id="y"></span></div>
    ++  <div>z:<span id="z"></span></div>
    ++</div>
    +
    +

    给它们添加些样式让它们显示在canvas元素之上(假设你的canvas元素充满了整个页面)。

    +
    <style>
    +#debug {
    +position: absolute;
    +left: 1em;
    +top: 1em;
    +padding: 1em;
    +background: rgba(0, 0, 0, 0.8);
    +color: white;
    +font-family: monospace;
    +}
    +</style>
    +
    +

    然后查找元素并设置其内容。

    +
    // at init time
    +const xElem = document.querySelector('#x');
    +const yElem = document.querySelector('#y');
    +const zElem = document.querySelector('#z');
    +
    +// at render or update time
    +xElem.textContent = someObject.position.x.toFixed(3);
    +yElem.textContent = someObject.position.y.toFixed(3);
    +zElem.textContent = someObject.position.z.toFixed(3);
    +
    +

    这在展示实时数据时更有用

    +

    + + +

    +

    + 将数据显示在屏幕上的另一种方法是制作一个”清除记录器“。这是我编的一个术语,我参与的很多游戏中都使用了这个方法。其思想是您有一个只显示一帧消息的缓冲区,有显示数据需求的时候,就会调用一些函数向该缓冲区添加每一帧的数据。相对于上一种方法为每个数据都添加一个html元素,这种方法会减少跟多工作量。 +

    +

    举个例子,我们把上面的html代码调整为这样

    +
    <canvas id="c"></canvas>
    +<div id="debug">
    +<pre></pre>
    +</div>
    +
    +

    接着我们只做一个简单的类来管理这些 “clear back buffer”

    +
    class ClearingLogger {
    +constructor(elem) {
    +  this.elem = elem;
    +  this.lines = [];
    +}
    +log(...args) {
    +  this.lines.push([...args].join(' '));
    +}
    +render() {
    +  this.elem.textContent = this.lines.join('\n');
    +  this.lines = [];
    +}
    +}
    +
    +

    接着我们做一个简单的例子:每次我们点击鼠标后,就会产生一个出现2秒钟的物体,并朝着一个随机的方向移动。我们将从一篇文章中的一个示例开始 making + things + responsive

    +

    下面是每次点击鼠标都新增一个Mesh + 的代码

    +
    const geometry = new THREE.SphereGeometry();
    +const material = new THREE.MeshBasicMaterial({color: 'red'});
    +
    +const things = [];
    +
    +function rand(min, max) {
    +if (max === undefined) {
    +  max = min;
    +  min = 0;
    +}
    +return Math.random() * (max - min) + min;
    +}
    +
    +function createThing() {
    +const mesh = new THREE.Mesh(geometry, material);
    +scene.add(mesh);
    +things.push({
    +  mesh,
    +  timer: 2,
    +  velocity: new THREE.Vector3(rand(-5, 5), rand(-5, 5), rand(-5, 5)),
    +});
    +}
    +
    +canvas.addEventListener('click', createThing);
    +
    +

    接着下面的代码描述了如何移动我们创造出来的mesh,记录它们的信息以及当它们的计时器到期的时候删除它们

    +
    const logger = new ClearingLogger(document.querySelector('#debug pre'));
    +
    +let then = 0;
    +function render(now) {
    +now *= 0.001;  // convert to seconds
    +const deltaTime = now - then;
    +then = now;
    +
    +...
    +
    +logger.log('fps:', (1 / deltaTime).toFixed(1));
    +logger.log('num things:', things.length);
    +for (let i = 0; i < things.length;) {
    +  const thing = things[i];
    +  const mesh = thing.mesh;
    +  const pos = mesh.position;
    +  logger.log(
    +      'timer:', thing.timer.toFixed(3), 
    +      'pos:', pos.x.toFixed(3), pos.y.toFixed(3), pos.z.toFixed(3));
    +  thing.timer -= deltaTime;
    +  if (thing.timer <= 0) {
    +    // remove this thing. Note we don't advance `i`
    +    things.splice(i, 1);
    +    scene.remove(mesh);
    +  } else {
    +    mesh.position.addScaledVector(thing.velocity, deltaTime);
    +    ++i;
    +  }
    +}
    +
    +renderer.render(scene, camera);
    +logger.render();
    +
    +requestAnimationFrame(render);
    +}
    +
    +

    现在在下面的例子中点击几次鼠标

    +

    + + +

    +

    查询参数

    +

    另一件需要记住的事情是,网页可以通过查询参数或锚(有时称为搜索和散列)将数据传递到网页中。

    +
    https://domain/path/?query#anchor
    +
    +

    可以使用这个参数使一些功能开启或关闭或传入参数。

    +

    以上一个例子为例,我们可以做到只有向URL中传入?debug=true参数的时候,上面的例子才会显示调试数据

    +

    首先我们需要一些代码来解析携带查询参数字符串

    +
    /**
    +* Returns the query parameters as a key/value object. 
    +* Example: If the query parameters are
    +*
    +*    abc=123&def=456&name=gman
    +*
    +* Then `getQuery()` will return an object like
    +*
    +*    {
    +*      abc: '123',
    +*      def: '456',
    +*      name: 'gman',
    +*    }
    +*/
    +function getQuery() {
    +return Object.fromEntries(new URLSearchParams(window.location.search).entries());
    +}
    +
    +

    接着我们可能想让显示调试信息的元素在默认情况下不出现

    +
    <canvas id="c"></canvas>
    ++<div id="debug" style="display: none;">
    +<pre></pre>
    +</div>
    +
    +

    接着在代码中我们通过获取特定参数来决定当且仅当?debug=true传入的时候才显示我们的调试信息

    + +
    const query = getQuery();
    +const debug = query.debug === 'true';
    +const logger = debug
    + ? new ClearingLogger(document.querySelector('#debug pre'))
    + : new DummyLogger();
    +if (debug) {
    +document.querySelector('#debug').style.display = '';
    +}
    +
    +

    同时我们也写了一个什么事情也不做的DummyLogger,并在?debug=true 没有被传入的时候使用它。

    +
    class DummyLogger {
    +log() {}
    +render() {}
    +}
    +
    +

    你可以看到在这个URL里

    +

    debug-js-params.html

    +

    没有调试信息。但是当我们使用这个url的时候:

    +

    debug-js-params.html?debug=true

    +

    就包含了调试信息

    +

    多个参数传递的时候需要以'&'分隔。例如somepage.html?someparam=somevalue&someotherparam=someothervalue. + 使用这样的参数我们就可以传入各种各样的选项。例如传入speed=0.01 + 以降低app速度来更好的理解某个过程。或者传入 + showHelpers=true + 来决定是否添加一个helper来辅助显示其他课程中提到过的光线、阴影或者相机的视锥 +

    + +

    学习使用调试器

    +

    每个浏览器都有一个调试器,您可以在其中逐行暂停程序并检查所有变量。

    +

    教您如何使用调试器对于本文来说是一个太大的主题,但这里有几个链接

    + +

    在调试器或其他地方检查NaN

    +

    NaN 不是数字的缩写。当你做了一些不符合数学的事情时,JavaScript会把它指定为一个值。

    +

    举一个简单的例子

    +
    +
    + +

    通常,当我在制作一些东西时,屏幕上什么也没有出现,我会检查一些值,如果我看到NaN + 我会立即知道问题所在

    +

    举一个例子,当我第一次在 + article about loading gLTF files 文章中创建路径的时候,我使用SplineCurve ——一个专门制作2D曲线的类,做了一条曲线。 +

    +

    接着我使用这条曲线使汽车像这样移动

    +
    curve.getPointAt(zeroToOnePointOnCurve, car.position);
    +
    +

    在内部 curve.getPointAt 方法将调用传入的第二个参数对象上的 set 函数。在例子中第二个变量是car.position也就是一个Vector3类型。 Vector3的 + set 函数需要三个参数, x, y, 和 z 但是 SplineCurve 是一个2D曲线,因此它仅向car.position.set方法传入了x和y值。 +

    +

    结果car.position.set 方法将x设置为了x,y设置成了y,z设置成了undefined.

    +

    在调试器中简单查看一下汽车的matrixWorld + 就会发现许多的 NaN 值。

    +
    + +

    看到矩阵中包含NaN值就表明一些像 + position, + rotation, scale 或者其他的会影响矩阵的函数就有坏数据。根据这一点来找bug就会很容易发现问题所在。 +

    +

    除了NaN 之外还有Infinity,也能表明一些地方有了数学bug

    +

    快来看看代码!

    +

    THREE.js是一个开源的库。别害怕深入库内部查看代码。 + 你可以在github里查看它的源代码。 + 您还可以通过在调试器中单步执行函数来查看内部。

    +

    requestAnimationFrame 放着在渲染函数的底部。

    +

    我经常看到如下的代码

    +
    function render() {
    + requestAnimationFrame(render);
    +
    + // -- do stuff --
    +
    + renderer.render(scene, camera);
    +}
    +requestAnimationFrame(render);
    +
    +

    我建议将requestAnimationFrame 的调用放在底部,如下所示

    +
    function render() {
    + // -- do stuff --
    +
    + renderer.render(scene, camera);
    +
    + requestAnimationFrame(render);
    +}
    +requestAnimationFrame(render);
    +
    +

    最大的原因是,在正常情况下,如果出现错误,代码执行将停止。但将requestAnimationFrame + 置于顶部意味着您的代码将继续运行,因为您已经请求了另一帧。在我看来,发现这些错误比忽略它们要好。它们很容易成为某些东西没有按预期出现的原因,但除非代码停止,否则您可能根本不会注意到。 +

    +

    检查你使用的单位

    +

    这基本上意味着知道何时使用度(degrees)和何时使用弧度(radians)。不幸的是THREE.js并不是在所有地方都使用相同的单位。 + 现在我能想到的情况就是摄像机的视野是以degrees为单位的。所有其他角度均以radians为单位。

    + +

    + 另一个值得注意的地方是你所使用的长度单位的大小。目前3D应用程序还可以选择他们想要的任何单位大小。 + 一个应用程序可能会选择1个单位=1厘米。另一个可能选择1个单位=1英尺。事实上,你可以为某些应用选择任何你想要的单位。 + 也就是说,THREE.js假设1个单位=1米。这对于基于物理的渲染(PBR)——使用米来计算照明效果之类的事情很重要。这对于AR和VR也很重要,因为它们需要处理真实世界中的长度,如手机所在的位置或VR控制器所在的位置。 +

    +

    + 在Stack Overflow上制作一个 + 最小的、完整的、可验证的 示例 +

    + +

    如果你决定问一个关于THREE.js的问题,你需要提供一个MCVE,即最小的(Minimal)、完整的(Complete)、可验证的(Verifiable)示例。

    + +

    最小的(Minimal) 是很重要的。 比如说在上一个例子loading a gLTF + article中你有一个关于运动轨迹的例子。那个例子有很多部分,比如 +

    +
      +
    1. 一些HTML
    2. +
    3. 一些 CSS
    4. +
    5. 光源
    6. +
    7. 阴影
    8. +
    9. 操作阴影的lil-gui 代码
    10. +
    11. 加载.GLTF文件的代码
    12. +
    13. 调整canvas大小的代码
    14. +
    15. 让汽车沿着路线移动的代码
    16. +
    +

    看起来真的很多。如果你的问题仅仅是关于路线跟随的部分,你可以将大部分HTML代码删除,因为你只需要一个<canvas> + 和一个<script>标记就可以了。你可以删除CSS和调整大小的代码,也可以删除.GLTF代码,因为你只关心路径。 + 你可以使用MeshBasicMaterial删除灯光和阴影。你当然也可以删除lil gui代码。代码中纹理创建地平面,如果使用GridHelper.会更容易。 + 最后,如果我们的问题是关于在路径上移动物体,我们可以在路径上使用立方体,而不是装载的汽车模型。 +

    +

    + 这里有一个更简单的例子,考虑了以上所有因素。它从271行缩减到135行。我们甚至可以考虑通过简化路径来进一步缩小它。也许一条有3点或4点的路径和我们有21点的路径一样有效。 +

    +

    + + +

    +

    我保留了 OrbitController 因为它是很有用的——别人可以通过移动相机 + 搞清楚发生了什么。但是根据实际情况你也可以移除它。 +

    +

    + 认真写一个MCVE所带来的好处就是我们经常能自己解决问题。删除所有不需要的内容,并尽我们所能制作最小的示例来重现问题的过程往往会使得错误原因的展现。 +

    +

    + 最重要的是,它尊重了查看你问题代码的其他人的时间。通过做一个简单的例子,你就可以让他们更容易地帮助你。你也将在这个过程中学习。 +

    +

    同样重要的是,当你去到Stack Overflow 提交问题的时候 将你的代码放在代码片段.里 + 你当然可以使用JSFiddle 或者 Codepen 或者相似的第三方网站去测试你的MCVE,但是一旦你在Stack + Overflow上面发布问题,你就需要把代码放在问题本身中重现你的问题。 +

    +

    + 还请注意,此站点上的所有实时示例都应作为片段运行。只需将HTML、CSS和JavaScript部分复制到 + 代码段编辑器 + 各自的部分。请记住,尽量删除与您的问题无关的部分,并尽量使您的代码达到所需的最小数量。 +

    +

    遵循这些建议你就可能在解决问题上得到帮助

    +

    使用MeshBasicMaterial

    +

    由于MeshBasicMaterial不使用光照,这样做就不会产生一些物体不显示的问题了。如果你的物体在使用MeshBasicMaterial + 的时候显示,但是在使用其他任何材料时候不显示,那么你便知道问题出在材料或者光照上而不是其他地方的代码。 +

    +

    检查你相机的 nearfar 设置 +

    +

    一个 PerspectiveCameranear 和 + far 设置——在 + article on cameras这篇文章中讲过。保证它的值的设置所能观察到的空间范围能够包裹你渲染的物体 + 甚至可以暂时性的设置为 near = 0.001 以及 far = 1000000。你可能遇到深度层级分辨率问题但是你至少可以看到你的物体——前提是它在你的相机前。 +

    +

    检查相机前的场景

    +

    有时候一些东西不会出现因为它们不在相机前。 如果你的相机是不可控制的,尝试添加一个相机控制器比如 + OrbitController,这样你就可以看到周围的景象并找到你的场景。 + 或者,尝试使用这篇文章中介绍的代码来设置场景的帧。该代码查找场景部分的大小,然后移动摄影机并调整nearfar设置以使其可见。然后可以查看调试器或添加一些 console.log 消息以打印场景的大小和中心。 +

    +

    在相机前放一些东西

    +

    + 这只是另一种说法,如果所有其他方法都失败了,那么就从一些有效的方法开始,然后慢慢地再添加一些东西。 + 如果你得到一个屏幕上没有任何东西,那么试着把一些东西直接放在相机前面。制作一个球体或长方体,给它一个简单的材质,比如 MeshBasicMaterial , + 确保你可以在屏幕上看到它。然后可以一次添加一些东西,然后再测试它。最终,你要么复现出你的bug,要么在途中发现它。 +

    +
    +

    以上这些就是调试JavaScript的一些建议。让我们开始浏览调试GLSL的一些建议吧。

    + +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/package.json b/package.json index e32548de4b3598..b2091a63717d1e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "three", - "version": "0.135.0", + "version": "0.136.0", "description": "JavaScript 3D library", "main": "build/three.js", "module": "build/three.module.js", @@ -55,6 +55,9 @@ "GPUTextureUsage": "readonly" }, "rules": { + "no-throw-literal": [ + "error" + ], "quotes": [ "error", "single" diff --git a/src/Three.Legacy.js b/src/Three.Legacy.js index d0e71c624b8d17..69ea7487eba24d 100644 --- a/src/Three.Legacy.js +++ b/src/Three.Legacy.js @@ -1597,7 +1597,19 @@ Object.defineProperties( WebGLRenderer.prototype, { } }, + gammaFactor: { + get: function () { + + console.warn( 'THREE.WebGLRenderer: .gammaFactor has been removed.' ); + return 2; + + }, + set: function () { + + console.warn( 'THREE.WebGLRenderer: .gammaFactor has been removed.' ); + } + } } ); Object.defineProperties( WebGLShadowMap.prototype, { diff --git a/src/animation/AnimationMixer.js b/src/animation/AnimationMixer.js index 53c01ce6997b2e..6411774457730b 100644 --- a/src/animation/AnimationMixer.js +++ b/src/animation/AnimationMixer.js @@ -48,6 +48,7 @@ class AnimationMixer extends EventDispatcher { if ( binding !== undefined ) { + ++ binding.referenceCount; bindings[ i ] = binding; } else { diff --git a/src/cameras/CubeCamera.js b/src/cameras/CubeCamera.js index c60e199c00cb0d..472247d20baea0 100644 --- a/src/cameras/CubeCamera.js +++ b/src/cameras/CubeCamera.js @@ -100,6 +100,8 @@ class CubeCamera extends Object3D { renderer.xr.enabled = currentXrEnabled; + renderTarget.texture.needsPMREMUpdate = true; + } } diff --git a/src/constants.js b/src/constants.js index 50b37bd272e033..f0cb11ebbff83a 100644 --- a/src/constants.js +++ b/src/constants.js @@ -1,4 +1,4 @@ -export const REVISION = '136dev'; +export const REVISION = '137dev'; export const MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 }; export const TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 }; export const CullFaceNone = 0; @@ -91,7 +91,6 @@ export const RGBFormat = 1022; export const RGBAFormat = 1023; export const LuminanceFormat = 1024; export const LuminanceAlphaFormat = 1025; -export const RGBEFormat = RGBAFormat; export const DepthFormat = 1026; export const DepthStencilFormat = 1027; export const RedFormat = 1028; @@ -127,20 +126,6 @@ export const RGBA_ASTC_10x10_Format = 37819; export const RGBA_ASTC_12x10_Format = 37820; export const RGBA_ASTC_12x12_Format = 37821; export const RGBA_BPTC_Format = 36492; -export const SRGB8_ALPHA8_ASTC_4x4_Format = 37840; -export const SRGB8_ALPHA8_ASTC_5x4_Format = 37841; -export const SRGB8_ALPHA8_ASTC_5x5_Format = 37842; -export const SRGB8_ALPHA8_ASTC_6x5_Format = 37843; -export const SRGB8_ALPHA8_ASTC_6x6_Format = 37844; -export const SRGB8_ALPHA8_ASTC_8x5_Format = 37845; -export const SRGB8_ALPHA8_ASTC_8x6_Format = 37846; -export const SRGB8_ALPHA8_ASTC_8x8_Format = 37847; -export const SRGB8_ALPHA8_ASTC_10x5_Format = 37848; -export const SRGB8_ALPHA8_ASTC_10x6_Format = 37849; -export const SRGB8_ALPHA8_ASTC_10x8_Format = 37850; -export const SRGB8_ALPHA8_ASTC_10x10_Format = 37851; -export const SRGB8_ALPHA8_ASTC_12x10_Format = 37852; -export const SRGB8_ALPHA8_ASTC_12x12_Format = 37853; export const LoopOnce = 2200; export const LoopRepeat = 2201; export const LoopPingPong = 2202; @@ -157,11 +142,6 @@ export const TriangleStripDrawMode = 1; export const TriangleFanDrawMode = 2; export const LinearEncoding = 3000; export const sRGBEncoding = 3001; -export const GammaEncoding = 3007; -export const RGBEEncoding = 3002; -export const RGBM7Encoding = 3004; -export const RGBM16Encoding = 3005; -export const RGBDEncoding = 3006; export const BasicDepthPacking = 3200; export const RGBADepthPacking = 3201; export const TangentSpaceNormalMap = 0; @@ -197,3 +177,6 @@ export const StreamCopyUsage = 35042; export const GLSL1 = '100'; export const GLSL3 = '300 es'; + +export const _SRGBFormat = 1034; // fallback for WebGL 1 +export const _SRGBAFormat = 1035; // fallback for WebGL 1 diff --git a/src/extras/ImageUtils.js b/src/extras/ImageUtils.js index 8ec60408c389c7..e7fcfef9b51fa0 100644 --- a/src/extras/ImageUtils.js +++ b/src/extras/ImageUtils.js @@ -1,4 +1,5 @@ import { createElementNS } from '../utils.js'; +import { SRGBToLinear } from '../math/Color.js'; let _canvas; @@ -61,6 +62,68 @@ class ImageUtils { } + static sRGBToLinear( image ) { + + if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || + ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || + ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { + + const canvas = createElementNS( 'canvas' ); + + canvas.width = image.width; + canvas.height = image.height; + + const context = canvas.getContext( '2d' ); + context.drawImage( image, 0, 0, image.width, image.height ); + + const imageData = context.getImageData( 0, 0, image.width, image.height ); + const data = imageData.data; + + for ( let i = 0; i < data.length; i ++ ) { + + data[ i ] = SRGBToLinear( data[ i ] / 255 ) * 255; + + } + + context.putImageData( imageData, 0, 0 ); + + return canvas; + + } else if ( image.data ) { + + const data = image.data.slice( 0 ); + + for ( let i = 0; i < data.length; i ++ ) { + + if ( data instanceof Uint8Array || data instanceof Uint8ClampedArray ) { + + data[ i ] = Math.floor( SRGBToLinear( data[ i ] / 255 ) * 255 ); + + } else { + + // assuming float + + data[ i ] = SRGBToLinear( data[ i ] ); + + } + + } + + return { + data: data, + width: image.width, + height: image.height + }; + + } else { + + console.warn( 'THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.' ); + return image; + + } + + } + } export { ImageUtils }; diff --git a/src/extras/PMREMGenerator.js b/src/extras/PMREMGenerator.js index 5b06fdc4024353..45fdb44447a840 100644 --- a/src/extras/PMREMGenerator.js +++ b/src/extras/PMREMGenerator.js @@ -2,19 +2,12 @@ import { CubeReflectionMapping, CubeRefractionMapping, CubeUVReflectionMapping, - GammaEncoding, LinearEncoding, + LinearFilter, NoToneMapping, - NearestFilter, NoBlending, - RGBDEncoding, - RGBEEncoding, RGBAFormat, - RGBEFormat, - RGBM16Encoding, - RGBM7Encoding, - UnsignedByteType, - sRGBEncoding + HalfFloatType } from '../constants.js'; import { BufferAttribute } from '../core/BufferAttribute.js'; @@ -47,16 +40,6 @@ const TOTAL_LODS = LOD_MAX - LOD_MIN + 1 + EXTRA_LOD_SIGMA.length; // samples and exit early, but not recompile the shader. const MAX_SAMPLES = 20; -const ENCODINGS = { - [ LinearEncoding ]: 0, - [ sRGBEncoding ]: 1, - [ RGBEEncoding ]: 2, - [ RGBM7Encoding ]: 3, - [ RGBM16Encoding ]: 4, - [ RGBDEncoding ]: 5, - [ GammaEncoding ]: 6 -}; - const _flatCamera = /*@__PURE__*/ new OrthographicCamera(); const { _lodPlanes, _sizeLods, _sigmas } = /*@__PURE__*/ _createPlanes(); const _clearColor = /*@__PURE__*/ new Color(); @@ -138,23 +121,23 @@ class PMREMGenerator { /** * Generates a PMREM from an equirectangular texture, which can be either LDR - * (RGBFormat) or HDR (RGBEFormat). The ideal input image size is 1k (1024 x 512), + * or HDR. The ideal input image size is 1k (1024 x 512), * as this matches best with the 256 x 256 cubemap output. */ - fromEquirectangular( equirectangular ) { + fromEquirectangular( equirectangular, renderTarget = null ) { - return this._fromTexture( equirectangular ); + return this._fromTexture( equirectangular, renderTarget ); } /** * Generates a PMREM from an cubemap texture, which can be either LDR - * (RGBFormat) or HDR (RGBEFormat). The ideal input cube size is 256 x 256, + * or HDR. The ideal input cube size is 256 x 256, * as this matches best with the 256 x 256 cubemap output. */ - fromCubemap( cubemap ) { + fromCubemap( cubemap, renderTarget = null ) { - return this._fromTexture( cubemap ); + return this._fromTexture( cubemap, renderTarget ); } @@ -219,10 +202,10 @@ class PMREMGenerator { } - _fromTexture( texture ) { + _fromTexture( texture, renderTarget ) { _oldTarget = this._renderer.getRenderTarget(); - const cubeUVRenderTarget = this._allocateTargets( texture ); + const cubeUVRenderTarget = renderTarget || this._allocateTargets( texture ); this._textureToCubeUV( texture, cubeUVRenderTarget ); this._applyPMREM( cubeUVRenderTarget ); this._cleanup( cubeUVRenderTarget ); @@ -234,12 +217,12 @@ class PMREMGenerator { _allocateTargets( texture ) { // warning: null texture is valid const params = { - magFilter: NearestFilter, - minFilter: NearestFilter, + magFilter: LinearFilter, + minFilter: LinearFilter, generateMipmaps: false, - type: UnsignedByteType, - format: RGBEFormat, - encoding: _isLDR( texture ) ? texture.encoding : RGBEEncoding, + type: HalfFloatType, + format: RGBAFormat, + encoding: LinearEncoding, depthBuffer: false }; @@ -267,12 +250,10 @@ class PMREMGenerator { const renderer = this._renderer; const originalAutoClear = renderer.autoClear; - const outputEncoding = renderer.outputEncoding; const toneMapping = renderer.toneMapping; renderer.getClearColor( _clearColor ); renderer.toneMapping = NoToneMapping; - renderer.outputEncoding = LinearEncoding; renderer.autoClear = false; const backgroundMaterial = new MeshBasicMaterial( { @@ -342,26 +323,11 @@ class PMREMGenerator { backgroundBox.material.dispose(); renderer.toneMapping = toneMapping; - renderer.outputEncoding = outputEncoding; renderer.autoClear = originalAutoClear; scene.background = background; } - _setEncoding( uniform, texture ) { - - if ( this._renderer.capabilities.isWebGL2 === true && texture.format === RGBAFormat && texture.type === UnsignedByteType && texture.encoding === sRGBEncoding ) { - - uniform.value = ENCODINGS[ LinearEncoding ]; - - } else { - - uniform.value = ENCODINGS[ texture.encoding ]; - - } - - } - _textureToCubeUV( texture, cubeUVRenderTarget ) { const renderer = this._renderer; @@ -399,9 +365,6 @@ class PMREMGenerator { } - this._setEncoding( uniforms[ 'inputEncoding' ], texture ); - this._setEncoding( uniforms[ 'outputEncoding' ], cubeUVRenderTarget.texture ); - _setViewport( cubeUVRenderTarget, 0, 0, 3 * SIZE_MAX, 2 * SIZE_MAX ); renderer.setRenderTarget( cubeUVRenderTarget ); @@ -532,9 +495,6 @@ class PMREMGenerator { blurUniforms[ 'dTheta' ].value = radiansPerPixel; blurUniforms[ 'mipInt' ].value = LOD_MAX - lodIn; - this._setEncoding( blurUniforms[ 'inputEncoding' ], targetIn.texture ); - this._setEncoding( blurUniforms[ 'outputEncoding' ], targetIn.texture ); - const outputSize = _sizeLods[ lodOut ]; const x = 3 * Math.max( 0, SIZE_MAX - 2 * outputSize ); const y = ( lodOut === 0 ? 0 : 2 * SIZE_MAX ) + 2 * outputSize * ( lodOut > LOD_MAX - LOD_MIN ? lodOut - LOD_MAX + LOD_MIN : 0 ); @@ -547,14 +507,6 @@ class PMREMGenerator { } -function _isLDR( texture ) { - - if ( texture === undefined || texture.type !== UnsignedByteType ) return false; - - return texture.encoding === LinearEncoding || texture.encoding === sRGBEncoding || texture.encoding === GammaEncoding; - -} - function _createPlanes() { const _lodPlanes = []; @@ -667,9 +619,7 @@ function _getBlurShader( maxSamples ) { 'latitudinal': { value: false }, 'dTheta': { value: 0 }, 'mipInt': { value: 0 }, - 'poleAxis': { value: poleAxis }, - 'inputEncoding': { value: ENCODINGS[ LinearEncoding ] }, - 'outputEncoding': { value: ENCODINGS[ LinearEncoding ] } + 'poleAxis': { value: poleAxis } }, vertexShader: _getCommonVertexShader(), @@ -689,8 +639,6 @@ function _getBlurShader( maxSamples ) { uniform float mipInt; uniform vec3 poleAxis; - ${ _getEncodings() } - #define ENVMAP_TYPE_CUBE_UV #include @@ -735,8 +683,6 @@ function _getBlurShader( maxSamples ) { } - gl_FragColor = linearToOutputTexel( gl_FragColor ); - } `, @@ -759,9 +705,7 @@ function _getEquirectShader() { uniforms: { 'envMap': { value: null }, - 'texelSize': { value: texelSize }, - 'inputEncoding': { value: ENCODINGS[ LinearEncoding ] }, - 'outputEncoding': { value: ENCODINGS[ LinearEncoding ] } + 'texelSize': { value: texelSize } }, vertexShader: _getCommonVertexShader(), @@ -776,8 +720,6 @@ function _getEquirectShader() { uniform sampler2D envMap; uniform vec2 texelSize; - ${ _getEncodings() } - #include void main() { @@ -789,20 +731,18 @@ function _getEquirectShader() { vec2 f = fract( uv / texelSize - 0.5 ); uv -= f * texelSize; - vec3 tl = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb; + vec3 tl = texture2D ( envMap, uv ).rgb; uv.x += texelSize.x; - vec3 tr = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb; + vec3 tr = texture2D ( envMap, uv ).rgb; uv.y += texelSize.y; - vec3 br = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb; + vec3 br = texture2D ( envMap, uv ).rgb; uv.x -= texelSize.x; - vec3 bl = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb; + vec3 bl = texture2D ( envMap, uv ).rgb; vec3 tm = mix( tl, tr, f.x ); vec3 bm = mix( bl, br, f.x ); gl_FragColor.rgb = mix( tm, bm, f.y ); - gl_FragColor = linearToOutputTexel( gl_FragColor ); - } `, @@ -823,9 +763,7 @@ function _getCubemapShader() { name: 'CubemapToCubeUV', uniforms: { - 'envMap': { value: null }, - 'inputEncoding': { value: ENCODINGS[ LinearEncoding ] }, - 'outputEncoding': { value: ENCODINGS[ LinearEncoding ] } + 'envMap': { value: null } }, vertexShader: _getCommonVertexShader(), @@ -839,13 +777,9 @@ function _getCubemapShader() { uniform samplerCube envMap; - ${ _getEncodings() } - void main() { - gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 ); - gl_FragColor.rgb = envMapTexelToLinear( textureCube( envMap, vec3( - vOutputDirection.x, vOutputDirection.yz ) ) ).rgb; - gl_FragColor = linearToOutputTexel( gl_FragColor ); + gl_FragColor = textureCube( envMap, vec3( - vOutputDirection.x, vOutputDirection.yz ) ); } `, @@ -923,90 +857,4 @@ function _getCommonVertexShader() { } -function _getEncodings() { - - return /* glsl */` - - uniform int inputEncoding; - uniform int outputEncoding; - - #include - - vec4 inputTexelToLinear( vec4 value ) { - - if ( inputEncoding == 0 ) { - - return value; - - } else if ( inputEncoding == 1 ) { - - return sRGBToLinear( value ); - - } else if ( inputEncoding == 2 ) { - - return RGBEToLinear( value ); - - } else if ( inputEncoding == 3 ) { - - return RGBMToLinear( value, 7.0 ); - - } else if ( inputEncoding == 4 ) { - - return RGBMToLinear( value, 16.0 ); - - } else if ( inputEncoding == 5 ) { - - return RGBDToLinear( value, 256.0 ); - - } else { - - return GammaToLinear( value, 2.2 ); - - } - - } - - vec4 linearToOutputTexel( vec4 value ) { - - if ( outputEncoding == 0 ) { - - return value; - - } else if ( outputEncoding == 1 ) { - - return LinearTosRGB( value ); - - } else if ( outputEncoding == 2 ) { - - return LinearToRGBE( value ); - - } else if ( outputEncoding == 3 ) { - - return LinearToRGBM( value, 7.0 ); - - } else if ( outputEncoding == 4 ) { - - return LinearToRGBM( value, 16.0 ); - - } else if ( outputEncoding == 5 ) { - - return LinearToRGBD( value, 256.0 ); - - } else { - - return LinearToGamma( value, 2.2 ); - - } - - } - - vec4 envMapTexelToLinear( vec4 color ) { - - return inputTexelToLinear( color ); - - } - `; - -} - export { PMREMGenerator }; diff --git a/src/extras/core/Interpolations.js b/src/extras/core/Interpolations.js index ccb479a964d114..a1e06c27d6bb28 100644 --- a/src/extras/core/Interpolations.js +++ b/src/extras/core/Interpolations.js @@ -1,6 +1,6 @@ /** * Bezier Curves formulas obtained from - * http://en.wikipedia.org/wiki/Bézier_curve + * https://en.wikipedia.org/wiki/B%C3%A9zier_curve */ function CatmullRom( t, p0, p1, p2, p3 ) { diff --git a/src/geometries/LatheGeometry.js b/src/geometries/LatheGeometry.js index 82cf2bda6fb33a..75d7aabaf42c5e 100644 --- a/src/geometries/LatheGeometry.js +++ b/src/geometries/LatheGeometry.js @@ -30,14 +30,75 @@ class LatheGeometry extends BufferGeometry { const indices = []; const vertices = []; const uvs = []; + const initNormals = []; + const normals = []; // helper variables const inverseSegments = 1.0 / segments; const vertex = new Vector3(); const uv = new Vector2(); + const normal = new Vector3(); + const curNormal = new Vector3(); + const prevNormal = new Vector3(); + let dx = 0; + let dy = 0; - // generate vertices and uvs + // pre-compute normals for initial "meridian" + + for ( let j = 0; j <= ( points.length - 1 ); j ++ ) { + + switch ( j ) { + + case 0: // special handling for 1st vertex on path + + dx = points[ j + 1 ].x - points[ j ].x; + dy = points[ j + 1 ].y - points[ j ].y; + + normal.x = dy * 1.0; + normal.y = - dx; + normal.z = dy * 0.0; + + prevNormal.copy( normal ); + + normal.normalize(); + + initNormals.push( normal.x, normal.y, normal.z ); + + break; + + case ( points.length - 1 ): // special handling for last Vertex on path + + initNormals.push( prevNormal.x, prevNormal.y, prevNormal.z ); + + break; + + default: // default handling for all vertices in between + + dx = points[ j + 1 ].x - points[ j ].x; + dy = points[ j + 1 ].y - points[ j ].y; + + normal.x = dy * 1.0; + normal.y = - dx; + normal.z = dy * 0.0; + + curNormal.copy( normal ); + + normal.x += prevNormal.x; + normal.y += prevNormal.y; + normal.z += prevNormal.z; + + normal.normalize(); + + initNormals.push( normal.x, normal.y, normal.z ); + + prevNormal.copy( curNormal ); + + } + + } + + // generate vertices, uvs and normals for ( let i = 0; i <= segments; i ++ ) { @@ -63,6 +124,13 @@ class LatheGeometry extends BufferGeometry { uvs.push( uv.x, uv.y ); + // normal + + const x = initNormals[ 3 * j + 0 ] * sin; + const y = initNormals[ 3 * j + 1 ]; + const z = initNormals[ 3 * j + 0 ] * cos; + + normals.push( x, y, z ); } @@ -95,52 +163,7 @@ class LatheGeometry extends BufferGeometry { this.setIndex( indices ); this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - - // generate normals - - this.computeVertexNormals(); - - // if the geometry is closed, we need to average the normals along the seam. - // because the corresponding vertices are identical (but still have different UVs). - - if ( phiLength === Math.PI * 2 ) { - - const normals = this.attributes.normal.array; - const n1 = new Vector3(); - const n2 = new Vector3(); - const n = new Vector3(); - - // this is the buffer offset for the last line of vertices - - const base = segments * points.length * 3; - - for ( let i = 0, j = 0; i < points.length; i ++, j += 3 ) { - - // select the normal of the vertex in the first line - - n1.x = normals[ j + 0 ]; - n1.y = normals[ j + 1 ]; - n1.z = normals[ j + 2 ]; - - // select the normal of the vertex in the last line - - n2.x = normals[ base + j + 0 ]; - n2.y = normals[ base + j + 1 ]; - n2.z = normals[ base + j + 2 ]; - - // average normals - - n.addVectors( n1, n2 ).normalize(); - - // assign the new values to both normals - - normals[ j + 0 ] = normals[ base + j + 0 ] = n.x; - normals[ j + 1 ] = normals[ base + j + 1 ] = n.y; - normals[ j + 2 ] = normals[ base + j + 2 ] = n.z; - - } - - } + this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); } diff --git a/src/helpers/CameraHelper.js b/src/helpers/CameraHelper.js index 42b7f478cded66..e789041707becc 100644 --- a/src/helpers/CameraHelper.js +++ b/src/helpers/CameraHelper.js @@ -13,7 +13,7 @@ const _camera = /*@__PURE__*/ new Camera(); * - shows frustum, line of sight and up of the camera * - suitable for fast updates * - based on frustum visualization in lightgl.js shadowmap example - * http://evanw.github.com/lightgl.js/tests/shadowmap.html + * https://github.com/evanw/lightgl.js/blob/master/tests/shadowmap.html */ class CameraHelper extends LineSegments { diff --git a/src/loaders/FileLoader.js b/src/loaders/FileLoader.js index d6a9864a8ff413..b42e55bc752ebf 100644 --- a/src/loaders/FileLoader.js +++ b/src/loaders/FileLoader.js @@ -84,6 +84,12 @@ class FileLoader extends Loader { } + if ( typeof ReadableStream === 'undefined' || response.body.getReader === undefined ) { + + return response; + + } + const callbacks = loading[ url ]; const reader = response.body.getReader(); const contentLength = response.headers.get( 'Content-Length' ); @@ -92,7 +98,7 @@ class FileLoader extends Loader { let loaded = 0; // periodically read data into the new stream tracking while download progress - return new ReadableStream( { + const stream = new ReadableStream( { start( controller ) { readData(); @@ -130,6 +136,8 @@ class FileLoader extends Loader { } ); + return new Response( stream ); + } else { throw Error( `fetch for "${response.url}" responded with ${response.status}: ${response.statusText}` ); @@ -137,9 +145,7 @@ class FileLoader extends Loader { } } ) - .then( stream => { - - const response = new Response( stream ); + .then( response => { switch ( this.responseType ) { diff --git a/src/math/Color.js b/src/math/Color.js index 295c60e1a1766b..42e77d471dbc30 100644 --- a/src/math/Color.js +++ b/src/math/Color.js @@ -298,44 +298,6 @@ class Color { } - copyGammaToLinear( color, 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( color, gammaFactor = 2.0 ) { - - const 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( gammaFactor ) { - - this.copyGammaToLinear( this, gammaFactor ); - - return this; - - } - - convertLinearToGamma( gammaFactor ) { - - this.copyLinearToGamma( this, gammaFactor ); - - return this; - - } - copySRGBToLinear( color ) { this.r = SRGBToLinear( color.r ); @@ -601,4 +563,4 @@ Color.prototype.r = 1; Color.prototype.g = 1; Color.prototype.b = 1; -export { Color }; +export { Color, SRGBToLinear }; diff --git a/src/math/Quaternion.js b/src/math/Quaternion.js index 485fe86537828e..08724e75250f4d 100644 --- a/src/math/Quaternion.js +++ b/src/math/Quaternion.js @@ -604,7 +604,7 @@ class Quaternion { slerpQuaternions( qa, qb, t ) { - this.copy( qa ).slerp( qb, t ); + return this.copy( qa ).slerp( qb, t ); } diff --git a/src/math/Ray.js b/src/math/Ray.js index 5798c7bf65681b..ad6c42a2b920b8 100644 --- a/src/math/Ray.js +++ b/src/math/Ray.js @@ -100,7 +100,7 @@ class Ray { distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) { - // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteDistRaySegment.h + // from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteDistRaySegment.h // It returns the min distance between the ray and the segment // defined by v0 and v1 // It can also set two optional targets : @@ -399,7 +399,7 @@ class Ray { // Compute the offset origin, edges, and normal. - // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h + // from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h _edge1.subVectors( b, a ); _edge2.subVectors( c, a ); diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index 97d64a8bd2b7c0..e834f422fd42ce 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -110,7 +110,6 @@ function WebGLRenderer( parameters = {} ) { // physically based shading - this.gammaFactor = 2.0; // for backwards compatibility this.outputEncoding = LinearEncoding; // physical lights @@ -573,6 +572,7 @@ function WebGLRenderer( parameters = {} ) { cubeuvmaps.dispose(); objects.dispose(); bindingStates.dispose(); + programCache.dispose(); xr.dispose(); @@ -657,6 +657,12 @@ function WebGLRenderer( parameters = {} ) { } ); + if ( material.isShaderMaterial ) { + + programCache.releaseShaderCache( material ); + + } + } } @@ -1569,6 +1575,7 @@ function WebGLRenderer( parameters = {} ) { materialProperties.numIntersection = parameters.numClipIntersection; materialProperties.vertexAlphas = parameters.vertexAlphas; materialProperties.vertexTangents = parameters.vertexTangents; + materialProperties.toneMapping = parameters.toneMapping; } @@ -1587,6 +1594,7 @@ function WebGLRenderer( parameters = {} ) { const morphTargets = !! geometry.morphAttributes.position; const morphNormals = !! geometry.morphAttributes.normal; const morphTargetsCount = !! geometry.morphAttributes.position ? geometry.morphAttributes.position.length : 0; + const toneMapping = material.toneMapped ? _this.toneMapping : NoToneMapping; const materialProperties = properties.get( material ); const lights = currentRenderState.state.lights; @@ -1668,6 +1676,10 @@ function WebGLRenderer( parameters = {} ) { needsProgramChange = true; + } else if ( materialProperties.toneMapping !== toneMapping ) { + + needsProgramChange = true; + } else if ( capabilities.isWebGL2 === true && materialProperties.morphTargetsCount !== morphTargetsCount ) { needsProgramChange = true; diff --git a/src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl.js index 5d1eace9c4596f..c6a0bc98983f84 100644 --- a/src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl.js @@ -5,7 +5,7 @@ export default /* glsl */` uniform float bumpScale; // Bump Mapping Unparametrized Surfaces on the GPU by Morten S. Mikkelsen - // http://api.unrealengine.com/attachments/Engine/Rendering/LightingAndShadows/BumpMappingWithoutTangentSpace/mm_sfgrad_bump.pdf + // https://mmikk.github.io/papers3d/mm_sfgrad_bump.pdf // Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2) diff --git a/src/renderers/shaders/ShaderChunk/cube_uv_reflection_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/cube_uv_reflection_fragment.glsl.js index 859cb8126ae122..5e5288c83b1485 100644 --- a/src/renderers/shaders/ShaderChunk/cube_uv_reflection_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/cube_uv_reflection_fragment.glsl.js @@ -89,11 +89,7 @@ export default /* glsl */` float texelSize = 1.0 / ( 3.0 * cubeUV_maxTileSize ); - vec2 uv = getUV( direction, face ) * ( faceSize - 1.0 ); - - vec2 f = fract( uv ); - - uv += 0.5 - f; + vec2 uv = getUV( direction, face ) * ( faceSize - 1.0 ) + 0.5; if ( face > 2.0 ) { @@ -117,25 +113,7 @@ export default /* glsl */` uv *= texelSize; - vec3 tl = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb; - - uv.x += texelSize; - - vec3 tr = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb; - - uv.y += texelSize; - - vec3 br = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb; - - uv.x -= texelSize; - - vec3 bl = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb; - - vec3 tm = mix( tl, tr, f.x ); - - vec3 bm = mix( bl, br, f.x ); - - return mix( tm, bm, f.y ); + return texture2D( envMap, uv ).rgb; } diff --git a/src/renderers/shaders/ShaderChunk/emissivemap_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/emissivemap_fragment.glsl.js index 3c2855627971fd..68c4a3c7df38aa 100644 --- a/src/renderers/shaders/ShaderChunk/emissivemap_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/emissivemap_fragment.glsl.js @@ -3,8 +3,6 @@ export default /* glsl */` vec4 emissiveColor = texture2D( emissiveMap, vUv ); - emissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb; - totalEmissiveRadiance *= emissiveColor.rgb; #endif diff --git a/src/renderers/shaders/ShaderChunk/encodings_pars_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/encodings_pars_fragment.glsl.js index 91cb07bf26423e..26371675293d38 100644 --- a/src/renderers/shaders/ShaderChunk/encodings_pars_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/encodings_pars_fragment.glsl.js @@ -1,62 +1,11 @@ export default /* glsl */` -// For a discussion of what this is, please read this: http://lousodrome.net/blog/light/2013/05/26/gamma-correct-and-hdr-rendering-in-a-32-bits-buffer/ vec4 LinearToLinear( in vec4 value ) { return value; } -vec4 GammaToLinear( in vec4 value, in float gammaFactor ) { - return vec4( pow( value.rgb, vec3( gammaFactor ) ), value.a ); -} - -vec4 LinearToGamma( in vec4 value, in float gammaFactor ) { - return vec4( pow( value.rgb, vec3( 1.0 / gammaFactor ) ), value.a ); -} - -vec4 sRGBToLinear( in vec4 value ) { - return vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.a ); -} - vec4 LinearTosRGB( in vec4 value ) { return vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a ); } -vec4 RGBEToLinear( in vec4 value ) { - return vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 ); -} - -vec4 LinearToRGBE( in vec4 value ) { - float maxComponent = max( max( value.r, value.g ), value.b ); - float fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 ); - return vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 ); - // return vec4( value.brg, ( 3.0 + 128.0 ) / 256.0 ); -} - -// reference: http://iwasbeingirony.blogspot.ca/2010/06/difference-between-rgbm-and-rgbd.html -vec4 RGBMToLinear( in vec4 value, in float maxRange ) { - return vec4( value.rgb * value.a * maxRange, 1.0 ); -} - -vec4 LinearToRGBM( in vec4 value, in float maxRange ) { - float maxRGB = max( value.r, max( value.g, value.b ) ); - float M = clamp( maxRGB / maxRange, 0.0, 1.0 ); - M = ceil( M * 255.0 ) / 255.0; - return vec4( value.rgb / ( M * maxRange ), M ); -} - -// reference: http://iwasbeingirony.blogspot.ca/2010/06/difference-between-rgbm-and-rgbd.html -vec4 RGBDToLinear( in vec4 value, in float maxRange ) { - return vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 ); -} - -vec4 LinearToRGBD( in vec4 value, in float maxRange ) { - float maxRGB = max( value.r, max( value.g, value.b ) ); - float D = max( maxRange / maxRGB, 1.0 ); - // NOTE: The implementation with min causes the shader to not compile on - // a common Alcatel A502DL in Chrome 78/Android 8.1. Some research suggests - // that the chipset is Mediatek MT6739 w/ IMG PowerVR GE8100 GPU. - // D = min( floor( D ) / 255.0, 1.0 ); - D = clamp( floor( D ) / 255.0, 0.0, 1.0 ); - return vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D ); -} `; diff --git a/src/renderers/shaders/ShaderChunk/envmap_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/envmap_fragment.glsl.js index 2ecf3c48d8f7c1..79454ff567aab8 100644 --- a/src/renderers/shaders/ShaderChunk/envmap_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/envmap_fragment.glsl.js @@ -38,8 +38,6 @@ export default /* glsl */` vec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) ); - envColor = envMapTexelToLinear( envColor ); - #elif defined( ENVMAP_TYPE_CUBE_UV ) vec4 envColor = textureCubeUV( envMap, reflectVec, 0.0 ); diff --git a/src/renderers/shaders/ShaderChunk/lightmap_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/lightmap_fragment.glsl.js index 2a8a907cfc26cf..e9542e54d11c6d 100644 --- a/src/renderers/shaders/ShaderChunk/lightmap_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/lightmap_fragment.glsl.js @@ -2,7 +2,7 @@ export default /* glsl */` #ifdef USE_LIGHTMAP vec4 lightMapTexel = texture2D( lightMap, vUv2 ); - vec3 lightMapIrradiance = lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity; + vec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity; #ifndef PHYSICALLY_CORRECT_LIGHTS diff --git a/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js b/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js index 37132de884a11e..b72838bcbb771c 100644 --- a/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js +++ b/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js @@ -4,7 +4,7 @@ export default /* glsl */` #ifdef USE_LIGHTMAP vec4 lightMapTexel = texture2D( lightMap, vUv2 ); - vec3 lightMapIrradiance = lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity; + vec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity; #ifndef PHYSICALLY_CORRECT_LIGHTS diff --git a/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js index 4a0a6f7d7d1316..1e47d88909f3cd 100644 --- a/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js @@ -24,7 +24,7 @@ material.roughness = min( material.roughness, 1.0 ); #ifdef USE_SPECULARCOLORMAP - specularColorFactor *= specularColorMapTexelToLinear( texture2D( specularColorMap, vUv ) ).rgb; + specularColorFactor *= texture2D( specularColorMap, vUv ).rgb; #endif @@ -79,7 +79,7 @@ material.roughness = min( material.roughness, 1.0 ); #ifdef USE_SHEENCOLORMAP - material.sheenColor *= sheenColorMapTexelToLinear( texture2D( sheenColorMap, vUv ) ).rgb; + material.sheenColor *= texture2D( sheenColorMap, vUv ).rgb; #endif diff --git a/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js index 18dd524bce40c2..61a116d53cd4f1 100644 --- a/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js @@ -22,6 +22,26 @@ struct PhysicalMaterial { // temporary vec3 clearcoatSpecular = vec3( 0.0 ); +vec3 sheenSpecular = vec3( 0.0 ); + +// This is a curve-fit approxmation to the "Charlie sheen" BRDF integrated over the hemisphere from +// Estevez and Kulla 2017, "Production Friendly Microfacet Sheen BRDF". The analysis can be found +// in the Sheen section of https://drive.google.com/file/d/1T0D1VSyR4AllqIJTQAraEIzjlb5h4FKH/view?usp=sharing +float IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness) { + + float dotNV = saturate( dot( normal, viewDir ) ); + + float r2 = roughness * roughness; + + float a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95; + + float b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72; + + float DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) ); + + return saturate( DG * RECIPROCAL_PI ); + +} // Analytical approximation of the DFG LUT, one half of the // split-sum approximation used in indirect specular lighting. @@ -133,7 +153,7 @@ void RE_Direct_Physical( const in IncidentLight directLight, const in GeometricC #ifdef USE_SHEEN - reflectedLight.directSpecular += irradiance * BRDF_Sheen( directLight.direction, geometry.viewDir, geometry.normal, material.sheenColor, material.sheenRoughness ); + sheenSpecular += irradiance * BRDF_Sheen( directLight.direction, geometry.viewDir, geometry.normal, material.sheenColor, material.sheenRoughness ); #endif @@ -157,6 +177,12 @@ void RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradia #endif + #ifdef USE_SHEEN + + sheenSpecular += irradiance * material.sheenColor * IBLSheenBRDF( geometry.normal, geometry.viewDir, material.sheenRoughness ); + + #endif + // Both indirect specular and indirect diffuse light accumulate here vec3 singleScattering = vec3( 0.0 ); diff --git a/src/renderers/shaders/ShaderChunk/map_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/map_fragment.glsl.js index 5938668d59c7c7..89ebc6f8b34ec0 100644 --- a/src/renderers/shaders/ShaderChunk/map_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/map_fragment.glsl.js @@ -1,10 +1,17 @@ export default /* glsl */` #ifdef USE_MAP - vec4 texelColor = texture2D( map, vUv ); + vec4 sampledDiffuseColor = texture2D( map, vUv ); - texelColor = mapTexelToLinear( texelColor ); - diffuseColor *= texelColor; + #ifdef DECODE_VIDEO_TEXTURE + + // inline sRGB decode (TODO: Remove this code when https://crbug.com/1256340 is solved) + + sampledDiffuseColor = vec4( mix( pow( sampledDiffuseColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), sampledDiffuseColor.rgb * 0.0773993808, vec3( lessThanEqual( sampledDiffuseColor.rgb, vec3( 0.04045 ) ) ) ), sampledDiffuseColor.w ); + + #endif + + diffuseColor *= sampledDiffuseColor; #endif `; diff --git a/src/renderers/shaders/ShaderChunk/map_particle_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/map_particle_fragment.glsl.js index 6bbc896acb9314..e1c7259cc1952d 100644 --- a/src/renderers/shaders/ShaderChunk/map_particle_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/map_particle_fragment.glsl.js @@ -7,8 +7,7 @@ export default /* glsl */` #ifdef USE_MAP - vec4 mapTexel = texture2D( map, uv ); - diffuseColor *= mapTexelToLinear( mapTexel ); + diffuseColor *= texture2D( map, uv ); #endif diff --git a/src/renderers/shaders/ShaderChunk/transmission_pars_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/transmission_pars_fragment.glsl.js index cb3b4bfcdc7e6b..0b949e24d41e9c 100644 --- a/src/renderers/shaders/ShaderChunk/transmission_pars_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/transmission_pars_fragment.glsl.js @@ -29,7 +29,7 @@ export default /* glsl */` varying vec3 vWorldPosition; - vec3 getVolumeTransmissionRay( vec3 n, vec3 v, float thickness, float ior, mat4 modelMatrix ) { + vec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) { // Direction of refracted light. vec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior ); @@ -45,7 +45,7 @@ export default /* glsl */` } - float applyIorToRoughness( float roughness, float ior ) { + float applyIorToRoughness( const in float roughness, const in float ior ) { // Scale roughness with IOR so that an IOR of 1.0 results in no microfacet refraction and // an IOR of 1.5 results in the default amount of microfacet refraction. @@ -53,7 +53,7 @@ export default /* glsl */` } - vec4 getTransmissionSample( vec2 fragCoord, float roughness, float ior ) { + vec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) { float framebufferLod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior ); @@ -69,7 +69,7 @@ export default /* glsl */` } - vec3 applyVolumeAttenuation( vec3 radiance, float transmissionDistance, vec3 attenuationColor, float attenuationDistance ) { + vec3 applyVolumeAttenuation( const in vec3 radiance, const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) { if ( attenuationDistance == 0.0 ) { @@ -87,9 +87,10 @@ export default /* glsl */` } - vec4 getIBLVolumeRefraction( vec3 n, vec3 v, float roughness, vec3 diffuseColor, vec3 specularColor, float specularF90, - vec3 position, mat4 modelMatrix, mat4 viewMatrix, mat4 projMatrix, float ior, float thickness, - vec3 attenuationColor, float attenuationDistance ) { + vec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor, + const in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix, + const in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness, + const in vec3 attenuationColor, const in float attenuationDistance ) { vec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix ); vec3 refractedRayExit = position + transmissionRay; diff --git a/src/renderers/shaders/ShaderLib.js b/src/renderers/shaders/ShaderLib.js index 59df621f21ed71..0eb045a995d6ec 100644 --- a/src/renderers/shaders/ShaderLib.js +++ b/src/renderers/shaders/ShaderLib.js @@ -299,7 +299,7 @@ ShaderLib.physical = { sheen: { value: 0 }, sheenColor: { value: new Color( 0x000000 ) }, sheenColorMap: { value: null }, - sheenRoughness: { value: 0 }, + sheenRoughness: { value: 1 }, sheenRoughnessMap: { value: null }, transmission: { value: 0 }, transmissionMap: { value: null }, @@ -309,7 +309,7 @@ ShaderLib.physical = { thicknessMap: { value: null }, attenuationDistance: { value: 0 }, attenuationColor: { value: new Color( 0x000000 ) }, - specularIntensity: { value: 0 }, + specularIntensity: { value: 1 }, specularIntensityMap: { value: null }, specularColor: { value: new Color( 1, 1, 1 ) }, specularColorMap: { value: null }, diff --git a/src/renderers/shaders/ShaderLib/background.glsl.js b/src/renderers/shaders/ShaderLib/background.glsl.js index a269da94a149e7..0ffff22930bb1e 100644 --- a/src/renderers/shaders/ShaderLib/background.glsl.js +++ b/src/renderers/shaders/ShaderLib/background.glsl.js @@ -18,9 +18,7 @@ varying vec2 vUv; void main() { - vec4 texColor = texture2D( t2D, vUv ); - - gl_FragColor = mapTexelToLinear( texColor ); + gl_FragColor = texture2D( t2D, vUv ); #include #include diff --git a/src/renderers/shaders/ShaderLib/equirect.glsl.js b/src/renderers/shaders/ShaderLib/equirect.glsl.js index b567619bae9a7a..f866aecd2aba26 100644 --- a/src/renderers/shaders/ShaderLib/equirect.glsl.js +++ b/src/renderers/shaders/ShaderLib/equirect.glsl.js @@ -26,9 +26,7 @@ void main() { vec2 sampleUV = equirectUv( direction ); - vec4 texColor = texture2D( tEquirect, sampleUV ); - - gl_FragColor = mapTexelToLinear( texColor ); + gl_FragColor = texture2D( tEquirect, sampleUV ); #include #include diff --git a/src/renderers/shaders/ShaderLib/meshbasic.glsl.js b/src/renderers/shaders/ShaderLib/meshbasic.glsl.js index d93243ede76ac7..3cd936dafe63b2 100644 --- a/src/renderers/shaders/ShaderLib/meshbasic.glsl.js +++ b/src/renderers/shaders/ShaderLib/meshbasic.glsl.js @@ -87,7 +87,7 @@ void main() { #ifdef USE_LIGHTMAP vec4 lightMapTexel= texture2D( lightMap, vUv2 ); - reflectedLight.indirectDiffuse += lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity; + reflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity; #else diff --git a/src/renderers/shaders/ShaderLib/meshmatcap.glsl.js b/src/renderers/shaders/ShaderLib/meshmatcap.glsl.js index 76b62c04eb6e17..4c7fd4896dc473 100644 --- a/src/renderers/shaders/ShaderLib/meshmatcap.glsl.js +++ b/src/renderers/shaders/ShaderLib/meshmatcap.glsl.js @@ -86,11 +86,10 @@ void main() { #ifdef USE_MATCAP vec4 matcapColor = texture2D( matcap, uv ); - matcapColor = matcapTexelToLinear( matcapColor ); #else - vec4 matcapColor = vec4( 1.0 ); + vec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 ); // default if matcap is missing #endif diff --git a/src/renderers/shaders/ShaderLib/meshphysical.glsl.js b/src/renderers/shaders/ShaderLib/meshphysical.glsl.js index 6060812e21f9b3..72fd958a037efd 100644 --- a/src/renderers/shaders/ShaderLib/meshphysical.glsl.js +++ b/src/renderers/shaders/ShaderLib/meshphysical.glsl.js @@ -175,6 +175,16 @@ void main() { vec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance; + #ifdef USE_SHEEN + + // Sheen energy compensation approximation calculation can be found at the end of + // https://drive.google.com/file/d/1T0D1VSyR4AllqIJTQAraEIzjlb5h4FKH/view?usp=sharing + float sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor ); + + outgoingLight = outgoingLight * sheenEnergyComp + sheenSpecular; + + #endif + #ifdef USE_CLEARCOAT float dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) ); diff --git a/src/renderers/webgl/WebGLCubeMaps.js b/src/renderers/webgl/WebGLCubeMaps.js index f59b36940367bb..f02d4237742ff1 100644 --- a/src/renderers/webgl/WebGLCubeMaps.js +++ b/src/renderers/webgl/WebGLCubeMaps.js @@ -40,14 +40,10 @@ function WebGLCubeMaps( renderer ) { if ( image && image.height > 0 ) { - const currentRenderTarget = renderer.getRenderTarget(); - const renderTarget = new WebGLCubeRenderTarget( image.height / 2 ); renderTarget.fromEquirectangularTexture( renderer, texture ); cubemaps.set( texture, renderTarget ); - renderer.setRenderTarget( currentRenderTarget ); - texture.addEventListener( 'dispose', onTextureDispose ); return mapTextureMapping( renderTarget.texture, texture.mapping ); diff --git a/src/renderers/webgl/WebGLCubeUVMaps.js b/src/renderers/webgl/WebGLCubeUVMaps.js index 8970980942ab64..f7c7bc3cd710d5 100644 --- a/src/renderers/webgl/WebGLCubeUVMaps.js +++ b/src/renderers/webgl/WebGLCubeUVMaps.js @@ -9,45 +9,58 @@ function WebGLCubeUVMaps( renderer ) { function get( texture ) { - if ( texture && texture.isTexture && texture.isRenderTargetTexture === false ) { + if ( texture && texture.isTexture ) { const mapping = texture.mapping; const isEquirectMap = ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ); const isCubeMap = ( mapping === CubeReflectionMapping || mapping === CubeRefractionMapping ); + // equirect/cube map to cubeUV conversion + if ( isEquirectMap || isCubeMap ) { - // equirect/cube map to cubeUV conversion + if ( texture.isRenderTargetTexture && texture.needsPMREMUpdate === true ) { + + texture.needsPMREMUpdate = false; + + let renderTarget = cubeUVmaps.get( texture ); + + if ( pmremGenerator === null ) pmremGenerator = new PMREMGenerator( renderer ); - if ( cubeUVmaps.has( texture ) ) { + renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture, renderTarget ) : pmremGenerator.fromCubemap( texture, renderTarget ); + cubeUVmaps.set( texture, renderTarget ); - return cubeUVmaps.get( texture ).texture; + return renderTarget.texture; } else { - const image = texture.image; + if ( cubeUVmaps.has( texture ) ) { - if ( ( isEquirectMap && image && image.height > 0 ) || ( isCubeMap && image && isCubeTextureComplete( image ) ) ) { + return cubeUVmaps.get( texture ).texture; - const currentRenderTarget = renderer.getRenderTarget(); + } else { - if ( pmremGenerator === null ) pmremGenerator = new PMREMGenerator( renderer ); + const image = texture.image; - const renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture ) : pmremGenerator.fromCubemap( texture ); - cubeUVmaps.set( texture, renderTarget ); + if ( ( isEquirectMap && image && image.height > 0 ) || ( isCubeMap && image && isCubeTextureComplete( image ) ) ) { - renderer.setRenderTarget( currentRenderTarget ); + if ( pmremGenerator === null ) pmremGenerator = new PMREMGenerator( renderer ); - texture.addEventListener( 'dispose', onTextureDispose ); + const renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture ) : pmremGenerator.fromCubemap( texture ); + cubeUVmaps.set( texture, renderTarget ); - return renderTarget.texture; + texture.addEventListener( 'dispose', onTextureDispose ); - } else { + return renderTarget.texture; + + } else { + + // image not yet ready. try the conversion next frame - // image not yet ready. try the conversion next frame + return null; - return null; + } } diff --git a/src/renderers/webgl/WebGLMorphtargets.js b/src/renderers/webgl/WebGLMorphtargets.js index 291bee52ad252b..b57c2fbab4e08c 100644 --- a/src/renderers/webgl/WebGLMorphtargets.js +++ b/src/renderers/webgl/WebGLMorphtargets.js @@ -135,6 +135,18 @@ function WebGLMorphtargets( gl, capabilities, textures ) { morphTextures.set( geometry, entry ); + function disposeTexture() { + + texture.dispose(); + + morphTextures.delete( geometry ); + + geometry.removeEventListener( 'dispose', disposeTexture ); + + } + + geometry.addEventListener( 'dispose', disposeTexture ); + } // diff --git a/src/renderers/webgl/WebGLProgram.js b/src/renderers/webgl/WebGLProgram.js index 933d68daae197d..ea8179e117b39d 100644 --- a/src/renderers/webgl/WebGLProgram.js +++ b/src/renderers/webgl/WebGLProgram.js @@ -1,7 +1,7 @@ import { WebGLUniforms } from './WebGLUniforms.js'; import { WebGLShader } from './WebGLShader.js'; import { ShaderChunk } from '../shaders/ShaderChunk.js'; -import { RGBFormat, NoToneMapping, AddOperation, MixOperation, MultiplyOperation, CubeRefractionMapping, CubeUVRefractionMapping, CubeUVReflectionMapping, CubeReflectionMapping, PCFSoftShadowMap, PCFShadowMap, VSMShadowMap, ACESFilmicToneMapping, CineonToneMapping, CustomToneMapping, ReinhardToneMapping, LinearToneMapping, GammaEncoding, RGBDEncoding, RGBM16Encoding, RGBM7Encoding, RGBEEncoding, sRGBEncoding, LinearEncoding, GLSL3 } from '../../constants.js'; +import { RGBFormat, NoToneMapping, AddOperation, MixOperation, MultiplyOperation, CubeRefractionMapping, CubeUVRefractionMapping, CubeUVReflectionMapping, CubeReflectionMapping, PCFSoftShadowMap, PCFShadowMap, VSMShadowMap, ACESFilmicToneMapping, CineonToneMapping, CustomToneMapping, ReinhardToneMapping, LinearToneMapping, sRGBEncoding, LinearEncoding, GLSL3 } from '../../constants.js'; // From https://www.khronos.org/registry/webgl/extensions/KHR_parallel_shader_compile/ const COMPLETION_STATUS_KHR = 0x91B1; @@ -30,16 +30,6 @@ function getEncodingComponents( encoding ) { return [ 'Linear', '( value )' ]; case sRGBEncoding: return [ 'sRGB', '( value )' ]; - case RGBEEncoding: - return [ 'RGBE', '( value )' ]; - case RGBM7Encoding: - return [ 'RGBM', '( value, 7.0 )' ]; - case RGBM16Encoding: - return [ 'RGBM', '( value, 16.0 )' ]; - case RGBDEncoding: - return [ 'RGBD', '( value, 256.0 )' ]; - case GammaEncoding: - return [ 'Gamma', '( value, float( GAMMA_FACTOR ) )' ]; default: console.warn( 'THREE.WebGLProgram: Unsupported encoding:', encoding ); return [ 'Linear', '( value )' ]; @@ -62,13 +52,6 @@ function getShaderErrors( gl, shader, type ) { } -function getTexelDecodingFunction( functionName, encoding ) { - - const components = getEncodingComponents( encoding ); - return 'vec4 ' + functionName + '( vec4 value ) { return ' + components[ 0 ] + 'ToLinear' + components[ 1 ] + '; }'; - -} - function getTexelEncodingFunction( functionName, encoding ) { const components = getEncodingComponents( encoding ); @@ -400,9 +383,6 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { const envMapModeDefine = generateEnvMapModeDefine( parameters ); const envMapBlendingDefine = generateEnvMapBlendingDefine( parameters ); - - const gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0; - const customExtensions = parameters.isWebGL2 ? '' : generateExtensions( parameters ); const customDefines = generateDefines( defines ); @@ -454,8 +434,6 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '', - '#define GAMMA_FACTOR ' + gammaFactorDefine, - '#define MAX_BONES ' + parameters.maxBones, ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '', ( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '', @@ -604,8 +582,6 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { customDefines, - '#define GAMMA_FACTOR ' + gammaFactorDefine, - ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '', ( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '', @@ -645,6 +621,8 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', + parameters.decodeVideoTexture ? '#define DECODE_VIDEO_TEXTURE' : '', + parameters.vertexTangents ? '#define USE_TANGENT' : '', parameters.vertexColors || parameters.instancingColor ? '#define USE_COLOR' : '', parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', @@ -682,13 +660,6 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.format === RGBFormat ? '#define OPAQUE' : '', ShaderChunk[ 'encodings_pars_fragment' ], // this code is required here because it is used by the various encoding/decoding function defined below - parameters.map ? getTexelDecodingFunction( 'mapTexelToLinear', parameters.mapEncoding ) : '', - parameters.matcap ? getTexelDecodingFunction( 'matcapTexelToLinear', parameters.matcapEncoding ) : '', - parameters.envMap ? getTexelDecodingFunction( 'envMapTexelToLinear', parameters.envMapEncoding ) : '', - parameters.emissiveMap ? getTexelDecodingFunction( 'emissiveMapTexelToLinear', parameters.emissiveMapEncoding ) : '', - parameters.specularColorMap ? getTexelDecodingFunction( 'specularColorMapTexelToLinear', parameters.specularColorMapEncoding ) : '', - parameters.sheenColorMap ? getTexelDecodingFunction( 'sheenColorMapTexelToLinear', parameters.sheenColorMapEncoding ) : '', - parameters.lightMap ? getTexelDecodingFunction( 'lightMapTexelToLinear', parameters.lightMapEncoding ) : '', getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputEncoding ), parameters.depthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '', diff --git a/src/renderers/webgl/WebGLPrograms.js b/src/renderers/webgl/WebGLPrograms.js index ff85e9c2dcc26c..54156988b2af01 100644 --- a/src/renderers/webgl/WebGLPrograms.js +++ b/src/renderers/webgl/WebGLPrograms.js @@ -1,13 +1,14 @@ -import { BackSide, DoubleSide, CubeUVRefractionMapping, CubeUVReflectionMapping, LinearEncoding, sRGBEncoding, ObjectSpaceNormalMap, TangentSpaceNormalMap, NoToneMapping, RGBAFormat, UnsignedByteType } from '../../constants.js'; +import { BackSide, DoubleSide, CubeUVRefractionMapping, CubeUVReflectionMapping, ObjectSpaceNormalMap, TangentSpaceNormalMap, NoToneMapping, sRGBEncoding } from '../../constants.js'; import { Layers } from '../../core/Layers.js'; import { WebGLProgram } from './WebGLProgram.js'; +import { WebGLShaderCache } from './WebGLShaderCache.js'; import { ShaderLib } from '../shaders/ShaderLib.js'; import { UniformsUtils } from '../shaders/UniformsUtils.js'; -import { hashString } from '../../utils.js'; function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ) { const _programLayers = new Layers(); + const _customShaders = new WebGLShaderCache(); const programs = []; const isWebGL2 = capabilities.isWebGL2; @@ -71,35 +72,6 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities } - function getTextureEncodingFromMap( map ) { - - let encoding; - - if ( map && map.isTexture ) { - - encoding = map.encoding; - - } else if ( map && map.isWebGLRenderTarget ) { - - console.warn( 'THREE.WebGLPrograms.getTextureEncodingFromMap: don\'t use render targets as textures. Use their .texture property instead.' ); - encoding = map.texture.encoding; - - } else { - - encoding = LinearEncoding; - - } - - if ( isWebGL2 && map && map.isTexture && map.format === RGBAFormat && map.type === UnsignedByteType && map.encoding === sRGBEncoding ) { - - encoding = LinearEncoding; // disable inline decode for sRGB textures in WebGL 2 - - } - - return encoding; - - } - function getParameters( material, lights, shadows, scene, object ) { const fog = scene.fog; @@ -127,6 +99,7 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities } let vertexShader, fragmentShader; + let customVertexShaderID, customFragmentShaderID; if ( shaderID ) { @@ -140,6 +113,11 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities vertexShader = material.vertexShader; fragmentShader = material.fragmentShader; + _customShaders.update( material ); + + customVertexShaderID = _customShaders.getVertexShaderID( material ); + customFragmentShaderID = _customShaders.getFragmentShaderID( material ); + } const currentRenderTarget = renderer.getRenderTarget(); @@ -158,6 +136,9 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities fragmentShader: fragmentShader, defines: material.defines, + customVertexShaderID: customVertexShaderID, + customFragmentShaderID: customFragmentShaderID, + isRawShaderMaterial: material.isRawShaderMaterial === true, glslVersion: material.glslVersion, @@ -167,25 +148,22 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities instancingColor: object.isInstancedMesh === true && object.instanceColor !== null, supportsVertexTextures: vertexTextures, - outputEncoding: ( currentRenderTarget !== null ) ? getTextureEncodingFromMap( currentRenderTarget.texture ) : renderer.outputEncoding, + outputEncoding: ( currentRenderTarget !== null ) ? currentRenderTarget.texture.encoding : renderer.outputEncoding, map: !! material.map, - mapEncoding: getTextureEncodingFromMap( material.map ), matcap: !! material.matcap, - matcapEncoding: getTextureEncodingFromMap( material.matcap ), envMap: !! envMap, envMapMode: envMap && envMap.mapping, - envMapEncoding: getTextureEncodingFromMap( envMap ), envMapCubeUV: ( !! envMap ) && ( ( envMap.mapping === CubeUVReflectionMapping ) || ( envMap.mapping === CubeUVRefractionMapping ) ), lightMap: !! material.lightMap, - lightMapEncoding: getTextureEncodingFromMap( material.lightMap ), aoMap: !! material.aoMap, emissiveMap: !! material.emissiveMap, - emissiveMapEncoding: getTextureEncodingFromMap( material.emissiveMap ), bumpMap: !! material.bumpMap, normalMap: !! material.normalMap, objectSpaceNormalMap: material.normalMapType === ObjectSpaceNormalMap, tangentSpaceNormalMap: material.normalMapType === TangentSpaceNormalMap, + decodeVideoTexture: !! material.map && ( material.map.isVideoTexture === true ) && ( material.map.encoding === sRGBEncoding ), + clearcoat: useClearcoat, clearcoatMap: useClearcoat && !! material.clearcoatMap, clearcoatRoughnessMap: useClearcoat && !! material.clearcoatRoughnessMap, @@ -197,7 +175,6 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities specularMap: !! material.specularMap, specularIntensityMap: !! material.specularIntensityMap, specularColorMap: !! material.specularColorMap, - specularColorMapEncoding: getTextureEncodingFromMap( material.specularColorMap ), alphaMap: !! material.alphaMap, alphaTest: useAlphaTest, @@ -206,7 +183,6 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities sheen: material.sheen > 0, sheenColorMap: !! material.sheenColorMap, - sheenColorMapEncoding: getTextureEncodingFromMap( material.sheenColorMap ), sheenRoughnessMap: !! material.sheenRoughnessMap, transmission: material.transmission > 0, @@ -297,8 +273,8 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities } else { - array.push( hashString( parameters.fragmentShader ) ); - array.push( hashString( parameters.vertexShader ) ); + array.push( parameters.customVertexShaderID ); + array.push( parameters.customFragmentShaderID ); } @@ -318,7 +294,6 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities getProgramCacheKeyParameters( array, parameters ); getProgramCacheKeyBooleans( array, parameters ); array.push( renderer.outputEncoding ); - array.push( renderer.gammaFactor ); } @@ -332,12 +307,7 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities array.push( parameters.precision ); array.push( parameters.outputEncoding ); - array.push( parameters.mapEncoding ); - array.push( parameters.matcapEncoding ); array.push( parameters.envMapMode ); - array.push( parameters.envMapEncoding ); - array.push( parameters.lightMapEncoding ); - array.push( parameters.emissiveMapEncoding ); array.push( parameters.combine ); array.push( parameters.vertexUvs ); array.push( parameters.fogExp2 ); @@ -357,8 +327,6 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities array.push( parameters.numClippingPlanes ); array.push( parameters.numClipIntersection ); array.push( parameters.format ); - array.push( parameters.specularColorMapEncoding ); - array.push( parameters.sheenColorMapEncoding ); } @@ -478,6 +446,8 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities _programLayers.enable( 20 ); if ( parameters.sheenRoughnessMap ) _programLayers.enable( 21 ); + if ( parameters.decodeVideoTexture ) + _programLayers.enable( 22 ); array.push( _programLayers.mask ); @@ -550,14 +520,28 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities } + function releaseShaderCache( material ) { + + _customShaders.remove( material ); + + } + + function dispose() { + + _customShaders.dispose(); + + } + return { getParameters: getParameters, getProgramCacheKey: getProgramCacheKey, getUniforms: getUniforms, acquireProgram: acquireProgram, releaseProgram: releaseProgram, + releaseShaderCache: releaseShaderCache, // Exposed for resource monitoring & error feedback via renderer.info: - programs: programs + programs: programs, + dispose: dispose }; } diff --git a/src/renderers/webgl/WebGLShaderCache.js b/src/renderers/webgl/WebGLShaderCache.js new file mode 100644 index 00000000000000..2d423a48504d8e --- /dev/null +++ b/src/renderers/webgl/WebGLShaderCache.js @@ -0,0 +1,120 @@ +let _id = 0; + +class WebGLShaderCache { + + constructor() { + + this.shaderCache = new Map(); + this.materialCache = new Map(); + + } + + update( material ) { + + const vertexShader = material.vertexShader; + const fragmentShader = material.fragmentShader; + + const vertexShaderStage = this._getShaderStage( vertexShader ); + const fragmentShaderStage = this._getShaderStage( fragmentShader ); + + const materialShaders = this._getShaderCacheForMaterial( material ); + + if ( materialShaders.has( vertexShaderStage ) === false ) { + + materialShaders.add( vertexShaderStage ); + vertexShaderStage.usedTimes ++; + + } + + if ( materialShaders.has( fragmentShaderStage ) === false ) { + + materialShaders.add( fragmentShaderStage ); + fragmentShaderStage.usedTimes ++; + + } + + return this; + + } + + remove( material ) { + + const materialShaders = this.materialCache.get( material ); + + for ( const shaderStage of materialShaders ) { + + shaderStage.usedTimes --; + + if ( shaderStage.usedTimes === 0 ) this.shaderCache.delete( shaderStage ); + + } + + this.materialCache.delete( material ); + + return this; + + } + + getVertexShaderID( material ) { + + return this._getShaderStage( material.vertexShader ).id; + + } + + getFragmentShaderID( material ) { + + return this._getShaderStage( material.fragmentShader ).id; + + } + + dispose() { + + this.shaderCache.clear(); + this.materialCache.clear(); + + } + + _getShaderCacheForMaterial( material ) { + + const cache = this.materialCache; + + if ( cache.has( material ) === false ) { + + cache.set( material, new Set() ); + + } + + return cache.get( material ); + + } + + _getShaderStage( code ) { + + const cache = this.shaderCache; + + if ( cache.has( code ) === false ) { + + const stage = new WebGLShaderStage(); + cache.set( code, stage ); + + } + + return cache.get( code ); + + } + +} + +class WebGLShaderStage { + + constructor() { + + this.id = _id ++; + + this.usedTimes = 0; + + } + +} + +export { WebGLShaderCache }; diff --git a/src/renderers/webgl/WebGLTextures.js b/src/renderers/webgl/WebGLTextures.js index 6e4bd81906579f..18a4b4301b30b3 100644 --- a/src/renderers/webgl/WebGLTextures.js +++ b/src/renderers/webgl/WebGLTextures.js @@ -1,5 +1,6 @@ -import { LinearFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, NearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, RGBFormat, RGBAFormat, DepthFormat, DepthStencilFormat, UnsignedShortType, UnsignedIntType, UnsignedInt248Type, FloatType, HalfFloatType, MirroredRepeatWrapping, ClampToEdgeWrapping, RepeatWrapping, sRGBEncoding } from '../../constants.js'; +import { LinearFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, NearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, RGBFormat, RGBAFormat, DepthFormat, DepthStencilFormat, UnsignedShortType, UnsignedIntType, UnsignedInt248Type, FloatType, HalfFloatType, MirroredRepeatWrapping, ClampToEdgeWrapping, RepeatWrapping, sRGBEncoding, LinearEncoding, UnsignedByteType, _SRGBFormat, _SRGBAFormat } from '../../constants.js'; import * as MathUtils from '../../math/MathUtils.js'; +import { ImageUtils } from '../../extras/ImageUtils.js'; import { createElementNS } from '../../utils.js'; function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) { @@ -130,7 +131,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } - function getInternalFormat( internalFormatName, glFormat, glType, encoding ) { + function getInternalFormat( internalFormatName, glFormat, glType, encoding, isVideoTexture = false ) { if ( isWebGL2 === false ) return glFormat; @@ -164,7 +165,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( glType === _gl.FLOAT ) internalFormat = _gl.RGBA32F; if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RGBA16F; - if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = ( encoding === sRGBEncoding ) ? _gl.SRGB8_ALPHA8 : _gl.RGBA8; + if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = ( encoding === sRGBEncoding && isVideoTexture === false ) ? _gl.SRGB8_ALPHA8 : _gl.RGBA8; } @@ -550,13 +551,14 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, _gl.pixelStorei( _gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, _gl.NONE ); const needsPowerOfTwo = textureNeedsPowerOfTwo( texture ) && isPowerOfTwo( texture.image ) === false; - const image = resizeImage( texture.image, needsPowerOfTwo, false, maxTextureSize ); + let image = resizeImage( texture.image, needsPowerOfTwo, false, maxTextureSize ); + image = verifyColorSpace( texture, image ); const supportsMips = isPowerOfTwo( image ) || isWebGL2, - glFormat = utils.convert( texture.format ); + glFormat = utils.convert( texture.format, texture.encoding ); let glType = utils.convert( texture.type ), - glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); + glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding, texture.isVideoTexture ); setTextureParameters( textureType, texture, supportsMips ); @@ -900,11 +902,13 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } + cubeImage[ i ] = verifyColorSpace( texture, cubeImage[ i ] ); + } const image = cubeImage[ 0 ], supportsMips = isPowerOfTwo( image ) || isWebGL2, - glFormat = utils.convert( texture.format ), + glFormat = utils.convert( texture.format, texture.encoding ), glType = utils.convert( texture.type ), glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); @@ -1069,7 +1073,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, // Setup storage for target texture and bind it to correct framebuffer function setupFrameBufferTexture( framebuffer, renderTarget, texture, attachment, textureTarget ) { - const glFormat = utils.convert( texture.format ); + const glFormat = utils.convert( texture.format, texture.encoding ); const glType = utils.convert( texture.type ); const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); const renderTargetProperties = properties.get( renderTarget ); @@ -1177,7 +1181,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, // Use the first texture for MRT so far const texture = renderTarget.isWebGLMultipleRenderTargets === true ? renderTarget.texture[ 0 ] : renderTarget.texture; - const glFormat = utils.convert( texture.format ); + const glFormat = utils.convert( texture.format, texture.encoding ); const glType = utils.convert( texture.type ); const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); const samples = getRenderTargetSamples( renderTarget ); @@ -1412,7 +1416,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer ); - const glFormat = utils.convert( texture.format ); + const glFormat = utils.convert( texture.format, texture.encoding ); const glType = utils.convert( texture.type ); const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); const samples = getRenderTargetSamples( renderTarget ); @@ -1631,6 +1635,66 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } + function verifyColorSpace( texture, image ) { + + const encoding = texture.encoding; + const format = texture.format; + const type = texture.type; + + if ( texture.isCompressedTexture === true || texture.format === _SRGBFormat || texture.format === _SRGBAFormat ) return image; + + if ( encoding !== LinearEncoding ) { + + // sRGB + + if ( encoding === sRGBEncoding && texture.isVideoTexture !== true ) { + + if ( isWebGL2 === false ) { + + // in WebGL 1, try to use EXT_sRGB extension and unsized formats + + if ( extensions.has( 'EXT_sRGB' ) === true && ( format === RGBFormat || format === RGBAFormat ) ) { + + if ( format === RGBFormat ) texture.format = _SRGBFormat; + if ( format === RGBAFormat ) texture.format = _SRGBAFormat; + + // it's not possible to generate mips in WebGL 1 with the above formats + + texture.minFilter = LinearFilter; + texture.generateMipmaps = false; + + } else { + + // slow fallback (CPU decode) + + image = ImageUtils.sRGBToLinear( image ); + + } + + } else { + + // in WebGL 2 uncompressed textures can only be sRGB encoded if they have the RGBA8 format + + if ( format !== RGBAFormat || type !== UnsignedByteType ) { + + console.warn( 'THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType.' ); + + } + + } + + } else { + + console.error( 'THREE.WebGLTextures: Unsupported texture encoding:', encoding ); + + } + + } + + return image; + + } + // backwards compatibility let warnedTexture2D = false; diff --git a/src/renderers/webgl/WebGLUtils.js b/src/renderers/webgl/WebGLUtils.js index fb180aa2c3dee9..b1d9ca8b11d616 100644 --- a/src/renderers/webgl/WebGLUtils.js +++ b/src/renderers/webgl/WebGLUtils.js @@ -1,10 +1,10 @@ -import { RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_10x10_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT5_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT1_Format, RGB_S3TC_DXT1_Format, DepthFormat, DepthStencilFormat, LuminanceAlphaFormat, LuminanceFormat, RedFormat, RGBAFormat, RGBFormat, AlphaFormat, RedIntegerFormat, RGFormat, RGIntegerFormat, RGBIntegerFormat, RGBAIntegerFormat, HalfFloatType, FloatType, UnsignedIntType, IntType, UnsignedShortType, ShortType, ByteType, UnsignedInt248Type, UnsignedShort565Type, UnsignedShort5551Type, UnsignedShort4444Type, UnsignedByteType, SRGB8_ALPHA8_ASTC_4x4_Format, SRGB8_ALPHA8_ASTC_5x4_Format, SRGB8_ALPHA8_ASTC_5x5_Format, SRGB8_ALPHA8_ASTC_6x5_Format, SRGB8_ALPHA8_ASTC_6x6_Format, SRGB8_ALPHA8_ASTC_8x5_Format, SRGB8_ALPHA8_ASTC_8x6_Format, SRGB8_ALPHA8_ASTC_8x8_Format, SRGB8_ALPHA8_ASTC_10x5_Format, SRGB8_ALPHA8_ASTC_10x6_Format, SRGB8_ALPHA8_ASTC_10x8_Format, SRGB8_ALPHA8_ASTC_10x10_Format, SRGB8_ALPHA8_ASTC_12x10_Format, SRGB8_ALPHA8_ASTC_12x12_Format, RGBA_BPTC_Format } from '../../constants.js'; +import { RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_10x10_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT5_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT1_Format, RGB_S3TC_DXT1_Format, DepthFormat, DepthStencilFormat, LuminanceAlphaFormat, LuminanceFormat, RedFormat, RGBAFormat, RGBFormat, AlphaFormat, RedIntegerFormat, RGFormat, RGIntegerFormat, RGBIntegerFormat, RGBAIntegerFormat, HalfFloatType, FloatType, UnsignedIntType, IntType, UnsignedShortType, ShortType, ByteType, UnsignedInt248Type, UnsignedShort565Type, UnsignedShort5551Type, UnsignedShort4444Type, UnsignedByteType, RGBA_BPTC_Format, sRGBEncoding, _SRGBFormat, _SRGBAFormat } from '../../constants.js'; function WebGLUtils( gl, extensions, capabilities ) { const isWebGL2 = capabilities.isWebGL2; - function convert( p ) { + function convert( p, encoding = null ) { let extension; @@ -47,6 +47,25 @@ function WebGLUtils( gl, extensions, capabilities ) { if ( p === DepthStencilFormat ) return gl.DEPTH_STENCIL; if ( p === RedFormat ) return gl.RED; + // WebGL 1 sRGB fallback + + if ( p === _SRGBFormat || p === _SRGBAFormat ) { + + extension = extensions.get( 'EXT_sRGB' ); + + if ( extension !== null ) { + + if ( p === _SRGBFormat ) return extension.SRGB_EXT; + if ( p === _SRGBAFormat ) return extension.SRGB_ALPHA_EXT; + + } else { + + return null; + + } + + } + // WebGL2 formats. if ( p === RedIntegerFormat ) return gl.RED_INTEGER; @@ -55,28 +74,51 @@ function WebGLUtils( gl, extensions, capabilities ) { if ( p === RGBIntegerFormat ) return gl.RGB_INTEGER; if ( p === RGBAIntegerFormat ) return gl.RGBA_INTEGER; - if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || - p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) { + // S3TC - extension = extensions.get( 'WEBGL_compressed_texture_s3tc' ); + if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) { - if ( extension !== null ) { + if ( encoding === sRGBEncoding ) { + + extension = extensions.get( 'WEBGL_compressed_texture_s3tc_srgb' ); + + if ( extension !== null ) { + + if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_SRGB_S3TC_DXT1_EXT; + if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT; + if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT; + if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; + + } else { - if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT; - if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT; - if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT; - if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT; + return null; + + } } else { - return null; + extension = extensions.get( 'WEBGL_compressed_texture_s3tc' ); + + if ( extension !== null ) { + + if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT; + if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT; + if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT; + if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT; + + } else { + + return null; + + } } } - if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || - p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) { + // PVRTC + + if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) { extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' ); @@ -95,6 +137,8 @@ function WebGLUtils( gl, extensions, capabilities ) { } + // ETC1 + if ( p === RGB_ETC1_Format ) { extension = extensions.get( 'WEBGL_compressed_texture_etc1' ); @@ -111,37 +155,51 @@ function WebGLUtils( gl, extensions, capabilities ) { } + // ETC2 + if ( p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format ) { extension = extensions.get( 'WEBGL_compressed_texture_etc' ); if ( extension !== null ) { - if ( p === RGB_ETC2_Format ) return extension.COMPRESSED_RGB8_ETC2; - if ( p === RGBA_ETC2_EAC_Format ) return extension.COMPRESSED_RGBA8_ETC2_EAC; + if ( p === RGB_ETC2_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2; + if ( p === RGBA_ETC2_EAC_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC; + + } else { + + return null; } } + // ASTC + if ( p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format || p === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format || p === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format || p === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format || - p === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format || - p === SRGB8_ALPHA8_ASTC_4x4_Format || p === SRGB8_ALPHA8_ASTC_5x4_Format || p === SRGB8_ALPHA8_ASTC_5x5_Format || - p === SRGB8_ALPHA8_ASTC_6x5_Format || p === SRGB8_ALPHA8_ASTC_6x6_Format || p === SRGB8_ALPHA8_ASTC_8x5_Format || - p === SRGB8_ALPHA8_ASTC_8x6_Format || p === SRGB8_ALPHA8_ASTC_8x8_Format || p === SRGB8_ALPHA8_ASTC_10x5_Format || - p === SRGB8_ALPHA8_ASTC_10x6_Format || p === SRGB8_ALPHA8_ASTC_10x8_Format || p === SRGB8_ALPHA8_ASTC_10x10_Format || - p === SRGB8_ALPHA8_ASTC_12x10_Format || p === SRGB8_ALPHA8_ASTC_12x12_Format ) { + p === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format ) { extension = extensions.get( 'WEBGL_compressed_texture_astc' ); if ( extension !== null ) { - // TODO Complete? - - return p; + if ( p === RGBA_ASTC_4x4_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : extension.COMPRESSED_RGBA_ASTC_4x4_KHR; + if ( p === RGBA_ASTC_5x4_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : extension.COMPRESSED_RGBA_ASTC_5x4_KHR; + if ( p === RGBA_ASTC_5x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : extension.COMPRESSED_RGBA_ASTC_5x5_KHR; + if ( p === RGBA_ASTC_6x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : extension.COMPRESSED_RGBA_ASTC_6x5_KHR; + if ( p === RGBA_ASTC_6x6_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : extension.COMPRESSED_RGBA_ASTC_6x6_KHR; + if ( p === RGBA_ASTC_8x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : extension.COMPRESSED_RGBA_ASTC_8x5_KHR; + if ( p === RGBA_ASTC_8x6_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : extension.COMPRESSED_RGBA_ASTC_8x6_KHR; + if ( p === RGBA_ASTC_8x8_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : extension.COMPRESSED_RGBA_ASTC_8x8_KHR; + if ( p === RGBA_ASTC_10x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : extension.COMPRESSED_RGBA_ASTC_10x5_KHR; + if ( p === RGBA_ASTC_10x6_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : extension.COMPRESSED_RGBA_ASTC_10x6_KHR; + if ( p === RGBA_ASTC_10x8_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : extension.COMPRESSED_RGBA_ASTC_10x8_KHR; + if ( p === RGBA_ASTC_10x10_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : extension.COMPRESSED_RGBA_ASTC_10x10_KHR; + if ( p === RGBA_ASTC_12x10_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : extension.COMPRESSED_RGBA_ASTC_12x10_KHR; + if ( p === RGBA_ASTC_12x12_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : extension.COMPRESSED_RGBA_ASTC_12x12_KHR; } else { @@ -151,15 +209,15 @@ function WebGLUtils( gl, extensions, capabilities ) { } + // BPTC + if ( p === RGBA_BPTC_Format ) { extension = extensions.get( 'EXT_texture_compression_bptc' ); if ( extension !== null ) { - // TODO Complete? - - return p; + if ( p === RGBA_BPTC_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT : extension.COMPRESSED_RGBA_BPTC_UNORM_EXT; } else { @@ -169,6 +227,8 @@ function WebGLUtils( gl, extensions, capabilities ) { } + // + if ( p === UnsignedInt248Type ) { if ( isWebGL2 ) return gl.UNSIGNED_INT_24_8; diff --git a/src/renderers/webxr/WebXRManager.js b/src/renderers/webxr/WebXRManager.js index 99588561c4cc1e..a0c6d51cb2d8a1 100644 --- a/src/renderers/webxr/WebXRManager.js +++ b/src/renderers/webxr/WebXRManager.js @@ -13,6 +13,7 @@ import { DepthStencilFormat, RGBAFormat, RGBFormat, + sRGBEncoding, UnsignedByteType, UnsignedShortType, UnsignedInt248Type, @@ -286,6 +287,12 @@ class WebXRManager extends EventDispatcher { scaleFactor: framebufferScaleFactor }; + if ( renderer.outputEncoding === sRGBEncoding ) { + + projectionlayerInit.colorFormat = ( attributes.alpha || isMultisample ) ? gl.SRGB8_ALPHA8 : gl.SRGB8; + + } + glBinding = new XRWebGLBinding( session, gl ); glProjLayer = glBinding.createProjectionLayer( projectionlayerInit ); diff --git a/src/textures/Texture.js b/src/textures/Texture.js index 108642328b468a..49713629101fd0 100644 --- a/src/textures/Texture.js +++ b/src/textures/Texture.js @@ -70,7 +70,8 @@ class Texture extends EventDispatcher { this.version = 0; this.onUpdate = null; - this.isRenderTargetTexture = false; + this.isRenderTargetTexture = false; // indicates whether a texture belongs to a render target or not + this.needsPMREMUpdate = false; // indicates whether this texture should be processed by PMREMGenerator or not (only relevant for render target textures) } diff --git a/src/utils.js b/src/utils.js index 5ab11cb1b8fe30..660e6301b84730 100644 --- a/src/utils.js +++ b/src/utils.js @@ -54,40 +54,4 @@ function createElementNS( name ) { } -/** - * cyrb53 hash for string from: https://stackoverflow.com/a/52171480 - * - * Public Domain, @bryc - https://stackoverflow.com/users/815680/bryc - * - * It is roughly similar to the well-known MurmurHash/xxHash algorithms. It uses a combination - * of multiplication and Xorshift to generate the hash, but not as thorough. As a result it's - * faster than either would be in JavaScript and significantly simpler to implement. Keep in - * mind this is not a secure algorithm, if privacy/security is a concern, this is not for you. - * - * @param {string} str - * @param {number} seed, default 0 - * @returns number - */ -function hashString( str, seed = 0 ) { - - let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed; - - for ( let i = 0, ch; i < str.length; i ++ ) { - - ch = str.charCodeAt( i ); - - h1 = Math.imul( h1 ^ ch, 2654435761 ); - - h2 = Math.imul( h2 ^ ch, 1597334677 ); - - } - - h1 = Math.imul( h1 ^ ( h1 >>> 16 ), 2246822507 ) ^ Math.imul( h2 ^ ( h2 >>> 13 ), 3266489909 ); - - h2 = Math.imul( h2 ^ ( h2 >>> 16 ), 2246822507 ) ^ Math.imul( h1 ^ ( h1 >>> 13 ), 3266489909 ); - - return 4294967296 * ( 2097151 & h2 ) + ( h1 >>> 0 ); - -} - -export { arrayMin, arrayMax, getTypedArray, createElementNS, hashString }; +export { arrayMin, arrayMax, getTypedArray, createElementNS }; diff --git a/test/benchmark/benchmark.js b/test/benchmark/benchmark.js index 5fe06714ac46ad..3c237bfeed2562 100644 --- a/test/benchmark/benchmark.js +++ b/test/benchmark/benchmark.js @@ -1,79 +1,103 @@ -var BenchClass = function() { - this.suites = []; - this.THREE = window.THREE ; - window.THREE = undefined; - Benchmark.options.maxTime = 1.0; - return this; -} - -BenchClass.prototype.isTHREELoaded = function() { - return _.isObject(this.THREE); -} - -BenchClass.prototype.newSuite = function(name) { - var s = new Benchmark.Suite(name); - this.suites.push(s); - return s; -} - -BenchClass.prototype.display = function() { - for (x of this.suites) { - var s = new SuiteUI(x); - s.render(); - } -} - -BenchClass.prototype.warning = function(message) { - console.error(message); -} - -var SuiteUI = function(suite) { - this.suite = suite; - this.isRunning = false; - return this; -} - -SuiteUI.prototype.render = function() { - var n = document.importNode(this.suiteTemplate, true); - this.elem = n.querySelector("article"); - this.results = n.querySelector(".results"); - this.title = n.querySelector("h2"); - this.runButton = n.querySelector("h3"); - - this.title.innerText = this.suite.name; - this.runButton.onclick = this.run.bind(this); - - this.section.appendChild(n); -} - -SuiteUI.prototype.run = function() { - this.runButton.click = _.noop; - this.runButton.innerText = "Running..." - this.suite.on("complete", this.complete.bind(this)); - this.suite.run({ - async: true - }); -} - -SuiteUI.prototype.complete = function() { - this.runButton.style.display = "none"; - this.results.style.display = "block"; - var f = _.orderBy(this.suite, ["hz"], ["desc"]); - for (var i = 0; i < f.length; i++) { - var x = f[i]; - var n = document.importNode(this.suiteTestTemplate, true); - n.querySelector(".name").innerText = x.name; - n.querySelector(".ops").innerText = x.hz.toFixed(); - n.querySelector(".desv").innerText = x.stats.rme.toFixed(2); - this.results.appendChild(n); - } -} +var BenchClass = function () { + + this.suites = []; + this.THREE = window.THREE; + window.THREE = undefined; + Benchmark.options.maxTime = 1.0; + return this; + +}; + +BenchClass.prototype.isTHREELoaded = function () { + + return _.isObject( this.THREE ); + +}; + +BenchClass.prototype.newSuite = function ( name ) { + + var s = new Benchmark.Suite( name ); + this.suites.push( s ); + return s; + +}; + +BenchClass.prototype.display = function () { + + for ( x of this.suites ) { + + var s = new SuiteUI( x ); + s.render(); + + } + +}; + +BenchClass.prototype.warning = function ( message ) { + + console.error( message ); + +}; + +var SuiteUI = function ( suite ) { + + this.suite = suite; + this.isRunning = false; + return this; + +}; + +SuiteUI.prototype.render = function () { + + var n = document.importNode( this.suiteTemplate, true ); + this.elem = n.querySelector( 'article' ); + this.results = n.querySelector( '.results' ); + this.title = n.querySelector( 'h2' ); + this.runButton = n.querySelector( 'h3' ); + + this.title.innerText = this.suite.name; + this.runButton.onclick = this.run.bind( this ); + + this.section.appendChild( n ); + +}; + +SuiteUI.prototype.run = function () { + + this.runButton.click = _.noop; + this.runButton.innerText = 'Running...'; + this.suite.on( 'complete', this.complete.bind( this ) ); + this.suite.run( { + async: true + } ); + +}; + +SuiteUI.prototype.complete = function () { + + this.runButton.style.display = 'none'; + this.results.style.display = 'block'; + var f = _.orderBy( this.suite, [ 'hz' ], [ 'desc' ] ); + for ( var i = 0; i < f.length; i ++ ) { + + var x = f[ i ]; + var n = document.importNode( this.suiteTestTemplate, true ); + n.querySelector( '.name' ).innerText = x.name; + n.querySelector( '.ops' ).innerText = x.hz.toFixed(); + n.querySelector( '.desv' ).innerText = x.stats.rme.toFixed( 2 ); + this.results.appendChild( n ); + + } + +}; var Bench = new BenchClass(); -window.addEventListener('load', function() { - SuiteUI.prototype.suiteTemplate = document.querySelector("#suite").content; - SuiteUI.prototype.suiteTestTemplate = document.querySelector("#suite-test").content; - SuiteUI.prototype.section = document.querySelector("section"); +window.addEventListener( 'load', function () { + + SuiteUI.prototype.suiteTemplate = document.querySelector( '#suite' ).content; + SuiteUI.prototype.suiteTestTemplate = document.querySelector( '#suite-test' ).content; + SuiteUI.prototype.section = document.querySelector( 'section' ); + + Bench.display(); - Bench.display(); -}) +} ); diff --git a/test/benchmark/core/Float32Array.js b/test/benchmark/core/Float32Array.js index eeda4c38370008..d1a4f07ba41428 100644 --- a/test/benchmark/core/Float32Array.js +++ b/test/benchmark/core/Float32Array.js @@ -1,82 +1,102 @@ -(function() { - - var input = new Float32Array(10000 * 3); - var output = new Float32Array(10000 * 3); - - for (var j = 0, jl = input.length; j < jl; j++) { - input[j] = j; - } - - var inputVectors = []; - var outputVectors = []; - - for (var j = 0, jl = input.length / 3; j < jl; j++) { - inputVectors.push(new THREE.Vector3(j * 3, j * 3 + 1, j * 3 + 2)); - outputVectors.push(new THREE.Vector3()); - } - - var s = Bench.newSuite("Float 32 Arrays"); - - s.add('Float32Array-Float32Array', function() { - var value3 = new Float32Array(3); - for (var i = 0, il = input.length / 3; i < il; i += 3) { - value3[0] = input[i + 0]; - value3[1] = input[i + 1]; - value3[2] = input[i + 2]; - value3[0] *= 1.01; - value3[1] *= 1.03; - value3[2] *= 0.98; - output[i + 0] = value3[0]; - output[i + 1] = value3[1]; - output[i + 2] = value3[2]; - } - }); - - s.add('Float32Array-Array', function() { - var value2 = [0, 0, 0]; - for (var i = 0, il = input.length / 3; i < il; i += 3) { - value2[0] = input[i + 0]; - value2[1] = input[i + 1]; - value2[2] = input[i + 2]; - value2[0] *= 1.01; - value2[1] *= 1.03; - value2[2] *= 0.98; - output[i + 0] = value2[0]; - output[i + 1] = value2[1]; - output[i + 2] = value2[2]; - } - }); - - s.add('Float32Array-Literal', function() { - var x, - y, - z; - for (var i = 0, il = input.length / 3; i < il; i += 3) { - x = input[i + 0]; - y = input[i + 1]; - z = input[i + 2]; - x *= 1.01; - y *= 1.03; - z *= 0.98; - output[i + 0] = x; - output[i + 1] = y; - output[i + 2] = z; - } - }); - - s.add('Float32Array-Vector3', function() { - var value = new THREE.Vector3(); - for (var i = 0, il = input.length / 3; i < il; i += 3) { - value.x = input[i + 0]; - value.y = input[i + 1]; - value.z = input[i + 2]; - value.x *= 1.01; - value.y *= 1.03; - value.z *= 0.98; - output[i + 0] = value.x; - output[i + 1] = value.y; - output[i + 2] = value.z; - } - }); - -})(); +( function () { + + var input = new Float32Array( 10000 * 3 ); + var output = new Float32Array( 10000 * 3 ); + + for ( var j = 0, jl = input.length; j < jl; j ++ ) { + + input[ j ] = j; + + } + + var inputVectors = []; + var outputVectors = []; + + for ( var j = 0, jl = input.length / 3; j < jl; j ++ ) { + + inputVectors.push( new THREE.Vector3( j * 3, j * 3 + 1, j * 3 + 2 ) ); + outputVectors.push( new THREE.Vector3() ); + + } + + var s = Bench.newSuite( 'Float 32 Arrays' ); + + s.add( 'Float32Array-Float32Array', function () { + + var value3 = new Float32Array( 3 ); + for ( var i = 0, il = input.length / 3; i < il; i += 3 ) { + + value3[ 0 ] = input[ i + 0 ]; + value3[ 1 ] = input[ i + 1 ]; + value3[ 2 ] = input[ i + 2 ]; + value3[ 0 ] *= 1.01; + value3[ 1 ] *= 1.03; + value3[ 2 ] *= 0.98; + output[ i + 0 ] = value3[ 0 ]; + output[ i + 1 ] = value3[ 1 ]; + output[ i + 2 ] = value3[ 2 ]; + + } + + } ); + + s.add( 'Float32Array-Array', function () { + + var value2 = [ 0, 0, 0 ]; + for ( var i = 0, il = input.length / 3; i < il; i += 3 ) { + + value2[ 0 ] = input[ i + 0 ]; + value2[ 1 ] = input[ i + 1 ]; + value2[ 2 ] = input[ i + 2 ]; + value2[ 0 ] *= 1.01; + value2[ 1 ] *= 1.03; + value2[ 2 ] *= 0.98; + output[ i + 0 ] = value2[ 0 ]; + output[ i + 1 ] = value2[ 1 ]; + output[ i + 2 ] = value2[ 2 ]; + + } + + } ); + + s.add( 'Float32Array-Literal', function () { + + var x, + y, + z; + for ( var i = 0, il = input.length / 3; i < il; i += 3 ) { + + x = input[ i + 0 ]; + y = input[ i + 1 ]; + z = input[ i + 2 ]; + x *= 1.01; + y *= 1.03; + z *= 0.98; + output[ i + 0 ] = x; + output[ i + 1 ] = y; + output[ i + 2 ] = z; + + } + + } ); + + s.add( 'Float32Array-Vector3', function () { + + var value = new THREE.Vector3(); + for ( var i = 0, il = input.length / 3; i < il; i += 3 ) { + + value.x = input[ i + 0 ]; + value.y = input[ i + 1 ]; + value.z = input[ i + 2 ]; + value.x *= 1.01; + value.y *= 1.03; + value.z *= 0.98; + output[ i + 0 ] = value.x; + output[ i + 1 ] = value.y; + output[ i + 2 ] = value.z; + + } + + } ); + +} )(); diff --git a/test/benchmark/core/TriangleClosestPoint.js b/test/benchmark/core/TriangleClosestPoint.js index 8f61724db13aaf..c2cb88065f114a 100644 --- a/test/benchmark/core/TriangleClosestPoint.js +++ b/test/benchmark/core/TriangleClosestPoint.js @@ -1,61 +1,80 @@ -(function() { - - THREE = Bench.THREE; - - // these vertices and triangles are those of a unit icosahedron centered at the origin - var phi = 1.618; - var verts = [ - [phi, 1, 0], [-phi, 1, 0], [phi, -1, 0], [-phi, -1, 0], - [1, 0, phi], [1, 0, -phi], [-1, 0, phi], [-1, 0, -phi], - [0, phi, 1], [0, -phi, 1], [0, phi, -1], [0, -phi, -1], - ]; - var createVertex = function(c) { - return new THREE.Vector3(c[0], c[1], c[2]); - }; - var createTriangle = function(i0, i1, i2) { - return new THREE.Triangle(createVertex(verts[i0]), createVertex(verts[i1]), createVertex(verts[i2])); - }; - var triangles = [ - createTriangle(0, 8, 4), - createTriangle(0, 5, 10), - createTriangle(2, 4, 9), - createTriangle(2, 11, 5), - createTriangle(1, 6, 8), - createTriangle(1, 10, 7), - createTriangle(3, 9, 6), - createTriangle(3, 7, 11), - createTriangle(0, 10, 8), - createTriangle(1, 8, 10), - createTriangle(2, 9, 11), - createTriangle(3, 9, 11), - createTriangle(4, 2, 0), - createTriangle(5, 0, 2), - createTriangle(6, 1, 3), - createTriangle(7, 3, 1), - createTriangle(8, 6, 4), - createTriangle(9, 4, 6), - createTriangle(10, 5, 7), - createTriangle(11, 7, 5), - ]; - // test a variety of points all in and around the icosahedron - var testPoints = []; - for (var x = -2; x <= 2; x += 0.5) { - for (var y = -2; y <= 2; y += 0.5) { - for (var z = -2; z <= 2; z += 0.5) { - testPoints.push(new THREE.Vector3(x, y, z)); - } - } - } - - var s = Bench.newSuite("Clamping point into triangles"); - - s.add('9^3 points, 20 triangles', function() { - var target = new THREE.Vector3(); - for (var tidx = 0; tidx < triangles.length; tidx++) { - var triangle = triangles[tidx]; - for (var pidx = 0; pidx < testPoints.length; pidx++) { - triangle.closestPointToPoint(testPoints[pidx], target); - } - } - }); -})(); +( function () { + + THREE = Bench.THREE; + + // these vertices and triangles are those of a unit icosahedron centered at the origin + var phi = 1.618; + var verts = [ + [ phi, 1, 0 ], [ - phi, 1, 0 ], [ phi, - 1, 0 ], [ - phi, - 1, 0 ], + [ 1, 0, phi ], [ 1, 0, - phi ], [ - 1, 0, phi ], [ - 1, 0, - phi ], + [ 0, phi, 1 ], [ 0, - phi, 1 ], [ 0, phi, - 1 ], [ 0, - phi, - 1 ], + ]; + var createVertex = function ( c ) { + + return new THREE.Vector3( c[ 0 ], c[ 1 ], c[ 2 ] ); + + }; + + var createTriangle = function ( i0, i1, i2 ) { + + return new THREE.Triangle( createVertex( verts[ i0 ] ), createVertex( verts[ i1 ] ), createVertex( verts[ i2 ] ) ); + + }; + + var triangles = [ + createTriangle( 0, 8, 4 ), + createTriangle( 0, 5, 10 ), + createTriangle( 2, 4, 9 ), + createTriangle( 2, 11, 5 ), + createTriangle( 1, 6, 8 ), + createTriangle( 1, 10, 7 ), + createTriangle( 3, 9, 6 ), + createTriangle( 3, 7, 11 ), + createTriangle( 0, 10, 8 ), + createTriangle( 1, 8, 10 ), + createTriangle( 2, 9, 11 ), + createTriangle( 3, 9, 11 ), + createTriangle( 4, 2, 0 ), + createTriangle( 5, 0, 2 ), + createTriangle( 6, 1, 3 ), + createTriangle( 7, 3, 1 ), + createTriangle( 8, 6, 4 ), + createTriangle( 9, 4, 6 ), + createTriangle( 10, 5, 7 ), + createTriangle( 11, 7, 5 ), + ]; + // test a variety of points all in and around the icosahedron + var testPoints = []; + for ( var x = - 2; x <= 2; x += 0.5 ) { + + for ( var y = - 2; y <= 2; y += 0.5 ) { + + for ( var z = - 2; z <= 2; z += 0.5 ) { + + testPoints.push( new THREE.Vector3( x, y, z ) ); + + } + + } + + } + + var s = Bench.newSuite( 'Clamping point into triangles' ); + + s.add( '9^3 points, 20 triangles', function () { + + var target = new THREE.Vector3(); + for ( var tidx = 0; tidx < triangles.length; tidx ++ ) { + + var triangle = triangles[ tidx ]; + for ( var pidx = 0; pidx < testPoints.length; pidx ++ ) { + + triangle.closestPointToPoint( testPoints[ pidx ], target ); + + } + + } + + } ); + +} )(); diff --git a/test/benchmark/core/UpdateMatrixWorld.js b/test/benchmark/core/UpdateMatrixWorld.js index 50ff37a4f5dd3d..eea371661d0d25 100644 --- a/test/benchmark/core/UpdateMatrixWorld.js +++ b/test/benchmark/core/UpdateMatrixWorld.js @@ -1,48 +1,69 @@ -(function() { - - THREE = Bench.THREE; - - var position = new THREE.Vector3(1, 1, 1); - var scale = new THREE.Vector3(2, 1, 0.5); - var rotation = new THREE.Quaternion(); - rotation.setFromAxisAngle(new THREE.Vector3(0, 1, 0), Math.PI / 8); - var createLocallyOffsetChild = function() { - var child = new THREE.Object3D(); - child.position.copy(position); - child.scale.copy(scale); - child.rotation.copy(rotation); - return child; - }; - - var generateSceneGraph = function(root, depth, breadth, initObject) { - if (depth > 0) { - for (var i = 0; i < breadth; i++) { - var child = initObject(); - root.add(child); - generateSceneGraph(child, depth - 1, breadth, initObject); - } - } - return root; - }; - - var nodeCount = function(root) { - return root.children.reduce(function(acc, x) { return acc + nodeCount(x); }, 1); - }; - - var rootA = generateSceneGraph(new THREE.Object3D(), 100, 1, createLocallyOffsetChild); - var rootB = generateSceneGraph(new THREE.Object3D(), 3, 10, createLocallyOffsetChild); - var rootC = generateSceneGraph(new THREE.Object3D(), 9, 3, createLocallyOffsetChild); - - var s = Bench.newSuite("Update world transforms"); - - s.add('Update graph depth=100, breadth=1 (' + nodeCount(rootA) + ' nodes)', function() { - rootA.updateMatrixWorld(true); - }); - s.add('Update graph depth=3, breadth=10 (' + nodeCount(rootB) + ' nodes)', function() { - rootB.updateMatrixWorld(true); - }); - s.add('Update graph depth=9, breadth=3 (' + nodeCount(rootC) + ' nodes)', function() { - rootC.updateMatrixWorld(true); - }); - -})(); +( function () { + + THREE = Bench.THREE; + + var position = new THREE.Vector3( 1, 1, 1 ); + var scale = new THREE.Vector3( 2, 1, 0.5 ); + var rotation = new THREE.Quaternion(); + rotation.setFromAxisAngle( new THREE.Vector3( 0, 1, 0 ), Math.PI / 8 ); + var createLocallyOffsetChild = function () { + + var child = new THREE.Object3D(); + child.position.copy( position ); + child.scale.copy( scale ); + child.rotation.copy( rotation ); + return child; + + }; + + var generateSceneGraph = function ( root, depth, breadth, initObject ) { + + if ( depth > 0 ) { + + for ( var i = 0; i < breadth; i ++ ) { + + var child = initObject(); + root.add( child ); + generateSceneGraph( child, depth - 1, breadth, initObject ); + + } + + } + + return root; + + }; + + var nodeCount = function ( root ) { + + return root.children.reduce( function ( acc, x ) { + + return acc + nodeCount( x ); + + }, 1 ); + + }; + + var rootA = generateSceneGraph( new THREE.Object3D(), 100, 1, createLocallyOffsetChild ); + var rootB = generateSceneGraph( new THREE.Object3D(), 3, 10, createLocallyOffsetChild ); + var rootC = generateSceneGraph( new THREE.Object3D(), 9, 3, createLocallyOffsetChild ); + + var s = Bench.newSuite( 'Update world transforms' ); + + s.add( 'Update graph depth=100, breadth=1 (' + nodeCount( rootA ) + ' nodes)', function () { + + rootA.updateMatrixWorld( true ); + + } ); + s.add( 'Update graph depth=3, breadth=10 (' + nodeCount( rootB ) + ' nodes)', function () { + + rootB.updateMatrixWorld( true ); + + } ); + s.add( 'Update graph depth=9, breadth=3 (' + nodeCount( rootC ) + ' nodes)', function () { + + rootC.updateMatrixWorld( true ); + + } ); + +} )(); diff --git a/test/benchmark/core/Vector3Components.js b/test/benchmark/core/Vector3Components.js index 8acfad2d47b199..3a2315bdf6e876 100644 --- a/test/benchmark/core/Vector3Components.js +++ b/test/benchmark/core/Vector3Components.js @@ -1,110 +1,146 @@ -(function() { - - var s = Bench.newSuite("Vector 3 Components"); - - THREE = {}; - - THREE.Vector3 = function(x, y, z) { - this.x = x || 0; - this.y = y || 0; - this.z = z || 0; - }; - - THREE.Vector3.prototype = { - constructor: THREE.Vector3, - setComponent: function(index, value) { - this[THREE.Vector3.__indexToName[index]] = value; - }, - - getComponent: function(index) { - return this[THREE.Vector3.__indexToName[index]]; - }, - - setComponent2: 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); - } - }, - - getComponent2: 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); - } - }, - - - getComponent3: function(index) { - if (index === 0) return this.x; - if (index === 1) return this.y; - if (index === 2) return this.z; - throw new Error("index is out of range: " + index); - }, - - getComponent4: function(index) { - if (index === 0) return this.x;else if (index === 1) return this.y;else if (index === 2) return this.z; - else - throw new Error("index is out of range: " + index); - } - }; - - - THREE.Vector3.__indexToName = { - 0: 'x', - 1: 'y', - 2: 'z' - }; - - var a = []; - for (var i = 0; i < 100000; i++) { - a[i] = new THREE.Vector3(i * 0.01, i * 2, i * -1.3); - } - - - - - s.add('IndexToName', function() { - var result = 0; - for (var i = 0; i < 100000; i++) { - result += a[i].getComponent(i % 3); - } - }); - - s.add('SwitchStatement', function() { - var result = 0; - for (var i = 0; i < 100000; i++) { - result += a[i].getComponent2(i % 3); - } - }); - - s.add('IfAndReturnSeries', function() { - var result = 0; - for (var i = 0; i < 100000; i++) { - result += a[i].getComponent3(i % 3); - } - }); - - s.add('IfReturnElseSeries', function() { - var result = 0; - for (var i = 0; i < 100000; i++) { - result += a[i].getComponent4(i % 3); - } - }); - -})(); +( function () { + + var s = Bench.newSuite( 'Vector 3 Components' ); + + THREE = {}; + + THREE.Vector3 = function ( x, y, z ) { + + this.x = x || 0; + this.y = y || 0; + this.z = z || 0; + + }; + + THREE.Vector3.prototype = { + constructor: THREE.Vector3, + setComponent: function ( index, value ) { + + this[ THREE.Vector3.__indexToName[ index ] ] = value; + + }, + + getComponent: function ( index ) { + + return this[ THREE.Vector3.__indexToName[ index ] ]; + + }, + + setComponent2: 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 ); + + } + + }, + + getComponent2: 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 ); + + } + + }, + + + getComponent3: function ( index ) { + + if ( index === 0 ) return this.x; + if ( index === 1 ) return this.y; + if ( index === 2 ) return this.z; + throw new Error( 'index is out of range: ' + index ); + + }, + + getComponent4: function ( index ) { + + if ( index === 0 ) return this.x; else if ( index === 1 ) return this.y; else if ( index === 2 ) return this.z; + else + throw new Error( 'index is out of range: ' + index ); + + } + }; + + + THREE.Vector3.__indexToName = { + 0: 'x', + 1: 'y', + 2: 'z' + }; + + var a = []; + for ( var i = 0; i < 100000; i ++ ) { + + a[ i ] = new THREE.Vector3( i * 0.01, i * 2, i * - 1.3 ); + + } + + + + + s.add( 'IndexToName', function () { + + var result = 0; + for ( var i = 0; i < 100000; i ++ ) { + + result += a[ i ].getComponent( i % 3 ); + + } + + } ); + + s.add( 'SwitchStatement', function () { + + var result = 0; + for ( var i = 0; i < 100000; i ++ ) { + + result += a[ i ].getComponent2( i % 3 ); + + } + + } ); + + s.add( 'IfAndReturnSeries', function () { + + var result = 0; + for ( var i = 0; i < 100000; i ++ ) { + + result += a[ i ].getComponent3( i % 3 ); + + } + + } ); + + s.add( 'IfReturnElseSeries', function () { + + var result = 0; + for ( var i = 0; i < 100000; i ++ ) { + + result += a[ i ].getComponent4( i % 3 ); + + } + + } ); + +} )(); diff --git a/test/benchmark/core/Vector3Length.js b/test/benchmark/core/Vector3Length.js index 2256edeb9ab43c..850e01de30bfd1 100644 --- a/test/benchmark/core/Vector3Length.js +++ b/test/benchmark/core/Vector3Length.js @@ -1,59 +1,79 @@ -(function() { +( function () { - var THREE = {}; + var THREE = {}; - THREE.Vector3 = function(x, y, z) { + THREE.Vector3 = function ( x, y, z ) { - this.x = x || 0; - this.y = y || 0; - this.z = z || 0; + this.x = x || 0; + this.y = y || 0; + this.z = z || 0; - }; + }; - THREE.Vector3.prototype = { - constructor: THREE.Vector3, - lengthSq: function() { - return this.x * this.x + this.y * this.y + this.z * this.z; - }, + THREE.Vector3.prototype = { + constructor: THREE.Vector3, + lengthSq: function () { - length: function() { - return Math.sqrt(this.lengthSq()); - }, + return this.x * this.x + this.y * this.y + this.z * this.z; - length2: function() { - return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); - } + }, - }; + length: function () { - var a = []; - for (var i = 0; i < 100000; i++) { - a[i] = new THREE.Vector3(i * 0.01, i * 2, i * -1.3); - } + return Math.sqrt( this.lengthSq() ); + }, - var suite = Bench.newSuite("Vector 3 Length"); + length2: function () { - suite.add('NoCallTest', function() { - var result = 0; - for (var i = 0; i < 100000; i++) { - var v = a[i]; - result += Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z); - } - }); + return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); - suite.add('InlineCallTest', function() { - var result = 0; - for (var i = 0; i < 100000; i++) { - result += a[i].length2(); - } - }); + } - suite.add('FunctionCallTest', function() { - var result = 0; - for (var i = 0; i < 100000; i++) { - result += a[i].length(); - } - }); + }; -})(); + var a = []; + for ( var i = 0; i < 100000; i ++ ) { + + a[ i ] = new THREE.Vector3( i * 0.01, i * 2, i * - 1.3 ); + + } + + + var suite = Bench.newSuite( 'Vector 3 Length' ); + + suite.add( 'NoCallTest', function () { + + var result = 0; + for ( var i = 0; i < 100000; i ++ ) { + + var v = a[ i ]; + result += Math.sqrt( v.x * v.x + v.y * v.y + v.z * v.z ); + + } + + } ); + + suite.add( 'InlineCallTest', function () { + + var result = 0; + for ( var i = 0; i < 100000; i ++ ) { + + result += a[ i ].length2(); + + } + + } ); + + suite.add( 'FunctionCallTest', function () { + + var result = 0; + for ( var i = 0; i < 100000; i ++ ) { + + result += a[ i ].length(); + + } + + } ); + +} )(); diff --git a/test/benchmark/core/Vector3Storage.js b/test/benchmark/core/Vector3Storage.js index 3b7a853d1510a1..666d1e55033503 100644 --- a/test/benchmark/core/Vector3Storage.js +++ b/test/benchmark/core/Vector3Storage.js @@ -1,113 +1,128 @@ -(function() { +( function () { - THREE = {}; + THREE = {}; - THREE.Vector3 = function(x, y, z) { + THREE.Vector3 = function ( x, y, z ) { - this.x = x || 0; - this.y = y || 0; - this.z = z || 0; + this.x = x || 0; + this.y = y || 0; + this.z = z || 0; - }; + }; - THREE.Vector3.prototype = { + THREE.Vector3.prototype = { - constructor: THREE.Vector3, + constructor: THREE.Vector3, - length: function() { + length: function () { - return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); + return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); - } + } - }; + }; - THREE.Vector3X = function(x, y, z) { + THREE.Vector3X = function ( x, y, z ) { - var elements = this.elements = new Float32Array(3); - elements[0] = x || 0; - elements[1] = y || 1; - elements[2] = z || 2; + var elements = this.elements = new Float32Array( 3 ); + elements[ 0 ] = x || 0; + elements[ 1 ] = y || 1; + elements[ 2 ] = z || 2; - }; + }; - THREE.Vector3X.prototype = { + THREE.Vector3X.prototype = { - constructor: THREE.Vector3X, + constructor: THREE.Vector3X, - length: function() { + length: function () { - return Math.sqrt(this.elements[0] * this.elements[0] + this.elements[1] * this.elements[1] + this.elements[2] * this.elements[2]); + return Math.sqrt( this.elements[ 0 ] * this.elements[ 0 ] + this.elements[ 1 ] * this.elements[ 1 ] + this.elements[ 2 ] * this.elements[ 2 ] ); - } + } - }; + }; - THREE.Vector3Y = function(x, y, z) { + THREE.Vector3Y = function ( x, y, z ) { - this.elements = [x || 0, y || 1, z || 2]; + this.elements = [ x || 0, y || 1, z || 2 ]; - }; + }; - THREE.Vector3Y.prototype = { + THREE.Vector3Y.prototype = { - constructor: THREE.Vector3Y, + constructor: THREE.Vector3Y, - length: function() { + length: function () { - return Math.sqrt(this.elements[0] * this.elements[0] + this.elements[1] * this.elements[1] + this.elements[2] * this.elements[2]); + return Math.sqrt( this.elements[ 0 ] * this.elements[ 0 ] + this.elements[ 1 ] * this.elements[ 1 ] + this.elements[ 2 ] * this.elements[ 2 ] ); - } + } - }; + }; - var suite = Bench.newSuite("Vector 3 Storage"); + var suite = Bench.newSuite( 'Vector 3 Storage' ); - suite.add('Vector3-Set', function() { + suite.add( 'Vector3-Set', function () { - var array = []; - for (var i = 0; i < 100000; i++) { - var v = new THREE.Vector3(i, i, i); - array.push(v); - } + var array = []; + for ( var i = 0; i < 100000; i ++ ) { - var result = 0; - for (var i = 0; i < 100000; i++) { - var v = array[i]; - result += v.length(); - } - }); + var v = new THREE.Vector3( i, i, i ); + array.push( v ); - suite.add('Vector3-Float32Array', function() { + } - var array = []; - for (var i = 0; i < 100000; i++) { - var v = new THREE.Vector3X(i, i, i); - array.push(v); - } + var result = 0; + for ( var i = 0; i < 100000; i ++ ) { - var result = 0; - for (var i = 0; i < 100000; i++) { - var v = array[i]; - result += v.length(); - } - }); + var v = array[ i ]; + result += v.length(); - suite.add('Vector3-Array', function() { + } - var array = []; - for (var i = 0; i < 100000; i++) { - var v = new THREE.Vector3Y(i, i, i); - array.push(v); - } + } ); - var result = 0; - for (var i = 0; i < 100000; i++) { - var v = array[i]; - result += v.length(); - } - }); + suite.add( 'Vector3-Float32Array', function () { -})(); + var array = []; + for ( var i = 0; i < 100000; i ++ ) { + + var v = new THREE.Vector3X( i, i, i ); + array.push( v ); + + } + + var result = 0; + for ( var i = 0; i < 100000; i ++ ) { + + var v = array[ i ]; + result += v.length(); + + } + + } ); + + suite.add( 'Vector3-Array', function () { + + var array = []; + for ( var i = 0; i < 100000; i ++ ) { + + var v = new THREE.Vector3Y( i, i, i ); + array.push( v ); + + } + + var result = 0; + for ( var i = 0; i < 100000; i ++ ) { + + var v = array[ i ]; + result += v.length(); + + } + + } ); + +} )(); diff --git a/test/e2e/puppeteer.js b/test/e2e/puppeteer.js index 5c00678f84bc9e..5c7dcd29d02942 100644 --- a/test/e2e/puppeteer.js +++ b/test/e2e/puppeteer.js @@ -47,8 +47,11 @@ const exceptionList = [ 'webgpu_lights_custom', 'webgpu_lights_selective', 'webgpu_materials', + 'webgpu_nodes_playground', 'webgpu_rtt', - 'webgpu_sandbox' + 'webgpu_sandbox', + 'webgpu_skinning_points', + 'webgpu_skinning' ].concat( ( process.platform === 'win32' ) ? [ 'webgl_effects_ascii' // windows fonts not supported diff --git a/test/unit/example/objects/Lensflare.tests.js b/test/unit/example/objects/Lensflare.tests.js index ff046d87c68580..55356264c89291 100644 --- a/test/unit/example/objects/Lensflare.tests.js +++ b/test/unit/example/objects/Lensflare.tests.js @@ -7,16 +7,16 @@ export default QUnit.module( 'Objects', () => { QUnit.module( 'Lensflare', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/animation/AnimationAction.tests.js b/test/unit/src/animation/AnimationAction.tests.js index 264a2d1ff01746..99d86c50297055 100644 --- a/test/unit/src/animation/AnimationAction.tests.js +++ b/test/unit/src/animation/AnimationAction.tests.js @@ -12,8 +12,8 @@ function createAnimation() { var root = new Object3D(); var mixer = new AnimationMixer( root ); - var track = new NumberKeyframeTrack( ".rotation[x]", [ 0, 1000 ], [ 0, 360 ] ); - var clip = new AnimationClip( "clip1", 1000, [ track ] ); + var track = new NumberKeyframeTrack( '.rotation[x]', [ 0, 1000 ], [ 0, 360 ] ); + var clip = new AnimationClip( 'clip1', 1000, [ track ] ); var animationAction = mixer.clipAction( clip ); return { @@ -30,12 +30,12 @@ function createTwoAnimations() { var root = new Object3D(); var mixer = new AnimationMixer( root ); - var track = new NumberKeyframeTrack( ".rotation[x]", [ 0, 1000 ], [ 0, 360 ] ); - var clip = new AnimationClip( "clip1", 1000, [ track ] ); + var track = new NumberKeyframeTrack( '.rotation[x]', [ 0, 1000 ], [ 0, 360 ] ); + var clip = new AnimationClip( 'clip1', 1000, [ track ] ); var animationAction = mixer.clipAction( clip ); - var track2 = new NumberKeyframeTrack( ".rotation[y]", [ 0, 1000 ], [ 0, 360 ] ); - var clip2 = new AnimationClip( "clip2", 1000, [ track ] ); + var track2 = new NumberKeyframeTrack( '.rotation[y]', [ 0, 1000 ], [ 0, 360 ] ); + var clip2 = new AnimationClip( 'clip2', 1000, [ track ] ); var animationAction2 = mixer.clipAction( clip2 ); return { @@ -57,26 +57,26 @@ export default QUnit.module( 'Animation', () => { QUnit.module( 'AnimationAction', () => { // INSTANCING - QUnit.test( "Instancing", ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { var mixer = new AnimationMixer(); - var clip = new AnimationClip( "nonname", - 1, [] ); + var clip = new AnimationClip( 'nonname', - 1, [] ); var animationAction = new AnimationAction( mixer, clip ); - assert.ok( animationAction, "animationAction instanciated" ); + assert.ok( animationAction, 'animationAction instanciated' ); } ); // PUBLIC STUFF - QUnit.test( "play", ( assert ) => { + QUnit.test( 'play', ( assert ) => { var { mixer, animationAction } = createAnimation(); var animationAction2 = animationAction.play(); - assert.equal( animationAction, animationAction2, "AnimationAction.play can be chained." ); + assert.equal( animationAction, animationAction2, 'AnimationAction.play can be chained.' ); var UserException = function () { - this.message = "AnimationMixer must activate AnimationAction on play."; + this.message = 'AnimationMixer must activate AnimationAction on play.'; }; @@ -98,15 +98,15 @@ export default QUnit.module( 'Animation', () => { } ); - QUnit.test( "stop", ( assert ) => { + QUnit.test( 'stop', ( assert ) => { var { mixer, animationAction } = createAnimation(); var animationAction2 = animationAction.stop(); - assert.equal( animationAction, animationAction2, "AnimationAction.stop can be chained." ); + assert.equal( animationAction, animationAction2, 'AnimationAction.stop can be chained.' ); var UserException = function () { - this.message = "AnimationMixer must deactivate AnimationAction on stop."; + this.message = 'AnimationMixer must deactivate AnimationAction on stop.'; }; @@ -128,319 +128,319 @@ export default QUnit.module( 'Animation', () => { } ); - QUnit.test( "reset", ( assert ) => { + QUnit.test( 'reset', ( assert ) => { var { mixer, animationAction } = createAnimation(); var animationAction2 = animationAction.stop(); - assert.equal( animationAction, animationAction2, "AnimationAction.reset can be chained." ); - assert.equal( animationAction2.paused, false, "AnimationAction.reset() sets paused false" ); - assert.equal( animationAction2.enabled, true, "AnimationAction.reset() sets enabled true" ); - assert.equal( animationAction2.time, 0, "AnimationAction.reset() resets time." ); - assert.equal( animationAction2._loopCount, - 1, "AnimationAction.reset() resets loopcount." ); - assert.equal( animationAction2._startTime, null, "AnimationAction.reset() removes starttime." ); + assert.equal( animationAction, animationAction2, 'AnimationAction.reset can be chained.' ); + assert.equal( animationAction2.paused, false, 'AnimationAction.reset() sets paused false' ); + assert.equal( animationAction2.enabled, true, 'AnimationAction.reset() sets enabled true' ); + assert.equal( animationAction2.time, 0, 'AnimationAction.reset() resets time.' ); + assert.equal( animationAction2._loopCount, - 1, 'AnimationAction.reset() resets loopcount.' ); + assert.equal( animationAction2._startTime, null, 'AnimationAction.reset() removes starttime.' ); } ); - QUnit.test( "isRunning", ( assert ) => { + QUnit.test( 'isRunning', ( assert ) => { var { mixer, animationAction } = createAnimation(); - assert.notOk( animationAction.isRunning(), "When an animation is just made, it is not running." ); + assert.notOk( animationAction.isRunning(), 'When an animation is just made, it is not running.' ); animationAction.play(); - assert.ok( animationAction.isRunning(), "When an animation is started, it is running." ); + assert.ok( animationAction.isRunning(), 'When an animation is started, it is running.' ); animationAction.stop(); - assert.notOk( animationAction.isRunning(), "When an animation is stopped, it is not running." ); + assert.notOk( animationAction.isRunning(), 'When an animation is stopped, it is not running.' ); animationAction.play(); animationAction.paused = true; - assert.notOk( animationAction.isRunning(), "When an animation is paused, it is not running." ); + assert.notOk( animationAction.isRunning(), 'When an animation is paused, it is not running.' ); animationAction.paused = false; animationAction.enabled = false; - assert.notOk( animationAction.isRunning(), "When an animation is not enabled, it is not running." ); + assert.notOk( animationAction.isRunning(), 'When an animation is not enabled, it is not running.' ); animationAction.enabled = true; - assert.ok( animationAction.isRunning(), "When an animation is enabled, it is running." ); + assert.ok( animationAction.isRunning(), 'When an animation is enabled, it is running.' ); } ); - QUnit.test( "isScheduled", ( assert ) => { + QUnit.test( 'isScheduled', ( assert ) => { var { mixer, animationAction } = createAnimation(); - assert.notOk( animationAction.isScheduled(), "When an animation is just made, it is not scheduled." ); + assert.notOk( animationAction.isScheduled(), 'When an animation is just made, it is not scheduled.' ); animationAction.play(); - assert.ok( animationAction.isScheduled(), "When an animation is started, it is scheduled." ); + assert.ok( animationAction.isScheduled(), 'When an animation is started, it is scheduled.' ); mixer.update( 1 ); - assert.ok( animationAction.isScheduled(), "When an animation is updated, it is scheduled." ); + assert.ok( animationAction.isScheduled(), 'When an animation is updated, it is scheduled.' ); animationAction.stop(); - assert.notOk( animationAction.isScheduled(), "When an animation is stopped, it isn't scheduled anymore." ); + assert.notOk( animationAction.isScheduled(), 'When an animation is stopped, it isn\'t scheduled anymore.' ); } ); - QUnit.test( "startAt", ( assert ) => { + QUnit.test( 'startAt', ( assert ) => { var { mixer, animationAction } = createAnimation(); animationAction.startAt( 2 ); animationAction.play(); - assert.notOk( animationAction.isRunning(), "When an animation is started at a specific time, it is not running." ); - assert.ok( animationAction.isScheduled(), "When an animation is started at a specific time, it is scheduled." ); + assert.notOk( animationAction.isRunning(), 'When an animation is started at a specific time, it is not running.' ); + assert.ok( animationAction.isScheduled(), 'When an animation is started at a specific time, it is scheduled.' ); mixer.update( 1 ); - assert.notOk( animationAction.isRunning(), "When an animation is started at a specific time and the interval is not passed, it is not running." ); - assert.ok( animationAction.isScheduled(), "When an animation is started at a specific time and the interval is not passed, it is scheduled." ); + assert.notOk( animationAction.isRunning(), 'When an animation is started at a specific time and the interval is not passed, it is not running.' ); + assert.ok( animationAction.isScheduled(), 'When an animation is started at a specific time and the interval is not passed, it is scheduled.' ); mixer.update( 1 ); - assert.ok( animationAction.isRunning(), "When an animation is started at a specific time and the interval is passed, it is running." ); - assert.ok( animationAction.isScheduled(), "When an animation is started at a specific time and the interval is passed, it is scheduled." ); + assert.ok( animationAction.isRunning(), 'When an animation is started at a specific time and the interval is passed, it is running.' ); + assert.ok( animationAction.isScheduled(), 'When an animation is started at a specific time and the interval is passed, it is scheduled.' ); animationAction.stop(); - assert.notOk( animationAction.isRunning(), "When an animation is stopped, it is not running." ); - assert.notOk( animationAction.isScheduled(), "When an animation is stopped, it is not scheduled." ); + assert.notOk( animationAction.isRunning(), 'When an animation is stopped, it is not running.' ); + assert.notOk( animationAction.isScheduled(), 'When an animation is stopped, it is not scheduled.' ); } ); - QUnit.test( "setLoop LoopOnce", ( assert ) => { + QUnit.test( 'setLoop LoopOnce', ( assert ) => { var { mixer, animationAction } = createAnimation(); animationAction.setLoop( LoopOnce ); animationAction.play(); - assert.ok( animationAction.isRunning(), "When an animation is started, it is running." ); + assert.ok( animationAction.isRunning(), 'When an animation is started, it is running.' ); mixer.update( 500 ); - assert.ok( animationAction.isRunning(), "When an animation is in the first loop, it is running." ); + assert.ok( animationAction.isRunning(), 'When an animation is in the first loop, it is running.' ); mixer.update( 500 ); - assert.notOk( animationAction.isRunning(), "When an animation is ended, it is not running." ); + assert.notOk( animationAction.isRunning(), 'When an animation is ended, it is not running.' ); mixer.update( 500 ); - assert.notOk( animationAction.isRunning(), "When an animation is ended, it is not running." ); + assert.notOk( animationAction.isRunning(), 'When an animation is ended, it is not running.' ); } ); - QUnit.test( "setLoop LoopRepeat", ( assert ) => { + QUnit.test( 'setLoop LoopRepeat', ( assert ) => { var { root, mixer, animationAction } = createAnimation(); animationAction.setLoop( LoopRepeat, 3 ); animationAction.play(); - assert.ok( animationAction.isRunning(), "When an animation is started, it is running." ); + assert.ok( animationAction.isRunning(), 'When an animation is started, it is running.' ); mixer.update( 750 ); - assert.equal( root.rotation.x, 270, "When an animation is 3/4 in the first loop, it has changed to 3/4 when LoopRepeat." ); - assert.ok( animationAction.isRunning(), "When an animation is in the first loop, it is running." ); + assert.equal( root.rotation.x, 270, 'When an animation is 3/4 in the first loop, it has changed to 3/4 when LoopRepeat.' ); + assert.ok( animationAction.isRunning(), 'When an animation is in the first loop, it is running.' ); mixer.update( 1000 ); - assert.equal( root.rotation.x, 270, "When an animation is 3/4 in the second loop, it has changed to 3/4 when LoopRepeat." ); - assert.ok( animationAction.isRunning(), "When an animation is in second loop when in looprepeat 3 times, it is running." ); + assert.equal( root.rotation.x, 270, 'When an animation is 3/4 in the second loop, it has changed to 3/4 when LoopRepeat.' ); + assert.ok( animationAction.isRunning(), 'When an animation is in second loop when in looprepeat 3 times, it is running.' ); mixer.update( 1000 ); - assert.equal( root.rotation.x, 270, "When an animation is 3/4 in the third loop, it has changed to 3/4 when LoopRepeat." ); - assert.ok( animationAction.isRunning(), "When an animation is in third loop when in looprepeat 3 times, it is running." ); + assert.equal( root.rotation.x, 270, 'When an animation is 3/4 in the third loop, it has changed to 3/4 when LoopRepeat.' ); + assert.ok( animationAction.isRunning(), 'When an animation is in third loop when in looprepeat 3 times, it is running.' ); mixer.update( 1000 ); - assert.equal( root.rotation.x, 0, "When an animation ended his third loop when in looprepeat 3 times, it stays on the end result." ); - assert.notOk( animationAction.isRunning(), "When an animation ended his third loop when in looprepeat 3 times, it stays not running anymore." ); + assert.equal( root.rotation.x, 0, 'When an animation ended his third loop when in looprepeat 3 times, it stays on the end result.' ); + assert.notOk( animationAction.isRunning(), 'When an animation ended his third loop when in looprepeat 3 times, it stays not running anymore.' ); } ); - QUnit.test( "setLoop LoopPingPong", ( assert ) => { + QUnit.test( 'setLoop LoopPingPong', ( assert ) => { var { root, mixer, animationAction } = createAnimation(); animationAction.setLoop( LoopPingPong, 3 ); animationAction.play(); - assert.ok( animationAction.isRunning(), "When an animation is started, it is running." ); + assert.ok( animationAction.isRunning(), 'When an animation is started, it is running.' ); mixer.update( 750 ); - assert.equal( root.rotation.x, 270, "When an animation is 3/4 in the first loop, it has changed to 3/4 when LoopPingPong." ); - assert.ok( animationAction.isRunning(), "When an animation is in the first loop, it is running." ); + assert.equal( root.rotation.x, 270, 'When an animation is 3/4 in the first loop, it has changed to 3/4 when LoopPingPong.' ); + assert.ok( animationAction.isRunning(), 'When an animation is in the first loop, it is running.' ); mixer.update( 1000 ); - assert.equal( root.rotation.x, 90, "When an animation is 3/4 in the second loop, it has changed to 1/4 when LoopPingPong." ); - assert.ok( animationAction.isRunning(), "When an animation is in second loop when in looprepeat 3 times, it is running." ); + assert.equal( root.rotation.x, 90, 'When an animation is 3/4 in the second loop, it has changed to 1/4 when LoopPingPong.' ); + assert.ok( animationAction.isRunning(), 'When an animation is in second loop when in looprepeat 3 times, it is running.' ); mixer.update( 1000 ); - assert.equal( root.rotation.x, 270, "When an animation is 3/4 in the third loop, it has changed to 3/4 when LoopPingPong." ); - assert.ok( animationAction.isRunning(), "When an animation is in third loop when in looprepeat 3 times, it is running." ); + assert.equal( root.rotation.x, 270, 'When an animation is 3/4 in the third loop, it has changed to 3/4 when LoopPingPong.' ); + assert.ok( animationAction.isRunning(), 'When an animation is in third loop when in looprepeat 3 times, it is running.' ); mixer.update( 1000 ); - assert.equal( root.rotation.x, 0, "When an animation ended his fourth loop when in looprepeat 3 times, it stays on the end result." ); - assert.notOk( animationAction.isRunning(), "When an animation ended his fourth loop when in looprepeat 3 times, it stays not running anymore." ); + assert.equal( root.rotation.x, 0, 'When an animation ended his fourth loop when in looprepeat 3 times, it stays on the end result.' ); + assert.notOk( animationAction.isRunning(), 'When an animation ended his fourth loop when in looprepeat 3 times, it stays not running anymore.' ); } ); - QUnit.test( "setEffectiveWeight", ( assert ) => { + QUnit.test( 'setEffectiveWeight', ( assert ) => { var { animationAction } = createAnimation(); - assert.equal( animationAction.getEffectiveWeight(), 1, "When an animation is created, EffectiveWeight is 1." ); + assert.equal( animationAction.getEffectiveWeight(), 1, 'When an animation is created, EffectiveWeight is 1.' ); animationAction.setEffectiveWeight( 0.3 ); - assert.equal( animationAction.getEffectiveWeight(), 0.3, "When EffectiveWeight is set to 0.3 , EffectiveWeight is 0.3." ); + assert.equal( animationAction.getEffectiveWeight(), 0.3, 'When EffectiveWeight is set to 0.3 , EffectiveWeight is 0.3.' ); var { animationAction } = createAnimation(); - assert.equal( animationAction.getEffectiveWeight(), 1, "When an animation is created, EffectiveWeight is 1." ); + assert.equal( animationAction.getEffectiveWeight(), 1, 'When an animation is created, EffectiveWeight is 1.' ); animationAction.enabled = false; animationAction.setEffectiveWeight( 0.3 ); - assert.equal( animationAction.getEffectiveWeight(), 0, "When EffectiveWeight is set to 0.3 when disabled , EffectiveWeight is 0." ); + assert.equal( animationAction.getEffectiveWeight(), 0, 'When EffectiveWeight is set to 0.3 when disabled , EffectiveWeight is 0.' ); var { root, mixer, animationAction } = createAnimation(); animationAction.setEffectiveWeight( 0.5 ); animationAction.play(); mixer.update( 500 ); - assert.equal( root.rotation.x, 90, "When an animation has weight 0.5 and runs half through the animation, it has changed to 1/4." ); + assert.equal( root.rotation.x, 90, 'When an animation has weight 0.5 and runs half through the animation, it has changed to 1/4.' ); mixer.update( 1000 ); - assert.equal( root.rotation.x, 90, "When an animation has weight 0.5 and runs one and half through the animation, it has changed to 1/4." ); + assert.equal( root.rotation.x, 90, 'When an animation has weight 0.5 and runs one and half through the animation, it has changed to 1/4.' ); } ); - QUnit.test( "getEffectiveWeight", ( assert ) => { + QUnit.test( 'getEffectiveWeight', ( assert ) => { var { animationAction } = createAnimation(); - assert.equal( animationAction.getEffectiveWeight(), 1, "When an animation is created, EffectiveWeight is 1." ); + assert.equal( animationAction.getEffectiveWeight(), 1, 'When an animation is created, EffectiveWeight is 1.' ); animationAction.setEffectiveWeight( 0.3 ); - assert.equal( animationAction.getEffectiveWeight(), 0.3, "When EffectiveWeight is set to 0.3 , EffectiveWeight is 0.3." ); + assert.equal( animationAction.getEffectiveWeight(), 0.3, 'When EffectiveWeight is set to 0.3 , EffectiveWeight is 0.3.' ); var { animationAction } = createAnimation(); - assert.equal( animationAction.getEffectiveWeight(), 1, "When an animation is created, EffectiveWeight is 1." ); + assert.equal( animationAction.getEffectiveWeight(), 1, 'When an animation is created, EffectiveWeight is 1.' ); animationAction.enabled = false; animationAction.setEffectiveWeight( 0.3 ); - assert.equal( animationAction.getEffectiveWeight(), 0, "When EffectiveWeight is set to 0.3 when disabled , EffectiveWeight is 0." ); + assert.equal( animationAction.getEffectiveWeight(), 0, 'When EffectiveWeight is set to 0.3 when disabled , EffectiveWeight is 0.' ); } ); - QUnit.test( "fadeIn", ( assert ) => { + QUnit.test( 'fadeIn', ( assert ) => { var { mixer, animationAction } = createAnimation(); animationAction.fadeIn( 1000 ); animationAction.play(); - assert.equal( animationAction.getEffectiveWeight(), 1, "When an animation fadeIn is started, EffectiveWeight is 1." ); + assert.equal( animationAction.getEffectiveWeight(), 1, 'When an animation fadeIn is started, EffectiveWeight is 1.' ); mixer.update( 250 ); - assert.equal( animationAction.getEffectiveWeight(), 0.25, "When an animation fadeIn happened 1/4, EffectiveWeight is 0.25." ); + assert.equal( animationAction.getEffectiveWeight(), 0.25, 'When an animation fadeIn happened 1/4, EffectiveWeight is 0.25.' ); mixer.update( 250 ); - assert.equal( animationAction.getEffectiveWeight(), 0.5, "When an animation fadeIn is halfway , EffectiveWeight is 0.5." ); + assert.equal( animationAction.getEffectiveWeight(), 0.5, 'When an animation fadeIn is halfway , EffectiveWeight is 0.5.' ); mixer.update( 250 ); - assert.equal( animationAction.getEffectiveWeight(), 0.75, "When an animation fadeIn is halfway , EffectiveWeight is 0.75." ); + assert.equal( animationAction.getEffectiveWeight(), 0.75, 'When an animation fadeIn is halfway , EffectiveWeight is 0.75.' ); mixer.update( 500 ); - assert.equal( animationAction.getEffectiveWeight(), 1, "When an animation fadeIn is ended , EffectiveWeight is 1." ); + assert.equal( animationAction.getEffectiveWeight(), 1, 'When an animation fadeIn is ended , EffectiveWeight is 1.' ); } ); - QUnit.test( "fadeOut", ( assert ) => { + QUnit.test( 'fadeOut', ( assert ) => { var { mixer, animationAction } = createAnimation(); animationAction.fadeOut( 1000 ); animationAction.play(); - assert.equal( animationAction.getEffectiveWeight(), 1, "When an animation fadeOut is started, EffectiveWeight is 1." ); + assert.equal( animationAction.getEffectiveWeight(), 1, 'When an animation fadeOut is started, EffectiveWeight is 1.' ); mixer.update( 250 ); - assert.equal( animationAction.getEffectiveWeight(), 0.75, "When an animation fadeOut happened 1/4, EffectiveWeight is 0.75." ); + assert.equal( animationAction.getEffectiveWeight(), 0.75, 'When an animation fadeOut happened 1/4, EffectiveWeight is 0.75.' ); mixer.update( 250 ); - assert.equal( animationAction.getEffectiveWeight(), 0.5, "When an animation fadeOut is halfway , EffectiveWeight is 0.5." ); + assert.equal( animationAction.getEffectiveWeight(), 0.5, 'When an animation fadeOut is halfway , EffectiveWeight is 0.5.' ); mixer.update( 250 ); - assert.equal( animationAction.getEffectiveWeight(), 0.25, "When an animation fadeOut is happened 3/4 , EffectiveWeight is 0.25." ); + assert.equal( animationAction.getEffectiveWeight(), 0.25, 'When an animation fadeOut is happened 3/4 , EffectiveWeight is 0.25.' ); mixer.update( 500 ); - assert.equal( animationAction.getEffectiveWeight(), 0, "When an animation fadeOut is ended , EffectiveWeight is 0." ); + assert.equal( animationAction.getEffectiveWeight(), 0, 'When an animation fadeOut is ended , EffectiveWeight is 0.' ); } ); - QUnit.test( "crossFadeFrom", ( assert ) => { + QUnit.test( 'crossFadeFrom', ( assert ) => { var { mixer, animationAction, animationAction2 } = createTwoAnimations(); animationAction.crossFadeFrom( animationAction2, 1000, false ); animationAction.play(); animationAction2.play(); - assert.equal( animationAction.getEffectiveWeight(), 1, "When an animation crossFadeFrom is started, EffectiveWeight is 1." ); - assert.equal( animationAction2.getEffectiveWeight(), 1, "When an animation crossFadeFrom is started, EffectiveWeight is 1." ); + assert.equal( animationAction.getEffectiveWeight(), 1, 'When an animation crossFadeFrom is started, EffectiveWeight is 1.' ); + assert.equal( animationAction2.getEffectiveWeight(), 1, 'When an animation crossFadeFrom is started, EffectiveWeight is 1.' ); mixer.update( 250 ); - assert.equal( animationAction.getEffectiveWeight(), 0.25, "When an animation fadeOut happened 1/4, EffectiveWeight is 0.75." ); - assert.equal( animationAction2.getEffectiveWeight(), 0.75, "When an animation fadeOut happened 1/4, EffectiveWeight is 0.75." ); + assert.equal( animationAction.getEffectiveWeight(), 0.25, 'When an animation fadeOut happened 1/4, EffectiveWeight is 0.75.' ); + assert.equal( animationAction2.getEffectiveWeight(), 0.75, 'When an animation fadeOut happened 1/4, EffectiveWeight is 0.75.' ); mixer.update( 250 ); - assert.equal( animationAction.getEffectiveWeight(), 0.5, "When an animation fadeOut happened 1/4, EffectiveWeight is 0.75." ); - assert.equal( animationAction2.getEffectiveWeight(), 0.5, "When an animation fadeOut is halfway , EffectiveWeight is 0.5." ); + assert.equal( animationAction.getEffectiveWeight(), 0.5, 'When an animation fadeOut happened 1/4, EffectiveWeight is 0.75.' ); + assert.equal( animationAction2.getEffectiveWeight(), 0.5, 'When an animation fadeOut is halfway , EffectiveWeight is 0.5.' ); mixer.update( 250 ); - assert.equal( animationAction.getEffectiveWeight(), 0.75, "When an animation fadeOut happened 1/4, EffectiveWeight is 0.75." ); - assert.equal( animationAction2.getEffectiveWeight(), 0.25, "When an animation fadeOut is happened 3/4 , EffectiveWeight is 0.25." ); + assert.equal( animationAction.getEffectiveWeight(), 0.75, 'When an animation fadeOut happened 1/4, EffectiveWeight is 0.75.' ); + assert.equal( animationAction2.getEffectiveWeight(), 0.25, 'When an animation fadeOut is happened 3/4 , EffectiveWeight is 0.25.' ); mixer.update( 500 ); - assert.equal( animationAction.getEffectiveWeight(), 1, "When an animation fadeOut happened 1/4, EffectiveWeight is 0.75." ); - assert.equal( animationAction2.getEffectiveWeight(), 0, "When an animation fadeOut is ended , EffectiveWeight is 0." ); + assert.equal( animationAction.getEffectiveWeight(), 1, 'When an animation fadeOut happened 1/4, EffectiveWeight is 0.75.' ); + assert.equal( animationAction2.getEffectiveWeight(), 0, 'When an animation fadeOut is ended , EffectiveWeight is 0.' ); } ); - QUnit.test( "crossFadeTo", ( assert ) => { + QUnit.test( 'crossFadeTo', ( assert ) => { var { mixer, animationAction, animationAction2 } = createTwoAnimations(); animationAction2.crossFadeTo( animationAction, 1000, false ); animationAction.play(); animationAction2.play(); - assert.equal( animationAction.getEffectiveWeight(), 1, "When an animation crossFadeFrom is started, EffectiveWeight is 1." ); - assert.equal( animationAction2.getEffectiveWeight(), 1, "When an animation crossFadeFrom is started, EffectiveWeight is 1." ); + assert.equal( animationAction.getEffectiveWeight(), 1, 'When an animation crossFadeFrom is started, EffectiveWeight is 1.' ); + assert.equal( animationAction2.getEffectiveWeight(), 1, 'When an animation crossFadeFrom is started, EffectiveWeight is 1.' ); mixer.update( 250 ); - assert.equal( animationAction.getEffectiveWeight(), 0.25, "When an animation fadeOut happened 1/4, EffectiveWeight is 0.75." ); - assert.equal( animationAction2.getEffectiveWeight(), 0.75, "When an animation fadeOut happened 1/4, EffectiveWeight is 0.75." ); + assert.equal( animationAction.getEffectiveWeight(), 0.25, 'When an animation fadeOut happened 1/4, EffectiveWeight is 0.75.' ); + assert.equal( animationAction2.getEffectiveWeight(), 0.75, 'When an animation fadeOut happened 1/4, EffectiveWeight is 0.75.' ); mixer.update( 250 ); - assert.equal( animationAction.getEffectiveWeight(), 0.5, "When an animation fadeOut happened 1/4, EffectiveWeight is 0.75." ); - assert.equal( animationAction2.getEffectiveWeight(), 0.5, "When an animation fadeOut is halfway , EffectiveWeight is 0.5." ); + assert.equal( animationAction.getEffectiveWeight(), 0.5, 'When an animation fadeOut happened 1/4, EffectiveWeight is 0.75.' ); + assert.equal( animationAction2.getEffectiveWeight(), 0.5, 'When an animation fadeOut is halfway , EffectiveWeight is 0.5.' ); mixer.update( 250 ); - assert.equal( animationAction.getEffectiveWeight(), 0.75, "When an animation fadeOut happened 1/4, EffectiveWeight is 0.75." ); - assert.equal( animationAction2.getEffectiveWeight(), 0.25, "When an animation fadeOut is happened 3/4 , EffectiveWeight is 0.25." ); + assert.equal( animationAction.getEffectiveWeight(), 0.75, 'When an animation fadeOut happened 1/4, EffectiveWeight is 0.75.' ); + assert.equal( animationAction2.getEffectiveWeight(), 0.25, 'When an animation fadeOut is happened 3/4 , EffectiveWeight is 0.25.' ); mixer.update( 500 ); - assert.equal( animationAction.getEffectiveWeight(), 1, "When an animation fadeOut happened 1/4, EffectiveWeight is 0.75." ); - assert.equal( animationAction2.getEffectiveWeight(), 0, "When an animation fadeOut is ended , EffectiveWeight is 0." ); + assert.equal( animationAction.getEffectiveWeight(), 1, 'When an animation fadeOut happened 1/4, EffectiveWeight is 0.75.' ); + assert.equal( animationAction2.getEffectiveWeight(), 0, 'When an animation fadeOut is ended , EffectiveWeight is 0.' ); } ); - QUnit.todo( "stopFading", ( assert ) => { + QUnit.todo( 'stopFading', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setEffectiveTimeScale", ( assert ) => { + QUnit.todo( 'setEffectiveTimeScale', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getEffectiveTimeScale", ( assert ) => { + QUnit.todo( 'getEffectiveTimeScale', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setDuration", ( assert ) => { + QUnit.todo( 'setDuration', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "syncWith", ( assert ) => { + QUnit.todo( 'syncWith', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "halt", ( assert ) => { + QUnit.todo( 'halt', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "warp", ( assert ) => { + QUnit.todo( 'warp', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "stopWarping", ( assert ) => { + QUnit.todo( 'stopWarping', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "getMixer", ( assert ) => { + QUnit.test( 'getMixer', ( assert ) => { var { mixer, animationAction } = createAnimation(); var mixer2 = animationAction.getMixer(); - assert.equal( mixer, mixer2, "mixer should be returned by getMixer." ); + assert.equal( mixer, mixer2, 'mixer should be returned by getMixer.' ); } ); - QUnit.test( "getClip", ( assert ) => { + QUnit.test( 'getClip', ( assert ) => { var { clip, animationAction } = createAnimation(); var clip2 = animationAction.getClip(); - assert.equal( clip, clip2, "clip should be returned by getClip." ); + assert.equal( clip, clip2, 'clip should be returned by getClip.' ); } ); - QUnit.test( "getRoot", ( assert ) => { + QUnit.test( 'getRoot', ( assert ) => { var { root, animationAction } = createAnimation(); var root2 = animationAction.getRoot(); - assert.equal( root, root2, "root should be returned by getRoot." ); + assert.equal( root, root2, 'root should be returned by getRoot.' ); } ); diff --git a/test/unit/src/animation/AnimationClip.tests.js b/test/unit/src/animation/AnimationClip.tests.js index 50a0241cc0ea5a..899151c76dd4e5 100644 --- a/test/unit/src/animation/AnimationClip.tests.js +++ b/test/unit/src/animation/AnimationClip.tests.js @@ -7,71 +7,71 @@ export default QUnit.module( 'Animation', () => { QUnit.module( 'AnimationClip', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // STATIC STUFF - QUnit.todo( "parse", ( assert ) => { + QUnit.todo( 'parse', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "toJSON", ( assert ) => { + QUnit.todo( 'toJSON', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "CreateFromMorphTargetSequence", ( assert ) => { + QUnit.todo( 'CreateFromMorphTargetSequence', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "findByName", ( assert ) => { + QUnit.todo( 'findByName', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "CreateClipsFromMorphTargetSequences", ( assert ) => { + QUnit.todo( 'CreateClipsFromMorphTargetSequences', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "parseAnimation", ( assert ) => { + QUnit.todo( 'parseAnimation', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "resetDuration", ( assert ) => { + QUnit.todo( 'resetDuration', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "trim", ( assert ) => { + QUnit.todo( 'trim', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "optimize", ( assert ) => { + QUnit.todo( 'optimize', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "validate", ( assert ) => { + QUnit.todo( 'validate', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/animation/AnimationMixer.tests.js b/test/unit/src/animation/AnimationMixer.tests.js index 5df8972570ab73..442cd22a3c4ef6 100644 --- a/test/unit/src/animation/AnimationMixer.tests.js +++ b/test/unit/src/animation/AnimationMixer.tests.js @@ -14,11 +14,11 @@ function getClips( pos1, pos2, scale1, scale2, dur ) { const clips = []; - let track = new VectorKeyframeTrack( ".scale", [ 0, dur ], [ scale1.x, scale1.y, scale1.z, scale2.x, scale2.y, scale2.z ] ); - clips.push( new AnimationClip( "scale", dur, [ track ] ) ); + let track = new VectorKeyframeTrack( '.scale', [ 0, dur ], [ scale1.x, scale1.y, scale1.z, scale2.x, scale2.y, scale2.z ] ); + clips.push( new AnimationClip( 'scale', dur, [ track ] ) ); - track = new VectorKeyframeTrack( ".position", [ 0, dur ], [ pos1.x, pos1.y, pos1.z, pos2.x, pos2.y, pos2.z ] ); - clips.push( new AnimationClip( "position", dur, [ track ] ) ); + track = new VectorKeyframeTrack( '.position', [ 0, dur ], [ pos1.x, pos1.y, pos1.z, pos2.x, pos2.y, pos2.z ] ); + clips.push( new AnimationClip( 'position', dur, [ track ] ) ); return clips; @@ -29,33 +29,33 @@ export default QUnit.module( 'Animation', () => { QUnit.module( 'AnimationMixer', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "clipAction", ( assert ) => { + QUnit.todo( 'clipAction', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "existingAction", ( assert ) => { + QUnit.todo( 'existingAction', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "stopAllAction", ( assert ) => { + QUnit.test( 'stopAllAction', ( assert ) => { const obj = new Object3D(); const animMixer = new AnimationMixer( obj ); @@ -71,51 +71,51 @@ export default QUnit.module( 'Animation', () => { assert.ok( ! actionA.isRunning() && ! actionB.isRunning(), - "All actions stopped" ); + 'All actions stopped' ); assert.ok( obj.position.x == 0 && obj.position.y == 0 && obj.position.z == 0, - "Position reset as expected" + 'Position reset as expected' ); assert.ok( obj.scale.x == 1 && obj.scale.y == 1 && obj.scale.z == 1, - "Scale reset as expected" + 'Scale reset as expected' ); } ); - QUnit.todo( "update", ( assert ) => { + QUnit.todo( 'update', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "getRoot", ( assert ) => { + QUnit.test( 'getRoot', ( assert ) => { const obj = new Object3D(); const animMixer = new AnimationMixer( obj ); - assert.strictEqual( obj, animMixer.getRoot(), "Get original root object" ); + assert.strictEqual( obj, animMixer.getRoot(), 'Get original root object' ); } ); - QUnit.todo( "uncacheClip", ( assert ) => { + QUnit.todo( 'uncacheClip', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "uncacheRoot", ( assert ) => { + QUnit.todo( 'uncacheRoot', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "uncacheAction", ( assert ) => { + QUnit.todo( 'uncacheAction', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/animation/AnimationObjectGroup.tests.js b/test/unit/src/animation/AnimationObjectGroup.tests.js index bceb14af18b672..e6299dcad8f932 100644 --- a/test/unit/src/animation/AnimationObjectGroup.tests.js +++ b/test/unit/src/animation/AnimationObjectGroup.tests.js @@ -4,9 +4,9 @@ import { AnimationObjectGroup } from '../../../../src/animation/AnimationObjectG import { Object3D } from '../../../../src/core/Object3D'; import { PropertyBinding } from '../../../../src/animation/PropertyBinding'; -export default QUnit.module( "Animation", () => { +export default QUnit.module( 'Animation', () => { - QUnit.module( "AnimationObjectGroup", () => { + QUnit.module( 'AnimationObjectGroup', () => { var ObjectA = new Object3D(), ObjectB = new Object3D(), @@ -21,39 +21,39 @@ export default QUnit.module( "Animation", () => { ParsedPathC = PropertyBinding.parseTrackName( PathC ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isAnimationObjectGroup", ( assert ) => { + QUnit.todo( 'isAnimationObjectGroup', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "add", ( assert ) => { + QUnit.todo( 'add', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "remove", ( assert ) => { + QUnit.todo( 'remove', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "uncache", ( assert ) => { + QUnit.todo( 'uncache', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // OTHERS - QUnit.test( "smoke test", ( assert ) => { + QUnit.test( 'smoke test', ( assert ) => { var expect = function expect( testIndex, group, bindings, path, cached, roots ) { @@ -72,23 +72,23 @@ export default QUnit.module( "Animation", () => { } - assert.ok( pathsOk, QUnit.testIndex + " paths" ); - assert.ok( nodesOk, QUnit.testIndex + " nodes" ); - assert.ok( group.nCachedObjects_ === cached, QUnit.testIndex + " cache size" ); - assert.ok( bindings.length - group.nCachedObjects_ === roots.length, QUnit.testIndex + " object count" ); + assert.ok( pathsOk, QUnit.testIndex + ' paths' ); + assert.ok( nodesOk, QUnit.testIndex + ' nodes' ); + assert.ok( group.nCachedObjects_ === cached, QUnit.testIndex + ' cache size' ); + assert.ok( bindings.length - group.nCachedObjects_ === roots.length, QUnit.testIndex + ' object count' ); }; // initial state var groupA = new AnimationObjectGroup(); - assert.ok( groupA instanceof AnimationObjectGroup, "constructor (w/o args)" ); + assert.ok( groupA instanceof AnimationObjectGroup, 'constructor (w/o args)' ); var bindingsAA = groupA.subscribe_( PathA, ParsedPathA ); expect( 0, groupA, bindingsAA, PathA, 0, [] ); var groupB = new AnimationObjectGroup( ObjectA, ObjectB ); - assert.ok( groupB instanceof AnimationObjectGroup, "constructor (with args)" ); + assert.ok( groupB instanceof AnimationObjectGroup, 'constructor (with args)' ); var bindingsBB = groupB.subscribe_( PathB, ParsedPathB ); expect( 1, groupB, bindingsBB, PathB, 0, [ ObjectA, ObjectB ] ); @@ -127,7 +127,7 @@ export default QUnit.module( "Animation", () => { var copyOfBindingsBC = bindingsBC.slice(); groupB.unsubscribe_( PathC ); groupB.add( ObjectC ); - assert.deepEqual( bindingsBC, copyOfBindingsBC, "no more update after unsubscribe" ); + assert.deepEqual( bindingsBC, copyOfBindingsBC, 'no more update after unsubscribe' ); // uncache active diff --git a/test/unit/src/animation/AnimationUtils.tests.js b/test/unit/src/animation/AnimationUtils.tests.js index 14cb2a8195170f..bb961515b39024 100644 --- a/test/unit/src/animation/AnimationUtils.tests.js +++ b/test/unit/src/animation/AnimationUtils.tests.js @@ -7,39 +7,39 @@ export default QUnit.module( 'Animation', () => { QUnit.module( 'AnimationUtils', () => { // PUBLIC STUFF - QUnit.todo( "arraySlice", ( assert ) => { + QUnit.todo( 'arraySlice', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "convertArray", ( assert ) => { + QUnit.todo( 'convertArray', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "isTypedArray", ( assert ) => { + QUnit.todo( 'isTypedArray', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getKeyframeOrder", ( assert ) => { + QUnit.todo( 'getKeyframeOrder', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "sortedArray", ( assert ) => { + QUnit.todo( 'sortedArray', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "flattenJSON", ( assert ) => { + QUnit.todo( 'flattenJSON', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/animation/KeyframeTrack.tests.js b/test/unit/src/animation/KeyframeTrack.tests.js index 6348050699f8d5..c3c4a2036eee2a 100644 --- a/test/unit/src/animation/KeyframeTrack.tests.js +++ b/test/unit/src/animation/KeyframeTrack.tests.js @@ -8,89 +8,89 @@ export default QUnit.module( 'Animation', () => { QUnit.module( 'KeyframeTrack', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // STATIC STUFF - QUnit.todo( "toJSON", ( assert ) => { + QUnit.todo( 'toJSON', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "TimeBufferType", ( assert ) => { + QUnit.todo( 'TimeBufferType', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "ValueBufferType", ( assert ) => { + QUnit.todo( 'ValueBufferType', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "DefaultInterpolation", ( assert ) => { + QUnit.todo( 'DefaultInterpolation', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "InterpolantFactoryMethodDiscrete", ( assert ) => { + QUnit.todo( 'InterpolantFactoryMethodDiscrete', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "InterpolantFactoryMethodLinear", ( assert ) => { + QUnit.todo( 'InterpolantFactoryMethodLinear', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "InterpolantFactoryMethodSmooth", ( assert ) => { + QUnit.todo( 'InterpolantFactoryMethodSmooth', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setInterpolation", ( assert ) => { + QUnit.todo( 'setInterpolation', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getInterpolation", ( assert ) => { + QUnit.todo( 'getInterpolation', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getValueSize", ( assert ) => { + QUnit.todo( 'getValueSize', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "shift", ( assert ) => { + QUnit.todo( 'shift', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "scale", ( assert ) => { + QUnit.todo( 'scale', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "trim", ( assert ) => { + QUnit.todo( 'trim', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/animation/PropertyBinding.tests.js b/test/unit/src/animation/PropertyBinding.tests.js index a77e71ab3c1839..4f4bec8de8fce1 100644 --- a/test/unit/src/animation/PropertyBinding.tests.js +++ b/test/unit/src/animation/PropertyBinding.tests.js @@ -10,22 +10,22 @@ export default QUnit.module( 'Animation', () => { QUnit.module( 'PropertyBinding', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // STATIC STUFF - QUnit.todo( "Composite", ( assert ) => { + QUnit.todo( 'Composite', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "create", ( assert ) => { + QUnit.todo( 'create', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); @@ -282,40 +282,40 @@ export default QUnit.module( 'Animation', () => { } ); - QUnit.todo( "findNode", ( assert ) => { + QUnit.todo( 'findNode', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "BindingType", ( assert ) => { + QUnit.todo( 'BindingType', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "Versioning", ( assert ) => { + QUnit.todo( 'Versioning', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "GetterByBindingType", ( assert ) => { + QUnit.todo( 'GetterByBindingType', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "SetterByBindingTypeAndVersioning", ( assert ) => { + QUnit.todo( 'SetterByBindingTypeAndVersioning', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getValue", ( assert ) => { + QUnit.todo( 'getValue', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); @@ -356,15 +356,15 @@ export default QUnit.module( 'Animation', () => { } ); - QUnit.todo( "bind", ( assert ) => { + QUnit.todo( 'bind', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "unbind", ( assert ) => { + QUnit.todo( 'unbind', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/animation/PropertyMixer.tests.js b/test/unit/src/animation/PropertyMixer.tests.js index cf12db9cf23fec..f3a4217fd3f117 100644 --- a/test/unit/src/animation/PropertyMixer.tests.js +++ b/test/unit/src/animation/PropertyMixer.tests.js @@ -7,34 +7,34 @@ export default QUnit.module( 'Animation', () => { QUnit.module( 'PropertyMixer', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "accumulate", ( assert ) => { + QUnit.todo( 'accumulate', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "apply", ( assert ) => { + QUnit.todo( 'apply', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "saveOriginalState", ( assert ) => { + QUnit.todo( 'saveOriginalState', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "restoreOriginalState", ( assert ) => { + QUnit.todo( 'restoreOriginalState', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/animation/tracks/BooleanKeyframeTrack.tests.js b/test/unit/src/animation/tracks/BooleanKeyframeTrack.tests.js index 0ec23997edfa1e..d9a0247dcd887b 100644 --- a/test/unit/src/animation/tracks/BooleanKeyframeTrack.tests.js +++ b/test/unit/src/animation/tracks/BooleanKeyframeTrack.tests.js @@ -10,7 +10,7 @@ export default QUnit.module( 'Animation', () => { QUnit.todo( 'write me !', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/animation/tracks/ColorKeyframeTrack.tests.js b/test/unit/src/animation/tracks/ColorKeyframeTrack.tests.js index 99e115f3775aa5..91903158cc64bf 100644 --- a/test/unit/src/animation/tracks/ColorKeyframeTrack.tests.js +++ b/test/unit/src/animation/tracks/ColorKeyframeTrack.tests.js @@ -10,7 +10,7 @@ export default QUnit.module( 'Animation', () => { QUnit.todo( 'write me !', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/animation/tracks/NumberKeyframeTrack.tests.js b/test/unit/src/animation/tracks/NumberKeyframeTrack.tests.js index f6c215c0c44a5b..e8cd235d15b3a9 100644 --- a/test/unit/src/animation/tracks/NumberKeyframeTrack.tests.js +++ b/test/unit/src/animation/tracks/NumberKeyframeTrack.tests.js @@ -10,7 +10,7 @@ export default QUnit.module( 'Animation', () => { QUnit.todo( 'write me !', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/animation/tracks/QuaternionKeyframeTrack.tests.js b/test/unit/src/animation/tracks/QuaternionKeyframeTrack.tests.js index 823984b1a59563..7f9a1820ef87cf 100644 --- a/test/unit/src/animation/tracks/QuaternionKeyframeTrack.tests.js +++ b/test/unit/src/animation/tracks/QuaternionKeyframeTrack.tests.js @@ -10,7 +10,7 @@ export default QUnit.module( 'Animation', () => { QUnit.todo( 'write me !', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/animation/tracks/StringKeyframeTrack.tests.js b/test/unit/src/animation/tracks/StringKeyframeTrack.tests.js index 874eefb6650760..1c26aee7a9b749 100644 --- a/test/unit/src/animation/tracks/StringKeyframeTrack.tests.js +++ b/test/unit/src/animation/tracks/StringKeyframeTrack.tests.js @@ -10,7 +10,7 @@ export default QUnit.module( 'Animation', () => { QUnit.todo( 'write me !', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/animation/tracks/VectorKeyframeTrack.tests.js b/test/unit/src/animation/tracks/VectorKeyframeTrack.tests.js index 4140b75f70b621..743c7b38929b55 100644 --- a/test/unit/src/animation/tracks/VectorKeyframeTrack.tests.js +++ b/test/unit/src/animation/tracks/VectorKeyframeTrack.tests.js @@ -10,7 +10,7 @@ export default QUnit.module( 'Animation', () => { QUnit.todo( 'write me !', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/audio/Audio.tests.js b/test/unit/src/audio/Audio.tests.js index a219f6ae8c8ea7..fdcd46fd454092 100644 --- a/test/unit/src/audio/Audio.tests.js +++ b/test/unit/src/audio/Audio.tests.js @@ -7,131 +7,131 @@ export default QUnit.module( 'Audios', () => { QUnit.module( 'Audio', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "getOutput", ( assert ) => { + QUnit.todo( 'getOutput', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setNodeSource", ( assert ) => { + QUnit.todo( 'setNodeSource', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setBuffer", ( assert ) => { + QUnit.todo( 'setBuffer', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "play", ( assert ) => { + QUnit.todo( 'play', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "pause", ( assert ) => { + QUnit.todo( 'pause', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "stop", ( assert ) => { + QUnit.todo( 'stop', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "connect", ( assert ) => { + QUnit.todo( 'connect', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "disconnect", ( assert ) => { + QUnit.todo( 'disconnect', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getFilters", ( assert ) => { + QUnit.todo( 'getFilters', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setFilters", ( assert ) => { + QUnit.todo( 'setFilters', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getFilter", ( assert ) => { + QUnit.todo( 'getFilter', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setFilter", ( assert ) => { + QUnit.todo( 'setFilter', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setPlaybackRate", ( assert ) => { + QUnit.todo( 'setPlaybackRate', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getPlaybackRate", ( assert ) => { + QUnit.todo( 'getPlaybackRate', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "onEnded", ( assert ) => { + QUnit.todo( 'onEnded', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getLoop", ( assert ) => { + QUnit.todo( 'getLoop', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setLoop", ( assert ) => { + QUnit.todo( 'setLoop', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getVolume", ( assert ) => { + QUnit.todo( 'getVolume', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setVolume", ( assert ) => { + QUnit.todo( 'setVolume', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/audio/AudioAnalyser.tests.js b/test/unit/src/audio/AudioAnalyser.tests.js index e3d8bb30f92847..0798b0b938c0e8 100644 --- a/test/unit/src/audio/AudioAnalyser.tests.js +++ b/test/unit/src/audio/AudioAnalyser.tests.js @@ -7,22 +7,22 @@ export default QUnit.module( 'Audios', () => { QUnit.module( 'AudioAnalyser', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "getFrequencyData", ( assert ) => { + QUnit.todo( 'getFrequencyData', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getAverageFrequency", ( assert ) => { + QUnit.todo( 'getAverageFrequency', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/audio/AudioContext.tests.js b/test/unit/src/audio/AudioContext.tests.js index f1b544ee190794..5d69a5947cc954 100644 --- a/test/unit/src/audio/AudioContext.tests.js +++ b/test/unit/src/audio/AudioContext.tests.js @@ -7,15 +7,15 @@ export default QUnit.module( 'Audios', () => { QUnit.module( 'AudioContext', () => { // PUBLIC STUFF - QUnit.todo( "getContext", ( assert ) => { + QUnit.todo( 'getContext', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setContext", ( assert ) => { + QUnit.todo( 'setContext', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/audio/AudioListener.tests.js b/test/unit/src/audio/AudioListener.tests.js index 6419adf4a90b00..afba956e338599 100644 --- a/test/unit/src/audio/AudioListener.tests.js +++ b/test/unit/src/audio/AudioListener.tests.js @@ -7,59 +7,59 @@ export default QUnit.module( 'Audios', () => { QUnit.module( 'AudioListener', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "getInput", ( assert ) => { + QUnit.todo( 'getInput', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "removeFilter", ( assert ) => { + QUnit.todo( 'removeFilter', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getFilter", ( assert ) => { + QUnit.todo( 'getFilter', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setFilter", ( assert ) => { + QUnit.todo( 'setFilter', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getMasterVolume", ( assert ) => { + QUnit.todo( 'getMasterVolume', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setMasterVolume", ( assert ) => { + QUnit.todo( 'setMasterVolume', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "updateMatrixWorld", ( assert ) => { + QUnit.todo( 'updateMatrixWorld', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/audio/PositionalAudio.tests.js b/test/unit/src/audio/PositionalAudio.tests.js index 06a86b4166b99f..c4c43557f6d1f5 100644 --- a/test/unit/src/audio/PositionalAudio.tests.js +++ b/test/unit/src/audio/PositionalAudio.tests.js @@ -7,77 +7,77 @@ export default QUnit.module( 'Audios', () => { QUnit.module( 'PositionalAudio', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "getOutput", ( assert ) => { + QUnit.todo( 'getOutput', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getRefDistance", ( assert ) => { + QUnit.todo( 'getRefDistance', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setRefDistance", ( assert ) => { + QUnit.todo( 'setRefDistance', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getRolloffFactor", ( assert ) => { + QUnit.todo( 'getRolloffFactor', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setRolloffFactor", ( assert ) => { + QUnit.todo( 'setRolloffFactor', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getDistanceModel", ( assert ) => { + QUnit.todo( 'getDistanceModel', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setDistanceModel", ( assert ) => { + QUnit.todo( 'setDistanceModel', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getMaxDistance", ( assert ) => { + QUnit.todo( 'getMaxDistance', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setMaxDistance", ( assert ) => { + QUnit.todo( 'setMaxDistance', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "updateMatrixWorld", ( assert ) => { + QUnit.todo( 'updateMatrixWorld', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/cameras/ArrayCamera.tests.js b/test/unit/src/cameras/ArrayCamera.tests.js index 0efe3aa4c94546..52aa87050c5428 100644 --- a/test/unit/src/cameras/ArrayCamera.tests.js +++ b/test/unit/src/cameras/ArrayCamera.tests.js @@ -7,23 +7,23 @@ export default QUnit.module( 'Cameras', () => { QUnit.module( 'ArrayCamera', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isArrayCamera", ( assert ) => { + QUnit.todo( 'isArrayCamera', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/cameras/Camera.tests.js b/test/unit/src/cameras/Camera.tests.js index 78c2a277b385cb..ef008424182654 100644 --- a/test/unit/src/cameras/Camera.tests.js +++ b/test/unit/src/cameras/Camera.tests.js @@ -8,45 +8,45 @@ export default QUnit.module( 'Cameras', () => { QUnit.module( 'Camera', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isCamera", ( assert ) => { + QUnit.todo( 'isCamera', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "copy", ( assert ) => { + QUnit.todo( 'copy', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getWorldDirection", ( assert ) => { + QUnit.todo( 'getWorldDirection', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "updateMatrixWorld", ( assert ) => { + QUnit.todo( 'updateMatrixWorld', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "clone", ( assert ) => { + QUnit.test( 'clone', ( assert ) => { var cam = new Camera(); @@ -59,19 +59,19 @@ export default QUnit.module( 'Cameras', () => { // TODO: Uuuummmhhh DO NOT relie equality on object methods ! // TODO: What's append if matrix.equal is wrongly implemented ??? // TODO: this MUST be check by assert - assert.ok( cam.matrixWorldInverse.equals( clonedCam.matrixWorldInverse ), "matrixWorldInverse is equal" ); - assert.ok( cam.projectionMatrix.equals( clonedCam.projectionMatrix ), "projectionMatrix is equal" ); + assert.ok( cam.matrixWorldInverse.equals( clonedCam.matrixWorldInverse ), 'matrixWorldInverse is equal' ); + assert.ok( cam.projectionMatrix.equals( clonedCam.projectionMatrix ), 'projectionMatrix is equal' ); } ); // OTHERS // TODO: this should not be here !!! This is Object3D stuff !!! - QUnit.test( "lookAt", ( assert ) => { + QUnit.test( 'lookAt', ( assert ) => { var cam = new Camera(); cam.lookAt( new Vector3( 0, 1, - 1 ) ); - assert.numEqual( cam.rotation.x * ( 180 / Math.PI ), 45, "x is equal" ); + assert.numEqual( cam.rotation.x * ( 180 / Math.PI ), 45, 'x is equal' ); } ); diff --git a/test/unit/src/cameras/CubeCamera.tests.js b/test/unit/src/cameras/CubeCamera.tests.js index 2035200362a9c9..f8d3dd66ef582b 100644 --- a/test/unit/src/cameras/CubeCamera.tests.js +++ b/test/unit/src/cameras/CubeCamera.tests.js @@ -7,16 +7,16 @@ export default QUnit.module( 'Cameras', () => { QUnit.module( 'CubeCamera', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/cameras/OrthographicCamera.tests.js b/test/unit/src/cameras/OrthographicCamera.tests.js index 058078d3d8faed..1fa219c5edf041 100644 --- a/test/unit/src/cameras/OrthographicCamera.tests.js +++ b/test/unit/src/cameras/OrthographicCamera.tests.js @@ -7,45 +7,45 @@ export default QUnit.module( 'Cameras', () => { QUnit.module( 'OrthographicCamera', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isOrthographicCamera", ( assert ) => { + QUnit.todo( 'isOrthographicCamera', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "copy", ( assert ) => { + QUnit.todo( 'copy', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setViewOffset", ( assert ) => { + QUnit.todo( 'setViewOffset', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "clearViewOffset", ( assert ) => { + QUnit.todo( 'clearViewOffset', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "updateProjectionMatrix", ( assert ) => { + QUnit.test( 'updateProjectionMatrix', ( assert ) => { var left = - 1, right = 1, top = 1, bottom = - 1, near = 1, far = 3; var cam = new OrthographicCamera( left, right, top, bottom, near, far ); @@ -59,37 +59,37 @@ export default QUnit.module( 'Cameras', () => { // 0 0 -2/f-n -(f+n/f-n) // 0 0 0 1 - assert.ok( pMatrix[ 0 ] === 2 / ( right - left ), "m[0,0] === 2 / (r - l)" ); - assert.ok( pMatrix[ 5 ] === 2 / ( top - bottom ), "m[1,1] === 2 / (t - b)" ); - assert.ok( pMatrix[ 10 ] === - 2 / ( far - near ), "m[2,2] === -2 / (f - n)" ); - assert.ok( pMatrix[ 12 ] === - ( ( right + left ) / ( right - left ) ), "m[3,0] === -(r+l/r-l)" ); - assert.ok( pMatrix[ 13 ] === - ( ( top + bottom ) / ( top - bottom ) ), "m[3,1] === -(t+b/b-t)" ); - assert.ok( pMatrix[ 14 ] === - ( ( far + near ) / ( far - near ) ), "m[3,2] === -(f+n/f-n)" ); + assert.ok( pMatrix[ 0 ] === 2 / ( right - left ), 'm[0,0] === 2 / (r - l)' ); + assert.ok( pMatrix[ 5 ] === 2 / ( top - bottom ), 'm[1,1] === 2 / (t - b)' ); + assert.ok( pMatrix[ 10 ] === - 2 / ( far - near ), 'm[2,2] === -2 / (f - n)' ); + assert.ok( pMatrix[ 12 ] === - ( ( right + left ) / ( right - left ) ), 'm[3,0] === -(r+l/r-l)' ); + assert.ok( pMatrix[ 13 ] === - ( ( top + bottom ) / ( top - bottom ) ), 'm[3,1] === -(t+b/b-t)' ); + assert.ok( pMatrix[ 14 ] === - ( ( far + near ) / ( far - near ) ), 'm[3,2] === -(f+n/f-n)' ); } ); - QUnit.todo( "toJSON", ( assert ) => { + QUnit.todo( 'toJSON', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // OTHERS // TODO: no no no clone is a camera methods that relied to copy method - QUnit.test( "clone", ( assert ) => { + QUnit.test( 'clone', ( assert ) => { var left = - 1.5, right = 1.5, top = 1, bottom = - 1, near = 0.1, far = 42; var cam = new OrthographicCamera( left, right, top, bottom, near, far ); var clonedCam = cam.clone(); - assert.ok( cam.left === clonedCam.left, "left is equal" ); - assert.ok( cam.right === clonedCam.right, "right is equal" ); - assert.ok( cam.top === clonedCam.top, "top is equal" ); - assert.ok( cam.bottom === clonedCam.bottom, "bottom is equal" ); - assert.ok( cam.near === clonedCam.near, "near is equal" ); - assert.ok( cam.far === clonedCam.far, "far is equal" ); - assert.ok( cam.zoom === clonedCam.zoom, "zoom is equal" ); + assert.ok( cam.left === clonedCam.left, 'left is equal' ); + assert.ok( cam.right === clonedCam.right, 'right is equal' ); + assert.ok( cam.top === clonedCam.top, 'top is equal' ); + assert.ok( cam.bottom === clonedCam.bottom, 'bottom is equal' ); + assert.ok( cam.near === clonedCam.near, 'near is equal' ); + assert.ok( cam.far === clonedCam.far, 'far is equal' ); + assert.ok( cam.zoom === clonedCam.zoom, 'zoom is equal' ); } ); diff --git a/test/unit/src/cameras/PerspectiveCamera.tests.js b/test/unit/src/cameras/PerspectiveCamera.tests.js index d3ed274ff34ad4..dbfcf10040ac3b 100644 --- a/test/unit/src/cameras/PerspectiveCamera.tests.js +++ b/test/unit/src/cameras/PerspectiveCamera.tests.js @@ -16,6 +16,7 @@ export default QUnit.module( 'Cameras', () => { return false; } + for ( var i = 0, il = a.elements.length; i < il; i ++ ) { var delta = a.elements[ i ] - b.elements[ i ]; @@ -32,75 +33,75 @@ export default QUnit.module( 'Cameras', () => { }; // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isPerspectiveCamera", ( assert ) => { + QUnit.todo( 'isPerspectiveCamera', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "copy", ( assert ) => { + QUnit.todo( 'copy', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setFocalLength", ( assert ) => { + QUnit.todo( 'setFocalLength', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getFocalLength", ( assert ) => { + QUnit.todo( 'getFocalLength', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getEffectiveFOV", ( assert ) => { + QUnit.todo( 'getEffectiveFOV', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getFilmWidth", ( assert ) => { + QUnit.todo( 'getFilmWidth', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getFilmHeight", ( assert ) => { + QUnit.todo( 'getFilmHeight', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setViewOffset", ( assert ) => { + QUnit.todo( 'setViewOffset', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "clearViewOffset", ( assert ) => { + QUnit.todo( 'clearViewOffset', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "updateProjectionMatrix", ( assert ) => { + QUnit.test( 'updateProjectionMatrix', ( assert ) => { var cam = new PerspectiveCamera( 75, 16 / 9, 0.1, 300.0 ); @@ -127,15 +128,15 @@ export default QUnit.module( 'Cameras', () => { } ); - QUnit.todo( "toJSON", ( assert ) => { + QUnit.todo( 'toJSON', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // OTHERS // TODO: no no no clone is a camera methods that relied to copy method - QUnit.test( "clone", ( assert ) => { + QUnit.test( 'clone', ( assert ) => { var near = 1, far = 3, @@ -146,12 +147,12 @@ export default QUnit.module( 'Cameras', () => { var clonedCam = cam.clone(); - assert.ok( cam.fov === clonedCam.fov, "fov is equal" ); - assert.ok( cam.aspect === clonedCam.aspect, "aspect is equal" ); - assert.ok( cam.near === clonedCam.near, "near is equal" ); - assert.ok( cam.far === clonedCam.far, "far is equal" ); - assert.ok( cam.zoom === clonedCam.zoom, "zoom is equal" ); - assert.ok( cam.projectionMatrix.equals( clonedCam.projectionMatrix ), "projectionMatrix is equal" ); + assert.ok( cam.fov === clonedCam.fov, 'fov is equal' ); + assert.ok( cam.aspect === clonedCam.aspect, 'aspect is equal' ); + assert.ok( cam.near === clonedCam.near, 'near is equal' ); + assert.ok( cam.far === clonedCam.far, 'far is equal' ); + assert.ok( cam.zoom === clonedCam.zoom, 'zoom is equal' ); + assert.ok( cam.projectionMatrix.equals( clonedCam.projectionMatrix ), 'projectionMatrix is equal' ); } ); diff --git a/test/unit/src/cameras/StereoCamera.tests.js b/test/unit/src/cameras/StereoCamera.tests.js index f4bbb30eb87409..964f6efe2306e4 100644 --- a/test/unit/src/cameras/StereoCamera.tests.js +++ b/test/unit/src/cameras/StereoCamera.tests.js @@ -7,16 +7,16 @@ export default QUnit.module( 'Cameras', () => { QUnit.module( 'StereoCamera', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "update", ( assert ) => { + QUnit.todo( 'update', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/constants.tests.js b/test/unit/src/constants.tests.js index 83264e3c1f4619..b3c581fb729822 100644 --- a/test/unit/src/constants.tests.js +++ b/test/unit/src/constants.tests.js @@ -4,7 +4,7 @@ import * as Constants from '../../../src/constants'; export default QUnit.module( 'Constants', () => { - QUnit.test( "default values", ( assert ) => { + QUnit.test( 'default values', ( assert ) => { assert.propEqual( Constants.MOUSE, { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 }, 'MOUSE equal { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 }' ); assert.propEqual( Constants.TOUCH, { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 }, 'TOUCH equal { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 }' ); @@ -91,7 +91,6 @@ export default QUnit.module( 'Constants', () => { assert.equal( Constants.RGBAFormat, 1023, 'RGBAFormat is equal to 1023' ); assert.equal( Constants.LuminanceFormat, 1024, 'LuminanceFormat is equal to 1024' ); assert.equal( Constants.LuminanceAlphaFormat, 1025, 'LuminanceAlphaFormat is equal to 1025' ); - assert.equal( Constants.RGBEFormat, Constants.RGBAFormat, 'RGBEFormat is equal to RGBAFormat' ); assert.equal( Constants.DepthFormat, 1026, 'DepthFormat is equal to 1026' ); assert.equal( Constants.DepthStencilFormat, 1027, 'DepthStencilFormat is equal to 1027' ); assert.equal( Constants.RGB_S3TC_DXT1_Format, 33776, 'RGB_S3TC_DXT1_Format is equal to 33776' ); @@ -103,20 +102,20 @@ export default QUnit.module( 'Constants', () => { assert.equal( Constants.RGBA_PVRTC_4BPPV1_Format, 35842, 'RGBA_PVRTC_4BPPV1_Format is equal to 35842' ); assert.equal( Constants.RGBA_PVRTC_2BPPV1_Format, 35843, 'RGBA_PVRTC_2BPPV1_Format is equal to 35843' ); assert.equal( Constants.RGB_ETC1_Format, 36196, 'RGB_ETC1_Format is equal to 36196' ); - assert.equal( Constants.RGBA_ASTC_4x4_Format, 37808, "Constants.RGBA_ASTC_4x4_Format is equal to 37808" ); - assert.equal( Constants.RGBA_ASTC_5x4_Format, 37809, "Constants.RGBA_ASTC_5x4_Format is equal to 37809" ); - assert.equal( Constants.RGBA_ASTC_5x5_Format, 37810, "Constants.RGBA_ASTC_5x5_Format is equal to 37810" ); - assert.equal( Constants.RGBA_ASTC_6x5_Format, 37811, "Constants.RGBA_ASTC_6x5_Format is equal to 37811" ); - assert.equal( Constants.RGBA_ASTC_6x6_Format, 37812, "Constants.RGBA_ASTC_6x6_Format is equal to 37812" ); - assert.equal( Constants.RGBA_ASTC_8x5_Format, 37813, "Constants.RGBA_ASTC_8x5_Format is equal to 37813" ); - assert.equal( Constants.RGBA_ASTC_8x6_Format, 37814, "Constants.RGBA_ASTC_8x6_Format is equal to 37814" ); - assert.equal( Constants.RGBA_ASTC_8x8_Format, 37815, "Constants.RGBA_ASTC_8x8_Format is equal to 37815" ); - assert.equal( Constants.RGBA_ASTC_10x5_Format, 37816, "Constants.RGBA_ASTC_10x5_Format is equal to 37816" ); - assert.equal( Constants.RGBA_ASTC_10x6_Format, 37817, "Constants.RGBA_ASTC_10x6_Format is equal to 37817" ); - assert.equal( Constants.RGBA_ASTC_10x8_Format, 37818, "Constants.RGBA_ASTC_10x8_Format is equal to 37818" ); - assert.equal( Constants.RGBA_ASTC_10x10_Format, 37819, "Constants.RGBA_ASTC_10x10_Format is equal to 37819" ); - assert.equal( Constants.RGBA_ASTC_12x10_Format, 37820, "Constants.RGBA_ASTC_12x10_Format is equal to 37820" ); - assert.equal( Constants.RGBA_ASTC_12x12_Format, 37821, "Constants.RGBA_ASTC_12x12_Format is equal to 37821" ); + assert.equal( Constants.RGBA_ASTC_4x4_Format, 37808, 'Constants.RGBA_ASTC_4x4_Format is equal to 37808' ); + assert.equal( Constants.RGBA_ASTC_5x4_Format, 37809, 'Constants.RGBA_ASTC_5x4_Format is equal to 37809' ); + assert.equal( Constants.RGBA_ASTC_5x5_Format, 37810, 'Constants.RGBA_ASTC_5x5_Format is equal to 37810' ); + assert.equal( Constants.RGBA_ASTC_6x5_Format, 37811, 'Constants.RGBA_ASTC_6x5_Format is equal to 37811' ); + assert.equal( Constants.RGBA_ASTC_6x6_Format, 37812, 'Constants.RGBA_ASTC_6x6_Format is equal to 37812' ); + assert.equal( Constants.RGBA_ASTC_8x5_Format, 37813, 'Constants.RGBA_ASTC_8x5_Format is equal to 37813' ); + assert.equal( Constants.RGBA_ASTC_8x6_Format, 37814, 'Constants.RGBA_ASTC_8x6_Format is equal to 37814' ); + assert.equal( Constants.RGBA_ASTC_8x8_Format, 37815, 'Constants.RGBA_ASTC_8x8_Format is equal to 37815' ); + assert.equal( Constants.RGBA_ASTC_10x5_Format, 37816, 'Constants.RGBA_ASTC_10x5_Format is equal to 37816' ); + assert.equal( Constants.RGBA_ASTC_10x6_Format, 37817, 'Constants.RGBA_ASTC_10x6_Format is equal to 37817' ); + assert.equal( Constants.RGBA_ASTC_10x8_Format, 37818, 'Constants.RGBA_ASTC_10x8_Format is equal to 37818' ); + assert.equal( Constants.RGBA_ASTC_10x10_Format, 37819, 'Constants.RGBA_ASTC_10x10_Format is equal to 37819' ); + assert.equal( Constants.RGBA_ASTC_12x10_Format, 37820, 'Constants.RGBA_ASTC_12x10_Format is equal to 37820' ); + assert.equal( Constants.RGBA_ASTC_12x12_Format, 37821, 'Constants.RGBA_ASTC_12x12_Format is equal to 37821' ); assert.equal( Constants.LoopOnce, 2200, 'LoopOnce is equal to 2200' ); assert.equal( Constants.LoopRepeat, 2201, 'LoopRepeat is equal to 2201' ); assert.equal( Constants.LoopPingPong, 2202, 'LoopPingPong is equal to 2202' ); @@ -131,11 +130,6 @@ export default QUnit.module( 'Constants', () => { assert.equal( Constants.TriangleFanDrawMode, 2, 'TriangleFanDrawMode is equal to 2' ); assert.equal( Constants.LinearEncoding, 3000, 'LinearEncoding is equal to 3000' ); assert.equal( Constants.sRGBEncoding, 3001, 'sRGBEncoding is equal to 3001' ); - assert.equal( Constants.GammaEncoding, 3007, 'GammaEncoding is equal to 3007' ); - assert.equal( Constants.RGBEEncoding, 3002, 'RGBEEncoding is equal to 3002' ); - assert.equal( Constants.RGBM7Encoding, 3004, 'RGBM7Encoding is equal to 3004' ); - assert.equal( Constants.RGBM16Encoding, 3005, 'RGBM16Encoding is equal to 3005' ); - assert.equal( Constants.RGBDEncoding, 3006, 'RGBDEncoding is equal to 3006' ); assert.equal( Constants.BasicDepthPacking, 3200, 'BasicDepthPacking is equal to 3200' ); assert.equal( Constants.RGBADepthPacking, 3201, 'RGBADepthPacking is equal to 3201' ); diff --git a/test/unit/src/core/BufferAttribute.tests.js b/test/unit/src/core/BufferAttribute.tests.js index 535ce0bc568d61..52df816f60e3f6 100644 --- a/test/unit/src/core/BufferAttribute.tests.js +++ b/test/unit/src/core/BufferAttribute.tests.js @@ -12,7 +12,7 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'BufferAttribute', () => { // INSTANCING - QUnit.test( "Instancing", ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { assert.throws( function () { @@ -21,35 +21,35 @@ export default QUnit.module( 'Core', () => { }, /array should be a Typed Array/, - "Calling constructor with a simple array throws Error" + 'Calling constructor with a simple array throws Error' ); } ); // PROPERTIES - QUnit.todo( "needsUpdate", ( assert ) => { + QUnit.todo( 'needsUpdate', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isBufferAttribute", ( assert ) => { + QUnit.todo( 'isBufferAttribute', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "setUsage", ( assert ) => { + QUnit.test( 'setUsage', ( assert ) => { var attr = new BufferAttribute(); attr.setUsage( DynamicDrawUsage ); - assert.strictEqual( attr.usage, DynamicDrawUsage, "Usage was set" ); + assert.strictEqual( attr.usage, DynamicDrawUsage, 'Usage was set' ); } ); - QUnit.test( "copy", ( assert ) => { + QUnit.test( 'copy', ( assert ) => { var attr = new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3 ); attr.setUsage( DynamicDrawUsage ); @@ -65,7 +65,7 @@ export default QUnit.module( 'Core', () => { } ); - QUnit.test( "copyAt", ( assert ) => { + QUnit.test( 'copyAt', ( assert ) => { var attr = new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] ), 3 ); var attr2 = new BufferAttribute( new Float32Array( 9 ), 3 ); @@ -83,18 +83,18 @@ export default QUnit.module( 'Core', () => { } ); - QUnit.test( "copyArray", ( assert ) => { + QUnit.test( 'copyArray', ( assert ) => { var f32a = new Float32Array( [ 5, 6, 7, 8 ] ); var a = new BufferAttribute( new Float32Array( [ 1, 2, 3, 4 ] ), 2, false ); a.copyArray( f32a ); - assert.deepEqual( a.array, f32a, "Check array has new values" ); + assert.deepEqual( a.array, f32a, 'Check array has new values' ); } ); - QUnit.test( "copyColorsArray", ( assert ) => { + QUnit.test( 'copyColorsArray', ( assert ) => { var attr = new BufferAttribute( new Float32Array( 6 ), 3 ); @@ -109,7 +109,7 @@ export default QUnit.module( 'Core', () => { } ); - QUnit.test( "copyVector2sArray", ( assert ) => { + QUnit.test( 'copyVector2sArray', ( assert ) => { var attr = new BufferAttribute( new Float32Array( 4 ), 2 ); @@ -124,7 +124,7 @@ export default QUnit.module( 'Core', () => { } ); - QUnit.test( "copyVector3sArray", ( assert ) => { + QUnit.test( 'copyVector3sArray', ( assert ) => { var attr = new BufferAttribute( new Float32Array( 6 ), 2 ); @@ -139,7 +139,7 @@ export default QUnit.module( 'Core', () => { } ); - QUnit.test( "copyVector4sArray", ( assert ) => { + QUnit.test( 'copyVector4sArray', ( assert ) => { var attr = new BufferAttribute( new Float32Array( 8 ), 2 ); @@ -154,7 +154,7 @@ export default QUnit.module( 'Core', () => { } ); - QUnit.test( "set", ( assert ) => { + QUnit.test( 'set', ( assert ) => { var f32a = new Float32Array( [ 1, 2, 3, 4 ] ); var a = new BufferAttribute( f32a, 2, false ); @@ -163,11 +163,11 @@ export default QUnit.module( 'Core', () => { a.set( [ 9 ] ); a.set( [ 8 ], 2 ); - assert.deepEqual( a.array, expected, "Check array has expected values" ); + assert.deepEqual( a.array, expected, 'Check array has expected values' ); } ); - QUnit.test( "set[X, Y, Z, W, XYZ, XYZW]/get[X, Y, Z, W]", ( assert ) => { + QUnit.test( 'set[X, Y, Z, W, XYZ, XYZW]/get[X, Y, Z, W]', ( assert ) => { var f32a = new Float32Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); var a = new BufferAttribute( f32a, 4, false ); @@ -178,11 +178,11 @@ export default QUnit.module( 'Core', () => { a.setZ( 0, a.getZ( 0 ) * - 1 ); a.setW( 0, a.getW( 0 ) * - 1 ); - assert.deepEqual( a.array, expected, "Check all set* calls set the correct values" ); + assert.deepEqual( a.array, expected, 'Check all set* calls set the correct values' ); } ); - QUnit.test( "setXY", ( assert ) => { + QUnit.test( 'setXY', ( assert ) => { var f32a = new Float32Array( [ 1, 2, 3, 4 ] ); var a = new BufferAttribute( f32a, 2, false ); @@ -190,11 +190,11 @@ export default QUnit.module( 'Core', () => { a.setXY( 0, - 1, - 2 ); - assert.deepEqual( a.array, expected, "Check for the correct values" ); + assert.deepEqual( a.array, expected, 'Check for the correct values' ); } ); - QUnit.test( "setXYZ", ( assert ) => { + QUnit.test( 'setXYZ', ( assert ) => { var f32a = new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ); var a = new BufferAttribute( f32a, 3, false ); @@ -202,11 +202,11 @@ export default QUnit.module( 'Core', () => { a.setXYZ( 1, - 4, - 5, - 6 ); - assert.deepEqual( a.array, expected, "Check for the correct values" ); + assert.deepEqual( a.array, expected, 'Check for the correct values' ); } ); - QUnit.test( "setXYZW", ( assert ) => { + QUnit.test( 'setXYZW', ( assert ) => { var f32a = new Float32Array( [ 1, 2, 3, 4 ] ); var a = new BufferAttribute( f32a, 4, false ); @@ -214,22 +214,22 @@ export default QUnit.module( 'Core', () => { a.setXYZW( 0, - 1, - 2, - 3, - 4 ); - assert.deepEqual( a.array, expected, "Check for the correct values" ); + assert.deepEqual( a.array, expected, 'Check for the correct values' ); } ); - QUnit.test( "onUpload", ( assert ) => { + QUnit.test( 'onUpload', ( assert ) => { var a = new BufferAttribute(); var func = function () { }; a.onUpload( func ); - assert.strictEqual( a.onUploadCallback, func, "Check callback was set properly" ); + assert.strictEqual( a.onUploadCallback, func, 'Check callback was set properly' ); } ); - QUnit.test( "clone", ( assert ) => { + QUnit.test( 'clone', ( assert ) => { var attr = new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 0.12, - 12 ] ), 2 ); var attrCopy = attr.clone(); @@ -243,7 +243,7 @@ export default QUnit.module( 'Core', () => { } ); - QUnit.test( "toJSON", ( assert ) => { + QUnit.test( 'toJSON', ( assert ) => { const attr = new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3 ); assert.deepEqual( attr.toJSON(), { @@ -271,7 +271,7 @@ export default QUnit.module( 'Core', () => { } ); // OTHERS - QUnit.test( "count", ( assert ) => { + QUnit.test( 'count', ( assert ) => { assert.ok( new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3 ).count === 2, @@ -285,16 +285,16 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'Int8BufferAttribute', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); @@ -303,16 +303,16 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'Uint8BufferAttribute', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); @@ -321,16 +321,16 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'Uint8ClampedBufferAttribute', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); @@ -339,16 +339,16 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'Int16BufferAttribute', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); @@ -357,16 +357,16 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'Uint16BufferAttribute', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); @@ -375,16 +375,16 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'Int32BufferAttribute', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); @@ -393,16 +393,16 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'Uint32BufferAttribute', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); @@ -411,16 +411,16 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'Float32BufferAttribute', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); @@ -429,16 +429,16 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'Float64BufferAttribute', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/core/BufferGeometry.tests.js b/test/unit/src/core/BufferGeometry.tests.js index c07fe3bbf45722..b941c0a189775a 100644 --- a/test/unit/src/core/BufferGeometry.tests.js +++ b/test/unit/src/core/BufferGeometry.tests.js @@ -48,7 +48,7 @@ function getBBForVertices( vertices ) { var geometry = new BufferGeometry(); - geometry.setAttribute( "position", new BufferAttribute( new Float32Array( vertices ), 3 ) ); + geometry.setAttribute( 'position', new BufferAttribute( new Float32Array( vertices ), 3 ) ); geometry.computeBoundingBox(); return geometry.boundingBox; @@ -59,7 +59,7 @@ function getBSForVertices( vertices ) { var geometry = new BufferGeometry(); - geometry.setAttribute( "position", new BufferAttribute( new Float32Array( vertices ), 3 ) ); + geometry.setAttribute( 'position', new BufferAttribute( new Float32Array( vertices ), 3 ) ); geometry.computeBoundingSphere(); return geometry.boundingSphere; @@ -70,11 +70,11 @@ function getNormalsForVertices( vertices, assert ) { var geometry = new BufferGeometry(); - geometry.setAttribute( "position", new BufferAttribute( new Float32Array( vertices ), 3 ) ); + geometry.setAttribute( 'position', new BufferAttribute( new Float32Array( vertices ), 3 ) ); geometry.computeVertexNormals(); - assert.ok( geometry.attributes.normal !== undefined, "normal attribute was created" ); + assert.ok( geometry.attributes.normal !== undefined, 'normal attribute was created' ); return geometry.attributes.normal.array; @@ -85,56 +85,56 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'BufferGeometry', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isBufferGeometry", ( assert ) => { + QUnit.todo( 'isBufferGeometry', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "setIndex/getIndex", ( assert ) => { + QUnit.test( 'setIndex/getIndex', ( assert ) => { var a = new BufferGeometry(); var uint16 = [ 1, 2, 3 ]; var uint32 = [ 65535, 65536, 65537 ]; - var str = "foo"; + var str = 'foo'; a.setIndex( uint16 ); - assert.ok( a.getIndex() instanceof Uint16BufferAttribute, "Index has the right type" ); - assert.deepEqual( a.getIndex().array, new Uint16Array( uint16 ), "Small index gets stored correctly" ); + assert.ok( a.getIndex() instanceof Uint16BufferAttribute, 'Index has the right type' ); + assert.deepEqual( a.getIndex().array, new Uint16Array( uint16 ), 'Small index gets stored correctly' ); a.setIndex( uint32 ); - assert.ok( a.getIndex() instanceof Uint32BufferAttribute, "Index has the right type" ); - assert.deepEqual( a.getIndex().array, new Uint32Array( uint32 ), "Large index gets stored correctly" ); + assert.ok( a.getIndex() instanceof Uint32BufferAttribute, 'Index has the right type' ); + assert.deepEqual( a.getIndex().array, new Uint32Array( uint32 ), 'Large index gets stored correctly' ); a.setIndex( str ); - assert.strictEqual( a.getIndex(), str, "Weird index gets stored correctly" ); + assert.strictEqual( a.getIndex(), str, 'Weird index gets stored correctly' ); } ); - QUnit.todo( "getAttribute", ( assert ) => { + QUnit.todo( 'getAttribute', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "set / delete Attribute", ( assert ) => { + QUnit.test( 'set / delete Attribute', ( assert ) => { var geometry = new BufferGeometry(); - var attributeName = "position"; + var attributeName = 'position'; assert.ok( geometry.attributes[ attributeName ] === undefined, 'no attribute defined' ); @@ -148,7 +148,7 @@ export default QUnit.module( 'Core', () => { } ); - QUnit.test( "addGroup", ( assert ) => { + QUnit.test( 'addGroup', ( assert ) => { var a = new BufferGeometry(); var expected = [ @@ -167,19 +167,19 @@ export default QUnit.module( 'Core', () => { a.addGroup( 0, 1, 0 ); a.addGroup( 1, 2, 2 ); - assert.deepEqual( a.groups, expected, "Check groups were stored correctly and in order" ); + assert.deepEqual( a.groups, expected, 'Check groups were stored correctly and in order' ); a.clearGroups(); - assert.strictEqual( a.groups.length, 0, "Check groups were deleted correctly" ); + assert.strictEqual( a.groups.length, 0, 'Check groups were deleted correctly' ); } ); - QUnit.todo( "clearGroups", ( assert ) => { + QUnit.todo( 'clearGroups', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "setDrawRange", ( assert ) => { + QUnit.test( 'setDrawRange', ( assert ) => { var a = new BufferGeometry(); @@ -188,14 +188,14 @@ export default QUnit.module( 'Core', () => { assert.deepEqual( a.drawRange, { start: 1, count: 7 - }, "Check draw range was stored correctly" ); + }, 'Check draw range was stored correctly' ); } ); - QUnit.test( "applyMatrix4", ( assert ) => { + QUnit.test( 'applyMatrix4', ( assert ) => { var geometry = new BufferGeometry(); - geometry.setAttribute( "position", new BufferAttribute( new Float32Array( 6 ), 3 ) ); + geometry.setAttribute( 'position', new BufferAttribute( new Float32Array( 6 ), 3 ) ); var matrix = new Matrix4().set( 1, 0, 0, 1.5, @@ -207,16 +207,16 @@ export default QUnit.module( 'Core', () => { var position = geometry.attributes.position.array; var m = matrix.elements; - assert.ok( position[ 0 ] === m[ 12 ] && position[ 1 ] === m[ 13 ] && position[ 2 ] === m[ 14 ], "position was extracted from matrix" ); - assert.ok( position[ 3 ] === m[ 12 ] && position[ 4 ] === m[ 13 ] && position[ 5 ] === m[ 14 ], "position was extracted from matrix twice" ); - assert.ok( geometry.attributes.position.version === 1, "version was increased during update" ); + assert.ok( position[ 0 ] === m[ 12 ] && position[ 1 ] === m[ 13 ] && position[ 2 ] === m[ 14 ], 'position was extracted from matrix' ); + assert.ok( position[ 3 ] === m[ 12 ] && position[ 4 ] === m[ 13 ] && position[ 5 ] === m[ 14 ], 'position was extracted from matrix twice' ); + assert.ok( geometry.attributes.position.version === 1, 'version was increased during update' ); } ); - QUnit.test( "applyQuaternion", ( assert ) => { + QUnit.test( 'applyQuaternion', ( assert ) => { var geometry = new BufferGeometry(); - geometry.setAttribute( "position", new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3 ) ); + geometry.setAttribute( 'position', new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3 ) ); var q = new Quaternion( 0.5, 0.5, 0.5, 0.5 ); geometry.applyQuaternion( q ); @@ -225,13 +225,14 @@ export default QUnit.module( 'Core', () => { // geometry was rotated around the (1, 1, 1) axis. assert.ok( pos[ 0 ] === 3 && pos[ 1 ] === 1 && pos[ 2 ] === 2 && - pos[ 3 ] === 6 && pos[ 4 ] === 4 && pos[ 5 ] === 5, "vertices were rotated properly" ); + pos[ 3 ] === 6 && pos[ 4 ] === 4 && pos[ 5 ] === 5, 'vertices were rotated properly' ); + } ); - QUnit.test( "rotateX/Y/Z", ( assert ) => { + QUnit.test( 'rotateX/Y/Z', ( assert ) => { var geometry = new BufferGeometry(); - geometry.setAttribute( "position", new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3 ) ); + geometry.setAttribute( 'position', new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3 ) ); var pos = geometry.attributes.position.array; @@ -239,51 +240,51 @@ export default QUnit.module( 'Core', () => { // object was rotated around x so all items should be flipped but the x ones assert.ok( pos[ 0 ] === 1 && pos[ 1 ] === - 2 && pos[ 2 ] === - 3 && - pos[ 3 ] === 4 && pos[ 4 ] === - 5 && pos[ 5 ] === - 6, "vertices were rotated around x by 180 degrees" ); + pos[ 3 ] === 4 && pos[ 4 ] === - 5 && pos[ 5 ] === - 6, 'vertices were rotated around x by 180 degrees' ); geometry.rotateY( 180 * DegToRad ); // vertices were rotated around y so all items should be flipped again but the y ones assert.ok( pos[ 0 ] === - 1 && pos[ 1 ] === - 2 && pos[ 2 ] === 3 && - pos[ 3 ] === - 4 && pos[ 4 ] === - 5 && pos[ 5 ] === 6, "vertices were rotated around y by 180 degrees" ); + pos[ 3 ] === - 4 && pos[ 4 ] === - 5 && pos[ 5 ] === 6, 'vertices were rotated around y by 180 degrees' ); geometry.rotateZ( 180 * DegToRad ); // vertices were rotated around z so all items should be flipped again but the z ones assert.ok( pos[ 0 ] === 1 && pos[ 1 ] === 2 && pos[ 2 ] === 3 && - pos[ 3 ] === 4 && pos[ 4 ] === 5 && pos[ 5 ] === 6, "vertices were rotated around z by 180 degrees" ); + pos[ 3 ] === 4 && pos[ 4 ] === 5 && pos[ 5 ] === 6, 'vertices were rotated around z by 180 degrees' ); } ); - QUnit.test( "translate", ( assert ) => { + QUnit.test( 'translate', ( assert ) => { var geometry = new BufferGeometry(); - geometry.setAttribute( "position", new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3 ) ); + geometry.setAttribute( 'position', new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3 ) ); var pos = geometry.attributes.position.array; geometry.translate( 10, 20, 30 ); assert.ok( pos[ 0 ] === 11 && pos[ 1 ] === 22 && pos[ 2 ] === 33 && - pos[ 3 ] === 14 && pos[ 4 ] === 25 && pos[ 5 ] === 36, "vertices were translated" ); + pos[ 3 ] === 14 && pos[ 4 ] === 25 && pos[ 5 ] === 36, 'vertices were translated' ); } ); - QUnit.test( "scale", ( assert ) => { + QUnit.test( 'scale', ( assert ) => { var geometry = new BufferGeometry(); - geometry.setAttribute( "position", new BufferAttribute( new Float32Array( [ - 1, - 1, - 1, 2, 2, 2 ] ), 3 ) ); + geometry.setAttribute( 'position', new BufferAttribute( new Float32Array( [ - 1, - 1, - 1, 2, 2, 2 ] ), 3 ) ); var pos = geometry.attributes.position.array; geometry.scale( 1, 2, 3 ); assert.ok( pos[ 0 ] === - 1 && pos[ 1 ] === - 2 && pos[ 2 ] === - 3 && - pos[ 3 ] === 2 && pos[ 4 ] === 4 && pos[ 5 ] === 6, "vertices were scaled" ); + pos[ 3 ] === 2 && pos[ 4 ] === 4 && pos[ 5 ] === 6, 'vertices were scaled' ); } ); - QUnit.test( "lookAt", ( assert ) => { + QUnit.test( 'lookAt', ( assert ) => { var a = new BufferGeometry(); var vertices = new Float32Array( [ @@ -310,14 +311,14 @@ export default QUnit.module( 'Core', () => { a.lookAt( new Vector3( 0, 1, - 1 ) ); - assert.ok( bufferAttributeEquals( a.attributes.position.array, expected ), "Rotation is correct" ); + assert.ok( bufferAttributeEquals( a.attributes.position.array, expected ), 'Rotation is correct' ); } ); - QUnit.test( "center", ( assert ) => { + QUnit.test( 'center', ( assert ) => { var geometry = new BufferGeometry(); - geometry.setAttribute( "position", new BufferAttribute( new Float32Array( [ + geometry.setAttribute( 'position', new BufferAttribute( new Float32Array( [ - 1, - 1, - 1, 1, 1, 1, 4, 4, 4 @@ -331,64 +332,64 @@ export default QUnit.module( 'Core', () => { // after centering it the vertices should be placed between (-2.5, -2.5, -2.5) and (2.5, 2.5, 2.5) assert.ok( pos[ 0 ] === - 2.5 && pos[ 1 ] === - 2.5 && pos[ 2 ] === - 2.5 && pos[ 3 ] === - 0.5 && pos[ 4 ] === - 0.5 && pos[ 5 ] === - 0.5 && - pos[ 6 ] === 2.5 && pos[ 7 ] === 2.5 && pos[ 8 ] === 2.5, "vertices were replaced by boundingBox dimensions" ); + pos[ 6 ] === 2.5 && pos[ 7 ] === 2.5 && pos[ 8 ] === 2.5, 'vertices were replaced by boundingBox dimensions' ); } ); - QUnit.test( "computeBoundingBox", ( assert ) => { + QUnit.test( 'computeBoundingBox', ( assert ) => { var bb = getBBForVertices( [ - 1, - 2, - 3, 13, - 2, - 3.5, - 1, - 20, 0, - 4, 5, 6 ] ); - assert.ok( bb.min.x === - 4 && bb.min.y === - 20 && bb.min.z === - 3.5, "min values are set correctly" ); - assert.ok( bb.max.x === 13 && bb.max.y === 5 && bb.max.z === 6, "max values are set correctly" ); + assert.ok( bb.min.x === - 4 && bb.min.y === - 20 && bb.min.z === - 3.5, 'min values are set correctly' ); + assert.ok( bb.max.x === 13 && bb.max.y === 5 && bb.max.z === 6, 'max values are set correctly' ); var bb = getBBForVertices( [ - 1, - 1, - 1 ] ); - assert.ok( bb.min.x === bb.max.x && bb.min.y === bb.max.y && bb.min.z === bb.max.z, "since there is only one vertex, max and min are equal" ); - assert.ok( bb.min.x === - 1 && bb.min.y === - 1 && bb.min.z === - 1, "since there is only one vertex, min and max are this vertex" ); + assert.ok( bb.min.x === bb.max.x && bb.min.y === bb.max.y && bb.min.z === bb.max.z, 'since there is only one vertex, max and min are equal' ); + assert.ok( bb.min.x === - 1 && bb.min.y === - 1 && bb.min.z === - 1, 'since there is only one vertex, min and max are this vertex' ); } ); - QUnit.test( "computeBoundingSphere", ( assert ) => { + QUnit.test( 'computeBoundingSphere', ( assert ) => { var bs = getBSForVertices( [ - 10, 0, 0, 10, 0, 0 ] ); - assert.ok( bs.radius === ( 10 + 10 ) / 2, "radius is equal to deltaMinMax / 2" ); - assert.ok( bs.center.x === 0 && bs.center.y === 0 && bs.center.y === 0, "bounding sphere is at ( 0, 0, 0 )" ); + assert.ok( bs.radius === ( 10 + 10 ) / 2, 'radius is equal to deltaMinMax / 2' ); + assert.ok( bs.center.x === 0 && bs.center.y === 0 && bs.center.y === 0, 'bounding sphere is at ( 0, 0, 0 )' ); var bs = getBSForVertices( [ - 5, 11, - 3, 5, - 11, 3 ] ); var radius = new Vector3( 5, 11, 3 ).length(); - assert.ok( bs.radius === radius, "radius is equal to directionLength" ); - assert.ok( bs.center.x === 0 && bs.center.y === 0 && bs.center.y === 0, "bounding sphere is at ( 0, 0, 0 )" ); + assert.ok( bs.radius === radius, 'radius is equal to directionLength' ); + assert.ok( bs.center.x === 0 && bs.center.y === 0 && bs.center.y === 0, 'bounding sphere is at ( 0, 0, 0 )' ); } ); - QUnit.test( "computeVertexNormals", ( assert ) => { + QUnit.test( 'computeVertexNormals', ( assert ) => { // get normals for a counter clockwise created triangle var normals = getNormalsForVertices( [ - 1, 0, 0, 1, 0, 0, 0, 1, 0 ], assert ); assert.ok( normals[ 0 ] === 0 && normals[ 1 ] === 0 && normals[ 2 ] === 1, - "first normal is pointing to screen since the the triangle was created counter clockwise" ); + 'first normal is pointing to screen since the the triangle was created counter clockwise' ); assert.ok( normals[ 3 ] === 0 && normals[ 4 ] === 0 && normals[ 5 ] === 1, - "second normal is pointing to screen since the the triangle was created counter clockwise" ); + 'second normal is pointing to screen since the the triangle was created counter clockwise' ); assert.ok( normals[ 6 ] === 0 && normals[ 7 ] === 0 && normals[ 8 ] === 1, - "third normal is pointing to screen since the the triangle was created counter clockwise" ); + 'third normal is pointing to screen since the the triangle was created counter clockwise' ); // get normals for a clockwise created triangle var normals = getNormalsForVertices( [ 1, 0, 0, - 1, 0, 0, 0, 1, 0 ], assert ); assert.ok( normals[ 0 ] === 0 && normals[ 1 ] === 0 && normals[ 2 ] === - 1, - "first normal is pointing to screen since the the triangle was created clockwise" ); + 'first normal is pointing to screen since the the triangle was created clockwise' ); assert.ok( normals[ 3 ] === 0 && normals[ 4 ] === 0 && normals[ 5 ] === - 1, - "second normal is pointing to screen since the the triangle was created clockwise" ); + 'second normal is pointing to screen since the the triangle was created clockwise' ); assert.ok( normals[ 6 ] === 0 && normals[ 7 ] === 0 && normals[ 8 ] === - 1, - "third normal is pointing to screen since the the triangle was created clockwise" ); + 'third normal is pointing to screen since the the triangle was created clockwise' ); var normals = getNormalsForVertices( [ 0, 0, 1, 0, 0, - 1, 1, 1, 0 ], assert ); @@ -400,18 +401,18 @@ export default QUnit.module( 'Core', () => { // which can be taken from Number.EPSILON var direction = new Vector3( 1, 1, 0 ).normalize(); // a vector which should have 90 degrees difference to normals var difference = direction.dot( new Vector3( normals[ 0 ], normals[ 1 ], normals[ 2 ] ) ); - assert.ok( difference < Number.EPSILON, "normal is equal to reference vector" ); + assert.ok( difference < Number.EPSILON, 'normal is equal to reference vector' ); // get normals for a line should be NAN because you need min a triangle to calculate normals var normals = getNormalsForVertices( [ 1, 0, 0, - 1, 0, 0 ], assert ); for ( var i = 0; i < normals.length; i ++ ) { - assert.ok( ! normals[ i ], "normals can't be calculated which is good" ); + assert.ok( ! normals[ i ], 'normals can\'t be calculated which is good' ); } } ); - QUnit.test( "computeVertexNormals (indexed)", ( assert ) => { + QUnit.test( 'computeVertexNormals (indexed)', ( assert ) => { var sqrt = 0.5 * Math.sqrt( 2 ); var normal = new BufferAttribute( new Float32Array( [ @@ -429,36 +430,36 @@ export default QUnit.module( 'Core', () => { ] ), 1 ); var a = new BufferGeometry(); - a.setAttribute( "position", position ); + a.setAttribute( 'position', position ); a.computeVertexNormals(); assert.ok( - bufferAttributeEquals( normal, a.getAttribute( "normal" ) ), - "Regular geometry: first computed normals are correct" + bufferAttributeEquals( normal, a.getAttribute( 'normal' ) ), + 'Regular geometry: first computed normals are correct' ); // a second time to see if the existing normals get properly deleted a.computeVertexNormals(); assert.ok( - bufferAttributeEquals( normal, a.getAttribute( "normal" ) ), - "Regular geometry: second computed normals are correct" + bufferAttributeEquals( normal, a.getAttribute( 'normal' ) ), + 'Regular geometry: second computed normals are correct' ); // indexed geometry var a = new BufferGeometry(); - a.setAttribute( "position", position ); + a.setAttribute( 'position', position ); a.setIndex( index ); a.computeVertexNormals(); - assert.ok( bufferAttributeEquals( normal, a.getAttribute( "normal" ) ), "Indexed geometry: computed normals are correct" ); + assert.ok( bufferAttributeEquals( normal, a.getAttribute( 'normal' ) ), 'Indexed geometry: computed normals are correct' ); } ); - QUnit.test( "merge", ( assert ) => { + QUnit.test( 'merge', ( assert ) => { var geometry1 = new BufferGeometry(); - geometry1.setAttribute( "attrName", new BufferAttribute( new Float32Array( [ 1, 2, 3, 0, 0, 0 ] ), 3 ) ); + geometry1.setAttribute( 'attrName', new BufferAttribute( new Float32Array( [ 1, 2, 3, 0, 0, 0 ] ), 3 ) ); var geometry2 = new BufferGeometry(); - geometry2.setAttribute( "attrName", new BufferAttribute( new Float32Array( [ 4, 5, 6 ] ), 3 ) ); + geometry2.setAttribute( 'attrName', new BufferAttribute( new Float32Array( [ 4, 5, 6 ] ), 3 ) ); var attr = geometry1.attributes.attrName.array; @@ -467,7 +468,7 @@ export default QUnit.module( 'Core', () => { // merged array should be 1, 2, 3, 4, 5, 6 for ( var i = 0; i < attr.length; i ++ ) { - assert.ok( attr[ i ] === i + 1, "" ); + assert.ok( attr[ i ] === i + 1, '' ); } @@ -475,17 +476,17 @@ export default QUnit.module( 'Core', () => { geometry1.merge( geometry2 ); console.level = CONSOLE_LEVEL.DEFAULT; - assert.ok( attr[ 0 ] === 4 && attr[ 1 ] === 5 && attr[ 2 ] === 6, "copied the 3 attributes without offset" ); + assert.ok( attr[ 0 ] === 4 && attr[ 1 ] === 5 && attr[ 2 ] === 6, 'copied the 3 attributes without offset' ); } ); - QUnit.todo( "normalizeNormals", ( assert ) => { + QUnit.todo( 'normalizeNormals', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "toNonIndexed", ( assert ) => { + QUnit.test( 'toNonIndexed', ( assert ) => { var geometry = new BufferGeometry(); var vertices = new Float32Array( [ @@ -502,136 +503,136 @@ export default QUnit.module( 'Core', () => { var nonIndexed = geometry.toNonIndexed(); - assert.deepEqual( nonIndexed.getAttribute( "position" ).array, expected, "Expected vertices" ); + assert.deepEqual( nonIndexed.getAttribute( 'position' ).array, expected, 'Expected vertices' ); } ); - QUnit.test( "toJSON", ( assert ) => { + QUnit.test( 'toJSON', ( assert ) => { var index = new BufferAttribute( new Uint16Array( [ 0, 1, 2, 3 ] ), 1 ); var attribute1 = new BufferAttribute( new Uint16Array( [ 1, 3, 5, 7 ] ), 1 ); - attribute1.name = "attribute1"; + attribute1.name = 'attribute1'; var a = new BufferGeometry(); - a.name = "JSONQUnit.test"; + a.name = 'JSONQUnit.test'; // a.parameters = { "placeholder": 0 }; - a.setAttribute( "attribute1", attribute1 ); + a.setAttribute( 'attribute1', attribute1 ); a.setIndex( index ); a.addGroup( 0, 1, 2 ); a.boundingSphere = new Sphere( new Vector3( x, y, z ), 0.5 ); var j = a.toJSON(); var gold = { - "metadata": { - "version": 4.5, - "type": "BufferGeometry", - "generator": "BufferGeometry.toJSON" + 'metadata': { + 'version': 4.5, + 'type': 'BufferGeometry', + 'generator': 'BufferGeometry.toJSON' }, - "uuid": a.uuid, - "type": "BufferGeometry", - "name": "JSONQUnit.test", - "data": { - "attributes": { - "attribute1": { - "itemSize": 1, - "type": "Uint16Array", - "array": [ 1, 3, 5, 7 ], - "normalized": false, - "name": "attribute1" + 'uuid': a.uuid, + 'type': 'BufferGeometry', + 'name': 'JSONQUnit.test', + 'data': { + 'attributes': { + 'attribute1': { + 'itemSize': 1, + 'type': 'Uint16Array', + 'array': [ 1, 3, 5, 7 ], + 'normalized': false, + 'name': 'attribute1' } }, - "index": { - "type": "Uint16Array", - "array": [ 0, 1, 2, 3 ] + 'index': { + 'type': 'Uint16Array', + 'array': [ 0, 1, 2, 3 ] }, - "groups": [ + 'groups': [ { - "start": 0, - "count": 1, - "materialIndex": 2 + 'start': 0, + 'count': 1, + 'materialIndex': 2 } ], - "boundingSphere": { - "center": [ 2, 3, 4 ], - "radius": 0.5 + 'boundingSphere': { + 'center': [ 2, 3, 4 ], + 'radius': 0.5 } } }; - assert.deepEqual( j, gold, "Generated JSON is as expected" ); + assert.deepEqual( j, gold, 'Generated JSON is as expected' ); // add morphAttributes a.morphAttributes.attribute1 = []; a.morphAttributes.attribute1.push( attribute1.clone() ); j = a.toJSON(); gold.data.morphAttributes = { - "attribute1": [ { - "itemSize": 1, - "type": "Uint16Array", - "array": [ 1, 3, 5, 7 ], - "normalized": false, - "name": "attribute1" + 'attribute1': [ { + 'itemSize': 1, + 'type': 'Uint16Array', + 'array': [ 1, 3, 5, 7 ], + 'normalized': false, + 'name': 'attribute1' } ] }; gold.data.morphTargetsRelative = false; - assert.deepEqual( j, gold, "Generated JSON with morphAttributes is as expected" ); + assert.deepEqual( j, gold, 'Generated JSON with morphAttributes is as expected' ); } ); - QUnit.test( "clone", ( assert ) => { + QUnit.test( 'clone', ( assert ) => { var a = new BufferGeometry(); - a.setAttribute( "attribute1", new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3 ) ); - a.setAttribute( "attribute2", new BufferAttribute( new Float32Array( [ 0, 1, 3, 5, 6 ] ), 1 ) ); + a.setAttribute( 'attribute1', new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3 ) ); + a.setAttribute( 'attribute2', new BufferAttribute( new Float32Array( [ 0, 1, 3, 5, 6 ] ), 1 ) ); a.addGroup( 0, 1, 2 ); a.computeBoundingBox(); a.computeBoundingSphere(); a.setDrawRange( 0, 1 ); var b = a.clone(); - assert.notEqual( a, b, "A new object was created" ); - assert.notEqual( a.id, b.id, "New object has a different GUID" ); + assert.notEqual( a, b, 'A new object was created' ); + assert.notEqual( a.id, b.id, 'New object has a different GUID' ); assert.strictEqual( Object.keys( a.attributes ).count, Object.keys( b.attributes ).count, - "Both objects have the same amount of attributes" + 'Both objects have the same amount of attributes' ); assert.ok( - bufferAttributeEquals( a.getAttribute( "attribute1" ), b.getAttribute( "attribute1" ) ), - "First attributes buffer is identical" + bufferAttributeEquals( a.getAttribute( 'attribute1' ), b.getAttribute( 'attribute1' ) ), + 'First attributes buffer is identical' ); assert.ok( - bufferAttributeEquals( a.getAttribute( "attribute2" ), b.getAttribute( "attribute2" ) ), - "Second attributes buffer is identical" + bufferAttributeEquals( a.getAttribute( 'attribute2' ), b.getAttribute( 'attribute2' ) ), + 'Second attributes buffer is identical' ); - assert.deepEqual( a.groups, b.groups, "Groups are identical" ); + assert.deepEqual( a.groups, b.groups, 'Groups are identical' ); - assert.ok( a.boundingBox.equals( b.boundingBox ), "BoundingBoxes are equal" ); - assert.ok( a.boundingSphere.equals( b.boundingSphere ), "BoundingSpheres are equal" ); + assert.ok( a.boundingBox.equals( b.boundingBox ), 'BoundingBoxes are equal' ); + assert.ok( a.boundingSphere.equals( b.boundingSphere ), 'BoundingSpheres are equal' ); - assert.strictEqual( a.drawRange.start, b.drawRange.start, "DrawRange start is identical" ); - assert.strictEqual( a.drawRange.count, b.drawRange.count, "DrawRange count is identical" ); + assert.strictEqual( a.drawRange.start, b.drawRange.start, 'DrawRange start is identical' ); + assert.strictEqual( a.drawRange.count, b.drawRange.count, 'DrawRange count is identical' ); } ); - QUnit.test( "copy", ( assert ) => { + QUnit.test( 'copy', ( assert ) => { var geometry = new BufferGeometry(); - geometry.setAttribute( "attrName", new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3 ) ); - geometry.setAttribute( "attrName2", new BufferAttribute( new Float32Array( [ 0, 1, 3, 5, 6 ] ), 1 ) ); + geometry.setAttribute( 'attrName', new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3 ) ); + geometry.setAttribute( 'attrName2', new BufferAttribute( new Float32Array( [ 0, 1, 3, 5, 6 ] ), 1 ) ); var copy = new BufferGeometry().copy( geometry ); - assert.ok( copy !== geometry && geometry.id !== copy.id, "new object was created" ); + assert.ok( copy !== geometry && geometry.id !== copy.id, 'new object was created' ); Object.keys( geometry.attributes ).forEach( function ( key ) { var attribute = geometry.attributes[ key ]; - assert.ok( attribute !== undefined, "all attributes where copied" ); + assert.ok( attribute !== undefined, 'all attributes where copied' ); for ( var i = 0; i < attribute.array.length; i ++ ) { - assert.ok( attribute.array[ i ] === copy.attributes[ key ].array[ i ], "values of the attribute are equal" ); + assert.ok( attribute.array[ i ] === copy.attributes[ key ].array[ i ], 'values of the attribute are equal' ); } @@ -639,9 +640,9 @@ export default QUnit.module( 'Core', () => { } ); - QUnit.todo( "dispose", ( assert ) => { + QUnit.todo( 'dispose', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/core/EventDispatcher.tests.js b/test/unit/src/core/EventDispatcher.tests.js index 8fba152628d836..d64c94955791fb 100644 --- a/test/unit/src/core/EventDispatcher.tests.js +++ b/test/unit/src/core/EventDispatcher.tests.js @@ -7,66 +7,66 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'EventDispatcher', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.test( "addEventListener", ( assert ) => { + QUnit.test( 'addEventListener', ( assert ) => { var eventDispatcher = new EventDispatcher(); var listener = {}; eventDispatcher.addEventListener( 'anyType', listener ); - assert.ok( eventDispatcher._listeners.anyType.length === 1, "listener with unknown type was added" ); - assert.ok( eventDispatcher._listeners.anyType[ 0 ] === listener, "listener with unknown type was added" ); + assert.ok( eventDispatcher._listeners.anyType.length === 1, 'listener with unknown type was added' ); + assert.ok( eventDispatcher._listeners.anyType[ 0 ] === listener, 'listener with unknown type was added' ); eventDispatcher.addEventListener( 'anyType', listener ); - assert.ok( eventDispatcher._listeners.anyType.length === 1, "can't add one listener twice to same type" ); - assert.ok( eventDispatcher._listeners.anyType[ 0 ] === listener, "listener is still there" ); + assert.ok( eventDispatcher._listeners.anyType.length === 1, 'can\'t add one listener twice to same type' ); + assert.ok( eventDispatcher._listeners.anyType[ 0 ] === listener, 'listener is still there' ); } ); - QUnit.test( "hasEventListener", ( assert ) => { + QUnit.test( 'hasEventListener', ( assert ) => { var eventDispatcher = new EventDispatcher(); var listener = {}; eventDispatcher.addEventListener( 'anyType', listener ); - assert.ok( eventDispatcher.hasEventListener( 'anyType', listener ), "listener was found" ); - assert.ok( ! eventDispatcher.hasEventListener( 'anotherType', listener ), "listener was not found which is good" ); + assert.ok( eventDispatcher.hasEventListener( 'anyType', listener ), 'listener was found' ); + assert.ok( ! eventDispatcher.hasEventListener( 'anotherType', listener ), 'listener was not found which is good' ); } ); - QUnit.test( "removeEventListener", ( assert ) => { + QUnit.test( 'removeEventListener', ( assert ) => { var eventDispatcher = new EventDispatcher(); var listener = {}; - assert.ok( eventDispatcher._listeners === undefined, "there are no listeners by default" ); + assert.ok( eventDispatcher._listeners === undefined, 'there are no listeners by default' ); eventDispatcher.addEventListener( 'anyType', listener ); assert.ok( Object.keys( eventDispatcher._listeners ).length === 1 && - eventDispatcher._listeners.anyType.length === 1, "if a listener was added, there is a new key" ); + eventDispatcher._listeners.anyType.length === 1, 'if a listener was added, there is a new key' ); eventDispatcher.removeEventListener( 'anyType', listener ); - assert.ok( eventDispatcher._listeners.anyType.length === 0, "listener was deleted" ); + assert.ok( eventDispatcher._listeners.anyType.length === 0, 'listener was deleted' ); eventDispatcher.removeEventListener( 'unknownType', listener ); - assert.ok( eventDispatcher._listeners.unknownType === undefined, "unknown types will be ignored" ); + assert.ok( eventDispatcher._listeners.unknownType === undefined, 'unknown types will be ignored' ); eventDispatcher.removeEventListener( 'anyType', undefined ); - assert.ok( eventDispatcher._listeners.anyType.length === 0, "undefined listeners are ignored" ); + assert.ok( eventDispatcher._listeners.anyType.length === 0, 'undefined listeners are ignored' ); } ); - QUnit.test( "dispatchEvent", ( assert ) => { + QUnit.test( 'dispatchEvent', ( assert ) => { var eventDispatcher = new EventDispatcher(); @@ -78,13 +78,13 @@ export default QUnit.module( 'Core', () => { }; eventDispatcher.addEventListener( 'anyType', listener ); - assert.ok( callCount === 0, "no event, no call" ); + assert.ok( callCount === 0, 'no event, no call' ); eventDispatcher.dispatchEvent( { type: 'anyType' } ); - assert.ok( callCount === 1, "one event, one call" ); + assert.ok( callCount === 1, 'one event, one call' ); eventDispatcher.dispatchEvent( { type: 'anyType' } ); - assert.ok( callCount === 2, "two events, two calls" ); + assert.ok( callCount === 2, 'two events, two calls' ); } ); diff --git a/test/unit/src/core/InstancedBufferAttribute.tests.js b/test/unit/src/core/InstancedBufferAttribute.tests.js index 678db95f485d2a..70b5c0ae98d988 100644 --- a/test/unit/src/core/InstancedBufferAttribute.tests.js +++ b/test/unit/src/core/InstancedBufferAttribute.tests.js @@ -7,38 +7,38 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'InstancedBufferAttribute', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.test( "Instancing", ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { var instance = new InstancedBufferAttribute( new Float32Array( 10 ), 2 ); - assert.ok( instance.meshPerAttribute === 1, "ok" ); + assert.ok( instance.meshPerAttribute === 1, 'ok' ); var instance = new InstancedBufferAttribute( new Float32Array( 10 ), 2, false, 123 ); - assert.ok( instance.meshPerAttribute === 123, "ok" ); + assert.ok( instance.meshPerAttribute === 123, 'ok' ); } ); // PUBLIC STUFF - QUnit.test( "copy", ( assert ) => { + QUnit.test( 'copy', ( assert ) => { var array = new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ); var instance = new InstancedBufferAttribute( array, 2, true, 123 ); var copiedInstance = instance.copy( instance ); - assert.ok( copiedInstance instanceof InstancedBufferAttribute, "the clone has the correct type" ); - assert.ok( copiedInstance.itemSize === 2, "itemSize was copied" ); - assert.ok( copiedInstance.normalized === true, "normalized was copied" ); - assert.ok( copiedInstance.meshPerAttribute === 123, "meshPerAttribute was copied" ); + assert.ok( copiedInstance instanceof InstancedBufferAttribute, 'the clone has the correct type' ); + assert.ok( copiedInstance.itemSize === 2, 'itemSize was copied' ); + assert.ok( copiedInstance.normalized === true, 'normalized was copied' ); + assert.ok( copiedInstance.meshPerAttribute === 123, 'meshPerAttribute was copied' ); for ( var i = 0; i < array.length; i ++ ) { - assert.ok( copiedInstance.array[ i ] === array[ i ], "array was copied" ); + assert.ok( copiedInstance.array[ i ] === array[ i ], 'array was copied' ); } diff --git a/test/unit/src/core/InstancedBufferGeometry.tests.js b/test/unit/src/core/InstancedBufferGeometry.tests.js index f08b65d7357ea3..231a511dd5e0ef 100644 --- a/test/unit/src/core/InstancedBufferGeometry.tests.js +++ b/test/unit/src/core/InstancedBufferGeometry.tests.js @@ -22,21 +22,21 @@ export default QUnit.module( 'Core', () => { } // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.test( "copy", ( assert ) => { + QUnit.test( 'copy', ( assert ) => { var instanceMock1 = {}; var instanceMock2 = {}; @@ -54,28 +54,28 @@ export default QUnit.module( 'Core', () => { var copiedInstance = new InstancedBufferGeometry().copy( instance ); - assert.ok( copiedInstance instanceof InstancedBufferGeometry, "the clone has the correct type" ); + assert.ok( copiedInstance instanceof InstancedBufferGeometry, 'the clone has the correct type' ); - assert.equal( copiedInstance.index, indexMock, "index was copied" ); - assert.equal( copiedInstance.index.callCount, 1, "index.clone was called once" ); + assert.equal( copiedInstance.index, indexMock, 'index was copied' ); + assert.equal( copiedInstance.index.callCount, 1, 'index.clone was called once' ); - assert.ok( copiedInstance.attributes[ 'defaultAttribute1' ] instanceof BufferAttribute, "attribute was created" ); - assert.deepEqual( copiedInstance.attributes[ 'defaultAttribute1' ].array, defaultAttribute1.array, "attribute was copied" ); - assert.deepEqual( copiedInstance.attributes[ 'defaultAttribute2' ].array, defaultAttribute2.array, "attribute was copied" ); + assert.ok( copiedInstance.attributes[ 'defaultAttribute1' ] instanceof BufferAttribute, 'attribute was created' ); + assert.deepEqual( copiedInstance.attributes[ 'defaultAttribute1' ].array, defaultAttribute1.array, 'attribute was copied' ); + assert.deepEqual( copiedInstance.attributes[ 'defaultAttribute2' ].array, defaultAttribute2.array, 'attribute was copied' ); - assert.equal( copiedInstance.groups[ 0 ].start, 0, "group was copied" ); - assert.equal( copiedInstance.groups[ 0 ].count, 10, "group was copied" ); - assert.equal( copiedInstance.groups[ 0 ].materialIndex, instanceMock1, "group was copied" ); + assert.equal( copiedInstance.groups[ 0 ].start, 0, 'group was copied' ); + assert.equal( copiedInstance.groups[ 0 ].count, 10, 'group was copied' ); + assert.equal( copiedInstance.groups[ 0 ].materialIndex, instanceMock1, 'group was copied' ); - assert.equal( copiedInstance.groups[ 1 ].start, 10, "group was copied" ); - assert.equal( copiedInstance.groups[ 1 ].count, 5, "group was copied" ); - assert.equal( copiedInstance.groups[ 1 ].materialIndex, instanceMock2, "group was copied" ); + assert.equal( copiedInstance.groups[ 1 ].start, 10, 'group was copied' ); + assert.equal( copiedInstance.groups[ 1 ].count, 5, 'group was copied' ); + assert.equal( copiedInstance.groups[ 1 ].materialIndex, instanceMock2, 'group was copied' ); } ); - QUnit.todo( "clone", ( assert ) => { + QUnit.todo( 'clone', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/core/InstancedInterleavedBuffer.tests.js b/test/unit/src/core/InstancedInterleavedBuffer.tests.js index 847f971f72ed71..5524bfe1e94bdb 100644 --- a/test/unit/src/core/InstancedInterleavedBuffer.tests.js +++ b/test/unit/src/core/InstancedInterleavedBuffer.tests.js @@ -7,36 +7,36 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'InstancedInterleavedBuffer', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.test( "Instancing", ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { var array = new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ); var instance = new InstancedInterleavedBuffer( array, 3 ); - assert.ok( instance.meshPerAttribute === 1, "ok" ); + assert.ok( instance.meshPerAttribute === 1, 'ok' ); } ); // PUBLIC STUFF - QUnit.todo( "isInstancedInterleavedBuffer", ( assert ) => { + QUnit.todo( 'isInstancedInterleavedBuffer', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "copy", ( assert ) => { + QUnit.test( 'copy', ( assert ) => { var array = new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ); var instance = new InstancedInterleavedBuffer( array, 3 ); var copiedInstance = instance.copy( instance ); - assert.ok( copiedInstance.meshPerAttribute === 1, "additional attribute was copied" ); + assert.ok( copiedInstance.meshPerAttribute === 1, 'additional attribute was copied' ); } ); diff --git a/test/unit/src/core/InterleavedBuffer.tests.js b/test/unit/src/core/InterleavedBuffer.tests.js index ebee224e96f8a2..107deb981d1a47 100644 --- a/test/unit/src/core/InterleavedBuffer.tests.js +++ b/test/unit/src/core/InterleavedBuffer.tests.js @@ -9,54 +9,54 @@ export default QUnit.module( 'Core', () => { function checkInstanceAgainstCopy( instance, copiedInstance, assert ) { - assert.ok( copiedInstance instanceof InterleavedBuffer, "the clone has the correct type" ); + assert.ok( copiedInstance instanceof InterleavedBuffer, 'the clone has the correct type' ); for ( var i = 0; i < instance.array.length; i ++ ) { - assert.ok( copiedInstance.array[ i ] === instance.array[ i ], "array was copied" ); + assert.ok( copiedInstance.array[ i ] === instance.array[ i ], 'array was copied' ); } - assert.ok( copiedInstance.stride === instance.stride, "stride was copied" ); - assert.ok( copiedInstance.usage === DynamicDrawUsage, "usage was copied" ); + assert.ok( copiedInstance.stride === instance.stride, 'stride was copied' ); + assert.ok( copiedInstance.usage === DynamicDrawUsage, 'usage was copied' ); } // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PROPERTIES - QUnit.test( "needsUpdate", ( assert ) => { + QUnit.test( 'needsUpdate', ( assert ) => { var a = new InterleavedBuffer( new Float32Array( [ 1, 2, 3, 4 ] ), 2 ); a.needsUpdate = true; - assert.strictEqual( a.version, 1, "Check version increased" ); + assert.strictEqual( a.version, 1, 'Check version increased' ); } ); // PUBLIC STUFF - QUnit.todo( "isInterleavedBuffer", ( assert ) => { + QUnit.todo( 'isInterleavedBuffer', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "setUsage", ( assert ) => { + QUnit.test( 'setUsage', ( assert ) => { var instance = new InterleavedBuffer(); instance.setUsage( DynamicDrawUsage ); - assert.strictEqual( instance.usage, DynamicDrawUsage, "Usage was set" ); + assert.strictEqual( instance.usage, DynamicDrawUsage, 'Usage was set' ); } ); - QUnit.test( "copy", ( assert ) => { + QUnit.test( 'copy', ( assert ) => { var array = new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ); var instance = new InterleavedBuffer( array, 3 ); @@ -66,7 +66,7 @@ export default QUnit.module( 'Core', () => { } ); - QUnit.test( "copyAt", ( assert ) => { + QUnit.test( 'copyAt', ( assert ) => { var a = new InterleavedBuffer( new Float32Array( [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] ), 3 ); var b = new InterleavedBuffer( new Float32Array( 9 ), 3 ); @@ -76,36 +76,36 @@ export default QUnit.module( 'Core', () => { b.copyAt( 0, a, 1 ); b.copyAt( 2, a, 0 ); - assert.deepEqual( b.array, expected, "Check the right values were replaced" ); + assert.deepEqual( b.array, expected, 'Check the right values were replaced' ); } ); - QUnit.test( "set", ( assert ) => { + QUnit.test( 'set', ( assert ) => { var instance = new InterleavedBuffer( new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ), 3 ); instance.set( [ 0, - 1 ] ); - assert.ok( instance.array[ 0 ] === 0 && instance.array[ 1 ] === - 1, "replace at first by default" ); + assert.ok( instance.array[ 0 ] === 0 && instance.array[ 1 ] === - 1, 'replace at first by default' ); } ); - QUnit.test( "onUpload", ( assert ) => { + QUnit.test( 'onUpload', ( assert ) => { var a = new InterleavedBuffer(); var func = function () { }; a.onUpload( func ); - assert.strictEqual( a.onUploadCallback, func, "Check callback was set properly" ); + assert.strictEqual( a.onUploadCallback, func, 'Check callback was set properly' ); } ); // OTHERS - QUnit.test( "count", ( assert ) => { + QUnit.test( 'count', ( assert ) => { var instance = new InterleavedBuffer( new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ), 3 ); - assert.equal( instance.count, 2, "count is calculated via array length / stride" ); + assert.equal( instance.count, 2, 'count is calculated via array length / stride' ); } ); diff --git a/test/unit/src/core/InterleavedBufferAttribute.tests.js b/test/unit/src/core/InterleavedBufferAttribute.tests.js index 9f6ff45b1cee04..82dab86cd00888 100644 --- a/test/unit/src/core/InterleavedBufferAttribute.tests.js +++ b/test/unit/src/core/InterleavedBufferAttribute.tests.js @@ -8,32 +8,32 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'InterleavedBufferAttribute', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PROPERTIES - QUnit.test( "count", ( assert ) => { + QUnit.test( 'count', ( assert ) => { var buffer = new InterleavedBuffer( new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ), 3 ); var instance = new InterleavedBufferAttribute( buffer, 2, 0 ); - assert.ok( instance.count === 2, "count is calculated via array length / stride" ); + assert.ok( instance.count === 2, 'count is calculated via array length / stride' ); } ); - QUnit.todo( "array", ( assert ) => { + QUnit.todo( 'array', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF // setY, setZ and setW are calculated in the same way so not QUnit.testing this // TODO: ( you can't be sure that will be the case in future, or a mistake was introduce in one off them ! ) - QUnit.test( "setX", ( assert ) => { + QUnit.test( 'setX', ( assert ) => { var buffer = new InterleavedBuffer( new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ), 3 ); var instance = new InterleavedBufferAttribute( buffer, 2, 0 ); @@ -42,7 +42,7 @@ export default QUnit.module( 'Core', () => { instance.setX( 1, 321 ); assert.ok( instance.data.array[ 0 ] === 123 && - instance.data.array[ 3 ] === 321, "x was calculated correct based on index and default offset" ); + instance.data.array[ 3 ] === 321, 'x was calculated correct based on index and default offset' ); var buffer = new InterleavedBuffer( new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ), 3 ); var instance = new InterleavedBufferAttribute( buffer, 2, 1 ); @@ -52,67 +52,67 @@ export default QUnit.module( 'Core', () => { // the offset was defined as 1, so go one step futher in the array assert.ok( instance.data.array[ 1 ] === 123 && - instance.data.array[ 4 ] === 321, "x was calculated correct based on index and default offset" ); + instance.data.array[ 4 ] === 321, 'x was calculated correct based on index and default offset' ); } ); - QUnit.todo( "setY", ( assert ) => { + QUnit.todo( 'setY', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setZ", ( assert ) => { + QUnit.todo( 'setZ', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setW", ( assert ) => { + QUnit.todo( 'setW', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getX", ( assert ) => { + QUnit.todo( 'getX', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getY", ( assert ) => { + QUnit.todo( 'getY', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getZ", ( assert ) => { + QUnit.todo( 'getZ', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getW", ( assert ) => { + QUnit.todo( 'getW', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setXY", ( assert ) => { + QUnit.todo( 'setXY', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setXYZ", ( assert ) => { + QUnit.todo( 'setXYZ', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setXYZW", ( assert ) => { + QUnit.todo( 'setXYZW', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/core/Object3D.tests.js b/test/unit/src/core/Object3D.tests.js index 3a6db2d8fe6b17..871bbddaea8580 100644 --- a/test/unit/src/core/Object3D.tests.js +++ b/test/unit/src/core/Object3D.tests.js @@ -54,38 +54,38 @@ export default QUnit.module( 'Core', () => { }; // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // STATIC STUFF - QUnit.test( "DefaultUp", ( assert ) => { + QUnit.test( 'DefaultUp', ( assert ) => { const currentDefaultUp = new Vector3().copy( Object3D.DefaultUp ); const v = new Vector3(); try { - assert.deepEqual( Object3D.DefaultUp, v.set( 0, 1, 0 ), "default DefaultUp is Y-up" ); + assert.deepEqual( Object3D.DefaultUp, v.set( 0, 1, 0 ), 'default DefaultUp is Y-up' ); const object = new Object3D(); - assert.deepEqual( object.up, v.set( 0, 1, 0 ), ".up of a new object inherits Object3D.DefaultUp = Y-up" ); + assert.deepEqual( object.up, v.set( 0, 1, 0 ), '.up of a new object inherits Object3D.DefaultUp = Y-up' ); Object3D.DefaultUp.set( 0, 0, 1 ); const object2 = new Object3D(); - assert.deepEqual( object2.up, v.set( 0, 0, 1 ), ".up of a new object inherits Object3D.DefaultUp = Z-up" ); + assert.deepEqual( object2.up, v.set( 0, 0, 1 ), '.up of a new object inherits Object3D.DefaultUp = Z-up' ); } finally { @@ -95,23 +95,23 @@ export default QUnit.module( 'Core', () => { } ); - QUnit.test( "DefaultMatrixAutoUpdate", ( assert ) => { + QUnit.test( 'DefaultMatrixAutoUpdate', ( assert ) => { const currentDefaultMatrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate; try { - assert.equal( currentDefaultMatrixAutoUpdate, true, "default DefaultMatrixAutoUpdate is true" ); + assert.equal( currentDefaultMatrixAutoUpdate, true, 'default DefaultMatrixAutoUpdate is true' ); const object = new Object3D(); - assert.equal( object.matrixAutoUpdate, true, ".matrixAutoUpdate of a new object inherits Object3D.DefaultMatrixAutoUpdate = true" ); + assert.equal( object.matrixAutoUpdate, true, '.matrixAutoUpdate of a new object inherits Object3D.DefaultMatrixAutoUpdate = true' ); Object3D.DefaultMatrixAutoUpdate = false; const object2 = new Object3D(); - assert.equal( object2.matrixAutoUpdate, false, ".matrixAutoUpdate of a new object inherits Object3D.DefaultMatrixAutoUpdate = false" ); + assert.equal( object2.matrixAutoUpdate, false, '.matrixAutoUpdate of a new object inherits Object3D.DefaultMatrixAutoUpdate = false' ); } finally { @@ -122,25 +122,29 @@ export default QUnit.module( 'Core', () => { } ); // PUBLIC STUFF - QUnit.todo( "isObject3D", ( assert ) => { + QUnit.test( 'isObject3D', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + const object = new Object3D(); + assert.ok( object.isObject3D, 'Object3D.isObject3D should be true' ); + + const object2 = {}; + assert.ok( object2.isObject3D === undefined, 'other object isObject3D should be undefined' ); } ); - QUnit.todo( "onBeforeRender", ( assert ) => { + QUnit.todo( 'onBeforeRender', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "onAfterRender", ( assert ) => { + QUnit.todo( 'onAfterRender', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "applyMatrix4", ( assert ) => { + QUnit.test( 'applyMatrix4', ( assert ) => { var a = new Object3D(); var m = new Matrix4(); @@ -152,17 +156,17 @@ export default QUnit.module( 'Core', () => { a.applyMatrix4( m ); - assert.deepEqual( a.position, expectedPos, "Position has the expected values" ); + assert.deepEqual( a.position, expectedPos, 'Position has the expected values' ); assert.ok( Math.abs( a.quaternion.x - expectedQuat.x ) <= eps && Math.abs( a.quaternion.y - expectedQuat.y ) <= eps && Math.abs( a.quaternion.z - expectedQuat.z ) <= eps, - "Quaternion has the expected values" + 'Quaternion has the expected values' ); } ); - QUnit.test( "applyQuaternion", ( assert ) => { + QUnit.test( 'applyQuaternion', ( assert ) => { var a = new Object3D(); var sqrt = 0.5 * Math.sqrt( 2 ); @@ -176,12 +180,12 @@ export default QUnit.module( 'Core', () => { Math.abs( a.quaternion.x - expected.x ) <= eps && Math.abs( a.quaternion.y - expected.y ) <= eps && Math.abs( a.quaternion.z - expected.z ) <= eps, - "Quaternion has the expected values" + 'Quaternion has the expected values' ); } ); - QUnit.test( "setRotationFromAxisAngle", ( assert ) => { + QUnit.test( 'setRotationFromAxisAngle', ( assert ) => { var a = new Object3D(); var axis = new Vector3( 0, 1, 0 ); @@ -191,7 +195,7 @@ export default QUnit.module( 'Core', () => { a.setRotationFromAxisAngle( axis, angle ); euler.setFromQuaternion( a.getWorldQuaternion( new Quaternion() ) ); - assert.ok( eulerEquals( euler, expected ), "Correct values after rotation" ); + assert.ok( eulerEquals( euler, expected ), 'Correct values after rotation' ); axis.set( 1, 0, 0 ); var angle = 0; @@ -199,11 +203,11 @@ export default QUnit.module( 'Core', () => { a.setRotationFromAxisAngle( axis, angle ); euler.setFromQuaternion( a.getWorldQuaternion( new Quaternion() ) ); - assert.ok( eulerEquals( euler, expected ), "Correct values after zeroing" ); + assert.ok( eulerEquals( euler, expected ), 'Correct values after zeroing' ); } ); - QUnit.test( "setRotationFromEuler", ( assert ) => { + QUnit.test( 'setRotationFromEuler', ( assert ) => { var a = new Object3D(); var rotation = new Euler( ( 45 / RadToDeg ), 0, Math.PI ); @@ -212,11 +216,11 @@ export default QUnit.module( 'Core', () => { a.setRotationFromEuler( rotation ); euler.setFromQuaternion( a.getWorldQuaternion( new Quaternion() ) ); - assert.ok( eulerEquals( euler, expected ), "Correct values after rotation" ); + assert.ok( eulerEquals( euler, expected ), 'Correct values after rotation' ); } ); - QUnit.test( "setRotationFromMatrix", ( assert ) => { + QUnit.test( 'setRotationFromMatrix', ( assert ) => { var a = new Object3D(); var m = new Matrix4(); @@ -228,11 +232,11 @@ export default QUnit.module( 'Core', () => { m.lookAt( eye, target, up ); a.setRotationFromMatrix( m ); euler.setFromQuaternion( a.getWorldQuaternion( new Quaternion() ) ); - assert.numEqual( euler.x * RadToDeg, 45, "Correct rotation angle" ); + assert.numEqual( euler.x * RadToDeg, 45, 'Correct rotation angle' ); } ); - QUnit.test( "setRotationFromQuaternion", ( assert ) => { + QUnit.test( 'setRotationFromQuaternion', ( assert ) => { var a = new Object3D(); var rotation = new Quaternion().setFromEuler( new Euler( Math.PI, 0, - Math.PI ) ); @@ -240,56 +244,56 @@ export default QUnit.module( 'Core', () => { a.setRotationFromQuaternion( rotation ); euler.setFromQuaternion( a.getWorldQuaternion( new Quaternion() ) ); - assert.ok( eulerEquals( euler, new Euler( Math.PI, 0, - Math.PI ) ), "Correct values after rotation" ); + assert.ok( eulerEquals( euler, new Euler( Math.PI, 0, - Math.PI ) ), 'Correct values after rotation' ); } ); - QUnit.todo( "rotateOnAxis", ( assert ) => { + QUnit.todo( 'rotateOnAxis', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "rotateOnWorldAxis", ( assert ) => { + QUnit.todo( 'rotateOnWorldAxis', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "rotateX", ( assert ) => { + QUnit.test( 'rotateX', ( assert ) => { var obj = new Object3D(); var angleInRad = 1.562; obj.rotateX( angleInRad ); - assert.numEqual( obj.rotation.x, angleInRad, "x is equal" ); + assert.numEqual( obj.rotation.x, angleInRad, 'x is equal' ); } ); - QUnit.test( "rotateY", ( assert ) => { + QUnit.test( 'rotateY', ( assert ) => { var obj = new Object3D(); var angleInRad = - 0.346; obj.rotateY( angleInRad ); - assert.numEqual( obj.rotation.y, angleInRad, "y is equal" ); + assert.numEqual( obj.rotation.y, angleInRad, 'y is equal' ); } ); - QUnit.test( "rotateZ", ( assert ) => { + QUnit.test( 'rotateZ', ( assert ) => { var obj = new Object3D(); var angleInRad = 1; obj.rotateZ( angleInRad ); - assert.numEqual( obj.rotation.z, angleInRad, "z is equal" ); + assert.numEqual( obj.rotation.z, angleInRad, 'z is equal' ); } ); - QUnit.test( "translateOnAxis", ( assert ) => { + QUnit.test( 'translateOnAxis', ( assert ) => { var obj = new Object3D(); @@ -305,34 +309,34 @@ export default QUnit.module( 'Core', () => { } ); - QUnit.test( "translateX", ( assert ) => { + QUnit.test( 'translateX', ( assert ) => { var obj = new Object3D(); obj.translateX( 1.234 ); - assert.numEqual( obj.position.x, 1.234, "x is equal" ); + assert.numEqual( obj.position.x, 1.234, 'x is equal' ); } ); - QUnit.test( "translateY", ( assert ) => { + QUnit.test( 'translateY', ( assert ) => { var obj = new Object3D(); obj.translateY( 1.234 ); - assert.numEqual( obj.position.y, 1.234, "y is equal" ); + assert.numEqual( obj.position.y, 1.234, 'y is equal' ); } ); - QUnit.test( "translateZ", ( assert ) => { + QUnit.test( 'translateZ', ( assert ) => { var obj = new Object3D(); obj.translateZ( 1.234 ); - assert.numEqual( obj.position.z, 1.234, "z is equal" ); + assert.numEqual( obj.position.z, 1.234, 'z is equal' ); } ); - QUnit.test( "localToWorld", ( assert ) => { + QUnit.test( 'localToWorld', ( assert ) => { const v = new Vector3(); const expectedPosition = new Vector3( 5, - 1, - 4 ); @@ -357,12 +361,12 @@ export default QUnit.module( 'Core', () => { Math.abs( v.x - expectedPosition.x ) <= eps && Math.abs( v.y - expectedPosition.y ) <= eps && Math.abs( v.z - expectedPosition.z ) <= eps, - "local vector is converted to world" + 'local vector is converted to world' ); } ); - QUnit.test( "worldToLocal", ( assert ) => { + QUnit.test( 'worldToLocal', ( assert ) => { const v = new Vector3(); const expectedPosition = new Vector3( - 1, 0.5, - 1 ); @@ -387,68 +391,68 @@ export default QUnit.module( 'Core', () => { Math.abs( v.x - expectedPosition.x ) <= eps && Math.abs( v.y - expectedPosition.y ) <= eps && Math.abs( v.z - expectedPosition.z ) <= eps, - "world vector is converted to local" + 'world vector is converted to local' ); } ); - QUnit.test( "lookAt", ( assert ) => { + QUnit.test( 'lookAt', ( assert ) => { var obj = new Object3D(); obj.lookAt( new Vector3( 0, - 1, 1 ) ); - assert.numEqual( obj.rotation.x * RadToDeg, 45, "x is equal" ); + assert.numEqual( obj.rotation.x * RadToDeg, 45, 'x is equal' ); } ); - QUnit.test( "add/remove/clear", ( assert ) => { + QUnit.test( 'add/remove/clear', ( assert ) => { var a = new Object3D(); var child1 = new Object3D(); var child2 = new Object3D(); - assert.strictEqual( a.children.length, 0, "Starts with no children" ); + assert.strictEqual( a.children.length, 0, 'Starts with no children' ); a.add( child1 ); - assert.strictEqual( a.children.length, 1, "The first child was added" ); - assert.strictEqual( a.children[ 0 ], child1, "It's the right one" ); + assert.strictEqual( a.children.length, 1, 'The first child was added' ); + assert.strictEqual( a.children[ 0 ], child1, 'It\'s the right one' ); a.add( child2 ); - assert.strictEqual( a.children.length, 2, "The second child was added" ); - assert.strictEqual( a.children[ 1 ], child2, "It's the right one" ); - assert.strictEqual( a.children[ 0 ], child1, "The first one is still there" ); + assert.strictEqual( a.children.length, 2, 'The second child was added' ); + assert.strictEqual( a.children[ 1 ], child2, 'It\'s the right one' ); + assert.strictEqual( a.children[ 0 ], child1, 'The first one is still there' ); a.remove( child1 ); - assert.strictEqual( a.children.length, 1, "The first child was removed" ); - assert.strictEqual( a.children[ 0 ], child2, "The second one is still there" ); + assert.strictEqual( a.children.length, 1, 'The first child was removed' ); + assert.strictEqual( a.children[ 0 ], child2, 'The second one is still there' ); a.add( child1 ); a.remove( child1, child2 ); - assert.strictEqual( a.children.length, 0, "Both children were removed at once" ); + assert.strictEqual( a.children.length, 0, 'Both children were removed at once' ); child1.add( child2 ); - assert.strictEqual( child1.children.length, 1, "The second child was added to the first one" ); + assert.strictEqual( child1.children.length, 1, 'The second child was added to the first one' ); a.add( child2 ); - assert.strictEqual( a.children.length, 1, "The second one was added to the parent (no remove)" ); - assert.strictEqual( a.children[ 0 ], child2, "The second one is now the parent's child again" ); - assert.strictEqual( child1.children.length, 0, "The first one no longer has any children" ); + assert.strictEqual( a.children.length, 1, 'The second one was added to the parent (no remove)' ); + assert.strictEqual( a.children[ 0 ], child2, 'The second one is now the parent\'s child again' ); + assert.strictEqual( child1.children.length, 0, 'The first one no longer has any children' ); a.add( child1 ); - assert.strictEqual( a.children.length, 2, "The first child was added to the parent" ); + assert.strictEqual( a.children.length, 2, 'The first child was added to the parent' ); a.clear(); - assert.strictEqual( a.children.length, 0, "All childrens were removed" ); - assert.strictEqual( child1.parent, null, "First child has no parent" ); - assert.strictEqual( child2.parent, null, "Second child has no parent" ); + assert.strictEqual( a.children.length, 0, 'All childrens were removed' ); + assert.strictEqual( child1.parent, null, 'First child has no parent' ); + assert.strictEqual( child2.parent, null, 'Second child has no parent' ); a.add( child1 ); - assert.strictEqual( a.children.length, 1, "The child was added to the parent" ); + assert.strictEqual( a.children.length, 1, 'The child was added to the parent' ); child1.removeFromParent(); - assert.strictEqual( a.children.length, 0, "The child was removed" ); - assert.strictEqual( child1.parent, null, "Child has no parent" ); + assert.strictEqual( a.children.length, 0, 'The child was removed' ); + assert.strictEqual( child1.parent, null, 'Child has no parent' ); } ); - QUnit.test( "attach", ( assert ) => { + QUnit.test( 'attach', ( assert ) => { const object = new Object3D(); const oldParent = new Object3D(); @@ -472,9 +476,9 @@ export default QUnit.module( 'Core', () => { assert.ok( object.parent && object.parent == newParent && oldParent.children.indexOf( object ) === - 1, - "object is a child of a new parent" ); + 'object is a child of a new parent' ); - assert.ok( matrixEquals4( expectedMatrixWorld, object.matrixWorld ), "object's world matrix is maintained" ); + assert.ok( matrixEquals4( expectedMatrixWorld, object.matrixWorld ), 'object\'s world matrix is maintained' ); // Attach to a new parent from an old parent @@ -498,14 +502,14 @@ export default QUnit.module( 'Core', () => { assert.ok( object.parent && object.parent == newParent && newParent.children.indexOf( object ) !== - 1 && oldParent.children.indexOf( object ) === - 1, - "object is no longer a child of an old parent and is a child of a new parent now" ); + 'object is no longer a child of an old parent and is a child of a new parent now' ); assert.ok( matrixEquals4( expectedMatrixWorld, object.matrixWorld ), - "object's world matrix is maintained even it had a parent" ); + 'object\'s world matrix is maintained even it had a parent' ); } ); - QUnit.test( "getObjectById/getObjectByName/getObjectByProperty", ( assert ) => { + QUnit.test( 'getObjectById/getObjectByName/getObjectByProperty', ( assert ) => { var parent = new Object3D(); var childName = new Object3D(); @@ -513,20 +517,20 @@ export default QUnit.module( 'Core', () => { var childNothing = new Object3D(); parent.prop = true; - childName.name = "foo"; + childName.name = 'foo'; parent.add( childName, childId, childNothing ); - assert.strictEqual( parent.getObjectByProperty( 'prop', true ), parent, "Get parent by its own property" ); - assert.strictEqual( parent.getObjectByName( "foo" ), childName, "Get child by name" ); - assert.strictEqual( parent.getObjectById( parent.id + 2 ), childId, "Get child by Id" ); + assert.strictEqual( parent.getObjectByProperty( 'prop', true ), parent, 'Get parent by its own property' ); + assert.strictEqual( parent.getObjectByName( 'foo' ), childName, 'Get child by name' ); + assert.strictEqual( parent.getObjectById( parent.id + 2 ), childId, 'Get child by Id' ); assert.strictEqual( parent.getObjectByProperty( 'no-property', 'no-value' ), undefined, - "Unknown property results in undefined" + 'Unknown property results in undefined' ); } ); - QUnit.test( "getWorldPosition", ( assert ) => { + QUnit.test( 'getWorldPosition', ( assert ) => { var a = new Object3D(); var b = new Object3D(); @@ -539,25 +543,25 @@ export default QUnit.module( 'Core', () => { a.translateY( y ); a.translateZ( z ); - assert.deepEqual( a.getWorldPosition( position ), expectedSingle, "WorldPosition as expected for single object" ); + assert.deepEqual( a.getWorldPosition( position ), expectedSingle, 'WorldPosition as expected for single object' ); // translate child and then parent b.translateZ( 7 ); a.add( b ); a.translateZ( - z ); - assert.deepEqual( a.getWorldPosition( position ), expectedParent, "WorldPosition as expected for parent" ); - assert.deepEqual( b.getWorldPosition( position ), expectedChild, "WorldPosition as expected for child" ); + assert.deepEqual( a.getWorldPosition( position ), expectedParent, 'WorldPosition as expected for parent' ); + assert.deepEqual( b.getWorldPosition( position ), expectedChild, 'WorldPosition as expected for child' ); } ); - QUnit.todo( "getWorldQuaternion", ( assert ) => { + QUnit.todo( 'getWorldQuaternion', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "getWorldScale", ( assert ) => { + QUnit.test( 'getWorldScale', ( assert ) => { var a = new Object3D(); var m = new Matrix4().makeScale( x, y, z ); @@ -565,11 +569,11 @@ export default QUnit.module( 'Core', () => { a.applyMatrix4( m ); - assert.deepEqual( a.getWorldScale( new Vector3() ), expected, "WorldScale as expected" ); + assert.deepEqual( a.getWorldScale( new Vector3() ), expected, 'WorldScale as expected' ); } ); - QUnit.test( "getWorldDirection", ( assert ) => { + QUnit.test( 'getWorldDirection', ( assert ) => { var a = new Object3D(); var expected = new Vector3( 0, - 0.5 * Math.sqrt( 2 ), 0.5 * Math.sqrt( 2 ) ); @@ -582,12 +586,12 @@ export default QUnit.module( 'Core', () => { Math.abs( direction.x - expected.x ) <= eps && Math.abs( direction.y - expected.y ) <= eps && Math.abs( direction.z - expected.z ) <= eps, - "Direction has the expected values" + 'Direction has the expected values' ); } ); - QUnit.test( "localTransformVariableInstantiation", ( assert ) => { + QUnit.test( 'localTransformVariableInstantiation', ( assert ) => { var a = new Object3D(); var b = new Object3D(); @@ -597,47 +601,47 @@ export default QUnit.module( 'Core', () => { a.getWorldDirection( new Vector3() ); a.lookAt( new Vector3( 0, - 1, 1 ) ); - assert.ok( true, "Calling lookAt after getWorldDirection does not create errors" ); + assert.ok( true, 'Calling lookAt after getWorldDirection does not create errors' ); b.getWorldPosition( new Vector3() ); b.lookAt( new Vector3( 0, - 1, 1 ) ); - assert.ok( true, "Calling lookAt after getWorldPosition does not create errors" ); + assert.ok( true, 'Calling lookAt after getWorldPosition does not create errors' ); c.getWorldQuaternion( new Quaternion() ); c.lookAt( new Vector3( 0, - 1, 1 ) ); - assert.ok( true, "Calling lookAt after getWorldQuaternion does not create errors" ); + assert.ok( true, 'Calling lookAt after getWorldQuaternion does not create errors' ); d.getWorldScale( new Vector3() ); d.lookAt( new Vector3( 0, - 1, 1 ) ); - assert.ok( true, "Calling lookAt after getWorldScale does not create errors" ); + assert.ok( true, 'Calling lookAt after getWorldScale does not create errors' ); } ); - QUnit.todo( "raycast", ( assert ) => { + QUnit.todo( 'raycast', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "traverse/traverseVisible/traverseAncestors", ( assert ) => { + QUnit.test( 'traverse/traverseVisible/traverseAncestors', ( assert ) => { var a = new Object3D(); var b = new Object3D(); var c = new Object3D(); var d = new Object3D(); var names = []; - var expectedNormal = [ "parent", "child", "childchild 1", "childchild 2" ]; - var expectedVisible = [ "parent", "child", "childchild 2" ]; - var expectedAncestors = [ "child", "parent" ]; + var expectedNormal = [ 'parent', 'child', 'childchild 1', 'childchild 2' ]; + var expectedVisible = [ 'parent', 'child', 'childchild 2' ]; + var expectedAncestors = [ 'child', 'parent' ]; - a.name = "parent"; - b.name = "child"; - c.name = "childchild 1"; + a.name = 'parent'; + b.name = 'child'; + c.name = 'childchild 1'; c.visible = false; - d.name = "childchild 2"; + d.name = 'childchild 2'; b.add( c ); b.add( d ); @@ -648,7 +652,7 @@ export default QUnit.module( 'Core', () => { names.push( obj.name ); } ); - assert.deepEqual( names, expectedNormal, "Traversed objects in expected order" ); + assert.deepEqual( names, expectedNormal, 'Traversed objects in expected order' ); var names = []; a.traverseVisible( function ( obj ) { @@ -656,7 +660,7 @@ export default QUnit.module( 'Core', () => { names.push( obj.name ); } ); - assert.deepEqual( names, expectedVisible, "Traversed visible objects in expected order" ); + assert.deepEqual( names, expectedVisible, 'Traversed visible objects in expected order' ); var names = []; c.traverseAncestors( function ( obj ) { @@ -664,11 +668,11 @@ export default QUnit.module( 'Core', () => { names.push( obj.name ); } ); - assert.deepEqual( names, expectedAncestors, "Traversed ancestors in expected order" ); + assert.deepEqual( names, expectedAncestors, 'Traversed ancestors in expected order' ); } ); - QUnit.test( "updateMatrix", ( assert ) => { + QUnit.test( 'updateMatrix', ( assert ) => { const a = new Object3D(); a.position.set( 2, 3, 4 ); @@ -680,22 +684,22 @@ export default QUnit.module( 'Core', () => { 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 - ], "Updating position, quaternion, or scale has no effect to matrix until calling updateMatrix()" ); + ], 'Updating position, quaternion, or scale has no effect to matrix until calling updateMatrix()' ); a.updateMatrix(); assert.deepEqual( a.matrix.elements, [ - -1521, 1548, -234, 0, - -520, -1470, 1640, 0, - 1826, 44, -1331, 0, + - 1521, 1548, - 234, 0, + - 520, - 1470, 1640, 0, + 1826, 44, - 1331, 0, 2, 3, 4, 1 - ], "matrix is calculated from position, quaternion, and scale" ); + ], 'matrix is calculated from position, quaternion, and scale' ); - assert.equal( a.matrixWorldNeedsUpdate, true, "The flag indicating world matrix needs to be updated should be true" ); + assert.equal( a.matrixWorldNeedsUpdate, true, 'The flag indicating world matrix needs to be updated should be true' ); } ); - QUnit.test( "updateMatrixWorld", ( assert ) => { + QUnit.test( 'updateMatrixWorld', ( assert ) => { const parent = new Object3D(); const child = new Object3D(); @@ -713,30 +717,30 @@ export default QUnit.module( 'Core', () => { 0, 1, 0, 0, 0, 0, 1, 0, 1, 2, 3, 1 - ], "updateMatrixWorld() updates local matrix" ); + ], 'updateMatrixWorld() updates local matrix' ); assert.deepEqual( parent.matrixWorld.elements, [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 2, 3, 1 - ], "updateMatrixWorld() updates world matrix" ); + ], 'updateMatrixWorld() updates world matrix' ); assert.deepEqual( child.matrix.elements, [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 4, 5, 6, 1 - ], "updateMatrixWorld() updates children's local matrix" ); + ], 'updateMatrixWorld() updates children\'s local matrix' ); assert.deepEqual( child.matrixWorld.elements, [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 5, 7, 9, 1 - ], "updateMatrixWorld() updates children's world matrices from their parent world matrix and their local matrices" ); + ], 'updateMatrixWorld() updates children\'s world matrices from their parent world matrix and their local matrices' ); - assert.equal( parent.matrixWorldNeedsUpdate || child.matrixWorldNeedsUpdate, false, "The flag indicating world matrix needs to be updated should be false after updating world matrix" ); + assert.equal( parent.matrixWorldNeedsUpdate || child.matrixWorldNeedsUpdate, false, 'The flag indicating world matrix needs to be updated should be false after updating world matrix' ); // -- No sync between local position/quaternion/scale/matrix and world matrix test @@ -748,7 +752,7 @@ export default QUnit.module( 'Core', () => { 0, 1, 0, 0, 0, 0, 1, 0, 1, 2, 3, 1 - ], "Updating position, quaternion, scale, or local matrix has no effect to world matrix until calling updateWorldMatrix()" ); + ], 'Updating position, quaternion, scale, or local matrix has no effect to world matrix until calling updateWorldMatrix()' ); // -- matrixAutoUpdate = false test @@ -766,21 +770,21 @@ export default QUnit.module( 'Core', () => { 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 - ], "updateMatrixWorld() doesn't update local matrix if matrixAutoUpdate is false" ); + ], 'updateMatrixWorld() doesn\'t update local matrix if matrixAutoUpdate is false' ); assert.deepEqual( parent.matrixWorld.elements, [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 - ], "World matrix isn't updated because local matrix isn't updated and the flag indicating world matrix needs to be updated didn't rise" ); + ], 'World matrix isn\'t updated because local matrix isn\'t updated and the flag indicating world matrix needs to be updated didn\'t rise' ); assert.deepEqual( child.matrixWorld.elements, [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 - ], "No effect to child world matrix if parent local and world matrices and child local matrix are not updated" ); + ], 'No effect to child world matrix if parent local and world matrices and child local matrix are not updated' ); // -- Propagation to children world matrices test @@ -792,7 +796,7 @@ export default QUnit.module( 'Core', () => { 0, 1, 0, 0, 0, 0, 1, 0, 1, 2, 3, 1 - ], "Updating parent world matrix has effect to children world matrices even if children local matrices aren't changed" ); + ], 'Updating parent world matrix has effect to children world matrices even if children local matrices aren\'t changed' ); // -- force argument test @@ -813,7 +817,7 @@ export default QUnit.module( 'Core', () => { 0, 1, 0, 0, 0, 0, 1, 0, 1, 2, 3, 1 - ], "force = true forces to update world matrix even if local matrix is not changed" ); + ], 'force = true forces to update world matrix even if local matrix is not changed' ); // -- Restriction test: No effect to parent matrices @@ -834,25 +838,25 @@ export default QUnit.module( 'Core', () => { 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 - ], "updateMatrixWorld() doesn't update parent local matrix" ); + ], 'updateMatrixWorld() doesn\'t update parent local matrix' ); assert.deepEqual( parent.matrixWorld.elements, [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 - ], "updateMatrixWorld() doesn't update parent world matrix" ); + ], 'updateMatrixWorld() doesn\'t update parent world matrix' ); assert.deepEqual( child.matrixWorld.elements, [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 4, 5, 6, 1 - ], "updateMatrixWorld() calculates world matrix from the current parent world matrix" ); + ], 'updateMatrixWorld() calculates world matrix from the current parent world matrix' ); } ); - QUnit.test( "updateWorldMatrix", ( assert ) => { + QUnit.test( 'updateWorldMatrix', ( assert ) => { const object = new Object3D(); const parent = new Object3D(); @@ -874,27 +878,27 @@ export default QUnit.module( 'Core', () => { assert.deepEqual( parent.matrix.elements, m.elements, - "No effect to parents' local matrices" ); + 'No effect to parents\' local matrices' ); assert.deepEqual( parent.matrixWorld.elements, m.elements, - "No effect to parents' world matrices" ); + 'No effect to parents\' world matrices' ); assert.deepEqual( object.matrix.elements, m.setPosition( object.position ).elements, - "Object's local matrix is updated" ); + 'Object\'s local matrix is updated' ); assert.deepEqual( object.matrixWorld.elements, m.setPosition( object.position ).elements, - "Object's world matrix is updated" ); + 'Object\'s world matrix is updated' ); assert.deepEqual( child.matrix.elements, m.identity().elements, - "No effect to children's local matrices" ); + 'No effect to children\'s local matrices' ); assert.deepEqual( child.matrixWorld.elements, m.elements, - "No effect to children's world matrices" ); + 'No effect to children\'s world matrices' ); // Update the world matrices of an object and its parents @@ -905,27 +909,27 @@ export default QUnit.module( 'Core', () => { assert.deepEqual( parent.matrix.elements, m.setPosition( parent.position ).elements, - "Parents' local matrices are updated" ); + 'Parents\' local matrices are updated' ); assert.deepEqual( parent.matrixWorld.elements, m.setPosition( parent.position ).elements, - "Parents' world matrices are updated" ); + 'Parents\' world matrices are updated' ); assert.deepEqual( object.matrix.elements, m.setPosition( object.position ).elements, - "Object's local matrix is updated" ); + 'Object\'s local matrix is updated' ); assert.deepEqual( object.matrixWorld.elements, m.setPosition( v.copy( parent.position ).add( object.position ) ).elements, - "Object's world matrix is updated" ); + 'Object\'s world matrix is updated' ); assert.deepEqual( child.matrix.elements, m.identity().elements, - "No effect to children's local matrices" ); + 'No effect to children\'s local matrices' ); assert.deepEqual( child.matrixWorld.elements, m.identity().elements, - "No effect to children's world matrices" ); + 'No effect to children\'s world matrices' ); // Update the world matrices of an object and its children @@ -938,27 +942,27 @@ export default QUnit.module( 'Core', () => { assert.deepEqual( parent.matrix.elements, m.elements, - "No effect to parents' local matrices" ); + 'No effect to parents\' local matrices' ); assert.deepEqual( parent.matrixWorld.elements, m.elements, - "No effect to parents' world matrices" ); + 'No effect to parents\' world matrices' ); assert.deepEqual( object.matrix.elements, m.setPosition( object.position ).elements, - "Object's local matrix is updated" ); + 'Object\'s local matrix is updated' ); assert.deepEqual( object.matrixWorld.elements, m.setPosition( object.position ).elements, - "Object's world matrix is updated" ); + 'Object\'s world matrix is updated' ); assert.deepEqual( child.matrix.elements, m.setPosition( child.position ).elements, - "Children's local matrices are updated" ); + 'Children\'s local matrices are updated' ); assert.deepEqual( child.matrixWorld.elements, m.setPosition( v.copy( object.position ).add( child.position ) ).elements, - "Children's world matrices are updated" ); + 'Children\'s world matrices are updated' ); // Update the world matrices of an object and its parents and children @@ -971,27 +975,27 @@ export default QUnit.module( 'Core', () => { assert.deepEqual( parent.matrix.elements, m.setPosition( parent.position ).elements, - "Parents' local matrices are updated" ); + 'Parents\' local matrices are updated' ); assert.deepEqual( parent.matrixWorld.elements, m.setPosition( parent.position ).elements, - "Parents' world matrices are updated" ); + 'Parents\' world matrices are updated' ); assert.deepEqual( object.matrix.elements, m.setPosition( object.position ).elements, - "Object's local matrix is updated" ); + 'Object\'s local matrix is updated' ); assert.deepEqual( object.matrixWorld.elements, m.setPosition( v.copy( parent.position ).add( object.position ) ).elements, - "Object's world matrix is updated" ); + 'Object\'s world matrix is updated' ); assert.deepEqual( child.matrix.elements, m.setPosition( child.position ).elements, - "Children's local matrices are updated" ); + 'Children\'s local matrices are updated' ); assert.deepEqual( child.matrixWorld.elements, m.setPosition( v.copy( parent.position ).add( object.position ).add( child.position ) ).elements, - "Children's world matrices are updated" ); + 'Children\'s world matrices are updated' ); // object.matrixAutoUpdate = false test @@ -1003,60 +1007,60 @@ export default QUnit.module( 'Core', () => { assert.deepEqual( object.matrix.elements, m.identity().elements, - "No effect to object's local matrix if matrixAutoUpdate is false" ); + 'No effect to object\'s local matrix if matrixAutoUpdate is false' ); assert.deepEqual( object.matrixWorld.elements, m.setPosition( parent.position ).elements, - "object's world matrix is updated even if matrixAutoUpdate is false" ); + 'object\'s world matrix is updated even if matrixAutoUpdate is false' ); } ); - QUnit.test( "toJSON", ( assert ) => { + QUnit.test( 'toJSON', ( assert ) => { var a = new Object3D(); var child = new Object3D(); var childChild = new Object3D(); - a.name = "a's name"; + a.name = 'a\'s name'; a.matrix.set( 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ); a.visible = false; a.castShadow = true; a.receiveShadow = true; - a.userData[ "foo" ] = "bar"; + a.userData[ 'foo' ] = 'bar'; - child.uuid = "5D4E9AE8-DA61-4912-A575-71A5BE3D72CD"; - childChild.uuid = "B43854B3-E970-4E85-BD41-AAF8D7BFA189"; + child.uuid = '5D4E9AE8-DA61-4912-A575-71A5BE3D72CD'; + childChild.uuid = 'B43854B3-E970-4E85-BD41-AAF8D7BFA189'; child.add( childChild ); a.add( child ); var gold = { - "metadata": { - "version": 4.5, - "type": "Object", - "generator": "Object3D.toJSON" + 'metadata': { + 'version': 4.5, + 'type': 'Object', + 'generator': 'Object3D.toJSON' }, - "object": { - "uuid": "0A1E4F43-CB5B-4097-8F82-DC2969C0B8C2", - "type": "Object3D", - "name": "a's name", - "castShadow": true, - "receiveShadow": true, - "visible": false, - "userData": { "foo": "bar" }, - "layers": 1, - "matrix": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ], - "children": [ + 'object': { + 'uuid': '0A1E4F43-CB5B-4097-8F82-DC2969C0B8C2', + 'type': 'Object3D', + 'name': 'a\'s name', + 'castShadow': true, + 'receiveShadow': true, + 'visible': false, + 'userData': { 'foo': 'bar' }, + 'layers': 1, + 'matrix': [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ], + 'children': [ { - "uuid": "5D4E9AE8-DA61-4912-A575-71A5BE3D72CD", - "type": "Object3D", - "layers": 1, - "matrix": [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ], - "children": [ + 'uuid': '5D4E9AE8-DA61-4912-A575-71A5BE3D72CD', + 'type': 'Object3D', + 'layers': 1, + 'matrix': [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ], + 'children': [ { - "uuid": "B43854B3-E970-4E85-BD41-AAF8D7BFA189", - "type": "Object3D", - "layers": 1, - "matrix": [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ] + 'uuid': 'B43854B3-E970-4E85-BD41-AAF8D7BFA189', + 'type': 'Object3D', + 'layers': 1, + 'matrix': [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ] } ] } @@ -1066,36 +1070,36 @@ export default QUnit.module( 'Core', () => { // hacks var out = a.toJSON(); - out.object.uuid = "0A1E4F43-CB5B-4097-8F82-DC2969C0B8C2"; + out.object.uuid = '0A1E4F43-CB5B-4097-8F82-DC2969C0B8C2'; - assert.deepEqual( out, gold, "JSON is as expected" ); + assert.deepEqual( out, gold, 'JSON is as expected' ); } ); - QUnit.test( "clone", ( assert ) => { + QUnit.test( 'clone', ( assert ) => { var a; var b = new Object3D(); - assert.strictEqual( a, undefined, "Undefined pre-clone()" ); + assert.strictEqual( a, undefined, 'Undefined pre-clone()' ); a = b.clone(); - assert.notStrictEqual( a, b, "Defined but seperate instances post-clone()" ); + assert.notStrictEqual( a, b, 'Defined but seperate instances post-clone()' ); a.uuid = b.uuid; - assert.deepEqual( a, b, "But identical properties" ); + assert.deepEqual( a, b, 'But identical properties' ); } ); - QUnit.test( "copy", ( assert ) => { + QUnit.test( 'copy', ( assert ) => { var a = new Object3D(); var b = new Object3D(); var child = new Object3D(); var childChild = new Object3D(); - a.name = "original"; - b.name = "to-be-copied"; + a.name = 'original'; + b.name = 'to-be-copied'; b.position.set( x, y, z ); b.quaternion.set( x, y, z, w ); @@ -1117,12 +1121,12 @@ export default QUnit.module( 'Core', () => { b.frustumCulled = false; b.renderOrder = 1; - b.userData[ "foo" ] = "bar"; + b.userData[ 'foo' ] = 'bar'; child.add( childChild ); b.add( child ); - assert.notDeepEqual( a, b, "Objects are not equal pre-copy()" ); + assert.notDeepEqual( a, b, 'Objects are not equal pre-copy()' ); a.copy( b, true ); // check they're all unique instances @@ -1130,7 +1134,7 @@ export default QUnit.module( 'Core', () => { a.uuid !== b.uuid && a.children[ 0 ].uuid !== b.children[ 0 ].uuid && a.children[ 0 ].children[ 0 ].uuid !== b.children[ 0 ].children[ 0 ].uuid, - "UUIDs are all different" + 'UUIDs are all different' ); // and now fix that @@ -1138,7 +1142,7 @@ export default QUnit.module( 'Core', () => { a.children[ 0 ].uuid = b.children[ 0 ].uuid; a.children[ 0 ].children[ 0 ].uuid = b.children[ 0 ].children[ 0 ].uuid; - assert.deepEqual( a, b, "Objects are equal post-copy()" ); + assert.deepEqual( a, b, 'Objects are equal post-copy()' ); } ); diff --git a/test/unit/src/core/Raycaster.tests.js b/test/unit/src/core/Raycaster.tests.js index 00e4a8ec22c59b..37aebabd79e0f3 100644 --- a/test/unit/src/core/Raycaster.tests.js +++ b/test/unit/src/core/Raycaster.tests.js @@ -12,8 +12,8 @@ import { OrthographicCamera } from '../../../../src/cameras/OrthographicCamera'; function checkRayDirectionAgainstReferenceVector( rayDirection, refVector, assert ) { - assert.ok( refVector.x - rayDirection.x <= Number.EPSILON && refVector.y - rayDirection.y <= Number.EPSILON && refVector.z - rayDirection.z <= Number.EPSILON, "camera is pointing to" + - " the same direction as expected" ); + assert.ok( refVector.x - rayDirection.x <= Number.EPSILON && refVector.y - rayDirection.y <= Number.EPSILON && refVector.z - rayDirection.z <= Number.EPSILON, 'camera is pointing to' + + ' the same direction as expected' ); } @@ -73,32 +73,32 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'Raycaster', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.test( "set", ( assert ) => { + QUnit.test( 'set', ( assert ) => { var origin = new Vector3( 0, 0, 0 ); var direction = new Vector3( 0, 0, - 1 ); var a = new Raycaster( origin.clone(), direction.clone() ); - assert.deepEqual( a.ray.origin, origin, "Origin is correct" ); - assert.deepEqual( a.ray.direction, direction, "Direction is correct" ); + assert.deepEqual( a.ray.origin, origin, 'Origin is correct' ); + assert.deepEqual( a.ray.direction, direction, 'Direction is correct' ); origin.set( 1, 1, 1 ); direction.set( - 1, 0, 0 ); a.set( origin, direction ); - assert.deepEqual( a.ray.origin, origin, "Origin was set correctly" ); - assert.deepEqual( a.ray.direction, direction, "Direction was set correctly" ); + assert.deepEqual( a.ray.origin, origin, 'Origin was set correctly' ); + assert.deepEqual( a.ray.direction, direction, 'Direction was set correctly' ); } ); - QUnit.test( "setFromCamera (Perspective)", ( assert ) => { + QUnit.test( 'setFromCamera (Perspective)', ( assert ) => { var raycaster = new Raycaster(); var rayDirection = raycaster.ray.direction; @@ -109,7 +109,7 @@ export default QUnit.module( 'Core', () => { y: 0 }, camera ); assert.ok( rayDirection.x === 0 && rayDirection.y === 0 && rayDirection.z === - 1, - "camera is looking straight to -z and so does the ray in the middle of the screen" ); + 'camera is looking straight to -z and so does the ray in the middle of the screen' ); var step = 0.1; @@ -132,7 +132,7 @@ export default QUnit.module( 'Core', () => { } ); - QUnit.test( "setFromCamera (Orthographic)", ( assert ) => { + QUnit.test( 'setFromCamera (Orthographic)', ( assert ) => { var raycaster = new Raycaster(); var rayOrigin = raycaster.ray.origin; @@ -145,82 +145,82 @@ export default QUnit.module( 'Core', () => { x: 0, y: 0 }, camera ); - assert.deepEqual( rayOrigin, expectedOrigin, "Ray origin has the right coordinates" ); - assert.deepEqual( rayDirection, expectedDirection, "Camera and Ray are pointing towards -z" ); + assert.deepEqual( rayOrigin, expectedOrigin, 'Ray origin has the right coordinates' ); + assert.deepEqual( rayDirection, expectedDirection, 'Camera and Ray are pointing towards -z' ); } ); - QUnit.test( "intersectObject", ( assert ) => { + QUnit.test( 'intersectObject', ( assert ) => { var raycaster = getRaycaster(); var objectsToCheck = getObjectsToCheck(); assert.ok( raycaster.intersectObject( objectsToCheck[ 0 ], false ).length === 1, - "no recursive search should lead to one hit" ); + 'no recursive search should lead to one hit' ); assert.ok( raycaster.intersectObject( objectsToCheck[ 0 ] ).length === 3, - "recursive search should lead to three hits" ); + 'recursive search should lead to three hits' ); var intersections = raycaster.intersectObject( objectsToCheck[ 0 ] ); for ( var i = 0; i < intersections.length - 1; i ++ ) { - assert.ok( intersections[ i ].distance <= intersections[ i + 1 ].distance, "intersections are sorted" ); + assert.ok( intersections[ i ].distance <= intersections[ i + 1 ].distance, 'intersections are sorted' ); } } ); - QUnit.test( "intersectObjects", ( assert ) => { + QUnit.test( 'intersectObjects', ( assert ) => { var raycaster = getRaycaster(); var objectsToCheck = getObjectsToCheck(); assert.ok( raycaster.intersectObjects( objectsToCheck, false ).length === 1, - "no recursive search should lead to one hit" ); + 'no recursive search should lead to one hit' ); assert.ok( raycaster.intersectObjects( objectsToCheck ).length === 3, - "recursive search should lead to three hits" ); + 'recursive search should lead to three hits' ); var intersections = raycaster.intersectObjects( objectsToCheck ); for ( var i = 0; i < intersections.length - 1; i ++ ) { - assert.ok( intersections[ i ].distance <= intersections[ i + 1 ].distance, "intersections are sorted" ); + assert.ok( intersections[ i ].distance <= intersections[ i + 1 ].distance, 'intersections are sorted' ); } } ); - QUnit.test( "Line intersection threshold", ( assert ) => { + QUnit.test( 'Line intersection threshold', ( assert ) => { var raycaster = getRaycaster(); - var points = [ new Vector3( -2, -10, -5 ), new Vector3( -2, 10, -5 ) ]; + var points = [ new Vector3( - 2, - 10, - 5 ), new Vector3( - 2, 10, - 5 ) ]; var geometry = new BufferGeometry().setFromPoints( points ); var line = new Line( geometry, null ); raycaster.params.Line.threshold = 1.999; assert.ok( raycaster.intersectObject( line ).length === 0, - "no Line intersection with a not-large-enough threshold" ); + 'no Line intersection with a not-large-enough threshold' ); raycaster.params.Line.threshold = 2.001; assert.ok( raycaster.intersectObject( line ).length === 1, - "successful Line intersection with a large-enough threshold" ); + 'successful Line intersection with a large-enough threshold' ); } ); - QUnit.test( "Points intersection threshold", ( assert ) => { + QUnit.test( 'Points intersection threshold', ( assert ) => { var raycaster = getRaycaster(); - var coordinates = [ new Vector3( -2, 0, -5 ) ]; + var coordinates = [ new Vector3( - 2, 0, - 5 ) ]; var geometry = new BufferGeometry().setFromPoints( coordinates ); var points = new Points( geometry, null ); raycaster.params.Points.threshold = 1.999; assert.ok( raycaster.intersectObject( points ).length === 0, - "no Points intersection with a not-large-enough threshold" ); + 'no Points intersection with a not-large-enough threshold' ); raycaster.params.Points.threshold = 2.001; assert.ok( raycaster.intersectObject( points ).length === 1, - "successful Points intersection with a large-enough threshold" ); + 'successful Points intersection with a large-enough threshold' ); } ); diff --git a/test/unit/src/core/Uniform.tests.js b/test/unit/src/core/Uniform.tests.js index db13c73d2c55ff..f0123dcb91b992 100644 --- a/test/unit/src/core/Uniform.tests.js +++ b/test/unit/src/core/Uniform.tests.js @@ -13,31 +13,31 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'Uniform', () => { // INSTANCING - QUnit.test( "Instancing", ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { var a; var b = new Vector3( x, y, z ); a = new Uniform( 5 ); - assert.strictEqual( a.value, 5, "New constructor works with simple values" ); + assert.strictEqual( a.value, 5, 'New constructor works with simple values' ); a = new Uniform( b ); - assert.ok( a.value.equals( b ), "New constructor works with complex values" ); + assert.ok( a.value.equals( b ), 'New constructor works with complex values' ); } ); // PUBLIC STUFF - QUnit.test( "clone", ( assert ) => { + QUnit.test( 'clone', ( assert ) => { var a = new Uniform( 23 ); var b = a.clone(); - assert.strictEqual( b.value, a.value, "clone() with simple values works" ); + assert.strictEqual( b.value, a.value, 'clone() with simple values works' ); var a = new Uniform( new Vector3( 1, 2, 3 ) ); var b = a.clone(); - assert.ok( b.value.equals( a.value ), "clone() with complex values works" ); + assert.ok( b.value.equals( a.value ), 'clone() with complex values works' ); } ); diff --git a/test/unit/src/extras/ShapeUtils.tests.js b/test/unit/src/extras/ShapeUtils.tests.js index adc515271b2794..0ff872918e0ff6 100644 --- a/test/unit/src/extras/ShapeUtils.tests.js +++ b/test/unit/src/extras/ShapeUtils.tests.js @@ -7,21 +7,21 @@ export default QUnit.module( 'Extras', () => { QUnit.module( 'ShapeUtils', () => { // PUBLIC STUFF - QUnit.todo( "area", ( assert ) => { + QUnit.todo( 'area', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "isClockWise", ( assert ) => { + QUnit.todo( 'isClockWise', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "triangulateShape", ( assert ) => { + QUnit.todo( 'triangulateShape', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/extras/core/Curve.tests.js b/test/unit/src/extras/core/Curve.tests.js index 1791b33f2412ed..8bf3819705d4a9 100644 --- a/test/unit/src/extras/core/Curve.tests.js +++ b/test/unit/src/extras/core/Curve.tests.js @@ -9,76 +9,76 @@ export default QUnit.module( 'Extras', () => { QUnit.module( 'Curve', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "getPoint", ( assert ) => { + QUnit.todo( 'getPoint', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getPointAt", ( assert ) => { + QUnit.todo( 'getPointAt', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getPoints", ( assert ) => { + QUnit.todo( 'getPoints', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getSpacedPoints", ( assert ) => { + QUnit.todo( 'getSpacedPoints', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getLength", ( assert ) => { + QUnit.todo( 'getLength', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getLengths", ( assert ) => { + QUnit.todo( 'getLengths', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "updateArcLengths", ( assert ) => { + QUnit.todo( 'updateArcLengths', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getUtoTmapping", ( assert ) => { + QUnit.todo( 'getUtoTmapping', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getTangent", ( assert ) => { + QUnit.todo( 'getTangent', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getTangentAt", ( assert ) => { + QUnit.todo( 'getTangentAt', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "computeFrenetFrames", ( assert ) => { + QUnit.todo( 'computeFrenetFrames', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/extras/core/CurvePath.tests.js b/test/unit/src/extras/core/CurvePath.tests.js index 613a0ed12e4d45..1a67f2cb1697f4 100644 --- a/test/unit/src/extras/core/CurvePath.tests.js +++ b/test/unit/src/extras/core/CurvePath.tests.js @@ -9,83 +9,83 @@ export default QUnit.module( 'Extras', () => { QUnit.module( 'CurvePath', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "add", ( assert ) => { + QUnit.todo( 'add', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "closePath", ( assert ) => { + QUnit.todo( 'closePath', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getPoint", ( assert ) => { + QUnit.todo( 'getPoint', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getLength", ( assert ) => { + QUnit.todo( 'getLength', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "updateArcLengths", ( assert ) => { + QUnit.todo( 'updateArcLengths', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getCurveLengths", ( assert ) => { + QUnit.todo( 'getCurveLengths', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getSpacedPoints", ( assert ) => { + QUnit.todo( 'getSpacedPoints', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getPoints", ( assert ) => { + QUnit.todo( 'getPoints', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "createPointsGeometry", ( assert ) => { + QUnit.todo( 'createPointsGeometry', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "createSpacedPointsGeometry", ( assert ) => { + QUnit.todo( 'createSpacedPointsGeometry', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "createGeometry", ( assert ) => { + QUnit.todo( 'createGeometry', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/extras/core/Interpolations.tests.js b/test/unit/src/extras/core/Interpolations.tests.js index bce7edf56c543f..5dc837145a0762 100644 --- a/test/unit/src/extras/core/Interpolations.tests.js +++ b/test/unit/src/extras/core/Interpolations.tests.js @@ -9,21 +9,21 @@ export default QUnit.module( 'Extras', () => { QUnit.module( 'Interpolations', () => { // PUBLIC STUFF - QUnit.todo( "CatmullRom", ( assert ) => { + QUnit.todo( 'CatmullRom', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "QuadraticBezier", ( assert ) => { + QUnit.todo( 'QuadraticBezier', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "CubicBezier", ( assert ) => { + QUnit.todo( 'CubicBezier', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/extras/core/Path.tests.js b/test/unit/src/extras/core/Path.tests.js index a900d699b020c3..76ece638a7f3fd 100644 --- a/test/unit/src/extras/core/Path.tests.js +++ b/test/unit/src/extras/core/Path.tests.js @@ -9,77 +9,77 @@ export default QUnit.module( 'Extras', () => { QUnit.module( 'Path', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "fromPoints", ( assert ) => { + QUnit.todo( 'fromPoints', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "moveTo", ( assert ) => { + QUnit.todo( 'moveTo', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "lineTo", ( assert ) => { + QUnit.todo( 'lineTo', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "quadraticCurveTo", ( assert ) => { + QUnit.todo( 'quadraticCurveTo', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "bezierCurveTo", ( assert ) => { + QUnit.todo( 'bezierCurveTo', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "splineThru", ( assert ) => { + QUnit.todo( 'splineThru', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "arc", ( assert ) => { + QUnit.todo( 'arc', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "absarc", ( assert ) => { + QUnit.todo( 'absarc', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "ellipse", ( assert ) => { + QUnit.todo( 'ellipse', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "absellipse", ( assert ) => { + QUnit.todo( 'absellipse', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/extras/core/Shape.tests.js b/test/unit/src/extras/core/Shape.tests.js index e7ba0150c65a1b..56749d2be7a0c2 100644 --- a/test/unit/src/extras/core/Shape.tests.js +++ b/test/unit/src/extras/core/Shape.tests.js @@ -9,35 +9,35 @@ export default QUnit.module( 'Extras', () => { QUnit.module( 'Shape', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "getPointsHoles", ( assert ) => { + QUnit.todo( 'getPointsHoles', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "extractAllPoints", ( assert ) => { + QUnit.todo( 'extractAllPoints', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "extractPoints", ( assert ) => { + QUnit.todo( 'extractPoints', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/extras/core/ShapePath.tests.js b/test/unit/src/extras/core/ShapePath.tests.js index 1369e501422fc6..649c57b99691cd 100644 --- a/test/unit/src/extras/core/ShapePath.tests.js +++ b/test/unit/src/extras/core/ShapePath.tests.js @@ -9,46 +9,46 @@ export default QUnit.module( 'Extras', () => { QUnit.module( 'ShapePath', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "moveTo", ( assert ) => { + QUnit.todo( 'moveTo', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "lineTo", ( assert ) => { + QUnit.todo( 'lineTo', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "quadraticCurveTo", ( assert ) => { + QUnit.todo( 'quadraticCurveTo', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "bezierCurveTo", ( assert ) => { + QUnit.todo( 'bezierCurveTo', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "splineThru", ( assert ) => { + QUnit.todo( 'splineThru', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "toShapes", ( assert ) => { + QUnit.todo( 'toShapes', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/extras/curves/ArcCurve.tests.js b/test/unit/src/extras/curves/ArcCurve.tests.js index f6299239711b0d..c1d2fc969b0d6e 100644 --- a/test/unit/src/extras/curves/ArcCurve.tests.js +++ b/test/unit/src/extras/curves/ArcCurve.tests.js @@ -9,23 +9,23 @@ export default QUnit.module( 'Extras', () => { QUnit.module( 'ArcCurve', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isArcCurve", ( assert ) => { + QUnit.todo( 'isArcCurve', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/extras/curves/CatmullRomCurve3.tests.js b/test/unit/src/extras/curves/CatmullRomCurve3.tests.js index 4b58aff3846ce9..25b3cc5ab3ab13 100644 --- a/test/unit/src/extras/curves/CatmullRomCurve3.tests.js +++ b/test/unit/src/extras/curves/CatmullRomCurve3.tests.js @@ -20,34 +20,34 @@ export default QUnit.module( 'Extras', () => { /* eslint-enable */ // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isCatmullRomCurve3", ( assert ) => { + QUnit.todo( 'isCatmullRomCurve3', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getPoint", ( assert ) => { + QUnit.todo( 'getPoint', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // OTHERS - QUnit.test( "catmullrom check", ( assert ) => { + QUnit.test( 'catmullrom check', ( assert ) => { var curve = new CatmullRomCurve3( positions ); curve.curveType = 'catmullrom'; @@ -82,7 +82,7 @@ export default QUnit.module( 'Extras', () => { } ); - QUnit.test( "chordal basic check", ( assert ) => { + QUnit.test( 'chordal basic check', ( assert ) => { var curve = new CatmullRomCurve3( positions ); @@ -116,7 +116,7 @@ export default QUnit.module( 'Extras', () => { } ); - QUnit.test( "centripetal basic check", ( assert ) => { + QUnit.test( 'centripetal basic check', ( assert ) => { var curve = new CatmullRomCurve3( positions ); curve.curveType = 'centripetal'; @@ -149,7 +149,7 @@ export default QUnit.module( 'Extras', () => { } ); - QUnit.test( "closed catmullrom basic check", ( assert ) => { + QUnit.test( 'closed catmullrom basic check', ( assert ) => { var curve = new CatmullRomCurve3( positions ); curve.curveType = 'catmullrom'; @@ -186,7 +186,7 @@ export default QUnit.module( 'Extras', () => { // // curve.type = 'catmullrom'; only from here on // - QUnit.test( "getLength/getLengths", ( assert ) => { + QUnit.test( 'getLength/getLengths', ( assert ) => { var curve = new CatmullRomCurve3( positions ); curve.curveType = 'catmullrom'; @@ -194,7 +194,7 @@ export default QUnit.module( 'Extras', () => { var length = curve.getLength(); var expectedLength = 551.549686276872; - assert.numEqual( length, expectedLength, "Correct length of curve" ); + assert.numEqual( length, expectedLength, 'Correct length of curve' ); var expectedLengths = [ 0, @@ -205,17 +205,17 @@ export default QUnit.module( 'Extras', () => { ]; var lengths = curve.getLengths( expectedLengths.length - 1 ); - assert.strictEqual( lengths.length, expectedLengths.length, "Correct number of segments" ); + assert.strictEqual( lengths.length, expectedLengths.length, 'Correct number of segments' ); lengths.forEach( function ( segment, i ) { - assert.numEqual( segment, expectedLengths[ i ], "segment[" + i + "] correct" ); + assert.numEqual( segment, expectedLengths[ i ], 'segment[' + i + '] correct' ); } ); } ); - QUnit.test( "getPointAt", ( assert ) => { + QUnit.test( 'getPointAt', ( assert ) => { var curve = new CatmullRomCurve3( positions ); curve.curveType = 'catmullrom'; @@ -234,11 +234,11 @@ export default QUnit.module( 'Extras', () => { curve.getPointAt( 1, new Vector3() ) ]; - assert.deepEqual( points, expectedPoints, "Correct points" ); + assert.deepEqual( points, expectedPoints, 'Correct points' ); } ); - QUnit.test( "getTangent/getTangentAt", ( assert ) => { + QUnit.test( 'getTangent/getTangentAt', ( assert ) => { var curve = new CatmullRomCurve3( positions ); curve.curveType = 'catmullrom'; @@ -263,8 +263,8 @@ export default QUnit.module( 'Extras', () => { var tangent = tangents[ i ]; - assert.numEqual( tangent.x, exp.x, "getTangent #" + i + ": x correct" ); - assert.numEqual( tangent.y, exp.y, "getTangent #" + i + ": y correct" ); + assert.numEqual( tangent.x, exp.x, 'getTangent #' + i + ': x correct' ); + assert.numEqual( tangent.y, exp.y, 'getTangent #' + i + ': y correct' ); } ); @@ -290,14 +290,14 @@ export default QUnit.module( 'Extras', () => { var tangent = tangents[ i ]; - assert.numEqual( tangent.x, exp.x, "getTangentAt #" + i + ": x correct" ); - assert.numEqual( tangent.y, exp.y, "getTangentAt #" + i + ": y correct" ); + assert.numEqual( tangent.x, exp.x, 'getTangentAt #' + i + ': x correct' ); + assert.numEqual( tangent.y, exp.y, 'getTangentAt #' + i + ': y correct' ); } ); } ); - QUnit.test( "computeFrenetFrames", ( assert ) => { + QUnit.test( 'computeFrenetFrames', ( assert ) => { var curve = new CatmullRomCurve3( positions ); curve.curveType = 'catmullrom'; @@ -326,9 +326,9 @@ export default QUnit.module( 'Extras', () => { expected[ group ].forEach( function ( vec, j ) { - assert.numEqual( frames[ group ][ j ].x, vec.x, "Frenet frames [" + i + ", " + j + "].x correct" ); - assert.numEqual( frames[ group ][ j ].y, vec.y, "Frenet frames [" + i + ", " + j + "].y correct" ); - assert.numEqual( frames[ group ][ j ].z, vec.z, "Frenet frames [" + i + ", " + j + "].z correct" ); + assert.numEqual( frames[ group ][ j ].x, vec.x, 'Frenet frames [' + i + ', ' + j + '].x correct' ); + assert.numEqual( frames[ group ][ j ].y, vec.y, 'Frenet frames [' + i + ', ' + j + '].y correct' ); + assert.numEqual( frames[ group ][ j ].z, vec.z, 'Frenet frames [' + i + ', ' + j + '].z correct' ); } ); @@ -336,7 +336,7 @@ export default QUnit.module( 'Extras', () => { } ); - QUnit.test( "getUtoTmapping", ( assert ) => { + QUnit.test( 'getUtoTmapping', ( assert ) => { var curve = new CatmullRomCurve3( positions ); curve.curveType = 'catmullrom'; @@ -347,13 +347,13 @@ export default QUnit.module( 'Extras', () => { var expectedSomewhere = 0.8964116382083199; - assert.strictEqual( start, 0, "getUtoTmapping( 0, 0 ) is the starting point" ); - assert.strictEqual( end, 1, "getUtoTmapping( 0, length ) is the ending point" ); - assert.numEqual( somewhere, expectedSomewhere, "getUtoTmapping( 0.5, 500 ) is correct" ); + assert.strictEqual( start, 0, 'getUtoTmapping( 0, 0 ) is the starting point' ); + assert.strictEqual( end, 1, 'getUtoTmapping( 0, length ) is the ending point' ); + assert.numEqual( somewhere, expectedSomewhere, 'getUtoTmapping( 0.5, 500 ) is correct' ); } ); - QUnit.test( "getSpacedPoints", ( assert ) => { + QUnit.test( 'getSpacedPoints', ( assert ) => { var curve = new CatmullRomCurve3( positions ); curve.curveType = 'catmullrom'; @@ -369,8 +369,8 @@ export default QUnit.module( 'Extras', () => { var points = curve.getSpacedPoints(); - assert.strictEqual( points.length, expectedPoints.length, "Correct number of points" ); - assert.deepEqual( points, expectedPoints, "Correct points calculated" ); + assert.strictEqual( points.length, expectedPoints.length, 'Correct number of points' ); + assert.deepEqual( points, expectedPoints, 'Correct points calculated' ); } ); diff --git a/test/unit/src/extras/curves/CubicBezierCurve.tests.js b/test/unit/src/extras/curves/CubicBezierCurve.tests.js index 73895a45044fcf..59978ed4397e8d 100644 --- a/test/unit/src/extras/curves/CubicBezierCurve.tests.js +++ b/test/unit/src/extras/curves/CubicBezierCurve.tests.js @@ -22,34 +22,34 @@ export default QUnit.module( 'Extras', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isCubicBezierCurve", ( assert ) => { + QUnit.todo( 'isCubicBezierCurve', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getPoint", ( assert ) => { + QUnit.todo( 'getPoint', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // OTHERS - QUnit.test( "Simple curve", ( assert ) => { + QUnit.test( 'Simple curve', ( assert ) => { var expectedPoints = [ new Vector2( - 10, 0 ), @@ -61,8 +61,8 @@ export default QUnit.module( 'Extras', () => { var points = curve.getPoints( expectedPoints.length - 1 ); - assert.strictEqual( points.length, expectedPoints.length, "Correct number of points" ); - assert.deepEqual( points, expectedPoints, "Correct points calculated" ); + assert.strictEqual( points.length, expectedPoints.length, 'Correct number of points' ); + assert.deepEqual( points, expectedPoints, 'Correct points calculated' ); // symmetry var curveRev = new CubicBezierCurve( @@ -71,17 +71,17 @@ export default QUnit.module( 'Extras', () => { var points = curveRev.getPoints( expectedPoints.length - 1 ); - assert.strictEqual( points.length, expectedPoints.length, "Reversed: Correct number of points" ); - assert.deepEqual( points, expectedPoints.reverse(), "Reversed: Correct points curve" ); + assert.strictEqual( points.length, expectedPoints.length, 'Reversed: Correct number of points' ); + assert.deepEqual( points, expectedPoints.reverse(), 'Reversed: Correct points curve' ); } ); - QUnit.test( "getLength/getLengths", ( assert ) => { + QUnit.test( 'getLength/getLengths', ( assert ) => { var length = curve.getLength(); var expectedLength = 36.64630888504102; - assert.numEqual( length, expectedLength, "Correct length of curve" ); + assert.numEqual( length, expectedLength, 'Correct length of curve' ); var expectedLengths = [ 0, @@ -92,17 +92,17 @@ export default QUnit.module( 'Extras', () => { ]; var lengths = curve.getLengths( expectedLengths.length - 1 ); - assert.strictEqual( lengths.length, expectedLengths.length, "Correct number of segments" ); + assert.strictEqual( lengths.length, expectedLengths.length, 'Correct number of segments' ); lengths.forEach( function ( segment, i ) { - assert.numEqual( segment, expectedLengths[ i ], "segment[" + i + "] correct" ); + assert.numEqual( segment, expectedLengths[ i ], 'segment[' + i + '] correct' ); } ); } ); - QUnit.test( "getPointAt", ( assert ) => { + QUnit.test( 'getPointAt', ( assert ) => { var expectedPoints = [ new Vector2( - 10, 0 ), @@ -118,11 +118,11 @@ export default QUnit.module( 'Extras', () => { curve.getPointAt( 1, new Vector2() ) ]; - assert.deepEqual( points, expectedPoints, "Correct points" ); + assert.deepEqual( points, expectedPoints, 'Correct points' ); } ); - QUnit.test( "getTangent/getTangentAt", ( assert ) => { + QUnit.test( 'getTangent/getTangentAt', ( assert ) => { var expectedTangents = [ new Vector2( 0.316370061632252, 0.9486358543207215 ), @@ -144,8 +144,8 @@ export default QUnit.module( 'Extras', () => { var tangent = tangents[ i ]; - assert.numEqual( tangent.x, exp.x, "getTangent #" + i + ": x correct" ); - assert.numEqual( tangent.y, exp.y, "getTangent #" + i + ": y correct" ); + assert.numEqual( tangent.x, exp.x, 'getTangent #' + i + ': x correct' ); + assert.numEqual( tangent.y, exp.y, 'getTangent #' + i + ': y correct' ); } ); @@ -171,14 +171,14 @@ export default QUnit.module( 'Extras', () => { var tangent = tangents[ i ]; - assert.numEqual( tangent.x, exp.x, "getTangentAt #" + i + ": x correct" ); - assert.numEqual( tangent.y, exp.y, "getTangentAt #" + i + ": y correct" ); + assert.numEqual( tangent.x, exp.x, 'getTangentAt #' + i + ': x correct' ); + assert.numEqual( tangent.y, exp.y, 'getTangentAt #' + i + ': y correct' ); } ); } ); - QUnit.test( "getUtoTmapping", ( assert ) => { + QUnit.test( 'getUtoTmapping', ( assert ) => { var start = curve.getUtoTmapping( 0, 0 ); var end = curve.getUtoTmapping( 0, curve.getLength() ); @@ -186,13 +186,13 @@ export default QUnit.module( 'Extras', () => { var expectedSomewhere = 0.02130029182257093; - assert.strictEqual( start, 0, "getUtoTmapping( 0, 0 ) is the starting point" ); - assert.strictEqual( end, 1, "getUtoTmapping( 0, length ) is the ending point" ); - assert.numEqual( somewhere, expectedSomewhere, "getUtoTmapping( 0.5, 1 ) is correct" ); + assert.strictEqual( start, 0, 'getUtoTmapping( 0, 0 ) is the starting point' ); + assert.strictEqual( end, 1, 'getUtoTmapping( 0, length ) is the ending point' ); + assert.numEqual( somewhere, expectedSomewhere, 'getUtoTmapping( 0.5, 1 ) is correct' ); } ); - QUnit.test( "getSpacedPoints", ( assert ) => { + QUnit.test( 'getSpacedPoints', ( assert ) => { var expectedPoints = [ new Vector2( - 10, 0 ), @@ -205,8 +205,8 @@ export default QUnit.module( 'Extras', () => { var points = curve.getSpacedPoints(); - assert.strictEqual( points.length, expectedPoints.length, "Correct number of points" ); - assert.deepEqual( points, expectedPoints, "Correct points calculated" ); + assert.strictEqual( points.length, expectedPoints.length, 'Correct number of points' ); + assert.deepEqual( points, expectedPoints, 'Correct points calculated' ); } ); diff --git a/test/unit/src/extras/curves/CubicBezierCurve3.tests.js b/test/unit/src/extras/curves/CubicBezierCurve3.tests.js index 51df23c0e09bfc..0f5429d190ea90 100644 --- a/test/unit/src/extras/curves/CubicBezierCurve3.tests.js +++ b/test/unit/src/extras/curves/CubicBezierCurve3.tests.js @@ -22,34 +22,34 @@ export default QUnit.module( 'Extras', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isCubicBezierCurve3", ( assert ) => { + QUnit.todo( 'isCubicBezierCurve3', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getPoint", ( assert ) => { + QUnit.todo( 'getPoint', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // OTHERS - QUnit.test( "Simple curve", ( assert ) => { + QUnit.test( 'Simple curve', ( assert ) => { var expectedPoints = [ new Vector3( - 10, 0, 2 ), @@ -61,8 +61,8 @@ export default QUnit.module( 'Extras', () => { var points = curve.getPoints( expectedPoints.length - 1 ); - assert.strictEqual( points.length, expectedPoints.length, "Correct number of points" ); - assert.deepEqual( points, expectedPoints, "Correct points calculated" ); + assert.strictEqual( points.length, expectedPoints.length, 'Correct number of points' ); + assert.deepEqual( points, expectedPoints, 'Correct points calculated' ); // symmetry var curveRev = new CubicBezierCurve3( @@ -71,17 +71,17 @@ export default QUnit.module( 'Extras', () => { points = curveRev.getPoints( expectedPoints.length - 1 ); - assert.strictEqual( points.length, expectedPoints.length, "Reversed: Correct number of points" ); - assert.deepEqual( points, expectedPoints.reverse(), "Reversed: Correct points curve" ); + assert.strictEqual( points.length, expectedPoints.length, 'Reversed: Correct number of points' ); + assert.deepEqual( points, expectedPoints.reverse(), 'Reversed: Correct points curve' ); } ); - QUnit.test( "getLength/getLengths", ( assert ) => { + QUnit.test( 'getLength/getLengths', ( assert ) => { var length = curve.getLength(); var expectedLength = 39.58103024989427; - assert.numEqual( length, expectedLength, "Correct length of curve" ); + assert.numEqual( length, expectedLength, 'Correct length of curve' ); var expectedLengths = [ 0, @@ -92,17 +92,17 @@ export default QUnit.module( 'Extras', () => { ]; var lengths = curve.getLengths( expectedLengths.length - 1 ); - assert.strictEqual( lengths.length, expectedLengths.length, "Correct number of segments" ); + assert.strictEqual( lengths.length, expectedLengths.length, 'Correct number of segments' ); lengths.forEach( function ( segment, i ) { - assert.numEqual( segment, expectedLengths[ i ], "segment[" + i + "] correct" ); + assert.numEqual( segment, expectedLengths[ i ], 'segment[' + i + '] correct' ); } ); } ); - QUnit.test( "getPointAt", ( assert ) => { + QUnit.test( 'getPointAt', ( assert ) => { var expectedPoints = [ new Vector3( - 10, 0, 2 ), @@ -118,11 +118,11 @@ export default QUnit.module( 'Extras', () => { curve.getPointAt( 1, new Vector3() ) ]; - assert.deepEqual( points, expectedPoints, "Correct points" ); + assert.deepEqual( points, expectedPoints, 'Correct points' ); } ); - QUnit.test( "getTangent/getTangentAt", ( assert ) => { + QUnit.test( 'getTangent/getTangentAt', ( assert ) => { var expectedTangents = [ new Vector3( 0.3138715439944244, 0.9411440474105875, 0.12542940601858074 ), @@ -144,8 +144,8 @@ export default QUnit.module( 'Extras', () => { var tangent = tangents[ i ]; - assert.numEqual( tangent.x, exp.x, "getTangent #" + i + ": x correct" ); - assert.numEqual( tangent.y, exp.y, "getTangent #" + i + ": y correct" ); + assert.numEqual( tangent.x, exp.x, 'getTangent #' + i + ': x correct' ); + assert.numEqual( tangent.y, exp.y, 'getTangent #' + i + ': y correct' ); } ); @@ -171,14 +171,14 @@ export default QUnit.module( 'Extras', () => { var tangent = tangents[ i ]; - assert.numEqual( tangent.x, exp.x, "getTangentAt #" + i + ": x correct" ); - assert.numEqual( tangent.y, exp.y, "getTangentAt #" + i + ": y correct" ); + assert.numEqual( tangent.x, exp.x, 'getTangentAt #' + i + ': x correct' ); + assert.numEqual( tangent.y, exp.y, 'getTangentAt #' + i + ': y correct' ); } ); } ); - QUnit.test( "getUtoTmapping", ( assert ) => { + QUnit.test( 'getUtoTmapping', ( assert ) => { var start = curve.getUtoTmapping( 0, 0 ); var end = curve.getUtoTmapping( 0, curve.getLength() ); @@ -186,13 +186,13 @@ export default QUnit.module( 'Extras', () => { var expectedSomewhere = 0.021163245321323316; - assert.strictEqual( start, 0, "getUtoTmapping( 0, 0 ) is the starting point" ); - assert.strictEqual( end, 1, "getUtoTmapping( 0, length ) is the ending point" ); - assert.numEqual( somewhere, expectedSomewhere, "getUtoTmapping( 0.5, 1 ) is correct" ); + assert.strictEqual( start, 0, 'getUtoTmapping( 0, 0 ) is the starting point' ); + assert.strictEqual( end, 1, 'getUtoTmapping( 0, length ) is the ending point' ); + assert.numEqual( somewhere, expectedSomewhere, 'getUtoTmapping( 0.5, 1 ) is correct' ); } ); - QUnit.test( "getSpacedPoints", ( assert ) => { + QUnit.test( 'getSpacedPoints', ( assert ) => { var expectedPoints = [ new Vector3( - 10, 0, 2 ), @@ -205,12 +205,12 @@ export default QUnit.module( 'Extras', () => { var points = curve.getSpacedPoints(); - assert.strictEqual( points.length, expectedPoints.length, "Correct number of points" ); - assert.deepEqual( points, expectedPoints, "Correct points calculated" ); + assert.strictEqual( points.length, expectedPoints.length, 'Correct number of points' ); + assert.deepEqual( points, expectedPoints, 'Correct points calculated' ); } ); - QUnit.test( "computeFrenetFrames", ( assert ) => { + QUnit.test( 'computeFrenetFrames', ( assert ) => { var expected = { binormals: [ @@ -236,9 +236,9 @@ export default QUnit.module( 'Extras', () => { expected[ group ].forEach( function ( vec, j ) { - assert.numEqual( frames[ group ][ j ].x, vec.x, "Frenet frames [" + i + ", " + j + "].x correct" ); - assert.numEqual( frames[ group ][ j ].y, vec.y, "Frenet frames [" + i + ", " + j + "].y correct" ); - assert.numEqual( frames[ group ][ j ].z, vec.z, "Frenet frames [" + i + ", " + j + "].z correct" ); + assert.numEqual( frames[ group ][ j ].x, vec.x, 'Frenet frames [' + i + ', ' + j + '].x correct' ); + assert.numEqual( frames[ group ][ j ].y, vec.y, 'Frenet frames [' + i + ', ' + j + '].y correct' ); + assert.numEqual( frames[ group ][ j ].z, vec.z, 'Frenet frames [' + i + ', ' + j + '].z correct' ); } ); diff --git a/test/unit/src/extras/curves/EllipseCurve.tests.js b/test/unit/src/extras/curves/EllipseCurve.tests.js index 396dd2fec87f73..234bb3e58dc432 100644 --- a/test/unit/src/extras/curves/EllipseCurve.tests.js +++ b/test/unit/src/extras/curves/EllipseCurve.tests.js @@ -23,34 +23,34 @@ export default QUnit.module( 'Extras', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isEllipseCurve", ( assert ) => { + QUnit.todo( 'isEllipseCurve', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getPoint", ( assert ) => { + QUnit.todo( 'getPoint', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // OTHERS - QUnit.test( "Simple curve", ( assert ) => { + QUnit.test( 'Simple curve', ( assert ) => { var expectedPoints = [ new Vector2( 10, 0 ), @@ -62,23 +62,23 @@ export default QUnit.module( 'Extras', () => { var points = curve.getPoints( expectedPoints.length - 1 ); - assert.strictEqual( points.length, expectedPoints.length, "Correct number of points" ); + assert.strictEqual( points.length, expectedPoints.length, 'Correct number of points' ); points.forEach( function ( point, i ) { - assert.numEqual( point.x, expectedPoints[ i ].x, "point[" + i + "].x correct" ); - assert.numEqual( point.y, expectedPoints[ i ].y, "point[" + i + "].y correct" ); + assert.numEqual( point.x, expectedPoints[ i ].x, 'point[' + i + '].x correct' ); + assert.numEqual( point.y, expectedPoints[ i ].y, 'point[' + i + '].y correct' ); } ); } ); - QUnit.test( "getLength/getLengths", ( assert ) => { + QUnit.test( 'getLength/getLengths', ( assert ) => { var length = curve.getLength(); var expectedLength = 62.829269247282795; - assert.numEqual( length, expectedLength, "Correct length of curve" ); + assert.numEqual( length, expectedLength, 'Correct length of curve' ); var lengths = curve.getLengths( 5 ); var expectedLengths = [ @@ -90,17 +90,17 @@ export default QUnit.module( 'Extras', () => { 58.77852522924731 ]; - assert.strictEqual( lengths.length, expectedLengths.length, "Correct number of segments" ); + assert.strictEqual( lengths.length, expectedLengths.length, 'Correct number of segments' ); lengths.forEach( function ( segment, i ) { - assert.numEqual( segment, expectedLengths[ i ], "segment[" + i + "] correct" ); + assert.numEqual( segment, expectedLengths[ i ], 'segment[' + i + '] correct' ); } ); } ); - QUnit.test( "getPoint/getPointAt", ( assert ) => { + QUnit.test( 'getPoint/getPointAt', ( assert ) => { var testValues = [ 0, 0.3, 0.5, 0.7, 1 ]; @@ -115,17 +115,17 @@ export default QUnit.module( 'Extras', () => { curve.getPoint( val, p ); curve.getPointAt( val, a ); - assert.numEqual( p.x, expectedX, "getPoint(" + val + ").x correct" ); - assert.numEqual( p.y, expectedY, "getPoint(" + val + ").y correct" ); + assert.numEqual( p.x, expectedX, 'getPoint(' + val + ').x correct' ); + assert.numEqual( p.y, expectedY, 'getPoint(' + val + ').y correct' ); - assert.numEqual( a.x, expectedX, "getPointAt(" + val + ").x correct" ); - assert.numEqual( a.y, expectedY, "getPointAt(" + val + ").y correct" ); + assert.numEqual( a.x, expectedX, 'getPointAt(' + val + ').x correct' ); + assert.numEqual( a.y, expectedY, 'getPointAt(' + val + ').y correct' ); } ); } ); - QUnit.test( "getTangent", ( assert ) => { + QUnit.test( 'getTangent', ( assert ) => { var expectedTangents = [ new Vector2( - 0.000314159260186071, 0.9999999506519786 ), @@ -147,14 +147,14 @@ export default QUnit.module( 'Extras', () => { var tangent = tangents[ i ]; - assert.numEqual( tangent.x, exp.x, "getTangent #" + i + ": x correct" ); - assert.numEqual( tangent.y, exp.y, "getTangent #" + i + ": y correct" ); + assert.numEqual( tangent.x, exp.x, 'getTangent #' + i + ': x correct' ); + assert.numEqual( tangent.y, exp.y, 'getTangent #' + i + ': y correct' ); } ); } ); - QUnit.test( "getUtoTmapping", ( assert ) => { + QUnit.test( 'getUtoTmapping', ( assert ) => { var start = curve.getUtoTmapping( 0, 0 ); var end = curve.getUtoTmapping( 0, curve.getLength() ); @@ -162,13 +162,13 @@ export default QUnit.module( 'Extras', () => { var expectedSomewhere = 0.01591614882650014; - assert.strictEqual( start, 0, "getUtoTmapping( 0, 0 ) is the starting point" ); - assert.strictEqual( end, 1, "getUtoTmapping( 0, length ) is the ending point" ); - assert.numEqual( somewhere, expectedSomewhere, "getUtoTmapping( 0.7, 1 ) is correct" ); + assert.strictEqual( start, 0, 'getUtoTmapping( 0, 0 ) is the starting point' ); + assert.strictEqual( end, 1, 'getUtoTmapping( 0, length ) is the ending point' ); + assert.numEqual( somewhere, expectedSomewhere, 'getUtoTmapping( 0.7, 1 ) is correct' ); } ); - QUnit.test( "getSpacedPoints", ( assert ) => { + QUnit.test( 'getSpacedPoints', ( assert ) => { var expectedPoints = [ new Vector2( 10, 0 ), @@ -181,14 +181,14 @@ export default QUnit.module( 'Extras', () => { var points = curve.getSpacedPoints(); - assert.strictEqual( points.length, expectedPoints.length, "Correct number of points" ); + assert.strictEqual( points.length, expectedPoints.length, 'Correct number of points' ); expectedPoints.forEach( function ( exp, i ) { var point = points[ i ]; - assert.numEqual( point.x, exp.x, "Point #" + i + ": x correct" ); - assert.numEqual( point.y, exp.y, "Point #" + i + ": y correct" ); + assert.numEqual( point.x, exp.x, 'Point #' + i + ': x correct' ); + assert.numEqual( point.y, exp.y, 'Point #' + i + ': y correct' ); } ); diff --git a/test/unit/src/extras/curves/LineCurve.tests.js b/test/unit/src/extras/curves/LineCurve.tests.js index 407800596e0476..977b7ccf2c1a7b 100644 --- a/test/unit/src/extras/curves/LineCurve.tests.js +++ b/test/unit/src/extras/curves/LineCurve.tests.js @@ -25,33 +25,33 @@ export default QUnit.module( 'Extras', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isLineCurve", ( assert ) => { + QUnit.todo( 'isLineCurve', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getPoint", ( assert ) => { + QUnit.todo( 'getPoint', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "getPointAt", ( assert ) => { + QUnit.test( 'getPointAt', ( assert ) => { var curve = new LineCurve( _points[ 0 ], _points[ 3 ] ); @@ -69,11 +69,11 @@ export default QUnit.module( 'Extras', () => { curve.getPointAt( 1, new Vector2() ) ]; - assert.deepEqual( points, expectedPoints, "Correct points" ); + assert.deepEqual( points, expectedPoints, 'Correct points' ); } ); - QUnit.test( "getTangent", ( assert ) => { + QUnit.test( 'getTangent', ( assert ) => { var curve = _curve; var tangent = new Vector2(); @@ -81,13 +81,13 @@ export default QUnit.module( 'Extras', () => { curve.getTangent( 0, tangent ); var expectedTangent = Math.sqrt( 0.5 ); - assert.numEqual( tangent.x, expectedTangent, "tangent.x correct" ); - assert.numEqual( tangent.y, expectedTangent, "tangent.y correct" ); + assert.numEqual( tangent.x, expectedTangent, 'tangent.x correct' ); + assert.numEqual( tangent.y, expectedTangent, 'tangent.y correct' ); } ); // OTHERS - QUnit.test( "Simple curve", ( assert ) => { + QUnit.test( 'Simple curve', ( assert ) => { var curve = _curve; @@ -102,7 +102,7 @@ export default QUnit.module( 'Extras', () => { var points = curve.getPoints(); - assert.deepEqual( points, expectedPoints, "Correct points for first curve" ); + assert.deepEqual( points, expectedPoints, 'Correct points for first curve' ); // @@ -119,18 +119,18 @@ export default QUnit.module( 'Extras', () => { points = curve.getPoints(); - assert.deepEqual( points, expectedPoints, "Correct points for second curve" ); + assert.deepEqual( points, expectedPoints, 'Correct points for second curve' ); } ); - QUnit.test( "getLength/getLengths", ( assert ) => { + QUnit.test( 'getLength/getLengths', ( assert ) => { var curve = _curve; var length = curve.getLength(); var expectedLength = Math.sqrt( 200 ); - assert.numEqual( length, expectedLength, "Correct length of curve" ); + assert.numEqual( length, expectedLength, 'Correct length of curve' ); var lengths = curve.getLengths( 5 ); var expectedLengths = [ @@ -142,17 +142,17 @@ export default QUnit.module( 'Extras', () => { Math.sqrt( 200 ) ]; - assert.strictEqual( lengths.length, expectedLengths.length, "Correct number of segments" ); + assert.strictEqual( lengths.length, expectedLengths.length, 'Correct number of segments' ); lengths.forEach( function ( segment, i ) { - assert.numEqual( segment, expectedLengths[ i ], "segment[" + i + "] correct" ); + assert.numEqual( segment, expectedLengths[ i ], 'segment[' + i + '] correct' ); } ); } ); - QUnit.test( "getUtoTmapping", ( assert ) => { + QUnit.test( 'getUtoTmapping', ( assert ) => { var curve = _curve; @@ -160,13 +160,13 @@ export default QUnit.module( 'Extras', () => { var end = curve.getUtoTmapping( 0, curve.getLength() ); var somewhere = curve.getUtoTmapping( 0.3, 0 ); - assert.strictEqual( start, 0, "getUtoTmapping( 0, 0 ) is the starting point" ); - assert.strictEqual( end, 1, "getUtoTmapping( 0, length ) is the ending point" ); - assert.numEqual( somewhere, 0.3, "getUtoTmapping( 0.3, 0 ) is correct" ); + assert.strictEqual( start, 0, 'getUtoTmapping( 0, 0 ) is the starting point' ); + assert.strictEqual( end, 1, 'getUtoTmapping( 0, length ) is the ending point' ); + assert.numEqual( somewhere, 0.3, 'getUtoTmapping( 0.3, 0 ) is correct' ); } ); - QUnit.test( "getSpacedPoints", ( assert ) => { + QUnit.test( 'getSpacedPoints', ( assert ) => { var curve = _curve; @@ -180,8 +180,8 @@ export default QUnit.module( 'Extras', () => { var points = curve.getSpacedPoints( 4 ); - assert.strictEqual( points.length, expectedPoints.length, "Correct number of points" ); - assert.deepEqual( points, expectedPoints, "Correct points calculated" ); + assert.strictEqual( points.length, expectedPoints.length, 'Correct number of points' ); + assert.deepEqual( points, expectedPoints, 'Correct points calculated' ); } ); diff --git a/test/unit/src/extras/curves/LineCurve3.tests.js b/test/unit/src/extras/curves/LineCurve3.tests.js index 103dbac89981a1..2522c4ecdf3af8 100644 --- a/test/unit/src/extras/curves/LineCurve3.tests.js +++ b/test/unit/src/extras/curves/LineCurve3.tests.js @@ -25,33 +25,33 @@ export default QUnit.module( 'Extras', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isCatmullRomCurve3", ( assert ) => { + QUnit.todo( 'isCatmullRomCurve3', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getPoint", ( assert ) => { + QUnit.todo( 'getPoint', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "getPointAt", ( assert ) => { + QUnit.test( 'getPointAt', ( assert ) => { var curve = new LineCurve3( _points[ 0 ], _points[ 3 ] ); @@ -69,12 +69,12 @@ export default QUnit.module( 'Extras', () => { curve.getPointAt( 1, new Vector3() ) ]; - assert.deepEqual( points, expectedPoints, "Correct getPointAt points" ); + assert.deepEqual( points, expectedPoints, 'Correct getPointAt points' ); } ); // OTHERS - QUnit.test( "Simple curve", ( assert ) => { + QUnit.test( 'Simple curve', ( assert ) => { var curve = _curve; @@ -89,7 +89,7 @@ export default QUnit.module( 'Extras', () => { var points = curve.getPoints(); - assert.deepEqual( points, expectedPoints, "Correct points for first curve" ); + assert.deepEqual( points, expectedPoints, 'Correct points for first curve' ); // @@ -106,18 +106,18 @@ export default QUnit.module( 'Extras', () => { points = curve.getPoints(); - assert.deepEqual( points, expectedPoints, "Correct points for second curve" ); + assert.deepEqual( points, expectedPoints, 'Correct points for second curve' ); } ); - QUnit.test( "getLength/getLengths", ( assert ) => { + QUnit.test( 'getLength/getLengths', ( assert ) => { var curve = _curve; var length = curve.getLength(); var expectedLength = Math.sqrt( 300 ); - assert.numEqual( length, expectedLength, "Correct length of curve" ); + assert.numEqual( length, expectedLength, 'Correct length of curve' ); var lengths = curve.getLengths( 5 ); var expectedLengths = [ @@ -129,17 +129,17 @@ export default QUnit.module( 'Extras', () => { Math.sqrt( 300 ) ]; - assert.strictEqual( lengths.length, expectedLengths.length, "Correct number of segments" ); + assert.strictEqual( lengths.length, expectedLengths.length, 'Correct number of segments' ); lengths.forEach( function ( segment, i ) { - assert.numEqual( segment, expectedLengths[ i ], "segment[" + i + "] correct" ); + assert.numEqual( segment, expectedLengths[ i ], 'segment[' + i + '] correct' ); } ); } ); - QUnit.test( "getTangent/getTangentAt", ( assert ) => { + QUnit.test( 'getTangent/getTangentAt', ( assert ) => { var curve = _curve; var tangent = new Vector3(); @@ -147,19 +147,19 @@ export default QUnit.module( 'Extras', () => { curve.getTangent( 0.5, tangent ); var expectedTangent = Math.sqrt( 1 / 3 ); - assert.numEqual( tangent.x, expectedTangent, "tangent.x correct" ); - assert.numEqual( tangent.y, expectedTangent, "tangent.y correct" ); - assert.numEqual( tangent.z, expectedTangent, "tangent.z correct" ); + assert.numEqual( tangent.x, expectedTangent, 'tangent.x correct' ); + assert.numEqual( tangent.y, expectedTangent, 'tangent.y correct' ); + assert.numEqual( tangent.z, expectedTangent, 'tangent.z correct' ); tangent = curve.getTangentAt( 0.5 ); - assert.numEqual( tangent.x, expectedTangent, "tangentAt.x correct" ); - assert.numEqual( tangent.y, expectedTangent, "tangentAt.y correct" ); - assert.numEqual( tangent.z, expectedTangent, "tangentAt.z correct" ); + assert.numEqual( tangent.x, expectedTangent, 'tangentAt.x correct' ); + assert.numEqual( tangent.y, expectedTangent, 'tangentAt.y correct' ); + assert.numEqual( tangent.z, expectedTangent, 'tangentAt.z correct' ); } ); - QUnit.test( "computeFrenetFrames", ( assert ) => { + QUnit.test( 'computeFrenetFrames', ( assert ) => { var curve = _curve; @@ -173,15 +173,15 @@ export default QUnit.module( 'Extras', () => { for ( var val in expected ) { - assert.numEqual( frames[ val ][ 0 ].x, expected[ val ].x, "Frenet frames " + val + ".x correct" ); - assert.numEqual( frames[ val ][ 0 ].y, expected[ val ].y, "Frenet frames " + val + ".y correct" ); - assert.numEqual( frames[ val ][ 0 ].z, expected[ val ].z, "Frenet frames " + val + ".z correct" ); + assert.numEqual( frames[ val ][ 0 ].x, expected[ val ].x, 'Frenet frames ' + val + '.x correct' ); + assert.numEqual( frames[ val ][ 0 ].y, expected[ val ].y, 'Frenet frames ' + val + '.y correct' ); + assert.numEqual( frames[ val ][ 0 ].z, expected[ val ].z, 'Frenet frames ' + val + '.z correct' ); } } ); - QUnit.test( "getUtoTmapping", ( assert ) => { + QUnit.test( 'getUtoTmapping', ( assert ) => { var curve = _curve; @@ -189,13 +189,13 @@ export default QUnit.module( 'Extras', () => { var end = curve.getUtoTmapping( 0, curve.getLength() ); var somewhere = curve.getUtoTmapping( 0.7, 0 ); - assert.strictEqual( start, 0, "getUtoTmapping( 0, 0 ) is the starting point" ); - assert.strictEqual( end, 1, "getUtoTmapping( 0, length ) is the ending point" ); - assert.numEqual( somewhere, 0.7, "getUtoTmapping( 0.7, 0 ) is correct" ); + assert.strictEqual( start, 0, 'getUtoTmapping( 0, 0 ) is the starting point' ); + assert.strictEqual( end, 1, 'getUtoTmapping( 0, length ) is the ending point' ); + assert.numEqual( somewhere, 0.7, 'getUtoTmapping( 0.7, 0 ) is correct' ); } ); - QUnit.test( "getSpacedPoints", ( assert ) => { + QUnit.test( 'getSpacedPoints', ( assert ) => { var curve = _curve; @@ -209,8 +209,8 @@ export default QUnit.module( 'Extras', () => { var points = curve.getSpacedPoints( 4 ); - assert.strictEqual( points.length, expectedPoints.length, "Correct number of points" ); - assert.deepEqual( points, expectedPoints, "Correct points calculated" ); + assert.strictEqual( points.length, expectedPoints.length, 'Correct number of points' ); + assert.deepEqual( points, expectedPoints, 'Correct points calculated' ); } ); diff --git a/test/unit/src/extras/curves/QuadraticBezierCurve.tests.js b/test/unit/src/extras/curves/QuadraticBezierCurve.tests.js index 2b20d17487c5ae..7e2a0819c4d2f9 100644 --- a/test/unit/src/extras/curves/QuadraticBezierCurve.tests.js +++ b/test/unit/src/extras/curves/QuadraticBezierCurve.tests.js @@ -21,34 +21,34 @@ export default QUnit.module( 'Extras', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isQuadraticBezierCurve", ( assert ) => { + QUnit.todo( 'isQuadraticBezierCurve', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getPoint", ( assert ) => { + QUnit.todo( 'getPoint', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // OTHERS - QUnit.test( "Simple curve", ( assert ) => { + QUnit.test( 'Simple curve', ( assert ) => { var curve = _curve; @@ -62,8 +62,8 @@ export default QUnit.module( 'Extras', () => { var points = curve.getPoints( expectedPoints.length - 1 ); - assert.strictEqual( points.length, expectedPoints.length, "Correct number of points" ); - assert.deepEqual( points, expectedPoints, "Correct points calculated" ); + assert.strictEqual( points.length, expectedPoints.length, 'Correct number of points' ); + assert.deepEqual( points, expectedPoints, 'Correct points calculated' ); // symmetry var curveRev = new QuadraticBezierCurve( @@ -72,19 +72,19 @@ export default QUnit.module( 'Extras', () => { points = curveRev.getPoints( expectedPoints.length - 1 ); - assert.strictEqual( points.length, expectedPoints.length, "Reversed: Correct number of points" ); - assert.deepEqual( points, expectedPoints.reverse(), "Reversed: Correct points curve" ); + assert.strictEqual( points.length, expectedPoints.length, 'Reversed: Correct number of points' ); + assert.deepEqual( points, expectedPoints.reverse(), 'Reversed: Correct points curve' ); } ); - QUnit.test( "getLength/getLengths", ( assert ) => { + QUnit.test( 'getLength/getLengths', ( assert ) => { var curve = _curve; var length = curve.getLength(); var expectedLength = 31.269026549416683; - assert.numEqual( length, expectedLength, "Correct length of curve" ); + assert.numEqual( length, expectedLength, 'Correct length of curve' ); var expectedLengths = [ 0, @@ -95,17 +95,17 @@ export default QUnit.module( 'Extras', () => { ]; var lengths = curve.getLengths( expectedLengths.length - 1 ); - assert.strictEqual( lengths.length, expectedLengths.length, "Correct number of segments" ); + assert.strictEqual( lengths.length, expectedLengths.length, 'Correct number of segments' ); lengths.forEach( function ( segment, i ) { - assert.numEqual( segment, expectedLengths[ i ], "segment[" + i + "] correct" ); + assert.numEqual( segment, expectedLengths[ i ], 'segment[' + i + '] correct' ); } ); } ); - QUnit.test( "getPointAt", ( assert ) => { + QUnit.test( 'getPointAt', ( assert ) => { var curve = _curve; @@ -123,11 +123,11 @@ export default QUnit.module( 'Extras', () => { curve.getPointAt( 1, new Vector2() ) ]; - assert.deepEqual( points, expectedPoints, "Correct points" ); + assert.deepEqual( points, expectedPoints, 'Correct points' ); } ); - QUnit.test( "getTangent/getTangentAt", ( assert ) => { + QUnit.test( 'getTangent/getTangentAt', ( assert ) => { var curve = _curve; @@ -151,8 +151,8 @@ export default QUnit.module( 'Extras', () => { var tangent = tangents[ i ]; - assert.numEqual( tangent.x, exp.x, "getTangent #" + i + ": x correct" ); - assert.numEqual( tangent.y, exp.y, "getTangent #" + i + ": y correct" ); + assert.numEqual( tangent.x, exp.x, 'getTangent #' + i + ': x correct' ); + assert.numEqual( tangent.y, exp.y, 'getTangent #' + i + ': y correct' ); } ); @@ -178,14 +178,14 @@ export default QUnit.module( 'Extras', () => { var tangent = tangents[ i ]; - assert.numEqual( tangent.x, exp.x, "getTangentAt #" + i + ": x correct" ); - assert.numEqual( tangent.y, exp.y, "getTangentAt #" + i + ": y correct" ); + assert.numEqual( tangent.x, exp.x, 'getTangentAt #' + i + ': x correct' ); + assert.numEqual( tangent.y, exp.y, 'getTangentAt #' + i + ': y correct' ); } ); } ); - QUnit.test( "getUtoTmapping", ( assert ) => { + QUnit.test( 'getUtoTmapping', ( assert ) => { var curve = _curve; @@ -195,13 +195,13 @@ export default QUnit.module( 'Extras', () => { var expectedSomewhere = 0.015073978276116116; - assert.strictEqual( start, 0, "getUtoTmapping( 0, 0 ) is the starting point" ); - assert.strictEqual( end, 1, "getUtoTmapping( 0, length ) is the ending point" ); - assert.numEqual( somewhere, expectedSomewhere, "getUtoTmapping( 0.5, 1 ) is correct" ); + assert.strictEqual( start, 0, 'getUtoTmapping( 0, 0 ) is the starting point' ); + assert.strictEqual( end, 1, 'getUtoTmapping( 0, length ) is the ending point' ); + assert.numEqual( somewhere, expectedSomewhere, 'getUtoTmapping( 0.5, 1 ) is correct' ); } ); - QUnit.test( "getSpacedPoints", ( assert ) => { + QUnit.test( 'getSpacedPoints', ( assert ) => { var curve = _curve; @@ -216,8 +216,8 @@ export default QUnit.module( 'Extras', () => { var points = curve.getSpacedPoints(); - assert.strictEqual( points.length, expectedPoints.length, "Correct number of points" ); - assert.deepEqual( points, expectedPoints, "Correct points calculated" ); + assert.strictEqual( points.length, expectedPoints.length, 'Correct number of points' ); + assert.deepEqual( points, expectedPoints, 'Correct points calculated' ); } ); diff --git a/test/unit/src/extras/curves/QuadraticBezierCurve3.tests.js b/test/unit/src/extras/curves/QuadraticBezierCurve3.tests.js index 4448e32419d6fd..c39d4e1033580c 100644 --- a/test/unit/src/extras/curves/QuadraticBezierCurve3.tests.js +++ b/test/unit/src/extras/curves/QuadraticBezierCurve3.tests.js @@ -21,34 +21,34 @@ export default QUnit.module( 'Extras', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isQuadraticBezierCurve3", ( assert ) => { + QUnit.todo( 'isQuadraticBezierCurve3', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getPoint", ( assert ) => { + QUnit.todo( 'getPoint', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // OTHERS - QUnit.test( "Simple curve", ( assert ) => { + QUnit.test( 'Simple curve', ( assert ) => { var curve = _curve; @@ -62,8 +62,8 @@ export default QUnit.module( 'Extras', () => { var points = curve.getPoints( expectedPoints.length - 1 ); - assert.strictEqual( points.length, expectedPoints.length, "Correct number of points" ); - assert.deepEqual( points, expectedPoints, "Correct points calculated" ); + assert.strictEqual( points.length, expectedPoints.length, 'Correct number of points' ); + assert.deepEqual( points, expectedPoints, 'Correct points calculated' ); // symmetry var curveRev = new QuadraticBezierCurve3( @@ -72,19 +72,19 @@ export default QUnit.module( 'Extras', () => { points = curveRev.getPoints( expectedPoints.length - 1 ); - assert.strictEqual( points.length, expectedPoints.length, "Reversed: Correct number of points" ); - assert.deepEqual( points, expectedPoints.reverse(), "Reversed: Correct points curve" ); + assert.strictEqual( points.length, expectedPoints.length, 'Reversed: Correct number of points' ); + assert.deepEqual( points, expectedPoints.reverse(), 'Reversed: Correct points curve' ); } ); - QUnit.test( "getLength/getLengths", ( assert ) => { + QUnit.test( 'getLength/getLengths', ( assert ) => { var curve = _curve; var length = curve.getLength(); var expectedLength = 35.47294274967861; - assert.numEqual( length, expectedLength, "Correct length of curve" ); + assert.numEqual( length, expectedLength, 'Correct length of curve' ); var expectedLengths = [ 0, @@ -95,17 +95,17 @@ export default QUnit.module( 'Extras', () => { ]; var lengths = curve.getLengths( expectedLengths.length - 1 ); - assert.strictEqual( lengths.length, expectedLengths.length, "Correct number of segments" ); + assert.strictEqual( lengths.length, expectedLengths.length, 'Correct number of segments' ); lengths.forEach( function ( segment, i ) { - assert.numEqual( segment, expectedLengths[ i ], "segment[" + i + "] correct" ); + assert.numEqual( segment, expectedLengths[ i ], 'segment[' + i + '] correct' ); } ); } ); - QUnit.test( "getPointAt", ( assert ) => { + QUnit.test( 'getPointAt', ( assert ) => { var curve = _curve; @@ -123,11 +123,11 @@ export default QUnit.module( 'Extras', () => { curve.getPointAt( 1, new Vector3() ) ]; - assert.deepEqual( points, expectedPoints, "Correct points" ); + assert.deepEqual( points, expectedPoints, 'Correct points' ); } ); - QUnit.test( "getTangent/getTangentAt", ( assert ) => { + QUnit.test( 'getTangent/getTangentAt', ( assert ) => { var curve = _curve; @@ -151,8 +151,8 @@ export default QUnit.module( 'Extras', () => { var tangent = tangents[ i ]; - assert.numEqual( tangent.x, exp.x, "getTangent #" + i + ": x correct" ); - assert.numEqual( tangent.y, exp.y, "getTangent #" + i + ": y correct" ); + assert.numEqual( tangent.x, exp.x, 'getTangent #' + i + ': x correct' ); + assert.numEqual( tangent.y, exp.y, 'getTangent #' + i + ': y correct' ); } ); @@ -178,14 +178,14 @@ export default QUnit.module( 'Extras', () => { var tangent = tangents[ i ]; - assert.numEqual( tangent.x, exp.x, "getTangentAt #" + i + ": x correct" ); - assert.numEqual( tangent.y, exp.y, "getTangentAt #" + i + ": y correct" ); + assert.numEqual( tangent.x, exp.x, 'getTangentAt #' + i + ': x correct' ); + assert.numEqual( tangent.y, exp.y, 'getTangentAt #' + i + ': y correct' ); } ); } ); - QUnit.test( "getUtoTmapping", ( assert ) => { + QUnit.test( 'getUtoTmapping', ( assert ) => { var curve = _curve; @@ -195,13 +195,13 @@ export default QUnit.module( 'Extras', () => { var expectedSomewhere = 0.014760890927167196; - assert.strictEqual( start, 0, "getUtoTmapping( 0, 0 ) is the starting point" ); - assert.strictEqual( end, 1, "getUtoTmapping( 0, length ) is the ending point" ); - assert.numEqual( somewhere, expectedSomewhere, "getUtoTmapping( 0.5, 1 ) is correct" ); + assert.strictEqual( start, 0, 'getUtoTmapping( 0, 0 ) is the starting point' ); + assert.strictEqual( end, 1, 'getUtoTmapping( 0, length ) is the ending point' ); + assert.numEqual( somewhere, expectedSomewhere, 'getUtoTmapping( 0.5, 1 ) is correct' ); } ); - QUnit.test( "getSpacedPoints", ( assert ) => { + QUnit.test( 'getSpacedPoints', ( assert ) => { var curve = _curve; @@ -216,12 +216,12 @@ export default QUnit.module( 'Extras', () => { var points = curve.getSpacedPoints(); - assert.strictEqual( points.length, expectedPoints.length, "Correct number of points" ); - assert.deepEqual( points, expectedPoints, "Correct points calculated" ); + assert.strictEqual( points.length, expectedPoints.length, 'Correct number of points' ); + assert.deepEqual( points, expectedPoints, 'Correct points calculated' ); } ); - QUnit.test( "computeFrenetFrames", ( assert ) => { + QUnit.test( 'computeFrenetFrames', ( assert ) => { var curve = _curve; @@ -249,9 +249,9 @@ export default QUnit.module( 'Extras', () => { expected[ group ].forEach( function ( vec, j ) { - assert.numEqual( frames[ group ][ j ].x, vec.x, "Frenet frames [" + i + ", " + j + "].x correct" ); - assert.numEqual( frames[ group ][ j ].y, vec.y, "Frenet frames [" + i + ", " + j + "].y correct" ); - assert.numEqual( frames[ group ][ j ].z, vec.z, "Frenet frames [" + i + ", " + j + "].z correct" ); + assert.numEqual( frames[ group ][ j ].x, vec.x, 'Frenet frames [' + i + ', ' + j + '].x correct' ); + assert.numEqual( frames[ group ][ j ].y, vec.y, 'Frenet frames [' + i + ', ' + j + '].y correct' ); + assert.numEqual( frames[ group ][ j ].z, vec.z, 'Frenet frames [' + i + ', ' + j + '].z correct' ); } ); diff --git a/test/unit/src/extras/curves/SplineCurve.tests.js b/test/unit/src/extras/curves/SplineCurve.tests.js index dc1c83c782bb58..3af38321837324 100644 --- a/test/unit/src/extras/curves/SplineCurve.tests.js +++ b/test/unit/src/extras/curves/SplineCurve.tests.js @@ -23,34 +23,34 @@ export default QUnit.module( 'Extras', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isSplineCurve", ( assert ) => { + QUnit.todo( 'isSplineCurve', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getPoint", ( assert ) => { + QUnit.todo( 'getPoint', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // OTHERS - QUnit.test( "Simple curve", ( assert ) => { + QUnit.test( 'Simple curve', ( assert ) => { var curve = _curve; @@ -65,12 +65,12 @@ export default QUnit.module( 'Extras', () => { var points = curve.getPoints( 5 ); - assert.strictEqual( points.length, expectedPoints.length, "1st: Correct number of points" ); + assert.strictEqual( points.length, expectedPoints.length, '1st: Correct number of points' ); points.forEach( function ( point, i ) { - assert.numEqual( point.x, expectedPoints[ i ].x, "points[" + i + "].x" ); - assert.numEqual( point.y, expectedPoints[ i ].y, "points[" + i + "].y" ); + assert.numEqual( point.x, expectedPoints[ i ].x, 'points[' + i + '].x' ); + assert.numEqual( point.y, expectedPoints[ i ].y, 'points[' + i + '].y' ); } ); @@ -78,18 +78,18 @@ export default QUnit.module( 'Extras', () => { points = curve.getPoints( 4 ); - assert.deepEqual( points, curve.points, "2nd: Returned points are identical to control points" ); + assert.deepEqual( points, curve.points, '2nd: Returned points are identical to control points' ); } ); - QUnit.test( "getLength/getLengths", ( assert ) => { + QUnit.test( 'getLength/getLengths', ( assert ) => { var curve = _curve; var length = curve.getLength(); var expectedLength = 28.876950901868135; - assert.numEqual( length, expectedLength, "Correct length of curve" ); + assert.numEqual( length, expectedLength, 'Correct length of curve' ); var expectedLengths = [ 0.0, @@ -101,26 +101,26 @@ export default QUnit.module( 'Extras', () => { var lengths = curve.getLengths( 4 ); - assert.deepEqual( lengths, expectedLengths, "Correct segment lengths" ); + assert.deepEqual( lengths, expectedLengths, 'Correct segment lengths' ); } ); - QUnit.test( "getPointAt", ( assert ) => { + QUnit.test( 'getPointAt', ( assert ) => { var curve = _curve; var point = new Vector2(); - assert.ok( curve.getPointAt( 0, point ).equals( curve.points[ 0 ] ), "PointAt 0.0 correct" ); - assert.ok( curve.getPointAt( 1, point ).equals( curve.points[ 4 ] ), "PointAt 1.0 correct" ); + assert.ok( curve.getPointAt( 0, point ).equals( curve.points[ 0 ] ), 'PointAt 0.0 correct' ); + assert.ok( curve.getPointAt( 1, point ).equals( curve.points[ 4 ] ), 'PointAt 1.0 correct' ); curve.getPointAt( 0.5, point ); - assert.numEqual( point.x, 0.0, "PointAt 0.5 x correct" ); - assert.numEqual( point.y, 0.0, "PointAt 0.5 y correct" ); + assert.numEqual( point.x, 0.0, 'PointAt 0.5 x correct' ); + assert.numEqual( point.y, 0.0, 'PointAt 0.5 y correct' ); } ); - QUnit.test( "getTangent", ( assert ) => { + QUnit.test( 'getTangent', ( assert ) => { var curve = _curve; @@ -138,14 +138,14 @@ export default QUnit.module( 'Extras', () => { tangents.forEach( function ( tangent, i ) { - assert.numEqual( tangent.x, expectedTangent[ i ].x, "tangent[" + i + "].x" ); - assert.numEqual( tangent.y, expectedTangent[ i ].y, "tangent[" + i + "].y" ); + assert.numEqual( tangent.x, expectedTangent[ i ].x, 'tangent[' + i + '].x' ); + assert.numEqual( tangent.y, expectedTangent[ i ].y, 'tangent[' + i + '].y' ); } ); } ); - QUnit.test( "getUtoTmapping", ( assert ) => { + QUnit.test( 'getUtoTmapping', ( assert ) => { var curve = _curve; @@ -153,13 +153,13 @@ export default QUnit.module( 'Extras', () => { var end = curve.getUtoTmapping( 0, curve.getLength() ); var middle = curve.getUtoTmapping( 0.5, 0 ); - assert.strictEqual( start, 0, "getUtoTmapping( 0, 0 ) is the starting point" ); - assert.strictEqual( end, 1, "getUtoTmapping( 0, length ) is the ending point" ); - assert.numEqual( middle, 0.5, "getUtoTmapping( 0.5, 0 ) is the middle" ); + assert.strictEqual( start, 0, 'getUtoTmapping( 0, 0 ) is the starting point' ); + assert.strictEqual( end, 1, 'getUtoTmapping( 0, length ) is the ending point' ); + assert.numEqual( middle, 0.5, 'getUtoTmapping( 0.5, 0 ) is the middle' ); } ); - QUnit.test( "getSpacedPoints", ( assert ) => { + QUnit.test( 'getSpacedPoints', ( assert ) => { var curve = _curve; @@ -173,12 +173,12 @@ export default QUnit.module( 'Extras', () => { var points = curve.getSpacedPoints( 4 ); - assert.strictEqual( points.length, expectedPoints.length, "Correct number of points" ); + assert.strictEqual( points.length, expectedPoints.length, 'Correct number of points' ); points.forEach( function ( point, i ) { - assert.numEqual( point.x, expectedPoints[ i ].x, "points[" + i + "].x" ); - assert.numEqual( point.y, expectedPoints[ i ].y, "points[" + i + "].y" ); + assert.numEqual( point.x, expectedPoints[ i ].x, 'points[' + i + '].x' ); + assert.numEqual( point.y, expectedPoints[ i ].y, 'points[' + i + '].y' ); } ); diff --git a/test/unit/src/geometries/BoxGeometry.tests.js b/test/unit/src/geometries/BoxGeometry.tests.js index 8c27947d360558..ffef404e5b27ac 100644 --- a/test/unit/src/geometries/BoxGeometry.tests.js +++ b/test/unit/src/geometries/BoxGeometry.tests.js @@ -29,16 +29,16 @@ export default QUnit.module( 'Geometries', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/geometries/CircleGeometry.tests.js b/test/unit/src/geometries/CircleGeometry.tests.js index dd3d3865c0c336..fc8bd1db667bd5 100644 --- a/test/unit/src/geometries/CircleGeometry.tests.js +++ b/test/unit/src/geometries/CircleGeometry.tests.js @@ -23,22 +23,22 @@ export default QUnit.module( 'Geometries', () => { new CircleGeometry( parameters.radius, parameters.segments ), new CircleGeometry( parameters.radius, parameters.segments, parameters.thetaStart ), new CircleGeometry( parameters.radius, parameters.segments, parameters.thetaStart, parameters.thetaLength ), - new CircleBufferGeometry(), + new CircleBufferGeometry(), ]; } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/geometries/ConeGeometry.tests.js b/test/unit/src/geometries/ConeGeometry.tests.js index 72241302041ee1..017a128357b982 100644 --- a/test/unit/src/geometries/ConeGeometry.tests.js +++ b/test/unit/src/geometries/ConeGeometry.tests.js @@ -18,16 +18,16 @@ export default QUnit.module( 'Geometries', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/geometries/CylinderGeometry.tests.js b/test/unit/src/geometries/CylinderGeometry.tests.js index 080b3168775c04..332379e11aad47 100644 --- a/test/unit/src/geometries/CylinderGeometry.tests.js +++ b/test/unit/src/geometries/CylinderGeometry.tests.js @@ -37,16 +37,16 @@ export default QUnit.module( 'Geometries', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/geometries/DodecahedronGeometry.tests.js b/test/unit/src/geometries/DodecahedronGeometry.tests.js index 2396d37530036c..c7734d7f58b72c 100644 --- a/test/unit/src/geometries/DodecahedronGeometry.tests.js +++ b/test/unit/src/geometries/DodecahedronGeometry.tests.js @@ -25,16 +25,16 @@ export default QUnit.module( 'Geometries', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/geometries/EdgesGeometry.tests.js b/test/unit/src/geometries/EdgesGeometry.tests.js index 9ffc4feda77773..cb29bc674be032 100644 --- a/test/unit/src/geometries/EdgesGeometry.tests.js +++ b/test/unit/src/geometries/EdgesGeometry.tests.js @@ -26,11 +26,11 @@ function testEdges( vertList, idxList, numAfter, assert ) { var geom = geoms[ i ]; var numBefore = idxList.length; - assert.equal( countEdges( geom ), numBefore, "Edges before!" ); + assert.equal( countEdges( geom ), numBefore, 'Edges before!' ); var egeom = new EdgesGeometry( geom ); - assert.equal( countEdges( egeom ), numAfter, "Edges after!" ); + assert.equal( countEdges( egeom ), numAfter, 'Edges after!' ); output( geom, egeom ); } @@ -213,39 +213,39 @@ export default QUnit.module( 'Geometries', () => { ]; // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // OTHERS - QUnit.test( "singularity", ( assert ) => { + QUnit.test( 'singularity', ( assert ) => { testEdges( vertList, [ 1, 1, 1 ], 0, assert ); } ); - QUnit.test( "needle", ( assert ) => { + QUnit.test( 'needle', ( assert ) => { testEdges( vertList, [ 0, 0, 1 ], 0, assert ); } ); - QUnit.test( "single triangle", ( assert ) => { + QUnit.test( 'single triangle', ( assert ) => { testEdges( vertList, [ 0, 1, 2 ], 3, assert ); } ); - QUnit.test( "two isolated triangles", ( assert ) => { + QUnit.test( 'two isolated triangles', ( assert ) => { var vertList = [ new Vector3( 0, 0, 0 ), @@ -260,37 +260,37 @@ export default QUnit.module( 'Geometries', () => { } ); - QUnit.test( "two flat triangles", ( assert ) => { + QUnit.test( 'two flat triangles', ( assert ) => { testEdges( vertList, [ 0, 1, 2, 0, 2, 3 ], 4, assert ); } ); - QUnit.test( "two flat triangles, inverted", ( assert ) => { + QUnit.test( 'two flat triangles, inverted', ( assert ) => { testEdges( vertList, [ 0, 1, 2, 0, 3, 2 ], 5, assert ); } ); - QUnit.test( "two non-coplanar triangles", ( assert ) => { + QUnit.test( 'two non-coplanar triangles', ( assert ) => { testEdges( vertList, [ 0, 1, 2, 0, 4, 2 ], 5, assert ); } ); - QUnit.test( "three triangles, coplanar first", ( assert ) => { + QUnit.test( 'three triangles, coplanar first', ( assert ) => { testEdges( vertList, [ 0, 2, 3, 0, 1, 2, 0, 4, 2 ], 7, assert ); } ); - QUnit.test( "three triangles, coplanar last", ( assert ) => { + QUnit.test( 'three triangles, coplanar last', ( assert ) => { testEdges( vertList, [ 0, 1, 2, 0, 4, 2, 0, 2, 3 ], 6, assert ); // Should be 7 } ); - QUnit.test( "tetrahedron", ( assert ) => { + QUnit.test( 'tetrahedron', ( assert ) => { testEdges( vertList, [ 0, 1, 2, 0, 1, 4, 0, 4, 2, 1, 2, 4 ], 6, assert ); diff --git a/test/unit/src/geometries/ExtrudeGeometry.tests.js b/test/unit/src/geometries/ExtrudeGeometry.tests.js index 550381b7e0cade..89ff75338ee1cb 100644 --- a/test/unit/src/geometries/ExtrudeGeometry.tests.js +++ b/test/unit/src/geometries/ExtrudeGeometry.tests.js @@ -7,16 +7,16 @@ export default QUnit.module( 'Geometries', () => { QUnit.module( 'ExtrudeGeometry', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/geometries/IcosahedronGeometry.tests.js b/test/unit/src/geometries/IcosahedronGeometry.tests.js index e6467975261d5f..77e0cb3cb9a0cd 100644 --- a/test/unit/src/geometries/IcosahedronGeometry.tests.js +++ b/test/unit/src/geometries/IcosahedronGeometry.tests.js @@ -25,16 +25,16 @@ export default QUnit.module( 'Geometries', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/geometries/LatheGeometry.tests.js b/test/unit/src/geometries/LatheGeometry.tests.js index d02144ff1d0a01..77e9d6d148f24e 100644 --- a/test/unit/src/geometries/LatheGeometry.tests.js +++ b/test/unit/src/geometries/LatheGeometry.tests.js @@ -25,16 +25,16 @@ export default QUnit.module( 'Geometries', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/geometries/OctahedronGeometry.tests.js b/test/unit/src/geometries/OctahedronGeometry.tests.js index 92291f826562db..01d38c782ad427 100644 --- a/test/unit/src/geometries/OctahedronGeometry.tests.js +++ b/test/unit/src/geometries/OctahedronGeometry.tests.js @@ -25,16 +25,16 @@ export default QUnit.module( 'Geometries', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/geometries/PlaneGeometry.tests.js b/test/unit/src/geometries/PlaneGeometry.tests.js index 8c7e30369ebe03..63ef0ccf5504aa 100644 --- a/test/unit/src/geometries/PlaneGeometry.tests.js +++ b/test/unit/src/geometries/PlaneGeometry.tests.js @@ -29,16 +29,16 @@ export default QUnit.module( 'Geometries', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/geometries/PolyhedronGeometry.tests.js b/test/unit/src/geometries/PolyhedronGeometry.tests.js index b964bf9f48e60d..bf8f62d692f3fa 100644 --- a/test/unit/src/geometries/PolyhedronGeometry.tests.js +++ b/test/unit/src/geometries/PolyhedronGeometry.tests.js @@ -26,16 +26,16 @@ export default QUnit.module( 'Geometries', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/geometries/RingGeometry.tests.js b/test/unit/src/geometries/RingGeometry.tests.js index 965c122350cf50..1866546d8e9f7a 100644 --- a/test/unit/src/geometries/RingGeometry.tests.js +++ b/test/unit/src/geometries/RingGeometry.tests.js @@ -33,16 +33,16 @@ export default QUnit.module( 'Geometries', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/geometries/ShapeGeometry.tests.js b/test/unit/src/geometries/ShapeGeometry.tests.js index 72b67aa68d1b2d..52115b33b982c7 100644 --- a/test/unit/src/geometries/ShapeGeometry.tests.js +++ b/test/unit/src/geometries/ShapeGeometry.tests.js @@ -24,23 +24,23 @@ export default QUnit.module( 'Geometries', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // OTHERS QUnit.todo( 'Standard geometry tests', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/geometries/SphereGeometry.tests.js b/test/unit/src/geometries/SphereGeometry.tests.js index 560143cf85b8df..ddb10eb0602032 100644 --- a/test/unit/src/geometries/SphereGeometry.tests.js +++ b/test/unit/src/geometries/SphereGeometry.tests.js @@ -35,16 +35,16 @@ export default QUnit.module( 'Geometries', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/geometries/TetrahedronGeometry.tests.js b/test/unit/src/geometries/TetrahedronGeometry.tests.js index 5959e2a7353888..a28d44586b8e47 100644 --- a/test/unit/src/geometries/TetrahedronGeometry.tests.js +++ b/test/unit/src/geometries/TetrahedronGeometry.tests.js @@ -25,16 +25,16 @@ export default QUnit.module( 'Geometries', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/geometries/TorusGeometry.tests.js b/test/unit/src/geometries/TorusGeometry.tests.js index 08d2e9e27a5f78..a566b5e5bba45f 100644 --- a/test/unit/src/geometries/TorusGeometry.tests.js +++ b/test/unit/src/geometries/TorusGeometry.tests.js @@ -31,16 +31,16 @@ export default QUnit.module( 'Geometries', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/geometries/TorusKnotGeometry.tests.js b/test/unit/src/geometries/TorusKnotGeometry.tests.js index f9786ec81a241f..00b154ef158a75 100644 --- a/test/unit/src/geometries/TorusKnotGeometry.tests.js +++ b/test/unit/src/geometries/TorusKnotGeometry.tests.js @@ -32,16 +32,16 @@ export default QUnit.module( 'Geometries', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/geometries/TubeGeometry.tests.js b/test/unit/src/geometries/TubeGeometry.tests.js index f3f064f29519fb..00ee94ce9bef0f 100644 --- a/test/unit/src/geometries/TubeGeometry.tests.js +++ b/test/unit/src/geometries/TubeGeometry.tests.js @@ -22,23 +22,23 @@ export default QUnit.module( 'Geometries', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // OTHERS QUnit.todo( 'Standard geometry tests', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/geometries/WireframeGeometry.tests.js b/test/unit/src/geometries/WireframeGeometry.tests.js index c75c930955ce24..922dd52a9039e8 100644 --- a/test/unit/src/geometries/WireframeGeometry.tests.js +++ b/test/unit/src/geometries/WireframeGeometry.tests.js @@ -16,23 +16,23 @@ export default QUnit.module( 'Geometries', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // OTHERS QUnit.todo( 'Standard geometry tests', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/helpers/ArrowHelper.tests.js b/test/unit/src/helpers/ArrowHelper.tests.js index 6f87562df92d53..681229f39364e0 100644 --- a/test/unit/src/helpers/ArrowHelper.tests.js +++ b/test/unit/src/helpers/ArrowHelper.tests.js @@ -7,35 +7,35 @@ export default QUnit.module( 'Helpers', () => { QUnit.module( 'ArrowHelper', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "setDirection", ( assert ) => { + QUnit.todo( 'setDirection', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setLength", ( assert ) => { + QUnit.todo( 'setLength', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setColor", ( assert ) => { + QUnit.todo( 'setColor', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/helpers/AxesHelper.tests.js b/test/unit/src/helpers/AxesHelper.tests.js index 52b7125f50a597..9806ce2a32a7eb 100644 --- a/test/unit/src/helpers/AxesHelper.tests.js +++ b/test/unit/src/helpers/AxesHelper.tests.js @@ -7,16 +7,16 @@ export default QUnit.module( 'Helpers', () => { QUnit.module( 'AxesHelper', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/helpers/Box3Helper.tests.js b/test/unit/src/helpers/Box3Helper.tests.js index 7a8f7f74e948a0..34ef73fb2095f0 100644 --- a/test/unit/src/helpers/Box3Helper.tests.js +++ b/test/unit/src/helpers/Box3Helper.tests.js @@ -7,23 +7,23 @@ export default QUnit.module( 'Helpers', () => { QUnit.module( 'Box3Helper', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "updateMatrixWorld", ( assert ) => { + QUnit.todo( 'updateMatrixWorld', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/helpers/BoxHelper.tests.js b/test/unit/src/helpers/BoxHelper.tests.js index 8b5692e20528a6..3d41589cc5efc7 100644 --- a/test/unit/src/helpers/BoxHelper.tests.js +++ b/test/unit/src/helpers/BoxHelper.tests.js @@ -29,29 +29,29 @@ export default QUnit.module( 'Helpers', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "update", ( assert ) => { + QUnit.todo( 'update', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setFromObject", ( assert ) => { + QUnit.todo( 'setFromObject', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/helpers/CameraHelper.tests.js b/test/unit/src/helpers/CameraHelper.tests.js index 59f024a4b5873d..fc6384de5d392b 100644 --- a/test/unit/src/helpers/CameraHelper.tests.js +++ b/test/unit/src/helpers/CameraHelper.tests.js @@ -7,23 +7,23 @@ export default QUnit.module( 'Helpers', () => { QUnit.module( 'CameraHelper', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "update", ( assert ) => { + QUnit.todo( 'update', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/helpers/DirectionalLightHelper.tests.js b/test/unit/src/helpers/DirectionalLightHelper.tests.js index 93f598c0849737..5358e77ecee160 100644 --- a/test/unit/src/helpers/DirectionalLightHelper.tests.js +++ b/test/unit/src/helpers/DirectionalLightHelper.tests.js @@ -7,29 +7,29 @@ export default QUnit.module( 'Helpers', () => { QUnit.module( 'DirectionalLightHelper', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "dispose", ( assert ) => { + QUnit.todo( 'dispose', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "update", ( assert ) => { + QUnit.todo( 'update', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/helpers/GridHelper.tests.js b/test/unit/src/helpers/GridHelper.tests.js index 3f28f3f20562b4..1daaa18b342690 100644 --- a/test/unit/src/helpers/GridHelper.tests.js +++ b/test/unit/src/helpers/GridHelper.tests.js @@ -7,16 +7,16 @@ export default QUnit.module( 'Helpers', () => { QUnit.module( 'GridHelper', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/helpers/HemisphereLightHelper.tests.js b/test/unit/src/helpers/HemisphereLightHelper.tests.js index 796c5e32660606..d5ee900cf311bb 100644 --- a/test/unit/src/helpers/HemisphereLightHelper.tests.js +++ b/test/unit/src/helpers/HemisphereLightHelper.tests.js @@ -7,29 +7,29 @@ export default QUnit.module( 'Helpers', () => { QUnit.module( 'HemisphereLightHelper', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "dispose", ( assert ) => { + QUnit.todo( 'dispose', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "update", ( assert ) => { + QUnit.todo( 'update', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/helpers/PlaneHelper.tests.js b/test/unit/src/helpers/PlaneHelper.tests.js index 8ae32aaa743f98..f0634b716e2794 100644 --- a/test/unit/src/helpers/PlaneHelper.tests.js +++ b/test/unit/src/helpers/PlaneHelper.tests.js @@ -7,23 +7,23 @@ export default QUnit.module( 'Helpers', () => { QUnit.module( 'PlaneHelper', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "updateMatrixWorld", ( assert ) => { + QUnit.todo( 'updateMatrixWorld', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/helpers/PointLightHelper.tests.js b/test/unit/src/helpers/PointLightHelper.tests.js index f417725cc21188..2119a4a25efb78 100644 --- a/test/unit/src/helpers/PointLightHelper.tests.js +++ b/test/unit/src/helpers/PointLightHelper.tests.js @@ -7,29 +7,29 @@ export default QUnit.module( 'Helpers', () => { QUnit.module( 'PointLightHelper', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "dispose", ( assert ) => { + QUnit.todo( 'dispose', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "update", ( assert ) => { + QUnit.todo( 'update', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/helpers/PolarGridHelper.tests.js b/test/unit/src/helpers/PolarGridHelper.tests.js index 7d0358640bd5bb..151737d96e2321 100644 --- a/test/unit/src/helpers/PolarGridHelper.tests.js +++ b/test/unit/src/helpers/PolarGridHelper.tests.js @@ -7,16 +7,16 @@ export default QUnit.module( 'Helpers', () => { QUnit.module( 'PolarGridHelper', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/helpers/SkeletonHelper.tests.js b/test/unit/src/helpers/SkeletonHelper.tests.js index 5dba7670a3d2cd..e5d0ce97970644 100644 --- a/test/unit/src/helpers/SkeletonHelper.tests.js +++ b/test/unit/src/helpers/SkeletonHelper.tests.js @@ -7,23 +7,23 @@ export default QUnit.module( 'Helpers', () => { QUnit.module( 'SkeletonHelper', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "updateMatrixWorld", ( assert ) => { + QUnit.todo( 'updateMatrixWorld', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/helpers/SpotLightHelper.tests.js b/test/unit/src/helpers/SpotLightHelper.tests.js index 1c50399cbc3b56..f48ca0da97797b 100644 --- a/test/unit/src/helpers/SpotLightHelper.tests.js +++ b/test/unit/src/helpers/SpotLightHelper.tests.js @@ -7,29 +7,29 @@ export default QUnit.module( 'Helpers', () => { QUnit.module( 'SpotLightHelper', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "dispose", ( assert ) => { + QUnit.todo( 'dispose', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "update", ( assert ) => { + QUnit.todo( 'update', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/lights/AmbientLight.tests.js b/test/unit/src/lights/AmbientLight.tests.js index c908f5c948ac19..58798710b793c1 100644 --- a/test/unit/src/lights/AmbientLight.tests.js +++ b/test/unit/src/lights/AmbientLight.tests.js @@ -24,23 +24,23 @@ export default QUnit.module( 'Lights', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isAmbiantLight", ( assert ) => { + QUnit.todo( 'isAmbiantLight', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/lights/DirectionalLight.tests.js b/test/unit/src/lights/DirectionalLight.tests.js index 9ab2a96422c8e0..49c0f131e7600d 100644 --- a/test/unit/src/lights/DirectionalLight.tests.js +++ b/test/unit/src/lights/DirectionalLight.tests.js @@ -24,29 +24,29 @@ export default QUnit.module( 'Lights', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isDirectionalLight", ( assert ) => { + QUnit.todo( 'isDirectionalLight', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "copy", ( assert ) => { + QUnit.todo( 'copy', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/lights/DirectionalLightShadow.tests.js b/test/unit/src/lights/DirectionalLightShadow.tests.js index 48146e7318d4ea..e694293ae6b624 100644 --- a/test/unit/src/lights/DirectionalLightShadow.tests.js +++ b/test/unit/src/lights/DirectionalLightShadow.tests.js @@ -9,43 +9,43 @@ export default QUnit.module( 'Lights', () => { QUnit.module( 'DirectionalLightShadow', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // OTHERS - QUnit.test( "clone/copy", ( assert ) => { + QUnit.test( 'clone/copy', ( assert ) => { var a = new DirectionalLightShadow(); var b = new DirectionalLightShadow(); var c; - assert.notDeepEqual( a, b, "Newly instanced shadows are not equal" ); + assert.notDeepEqual( a, b, 'Newly instanced shadows are not equal' ); c = a.clone(); - assert.smartEqual( a, c, "Shadows are identical after clone()" ); + assert.smartEqual( a, c, 'Shadows are identical after clone()' ); c.mapSize.set( 1024, 1024 ); - assert.notDeepEqual( a, c, "Shadows are different again after change" ); + assert.notDeepEqual( a, c, 'Shadows are different again after change' ); b.copy( a ); - assert.smartEqual( a, b, "Shadows are identical after copy()" ); + assert.smartEqual( a, b, 'Shadows are identical after copy()' ); b.mapSize.set( 512, 512 ); - assert.notDeepEqual( a, b, "Shadows are different again after change" ); + assert.notDeepEqual( a, b, 'Shadows are different again after change' ); } ); - QUnit.test( "toJSON", ( assert ) => { + QUnit.test( 'toJSON', ( assert ) => { var light = new DirectionalLight(); var shadow = new DirectionalLightShadow(); @@ -58,7 +58,7 @@ export default QUnit.module( 'Lights', () => { var json = light.toJSON(); var newLight = new ObjectLoader().parse( json ); - assert.smartEqual( newLight.shadow, light.shadow, "Reloaded shadow is identical to the original one" ); + assert.smartEqual( newLight.shadow, light.shadow, 'Reloaded shadow is identical to the original one' ); } ); diff --git a/test/unit/src/lights/HemisphereLight.tests.js b/test/unit/src/lights/HemisphereLight.tests.js index a40aaef461c743..d2b610be666af3 100644 --- a/test/unit/src/lights/HemisphereLight.tests.js +++ b/test/unit/src/lights/HemisphereLight.tests.js @@ -26,29 +26,29 @@ export default QUnit.module( 'Lights', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isHemisphereLight", ( assert ) => { + QUnit.todo( 'isHemisphereLight', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "copy", ( assert ) => { + QUnit.todo( 'copy', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/lights/Light.tests.js b/test/unit/src/lights/Light.tests.js index cee0e05525494c..9e724f15feb9bd 100644 --- a/test/unit/src/lights/Light.tests.js +++ b/test/unit/src/lights/Light.tests.js @@ -24,35 +24,35 @@ export default QUnit.module( 'Lights', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isLight", ( assert ) => { + QUnit.todo( 'isLight', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "copy", ( assert ) => { + QUnit.todo( 'copy', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "toJSON", ( assert ) => { + QUnit.todo( 'toJSON', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/lights/LightShadow.tests.js b/test/unit/src/lights/LightShadow.tests.js index 3eeac6ea86a4bf..c6911a461b41fb 100644 --- a/test/unit/src/lights/LightShadow.tests.js +++ b/test/unit/src/lights/LightShadow.tests.js @@ -8,38 +8,38 @@ export default QUnit.module( 'Lights', () => { QUnit.module( 'LightShadow', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.test( "clone/copy", ( assert ) => { + QUnit.test( 'clone/copy', ( assert ) => { var a = new LightShadow( new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) ); var b = new LightShadow( new OrthographicCamera( - 3, 3, 3, - 3, 0.3, 300 ) ); var c; - assert.notDeepEqual( a, b, "Newly instanced shadows are not equal" ); + assert.notDeepEqual( a, b, 'Newly instanced shadows are not equal' ); c = a.clone(); - assert.smartEqual( a, c, "Shadows are identical after clone()" ); + assert.smartEqual( a, c, 'Shadows are identical after clone()' ); c.mapSize.set( 256, 256 ); - assert.notDeepEqual( a, c, "Shadows are different again after change" ); + assert.notDeepEqual( a, c, 'Shadows are different again after change' ); b.copy( a ); - assert.smartEqual( a, b, "Shadows are identical after copy()" ); + assert.smartEqual( a, b, 'Shadows are identical after copy()' ); b.mapSize.set( 512, 512 ); - assert.notDeepEqual( a, b, "Shadows are different again after change" ); + assert.notDeepEqual( a, b, 'Shadows are different again after change' ); } ); - QUnit.todo( "toJSON", ( assert ) => { + QUnit.todo( 'toJSON', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/lights/PointLight.tests.js b/test/unit/src/lights/PointLight.tests.js index c091a3ddafaeba..38bccebbe7db11 100644 --- a/test/unit/src/lights/PointLight.tests.js +++ b/test/unit/src/lights/PointLight.tests.js @@ -28,45 +28,45 @@ export default QUnit.module( 'Lights', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PROPERTIES - QUnit.test( "power", ( assert ) => { + QUnit.test( 'power', ( assert ) => { var a = new PointLight( 0xaaaaaa ); a.intensity = 100; - assert.numEqual( a.power, 100 * Math.PI * 4, "Correct power for an intensity of 100" ); + assert.numEqual( a.power, 100 * Math.PI * 4, 'Correct power for an intensity of 100' ); a.intensity = 40; - assert.numEqual( a.power, 40 * Math.PI * 4, "Correct power for an intensity of 40" ); + assert.numEqual( a.power, 40 * Math.PI * 4, 'Correct power for an intensity of 40' ); a.power = 100; - assert.numEqual( a.intensity, 100 / ( 4 * Math.PI ), "Correct intensity for a power of 100" ); + assert.numEqual( a.intensity, 100 / ( 4 * Math.PI ), 'Correct intensity for a power of 100' ); } ); // PUBLIC STUFF - QUnit.todo( "isPointLight", ( assert ) => { + QUnit.todo( 'isPointLight', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "copy", ( assert ) => { + QUnit.todo( 'copy', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/lights/RectAreaLight.tests.js b/test/unit/src/lights/RectAreaLight.tests.js index 6c0612f2f62ca3..a504537dcf3550 100644 --- a/test/unit/src/lights/RectAreaLight.tests.js +++ b/test/unit/src/lights/RectAreaLight.tests.js @@ -27,35 +27,35 @@ export default QUnit.module( 'Lights', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isRectAreaLight", ( assert ) => { + QUnit.todo( 'isRectAreaLight', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "copy", ( assert ) => { + QUnit.todo( 'copy', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "toJSON", ( assert ) => { + QUnit.todo( 'toJSON', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/lights/SpotLight.tests.js b/test/unit/src/lights/SpotLight.tests.js index 65b6b561f6b50d..4423169f86dacb 100644 --- a/test/unit/src/lights/SpotLight.tests.js +++ b/test/unit/src/lights/SpotLight.tests.js @@ -31,45 +31,45 @@ export default QUnit.module( 'Lights', () => { } ); // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PROPERTIES - QUnit.test( "power", ( assert ) => { + QUnit.test( 'power', ( assert ) => { var a = new SpotLight( 0xaaaaaa ); a.intensity = 100; - assert.numEqual( a.power, 100 * Math.PI, "Correct power for an intensity of 100" ); + assert.numEqual( a.power, 100 * Math.PI, 'Correct power for an intensity of 100' ); a.intensity = 40; - assert.numEqual( a.power, 40 * Math.PI, "Correct power for an intensity of 40" ); + assert.numEqual( a.power, 40 * Math.PI, 'Correct power for an intensity of 40' ); a.power = 100; - assert.numEqual( a.intensity, 100 / Math.PI, "Correct intensity for a power of 100" ); + assert.numEqual( a.intensity, 100 / Math.PI, 'Correct intensity for a power of 100' ); } ); // PUBLIC STUFF - QUnit.todo( "isSpotLight", ( assert ) => { + QUnit.todo( 'isSpotLight', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "copy", ( assert ) => { + QUnit.todo( 'copy', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/lights/SpotLightShadow.tests.js b/test/unit/src/lights/SpotLightShadow.tests.js index bd90fedc46db4d..b8f13c2f47dbad 100644 --- a/test/unit/src/lights/SpotLightShadow.tests.js +++ b/test/unit/src/lights/SpotLightShadow.tests.js @@ -9,56 +9,56 @@ export default QUnit.module( 'Lights', () => { QUnit.module( 'SpotLightShadow', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isSpotLightShadow", ( assert ) => { + QUnit.todo( 'isSpotLightShadow', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "update", ( assert ) => { + QUnit.todo( 'update', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // OTHERS - QUnit.test( "clone/copy", ( assert ) => { + QUnit.test( 'clone/copy', ( assert ) => { var a = new SpotLightShadow(); var b = new SpotLightShadow(); var c; - assert.notDeepEqual( a, b, "Newly instanced shadows are not equal" ); + assert.notDeepEqual( a, b, 'Newly instanced shadows are not equal' ); c = a.clone(); - assert.smartEqual( a, c, "Shadows are identical after clone()" ); + assert.smartEqual( a, c, 'Shadows are identical after clone()' ); c.mapSize.set( 256, 256 ); - assert.notDeepEqual( a, c, "Shadows are different again after change" ); + assert.notDeepEqual( a, c, 'Shadows are different again after change' ); b.copy( a ); - assert.smartEqual( a, b, "Shadows are identical after copy()" ); + assert.smartEqual( a, b, 'Shadows are identical after copy()' ); b.mapSize.set( 512, 512 ); - assert.notDeepEqual( a, b, "Shadows are different again after change" ); + assert.notDeepEqual( a, b, 'Shadows are different again after change' ); } ); - QUnit.test( "toJSON", ( assert ) => { + QUnit.test( 'toJSON', ( assert ) => { var light = new SpotLight(); var shadow = new SpotLightShadow(); @@ -71,7 +71,7 @@ export default QUnit.module( 'Lights', () => { var json = light.toJSON(); var newLight = new ObjectLoader().parse( json ); - assert.smartEqual( newLight.shadow, light.shadow, "Reloaded shadow is equal to the original one" ); + assert.smartEqual( newLight.shadow, light.shadow, 'Reloaded shadow is equal to the original one' ); } ); diff --git a/test/unit/src/loaders/AnimationLoader.tests.js b/test/unit/src/loaders/AnimationLoader.tests.js index ed05b019efa96e..36c235ad047776 100644 --- a/test/unit/src/loaders/AnimationLoader.tests.js +++ b/test/unit/src/loaders/AnimationLoader.tests.js @@ -7,22 +7,22 @@ export default QUnit.module( 'Loaders', () => { QUnit.module( 'AnimationLoader', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "load", ( assert ) => { + QUnit.todo( 'load', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "parse", ( assert ) => { + QUnit.todo( 'parse', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/loaders/AudioLoader.tests.js b/test/unit/src/loaders/AudioLoader.tests.js index 336ebdcf9dd8a5..537d2039b5c8ce 100644 --- a/test/unit/src/loaders/AudioLoader.tests.js +++ b/test/unit/src/loaders/AudioLoader.tests.js @@ -7,16 +7,16 @@ export default QUnit.module( 'Loaders', () => { QUnit.module( 'AudioLoader', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "load", ( assert ) => { + QUnit.todo( 'load', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/loaders/BufferGeometryLoader.tests.js b/test/unit/src/loaders/BufferGeometryLoader.tests.js index 082fd0b34152fd..6c5a78748e733d 100644 --- a/test/unit/src/loaders/BufferGeometryLoader.tests.js +++ b/test/unit/src/loaders/BufferGeometryLoader.tests.js @@ -10,26 +10,26 @@ export default QUnit.module( 'Loaders', () => { QUnit.module( 'BufferGeometryLoader', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "load", ( assert ) => { + QUnit.todo( 'load', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "parse", ( assert ) => { + QUnit.todo( 'parse', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "parser - attributes - circlable", ( assert ) => { + QUnit.test( 'parser - attributes - circlable', ( assert ) => { const loader = new BufferGeometryLoader(); const geometry = new BufferGeometry(); diff --git a/test/unit/src/loaders/Cache.tests.js b/test/unit/src/loaders/Cache.tests.js index 2733398bfb0439..692eb52cd287d6 100644 --- a/test/unit/src/loaders/Cache.tests.js +++ b/test/unit/src/loaders/Cache.tests.js @@ -7,27 +7,27 @@ export default QUnit.module( 'Loaders', () => { QUnit.module( 'Cache', () => { // PUBLIC STUFF - QUnit.todo( "add", ( assert ) => { + QUnit.todo( 'add', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "get", ( assert ) => { + QUnit.todo( 'get', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "remove", ( assert ) => { + QUnit.todo( 'remove', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "clear", ( assert ) => { + QUnit.todo( 'clear', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/loaders/CompressedTextureLoader.tests.js b/test/unit/src/loaders/CompressedTextureLoader.tests.js index ffe9848d3d3f66..2bfcc7c0d204fb 100644 --- a/test/unit/src/loaders/CompressedTextureLoader.tests.js +++ b/test/unit/src/loaders/CompressedTextureLoader.tests.js @@ -7,22 +7,22 @@ export default QUnit.module( 'Loaders', () => { QUnit.module( 'CompressedTextureLoader', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "load", ( assert ) => { + QUnit.todo( 'load', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setPath", ( assert ) => { + QUnit.todo( 'setPath', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/loaders/CubeTextureLoader.tests.js b/test/unit/src/loaders/CubeTextureLoader.tests.js index 4244efaa78e9ba..e3f03a116e7039 100644 --- a/test/unit/src/loaders/CubeTextureLoader.tests.js +++ b/test/unit/src/loaders/CubeTextureLoader.tests.js @@ -7,28 +7,28 @@ export default QUnit.module( 'Loaders', () => { QUnit.module( 'CubeTextureLoader', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "load", ( assert ) => { + QUnit.todo( 'load', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setCrossOrigin", ( assert ) => { + QUnit.todo( 'setCrossOrigin', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setPath", ( assert ) => { + QUnit.todo( 'setPath', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/loaders/DataTextureLoader.tests.js b/test/unit/src/loaders/DataTextureLoader.tests.js index 21bb588553726f..4f9b376a2b4167 100644 --- a/test/unit/src/loaders/DataTextureLoader.tests.js +++ b/test/unit/src/loaders/DataTextureLoader.tests.js @@ -7,16 +7,16 @@ export default QUnit.module( 'Loaders', () => { QUnit.module( 'DataTextureLoader', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "load", ( assert ) => { + QUnit.todo( 'load', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/loaders/FileLoader.tests.js b/test/unit/src/loaders/FileLoader.tests.js index 50b5611f58c4fa..ac3fff4cc718ae 100644 --- a/test/unit/src/loaders/FileLoader.tests.js +++ b/test/unit/src/loaders/FileLoader.tests.js @@ -7,46 +7,46 @@ export default QUnit.module( 'Loaders', () => { QUnit.module( 'FileLoader', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "load", ( assert ) => { + QUnit.todo( 'load', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setPath", ( assert ) => { + QUnit.todo( 'setPath', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setResponseType", ( assert ) => { + QUnit.todo( 'setResponseType', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setWithCredentials", ( assert ) => { + QUnit.todo( 'setWithCredentials', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setMimeType", ( assert ) => { + QUnit.todo( 'setMimeType', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setRequestHeader", ( assert ) => { + QUnit.todo( 'setRequestHeader', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/loaders/ImageLoader.tests.js b/test/unit/src/loaders/ImageLoader.tests.js index 3322cdcbdba07e..a76f0b2a034749 100644 --- a/test/unit/src/loaders/ImageLoader.tests.js +++ b/test/unit/src/loaders/ImageLoader.tests.js @@ -7,28 +7,28 @@ export default QUnit.module( 'Loaders', () => { QUnit.module( 'ImageLoader', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "load", ( assert ) => { + QUnit.todo( 'load', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setCrossOrigin", ( assert ) => { + QUnit.todo( 'setCrossOrigin', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setPath", ( assert ) => { + QUnit.todo( 'setPath', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/loaders/Loader.tests.js b/test/unit/src/loaders/Loader.tests.js index 329feadcd9b5e1..2b7fea069e9d94 100644 --- a/test/unit/src/loaders/Loader.tests.js +++ b/test/unit/src/loaders/Loader.tests.js @@ -5,9 +5,9 @@ export default QUnit.module( 'Loaders', () => { QUnit.module( 'Loader', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/loaders/LoadingManager.tests.js b/test/unit/src/loaders/LoadingManager.tests.js index b1b3beaff7e388..b9b6f4f899be20 100644 --- a/test/unit/src/loaders/LoadingManager.tests.js +++ b/test/unit/src/loaders/LoadingManager.tests.js @@ -8,56 +8,56 @@ export default QUnit.module( 'Loaders', () => { QUnit.module( 'LoadingManager', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "onStart", ( assert ) => { + QUnit.todo( 'onStart', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "onLoad", ( assert ) => { + QUnit.todo( 'onLoad', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "onProgress", ( assert ) => { + QUnit.todo( 'onProgress', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "onError", ( assert ) => { + QUnit.todo( 'onError', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "itemStart", ( assert ) => { + QUnit.todo( 'itemStart', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "itemEnd", ( assert ) => { + QUnit.todo( 'itemEnd', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "itemError", ( assert ) => { + QUnit.todo( 'itemError', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "getHandler", ( assert ) => { + QUnit.test( 'getHandler', ( assert ) => { const loadingManager = new LoadingManager(); const loader = new Loader(); diff --git a/test/unit/src/loaders/MaterialLoader.tests.js b/test/unit/src/loaders/MaterialLoader.tests.js index f3ab0b7d039951..0f0a3699e634bb 100644 --- a/test/unit/src/loaders/MaterialLoader.tests.js +++ b/test/unit/src/loaders/MaterialLoader.tests.js @@ -7,28 +7,28 @@ export default QUnit.module( 'Loaders', () => { QUnit.module( 'MaterialLoader', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "load", ( assert ) => { + QUnit.todo( 'load', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setTextures", ( assert ) => { + QUnit.todo( 'setTextures', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "parse", ( assert ) => { + QUnit.todo( 'parse', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/loaders/ObjectLoader.tests.js b/test/unit/src/loaders/ObjectLoader.tests.js index 171fe8e332ae28..28a680d4b992cd 100644 --- a/test/unit/src/loaders/ObjectLoader.tests.js +++ b/test/unit/src/loaders/ObjectLoader.tests.js @@ -7,70 +7,70 @@ export default QUnit.module( 'Loaders', () => { QUnit.module( 'ObjectLoader', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "load", ( assert ) => { + QUnit.todo( 'load', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setTexturePath", ( assert ) => { + QUnit.todo( 'setTexturePath', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setCrossOrigin", ( assert ) => { + QUnit.todo( 'setCrossOrigin', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "parse", ( assert ) => { + QUnit.todo( 'parse', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "parseGeometries", ( assert ) => { + QUnit.todo( 'parseGeometries', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "parseMaterials", ( assert ) => { + QUnit.todo( 'parseMaterials', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "parseAnimations", ( assert ) => { + QUnit.todo( 'parseAnimations', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "parseImages", ( assert ) => { + QUnit.todo( 'parseImages', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "parseTextures", ( assert ) => { + QUnit.todo( 'parseTextures', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "parseObject", ( assert ) => { + QUnit.todo( 'parseObject', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/loaders/TextureLoader.tests.js b/test/unit/src/loaders/TextureLoader.tests.js index 38f54359eac386..72be4915fccd25 100644 --- a/test/unit/src/loaders/TextureLoader.tests.js +++ b/test/unit/src/loaders/TextureLoader.tests.js @@ -7,28 +7,28 @@ export default QUnit.module( 'Loaders', () => { QUnit.module( 'TextureLoader', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "load", ( assert ) => { + QUnit.todo( 'load', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setCrossOrigin", ( assert ) => { + QUnit.todo( 'setCrossOrigin', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setPath", ( assert ) => { + QUnit.todo( 'setPath', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/materials/LineBasicMaterial.tests.js b/test/unit/src/materials/LineBasicMaterial.tests.js index bf1173d03e6cf1..6b6cc1cf732183 100644 --- a/test/unit/src/materials/LineBasicMaterial.tests.js +++ b/test/unit/src/materials/LineBasicMaterial.tests.js @@ -7,29 +7,29 @@ export default QUnit.module( 'Materials', () => { QUnit.module( 'LineBasicMaterial', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isLineBasicMaterial", ( assert ) => { + QUnit.todo( 'isLineBasicMaterial', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "copy", ( assert ) => { + QUnit.todo( 'copy', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/materials/LineDashedMaterial.tests.js b/test/unit/src/materials/LineDashedMaterial.tests.js index bd46bfeb44f16d..2f7e4affac9651 100644 --- a/test/unit/src/materials/LineDashedMaterial.tests.js +++ b/test/unit/src/materials/LineDashedMaterial.tests.js @@ -7,29 +7,29 @@ export default QUnit.module( 'Materials', () => { QUnit.module( 'LineDashedMaterial', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isLineDashedMaterial", ( assert ) => { + QUnit.todo( 'isLineDashedMaterial', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "copy", ( assert ) => { + QUnit.todo( 'copy', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/materials/Material.tests.js b/test/unit/src/materials/Material.tests.js index 97cdf536caf916..f322beb666f874 100644 --- a/test/unit/src/materials/Material.tests.js +++ b/test/unit/src/materials/Material.tests.js @@ -7,52 +7,52 @@ export default QUnit.module( 'Materials', () => { QUnit.module( 'Material', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isMaterial", ( assert ) => { + QUnit.todo( 'isMaterial', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "onBeforeCompile", ( assert ) => { + QUnit.todo( 'onBeforeCompile', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setValues", ( assert ) => { + QUnit.todo( 'setValues', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "toJSON", ( assert ) => { + QUnit.todo( 'toJSON', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "clone", ( assert ) => { + QUnit.todo( 'clone', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "copy", ( assert ) => { + QUnit.todo( 'copy', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "dispose", ( assert ) => { + QUnit.todo( 'dispose', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/materials/MeshBasicMaterial.tests.js b/test/unit/src/materials/MeshBasicMaterial.tests.js index 56e096a70300df..74107073fbda97 100644 --- a/test/unit/src/materials/MeshBasicMaterial.tests.js +++ b/test/unit/src/materials/MeshBasicMaterial.tests.js @@ -7,29 +7,29 @@ export default QUnit.module( 'Materials', () => { QUnit.module( 'MeshBasicMaterial', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isMeshBasicMaterial", ( assert ) => { + QUnit.todo( 'isMeshBasicMaterial', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "copy", ( assert ) => { + QUnit.todo( 'copy', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/materials/MeshDepthMaterial.tests.js b/test/unit/src/materials/MeshDepthMaterial.tests.js index c633d5ccedb8e6..85d4e5d83f8a33 100644 --- a/test/unit/src/materials/MeshDepthMaterial.tests.js +++ b/test/unit/src/materials/MeshDepthMaterial.tests.js @@ -7,29 +7,29 @@ export default QUnit.module( 'Materials', () => { QUnit.module( 'MeshDepthMaterial', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isMeshDepthMaterial", ( assert ) => { + QUnit.todo( 'isMeshDepthMaterial', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "copy", ( assert ) => { + QUnit.todo( 'copy', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/materials/MeshDistanceMaterial.tests.js b/test/unit/src/materials/MeshDistanceMaterial.tests.js index 49db8758516823..e50bdc2ff1cf7d 100644 --- a/test/unit/src/materials/MeshDistanceMaterial.tests.js +++ b/test/unit/src/materials/MeshDistanceMaterial.tests.js @@ -7,29 +7,29 @@ export default QUnit.module( 'Materials', () => { QUnit.module( 'MeshDistanceMaterial', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isMeshDistanceMaterial", ( assert ) => { + QUnit.todo( 'isMeshDistanceMaterial', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "copy", ( assert ) => { + QUnit.todo( 'copy', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/materials/MeshLambertMaterial.tests.js b/test/unit/src/materials/MeshLambertMaterial.tests.js index 40f8c18491b9f2..1b1675052be9d4 100644 --- a/test/unit/src/materials/MeshLambertMaterial.tests.js +++ b/test/unit/src/materials/MeshLambertMaterial.tests.js @@ -7,29 +7,29 @@ export default QUnit.module( 'Materials', () => { QUnit.module( 'MeshLambertMaterial', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isMeshLambertMaterial", ( assert ) => { + QUnit.todo( 'isMeshLambertMaterial', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "copy", ( assert ) => { + QUnit.todo( 'copy', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/materials/MeshNormalMaterial.tests.js b/test/unit/src/materials/MeshNormalMaterial.tests.js index 2a0d88d8b1b239..2855e03f3f81c1 100644 --- a/test/unit/src/materials/MeshNormalMaterial.tests.js +++ b/test/unit/src/materials/MeshNormalMaterial.tests.js @@ -7,29 +7,29 @@ export default QUnit.module( 'Materials', () => { QUnit.module( 'MeshNormalMaterial', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isMeshNormalMaterial", ( assert ) => { + QUnit.todo( 'isMeshNormalMaterial', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "copy", ( assert ) => { + QUnit.todo( 'copy', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/materials/MeshPhongMaterial.tests.js b/test/unit/src/materials/MeshPhongMaterial.tests.js index 721433da7cb123..14bdb8277c723e 100644 --- a/test/unit/src/materials/MeshPhongMaterial.tests.js +++ b/test/unit/src/materials/MeshPhongMaterial.tests.js @@ -7,29 +7,29 @@ export default QUnit.module( 'Materials', () => { QUnit.module( 'MeshPhongMaterial', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isMeshPhongMaterial", ( assert ) => { + QUnit.todo( 'isMeshPhongMaterial', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "copy", ( assert ) => { + QUnit.todo( 'copy', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/materials/MeshPhysicalMaterial.tests.js b/test/unit/src/materials/MeshPhysicalMaterial.tests.js index 0287f74c3bd472..34054b4a83fd59 100644 --- a/test/unit/src/materials/MeshPhysicalMaterial.tests.js +++ b/test/unit/src/materials/MeshPhysicalMaterial.tests.js @@ -7,29 +7,29 @@ export default QUnit.module( 'Materials', () => { QUnit.module( 'MeshPhysicalMaterial', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isMeshPhysicalMaterial", ( assert ) => { + QUnit.todo( 'isMeshPhysicalMaterial', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "copy", ( assert ) => { + QUnit.todo( 'copy', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/materials/MeshStandardMaterial.tests.js b/test/unit/src/materials/MeshStandardMaterial.tests.js index ecd94422e42790..5317e49fd5311a 100644 --- a/test/unit/src/materials/MeshStandardMaterial.tests.js +++ b/test/unit/src/materials/MeshStandardMaterial.tests.js @@ -7,29 +7,29 @@ export default QUnit.module( 'Materials', () => { QUnit.module( 'MeshStandardMaterial', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isMeshStandardMaterial", ( assert ) => { + QUnit.todo( 'isMeshStandardMaterial', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "copy", ( assert ) => { + QUnit.todo( 'copy', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/materials/MeshToonMaterial.tests.js b/test/unit/src/materials/MeshToonMaterial.tests.js index 0aa3b172414bbf..c11e442d1617d2 100644 --- a/test/unit/src/materials/MeshToonMaterial.tests.js +++ b/test/unit/src/materials/MeshToonMaterial.tests.js @@ -7,29 +7,29 @@ export default QUnit.module( 'Materials', () => { QUnit.module( 'MeshToonMaterial', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isMeshToonMaterial", ( assert ) => { + QUnit.todo( 'isMeshToonMaterial', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "copy", ( assert ) => { + QUnit.todo( 'copy', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/materials/PointsMaterial.tests.js b/test/unit/src/materials/PointsMaterial.tests.js index b527f538a7f726..78f858443539e5 100644 --- a/test/unit/src/materials/PointsMaterial.tests.js +++ b/test/unit/src/materials/PointsMaterial.tests.js @@ -7,29 +7,29 @@ export default QUnit.module( 'Materials', () => { QUnit.module( 'PointsMaterial', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isPointsMaterial", ( assert ) => { + QUnit.todo( 'isPointsMaterial', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "copy", ( assert ) => { + QUnit.todo( 'copy', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/materials/RawShaderMaterial.tests.js b/test/unit/src/materials/RawShaderMaterial.tests.js index 3f0528d977b5b0..d74ed7c043f04b 100644 --- a/test/unit/src/materials/RawShaderMaterial.tests.js +++ b/test/unit/src/materials/RawShaderMaterial.tests.js @@ -7,23 +7,23 @@ export default QUnit.module( 'Materials', () => { QUnit.module( 'RawShaderMaterial', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isRawShaderMaterial", ( assert ) => { + QUnit.todo( 'isRawShaderMaterial', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/materials/ShaderMaterial.tests.js b/test/unit/src/materials/ShaderMaterial.tests.js index 6ffbc407736777..2d751f7e64078d 100644 --- a/test/unit/src/materials/ShaderMaterial.tests.js +++ b/test/unit/src/materials/ShaderMaterial.tests.js @@ -7,35 +7,35 @@ export default QUnit.module( 'Materials', () => { QUnit.module( 'ShaderMaterial', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isShaderwMaterial", ( assert ) => { + QUnit.todo( 'isShaderwMaterial', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "copy", ( assert ) => { + QUnit.todo( 'copy', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "toJSON", ( assert ) => { + QUnit.todo( 'toJSON', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/materials/ShadowMaterial.tests.js b/test/unit/src/materials/ShadowMaterial.tests.js index 3b7668c7c1a16e..5c09c6a184c087 100644 --- a/test/unit/src/materials/ShadowMaterial.tests.js +++ b/test/unit/src/materials/ShadowMaterial.tests.js @@ -7,23 +7,23 @@ export default QUnit.module( 'Materials', () => { QUnit.module( 'LineBasicMaterial', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isShadowMaterial", ( assert ) => { + QUnit.todo( 'isShadowMaterial', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/materials/SpriteMaterial.tests.js b/test/unit/src/materials/SpriteMaterial.tests.js index 21d6cb165ad538..5e0271add02d47 100644 --- a/test/unit/src/materials/SpriteMaterial.tests.js +++ b/test/unit/src/materials/SpriteMaterial.tests.js @@ -7,29 +7,29 @@ export default QUnit.module( 'Materials', () => { QUnit.module( 'SpriteMaterial', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isSpriteMaterial", ( assert ) => { + QUnit.todo( 'isSpriteMaterial', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "copy", ( assert ) => { + QUnit.todo( 'copy', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/math/Box2.tests.js b/test/unit/src/math/Box2.tests.js index 2714ac8cdc1c3a..51cf7e8730810e 100644 --- a/test/unit/src/math/Box2.tests.js +++ b/test/unit/src/math/Box2.tests.js @@ -16,232 +16,232 @@ export default QUnit.module( 'Maths', () => { QUnit.module( 'Box2', () => { // INSTANCING - QUnit.test( "Instancing", ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { var a = new Box2(); - assert.ok( a.min.equals( posInf2 ), "Passed!" ); - assert.ok( a.max.equals( negInf2 ), "Passed!" ); + assert.ok( a.min.equals( posInf2 ), 'Passed!' ); + assert.ok( a.max.equals( negInf2 ), 'Passed!' ); var a = new Box2( zero2.clone(), zero2.clone() ); - assert.ok( a.min.equals( zero2 ), "Passed!" ); - assert.ok( a.max.equals( zero2 ), "Passed!" ); + assert.ok( a.min.equals( zero2 ), 'Passed!' ); + assert.ok( a.max.equals( zero2 ), 'Passed!' ); var a = new Box2( zero2.clone(), one2.clone() ); - assert.ok( a.min.equals( zero2 ), "Passed!" ); - assert.ok( a.max.equals( one2 ), "Passed!" ); + assert.ok( a.min.equals( zero2 ), 'Passed!' ); + assert.ok( a.max.equals( one2 ), 'Passed!' ); } ); // PUBLIC STUFF - QUnit.test( "set", ( assert ) => { + QUnit.test( 'set', ( assert ) => { var a = new Box2(); a.set( zero2, one2 ); - assert.ok( a.min.equals( zero2 ), "Passed!" ); - assert.ok( a.max.equals( one2 ), "Passed!" ); + assert.ok( a.min.equals( zero2 ), 'Passed!' ); + assert.ok( a.max.equals( one2 ), 'Passed!' ); } ); - QUnit.test( "setFromPoints", ( assert ) => { + QUnit.test( 'setFromPoints', ( assert ) => { var a = new Box2(); a.setFromPoints( [ zero2, one2, two2 ] ); - assert.ok( a.min.equals( zero2 ), "Passed!" ); - assert.ok( a.max.equals( two2 ), "Passed!" ); + assert.ok( a.min.equals( zero2 ), 'Passed!' ); + assert.ok( a.max.equals( two2 ), 'Passed!' ); a.setFromPoints( [ one2 ] ); - assert.ok( a.min.equals( one2 ), "Passed!" ); - assert.ok( a.max.equals( one2 ), "Passed!" ); + assert.ok( a.min.equals( one2 ), 'Passed!' ); + assert.ok( a.max.equals( one2 ), 'Passed!' ); a.setFromPoints( [] ); - assert.ok( a.isEmpty(), "Passed!" ); + assert.ok( a.isEmpty(), 'Passed!' ); } ); - QUnit.test( "setFromCenterAndSize", ( assert ) => { + QUnit.test( 'setFromCenterAndSize', ( assert ) => { var a = new Box2(); a.setFromCenterAndSize( zero2, two2 ); - assert.ok( a.min.equals( negOne2 ), "Passed!" ); - assert.ok( a.max.equals( one2 ), "Passed!" ); + assert.ok( a.min.equals( negOne2 ), 'Passed!' ); + assert.ok( a.max.equals( one2 ), 'Passed!' ); a.setFromCenterAndSize( one2, two2 ); - assert.ok( a.min.equals( zero2 ), "Passed!" ); - assert.ok( a.max.equals( two2 ), "Passed!" ); + assert.ok( a.min.equals( zero2 ), 'Passed!' ); + assert.ok( a.max.equals( two2 ), 'Passed!' ); a.setFromCenterAndSize( zero2, zero2 ); - assert.ok( a.min.equals( zero2 ), "Passed!" ); - assert.ok( a.max.equals( zero2 ), "Passed!" ); + assert.ok( a.min.equals( zero2 ), 'Passed!' ); + assert.ok( a.max.equals( zero2 ), 'Passed!' ); } ); - QUnit.test( "clone", ( assert ) => { + QUnit.test( 'clone', ( assert ) => { var a = new Box2( zero2, zero2 ); var b = a.clone(); - assert.ok( b.min.equals( zero2 ), "Passed!" ); - assert.ok( b.max.equals( zero2 ), "Passed!" ); + assert.ok( b.min.equals( zero2 ), 'Passed!' ); + assert.ok( b.max.equals( zero2 ), 'Passed!' ); a = new Box2(); var b = a.clone(); - assert.ok( b.min.equals( posInf2 ), "Passed!" ); - assert.ok( b.max.equals( negInf2 ), "Passed!" ); + assert.ok( b.min.equals( posInf2 ), 'Passed!' ); + assert.ok( b.max.equals( negInf2 ), 'Passed!' ); } ); - QUnit.test( "copy", ( assert ) => { + QUnit.test( 'copy', ( assert ) => { var a = new Box2( zero2.clone(), one2.clone() ); var b = new Box2().copy( a ); - assert.ok( b.min.equals( zero2 ), "Passed!" ); - assert.ok( b.max.equals( one2 ), "Passed!" ); + assert.ok( b.min.equals( zero2 ), 'Passed!' ); + assert.ok( b.max.equals( one2 ), 'Passed!' ); // ensure that it is a true copy a.min = zero2; a.max = one2; - assert.ok( b.min.equals( zero2 ), "Passed!" ); - assert.ok( b.max.equals( one2 ), "Passed!" ); + assert.ok( b.min.equals( zero2 ), 'Passed!' ); + assert.ok( b.max.equals( one2 ), 'Passed!' ); } ); - QUnit.test( "empty/makeEmpty", ( assert ) => { + QUnit.test( 'empty/makeEmpty', ( assert ) => { var a = new Box2(); - assert.ok( a.isEmpty(), "Passed!" ); + assert.ok( a.isEmpty(), 'Passed!' ); var a = new Box2( zero2.clone(), one2.clone() ); - assert.ok( ! a.isEmpty(), "Passed!" ); + assert.ok( ! a.isEmpty(), 'Passed!' ); a.makeEmpty(); - assert.ok( a.isEmpty(), "Passed!" ); + assert.ok( a.isEmpty(), 'Passed!' ); } ); - QUnit.test( "isEmpty", ( assert ) => { + QUnit.test( 'isEmpty', ( assert ) => { var a = new Box2( zero2.clone(), zero2.clone() ); - assert.ok( ! a.isEmpty(), "Passed!" ); + assert.ok( ! a.isEmpty(), 'Passed!' ); var a = new Box2( zero2.clone(), one2.clone() ); - assert.ok( ! a.isEmpty(), "Passed!" ); + assert.ok( ! a.isEmpty(), 'Passed!' ); var a = new Box2( two2.clone(), one2.clone() ); - assert.ok( a.isEmpty(), "Passed!" ); + assert.ok( a.isEmpty(), 'Passed!' ); var a = new Box2( posInf2.clone(), negInf2.clone() ); - assert.ok( a.isEmpty(), "Passed!" ); + assert.ok( a.isEmpty(), 'Passed!' ); } ); - QUnit.test( "getCenter", ( assert ) => { + QUnit.test( 'getCenter', ( assert ) => { var a = new Box2( zero2.clone(), zero2.clone() ); var center = new Vector2(); - assert.ok( a.getCenter( center ).equals( zero2 ), "Passed!" ); + assert.ok( a.getCenter( center ).equals( zero2 ), 'Passed!' ); var a = new Box2( zero2, one2 ); var midpoint = one2.clone().multiplyScalar( 0.5 ); - assert.ok( a.getCenter( center ).equals( midpoint ), "Passed!" ); + assert.ok( a.getCenter( center ).equals( midpoint ), 'Passed!' ); } ); - QUnit.test( "getSize", ( assert ) => { + QUnit.test( 'getSize', ( assert ) => { var a = new Box2( zero2.clone(), zero2.clone() ); var size = new Vector2(); - assert.ok( a.getSize( size ).equals( zero2 ), "Passed!" ); + assert.ok( a.getSize( size ).equals( zero2 ), 'Passed!' ); var a = new Box2( zero2.clone(), one2.clone() ); - assert.ok( a.getSize( size ).equals( one2 ), "Passed!" ); + assert.ok( a.getSize( size ).equals( one2 ), 'Passed!' ); } ); - QUnit.test( "expandByPoint", ( assert ) => { + QUnit.test( 'expandByPoint', ( assert ) => { var a = new Box2( zero2.clone(), zero2.clone() ); var size = new Vector2(); var center = new Vector2(); a.expandByPoint( zero2 ); - assert.ok( a.getSize( size ).equals( zero2 ), "Passed!" ); + assert.ok( a.getSize( size ).equals( zero2 ), 'Passed!' ); a.expandByPoint( one2 ); - assert.ok( a.getSize( size ).equals( one2 ), "Passed!" ); + assert.ok( a.getSize( size ).equals( one2 ), 'Passed!' ); a.expandByPoint( one2.clone().negate() ); - assert.ok( a.getSize( size ).equals( one2.clone().multiplyScalar( 2 ) ), "Passed!" ); - assert.ok( a.getCenter( center ).equals( zero2 ), "Passed!" ); + assert.ok( a.getSize( size ).equals( one2.clone().multiplyScalar( 2 ) ), 'Passed!' ); + assert.ok( a.getCenter( center ).equals( zero2 ), 'Passed!' ); } ); - QUnit.test( "expandByVector", ( assert ) => { + QUnit.test( 'expandByVector', ( assert ) => { var a = new Box2( zero2.clone(), zero2.clone() ); var size = new Vector2(); var center = new Vector2(); a.expandByVector( zero2 ); - assert.ok( a.getSize( size ).equals( zero2 ), "Passed!" ); + assert.ok( a.getSize( size ).equals( zero2 ), 'Passed!' ); a.expandByVector( one2 ); - assert.ok( a.getSize( size ).equals( one2.clone().multiplyScalar( 2 ) ), "Passed!" ); - assert.ok( a.getCenter( center ).equals( zero2 ), "Passed!" ); + assert.ok( a.getSize( size ).equals( one2.clone().multiplyScalar( 2 ) ), 'Passed!' ); + assert.ok( a.getCenter( center ).equals( zero2 ), 'Passed!' ); } ); - QUnit.test( "expandByScalar", ( assert ) => { + QUnit.test( 'expandByScalar', ( assert ) => { var a = new Box2( zero2.clone(), zero2.clone() ); var size = new Vector2(); var center = new Vector2(); a.expandByScalar( 0 ); - assert.ok( a.getSize( size ).equals( zero2 ), "Passed!" ); + assert.ok( a.getSize( size ).equals( zero2 ), 'Passed!' ); a.expandByScalar( 1 ); - assert.ok( a.getSize( size ).equals( one2.clone().multiplyScalar( 2 ) ), "Passed!" ); - assert.ok( a.getCenter( center ).equals( zero2 ), "Passed!" ); + assert.ok( a.getSize( size ).equals( one2.clone().multiplyScalar( 2 ) ), 'Passed!' ); + assert.ok( a.getCenter( center ).equals( zero2 ), 'Passed!' ); } ); - QUnit.test( "containsPoint", ( assert ) => { + QUnit.test( 'containsPoint', ( assert ) => { var a = new Box2( zero2.clone(), zero2.clone() ); - assert.ok( a.containsPoint( zero2 ), "Passed!" ); - assert.ok( ! a.containsPoint( one2 ), "Passed!" ); + assert.ok( a.containsPoint( zero2 ), 'Passed!' ); + assert.ok( ! a.containsPoint( one2 ), 'Passed!' ); a.expandByScalar( 1 ); - assert.ok( a.containsPoint( zero2 ), "Passed!" ); - assert.ok( a.containsPoint( one2 ), "Passed!" ); - assert.ok( a.containsPoint( one2.clone().negate() ), "Passed!" ); + assert.ok( a.containsPoint( zero2 ), 'Passed!' ); + assert.ok( a.containsPoint( one2 ), 'Passed!' ); + assert.ok( a.containsPoint( one2.clone().negate() ), 'Passed!' ); } ); - QUnit.test( "containsBox", ( assert ) => { + QUnit.test( 'containsBox', ( assert ) => { var a = new Box2( zero2.clone(), zero2.clone() ); var b = new Box2( zero2.clone(), one2.clone() ); var c = new Box2( one2.clone().negate(), one2.clone() ); - assert.ok( a.containsBox( a ), "Passed!" ); - assert.ok( ! a.containsBox( b ), "Passed!" ); - assert.ok( ! a.containsBox( c ), "Passed!" ); + assert.ok( a.containsBox( a ), 'Passed!' ); + assert.ok( ! a.containsBox( b ), 'Passed!' ); + assert.ok( ! a.containsBox( c ), 'Passed!' ); - assert.ok( b.containsBox( a ), "Passed!" ); - assert.ok( c.containsBox( a ), "Passed!" ); - assert.ok( ! b.containsBox( c ), "Passed!" ); + assert.ok( b.containsBox( a ), 'Passed!' ); + assert.ok( c.containsBox( a ), 'Passed!' ); + assert.ok( ! b.containsBox( c ), 'Passed!' ); } ); - QUnit.test( "getParameter", ( assert ) => { + QUnit.test( 'getParameter', ( assert ) => { var a = new Box2( zero2.clone(), one2.clone() ); var b = new Box2( one2.clone().negate(), one2.clone() ); @@ -249,41 +249,41 @@ export default QUnit.module( 'Maths', () => { var parameter = new Vector2(); a.getParameter( zero2, parameter ); - assert.ok( parameter.equals( zero2 ), "Passed!" ); + assert.ok( parameter.equals( zero2 ), 'Passed!' ); a.getParameter( one2, parameter ); - assert.ok( parameter.equals( one2 ), "Passed!" ); + assert.ok( parameter.equals( one2 ), 'Passed!' ); b.getParameter( one2.clone().negate(), parameter ); - assert.ok( parameter.equals( zero2 ), "Passed!" ); + assert.ok( parameter.equals( zero2 ), 'Passed!' ); b.getParameter( zero2, parameter ); - assert.ok( parameter.equals( new Vector2( 0.5, 0.5 ) ), "Passed!" ); + assert.ok( parameter.equals( new Vector2( 0.5, 0.5 ) ), 'Passed!' ); b.getParameter( one2, parameter ); - assert.ok( parameter.equals( one2 ), "Passed!" ); + assert.ok( parameter.equals( one2 ), 'Passed!' ); } ); - QUnit.test( "intersectsBox", ( assert ) => { + QUnit.test( 'intersectsBox', ( assert ) => { var a = new Box2( zero2.clone(), zero2.clone() ); var b = new Box2( zero2.clone(), one2.clone() ); var c = new Box2( one2.clone().negate(), one2.clone() ); - assert.ok( a.intersectsBox( a ), "Passed!" ); - assert.ok( a.intersectsBox( b ), "Passed!" ); - assert.ok( a.intersectsBox( c ), "Passed!" ); + assert.ok( a.intersectsBox( a ), 'Passed!' ); + assert.ok( a.intersectsBox( b ), 'Passed!' ); + assert.ok( a.intersectsBox( c ), 'Passed!' ); - assert.ok( b.intersectsBox( a ), "Passed!" ); - assert.ok( c.intersectsBox( a ), "Passed!" ); - assert.ok( b.intersectsBox( c ), "Passed!" ); + assert.ok( b.intersectsBox( a ), 'Passed!' ); + assert.ok( c.intersectsBox( a ), 'Passed!' ); + assert.ok( b.intersectsBox( c ), 'Passed!' ); b.translate( two2 ); - assert.ok( ! a.intersectsBox( b ), "Passed!" ); - assert.ok( ! b.intersectsBox( a ), "Passed!" ); - assert.ok( ! b.intersectsBox( c ), "Passed!" ); + assert.ok( ! a.intersectsBox( b ), 'Passed!' ); + assert.ok( ! b.intersectsBox( a ), 'Passed!' ); + assert.ok( ! b.intersectsBox( c ), 'Passed!' ); } ); - QUnit.test( "clampPoint", ( assert ) => { + QUnit.test( 'clampPoint', ( assert ) => { var a = new Box2( zero2.clone(), zero2.clone() ); var b = new Box2( one2.clone().negate(), one2.clone() ); @@ -291,116 +291,116 @@ export default QUnit.module( 'Maths', () => { var point = new Vector2(); a.clampPoint( zero2, point ); - assert.ok( point.equals( new Vector2( 0, 0 ) ), "Passed!" ); + assert.ok( point.equals( new Vector2( 0, 0 ) ), 'Passed!' ); a.clampPoint( one2, point ); - assert.ok( point.equals( new Vector2( 0, 0 ) ), "Passed!" ); + assert.ok( point.equals( new Vector2( 0, 0 ) ), 'Passed!' ); a.clampPoint( one2.clone().negate(), point ); - assert.ok( point.equals( new Vector2( 0, 0 ) ), "Passed!" ); + assert.ok( point.equals( new Vector2( 0, 0 ) ), 'Passed!' ); b.clampPoint( two2, point ); - assert.ok( point.equals( new Vector2( 1, 1 ) ), "Passed!" ); + assert.ok( point.equals( new Vector2( 1, 1 ) ), 'Passed!' ); b.clampPoint( one2, point ); - assert.ok( point.equals( new Vector2( 1, 1 ) ), "Passed!" ); + assert.ok( point.equals( new Vector2( 1, 1 ) ), 'Passed!' ); b.clampPoint( zero2, point ); - assert.ok( point.equals( new Vector2( 0, 0 ) ), "Passed!" ); + assert.ok( point.equals( new Vector2( 0, 0 ) ), 'Passed!' ); b.clampPoint( one2.clone().negate(), point ); - assert.ok( point.equals( new Vector2( - 1, - 1 ) ), "Passed!" ); + assert.ok( point.equals( new Vector2( - 1, - 1 ) ), 'Passed!' ); b.clampPoint( two2.clone().negate(), point ); - assert.ok( point.equals( new Vector2( - 1, - 1 ) ), "Passed!" ); + assert.ok( point.equals( new Vector2( - 1, - 1 ) ), 'Passed!' ); } ); - QUnit.test( "distanceToPoint", ( assert ) => { + QUnit.test( 'distanceToPoint', ( assert ) => { var a = new Box2( zero2.clone(), zero2.clone() ); var b = new Box2( one2.clone().negate(), one2.clone() ); - assert.ok( a.distanceToPoint( new Vector2( 0, 0 ) ) == 0, "Passed!" ); - assert.ok( a.distanceToPoint( new Vector2( 1, 1 ) ) == Math.sqrt( 2 ), "Passed!" ); - assert.ok( a.distanceToPoint( new Vector2( - 1, - 1 ) ) == Math.sqrt( 2 ), "Passed!" ); + assert.ok( a.distanceToPoint( new Vector2( 0, 0 ) ) == 0, 'Passed!' ); + assert.ok( a.distanceToPoint( new Vector2( 1, 1 ) ) == Math.sqrt( 2 ), 'Passed!' ); + assert.ok( a.distanceToPoint( new Vector2( - 1, - 1 ) ) == Math.sqrt( 2 ), 'Passed!' ); - assert.ok( b.distanceToPoint( new Vector2( 2, 2 ) ) == Math.sqrt( 2 ), "Passed!" ); - assert.ok( b.distanceToPoint( new Vector2( 1, 1 ) ) == 0, "Passed!" ); - assert.ok( b.distanceToPoint( new Vector2( 0, 0 ) ) == 0, "Passed!" ); - assert.ok( b.distanceToPoint( new Vector2( - 1, - 1 ) ) == 0, "Passed!" ); - assert.ok( b.distanceToPoint( new Vector2( - 2, - 2 ) ) == Math.sqrt( 2 ), "Passed!" ); + assert.ok( b.distanceToPoint( new Vector2( 2, 2 ) ) == Math.sqrt( 2 ), 'Passed!' ); + assert.ok( b.distanceToPoint( new Vector2( 1, 1 ) ) == 0, 'Passed!' ); + assert.ok( b.distanceToPoint( new Vector2( 0, 0 ) ) == 0, 'Passed!' ); + assert.ok( b.distanceToPoint( new Vector2( - 1, - 1 ) ) == 0, 'Passed!' ); + assert.ok( b.distanceToPoint( new Vector2( - 2, - 2 ) ) == Math.sqrt( 2 ), 'Passed!' ); } ); - QUnit.test( "intersect", ( assert ) => { + QUnit.test( 'intersect', ( assert ) => { var a = new Box2( zero2.clone(), zero2.clone() ); var b = new Box2( zero2.clone(), one2.clone() ); var c = new Box2( one2.clone().negate(), one2.clone() ); - assert.ok( a.clone().intersect( a ).equals( a ), "Passed!" ); - assert.ok( a.clone().intersect( b ).equals( a ), "Passed!" ); - assert.ok( b.clone().intersect( b ).equals( b ), "Passed!" ); - assert.ok( a.clone().intersect( c ).equals( a ), "Passed!" ); - assert.ok( b.clone().intersect( c ).equals( b ), "Passed!" ); - assert.ok( c.clone().intersect( c ).equals( c ), "Passed!" ); + assert.ok( a.clone().intersect( a ).equals( a ), 'Passed!' ); + assert.ok( a.clone().intersect( b ).equals( a ), 'Passed!' ); + assert.ok( b.clone().intersect( b ).equals( b ), 'Passed!' ); + assert.ok( a.clone().intersect( c ).equals( a ), 'Passed!' ); + assert.ok( b.clone().intersect( c ).equals( b ), 'Passed!' ); + assert.ok( c.clone().intersect( c ).equals( c ), 'Passed!' ); } ); - QUnit.test( "union", ( assert ) => { + QUnit.test( 'union', ( assert ) => { var a = new Box2( zero2.clone(), zero2.clone() ); var b = new Box2( zero2.clone(), one2.clone() ); var c = new Box2( one2.clone().negate(), one2.clone() ); - assert.ok( a.clone().union( a ).equals( a ), "Passed!" ); - assert.ok( a.clone().union( b ).equals( b ), "Passed!" ); - assert.ok( a.clone().union( c ).equals( c ), "Passed!" ); - assert.ok( b.clone().union( c ).equals( c ), "Passed!" ); + assert.ok( a.clone().union( a ).equals( a ), 'Passed!' ); + assert.ok( a.clone().union( b ).equals( b ), 'Passed!' ); + assert.ok( a.clone().union( c ).equals( c ), 'Passed!' ); + assert.ok( b.clone().union( c ).equals( c ), 'Passed!' ); } ); - QUnit.test( "translate", ( assert ) => { + QUnit.test( 'translate', ( assert ) => { var a = new Box2( zero2.clone(), zero2.clone() ); var b = new Box2( zero2.clone(), one2.clone() ); var c = new Box2( one2.clone().negate(), one2.clone() ); var d = new Box2( one2.clone().negate(), zero2.clone() ); - assert.ok( a.clone().translate( one2 ).equals( new Box2( one2, one2 ) ), "Passed!" ); - assert.ok( a.clone().translate( one2 ).translate( one2.clone().negate() ).equals( a ), "Passed!" ); - assert.ok( d.clone().translate( one2 ).equals( b ), "Passed!" ); - assert.ok( b.clone().translate( one2.clone().negate() ).equals( d ), "Passed!" ); + assert.ok( a.clone().translate( one2 ).equals( new Box2( one2, one2 ) ), 'Passed!' ); + assert.ok( a.clone().translate( one2 ).translate( one2.clone().negate() ).equals( a ), 'Passed!' ); + assert.ok( d.clone().translate( one2 ).equals( b ), 'Passed!' ); + assert.ok( b.clone().translate( one2.clone().negate() ).equals( d ), 'Passed!' ); } ); - QUnit.test( "equals", ( assert ) => { + QUnit.test( 'equals', ( assert ) => { var a = new Box2(); var b = new Box2(); - assert.ok( b.equals( a ), "Passed!" ); - assert.ok( a.equals( b ), "Passed!" ); + assert.ok( b.equals( a ), 'Passed!' ); + assert.ok( a.equals( b ), 'Passed!' ); a = new Box2( one2, two2 ); b = new Box2( one2, two2 ); - assert.ok( b.equals( a ), "Passed!" ); - assert.ok( a.equals( b ), "Passed!" ); + assert.ok( b.equals( a ), 'Passed!' ); + assert.ok( a.equals( b ), 'Passed!' ); a = new Box2( one2, two2 ); b = a.clone(); - assert.ok( b.equals( a ), "Passed!" ); - assert.ok( a.equals( b ), "Passed!" ); + assert.ok( b.equals( a ), 'Passed!' ); + assert.ok( a.equals( b ), 'Passed!' ); a = new Box2( one2, two2 ); b = new Box2( one2, one2 ); - assert.ok( ! b.equals( a ), "Passed!" ); - assert.ok( ! a.equals( b ), "Passed!" ); + assert.ok( ! b.equals( a ), 'Passed!' ); + assert.ok( ! a.equals( b ), 'Passed!' ); a = new Box2(); b = new Box2( one2, one2 ); - assert.ok( ! b.equals( a ), "Passed!" ); - assert.ok( ! a.equals( b ), "Passed!" ); + assert.ok( ! b.equals( a ), 'Passed!' ); + assert.ok( ! a.equals( b ), 'Passed!' ); a = new Box2( one2, two2 ); b = new Box2( one2, one2 ); - assert.ok( ! b.equals( a ), "Passed!" ); - assert.ok( ! a.equals( b ), "Passed!" ); + assert.ok( ! b.equals( a ), 'Passed!' ); + assert.ok( ! a.equals( b ), 'Passed!' ); } ); diff --git a/test/unit/src/math/Box3.tests.js b/test/unit/src/math/Box3.tests.js index 099c004135aa5f..4a659c17f5d4b2 100644 --- a/test/unit/src/math/Box3.tests.js +++ b/test/unit/src/math/Box3.tests.js @@ -30,54 +30,54 @@ export default QUnit.module( 'Maths', () => { QUnit.module( 'Box3', () => { // INSTANCING - QUnit.test( "Instancing", ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { var a = new Box3(); - assert.ok( a.min.equals( posInf3 ), "Passed!" ); - assert.ok( a.max.equals( negInf3 ), "Passed!" ); + assert.ok( a.min.equals( posInf3 ), 'Passed!' ); + assert.ok( a.max.equals( negInf3 ), 'Passed!' ); var a = new Box3( zero3.clone(), zero3.clone() ); - assert.ok( a.min.equals( zero3 ), "Passed!" ); - assert.ok( a.max.equals( zero3 ), "Passed!" ); + assert.ok( a.min.equals( zero3 ), 'Passed!' ); + assert.ok( a.max.equals( zero3 ), 'Passed!' ); var a = new Box3( zero3.clone(), one3.clone() ); - assert.ok( a.min.equals( zero3 ), "Passed!" ); - assert.ok( a.max.equals( one3 ), "Passed!" ); + assert.ok( a.min.equals( zero3 ), 'Passed!' ); + assert.ok( a.max.equals( one3 ), 'Passed!' ); } ); // PUBLIC STUFF - QUnit.test( "isBox3", ( assert ) => { + QUnit.test( 'isBox3', ( assert ) => { var a = new Box3(); - assert.ok( a.isBox3 === true, "Passed!" ); + assert.ok( a.isBox3 === true, 'Passed!' ); var b = new Sphere(); - assert.ok( ! b.isBox3, "Passed!" ); + assert.ok( ! b.isBox3, 'Passed!' ); } ); - QUnit.test( "set", ( assert ) => { + QUnit.test( 'set', ( assert ) => { var a = new Box3(); a.set( zero3, one3 ); - assert.ok( a.min.equals( zero3 ), "Passed!" ); - assert.ok( a.max.equals( one3 ), "Passed!" ); + assert.ok( a.min.equals( zero3 ), 'Passed!' ); + assert.ok( a.max.equals( one3 ), 'Passed!' ); } ); - QUnit.test( "setFromArray", ( assert ) => { + QUnit.test( 'setFromArray', ( assert ) => { var a = new Box3(); a.setFromArray( [ 0, 0, 0, 1, 1, 1, 2, 2, 2 ] ); - assert.ok( a.min.equals( zero3 ), "Passed!" ); - assert.ok( a.max.equals( two3 ), "Passed!" ); + assert.ok( a.min.equals( zero3 ), 'Passed!' ); + assert.ok( a.max.equals( two3 ), 'Passed!' ); } ); - QUnit.test( "setFromBufferAttribute", ( assert ) => { + QUnit.test( 'setFromBufferAttribute', ( assert ) => { var a = new Box3( zero3.clone(), one3.clone() ); var bigger = new BufferAttribute( new Float32Array( [ @@ -90,36 +90,36 @@ export default QUnit.module( 'Maths', () => { var newMax = new Vector3( 2, 2, 2 ); a.setFromBufferAttribute( bigger ); - assert.ok( a.min.equals( newMin ), "Bigger box: correct new minimum" ); - assert.ok( a.max.equals( newMax ), "Bigger box: correct new maximum" ); + assert.ok( a.min.equals( newMin ), 'Bigger box: correct new minimum' ); + assert.ok( a.max.equals( newMax ), 'Bigger box: correct new maximum' ); newMin.set( - 0.5, - 0.5, - 0.5 ); newMax.set( 0.5, 0.5, 0.5 ); a.setFromBufferAttribute( smaller ); - assert.ok( a.min.equals( newMin ), "Smaller box: correct new minimum" ); - assert.ok( a.max.equals( newMax ), "Smaller box: correct new maximum" ); + assert.ok( a.min.equals( newMin ), 'Smaller box: correct new minimum' ); + assert.ok( a.max.equals( newMax ), 'Smaller box: correct new maximum' ); } ); - QUnit.test( "setFromPoints", ( assert ) => { + QUnit.test( 'setFromPoints', ( assert ) => { var a = new Box3(); a.setFromPoints( [ zero3, one3, two3 ] ); - assert.ok( a.min.equals( zero3 ), "Passed!" ); - assert.ok( a.max.equals( two3 ), "Passed!" ); + assert.ok( a.min.equals( zero3 ), 'Passed!' ); + assert.ok( a.max.equals( two3 ), 'Passed!' ); a.setFromPoints( [ one3 ] ); - assert.ok( a.min.equals( one3 ), "Passed!" ); - assert.ok( a.max.equals( one3 ), "Passed!" ); + assert.ok( a.min.equals( one3 ), 'Passed!' ); + assert.ok( a.max.equals( one3 ), 'Passed!' ); a.setFromPoints( [] ); - assert.ok( a.isEmpty(), "Passed!" ); + assert.ok( a.isEmpty(), 'Passed!' ); } ); - QUnit.test( "setFromCenterAndSize", ( assert ) => { + QUnit.test( 'setFromCenterAndSize', ( assert ) => { var a = new Box3( zero3.clone(), one3.clone() ); var b = a.clone(); @@ -132,27 +132,27 @@ export default QUnit.module( 'Maths', () => { a.getCenter( centerA ); a.getSize( sizeA ); a.setFromCenterAndSize( centerA, sizeA ); - assert.ok( a.equals( b ), "Same values: no changes" ); + assert.ok( a.equals( b ), 'Same values: no changes' ); a.setFromCenterAndSize( newCenter, sizeA ); a.getCenter( centerA ); a.getSize( sizeA ); b.getSize( sizeB ); - assert.ok( centerA.equals( newCenter ), "Move center: correct new center" ); - assert.ok( sizeA.equals( sizeB ), "Move center: no change in size" ); - assert.notOk( a.equals( b ), "Move center: no longer equal to old values" ); + assert.ok( centerA.equals( newCenter ), 'Move center: correct new center' ); + assert.ok( sizeA.equals( sizeB ), 'Move center: no change in size' ); + assert.notOk( a.equals( b ), 'Move center: no longer equal to old values' ); a.setFromCenterAndSize( centerA, newSize ); a.getCenter( centerA ); a.getSize( sizeA ); - assert.ok( centerA.equals( newCenter ), "Resize: no change to center" ); - assert.ok( sizeA.equals( newSize ), "Resize: correct new size" ); - assert.notOk( a.equals( b ), "Resize: no longer equal to old values" ); + assert.ok( centerA.equals( newCenter ), 'Resize: no change to center' ); + assert.ok( sizeA.equals( newSize ), 'Resize: correct new size' ); + assert.notOk( a.equals( b ), 'Resize: no longer equal to old values' ); } ); - QUnit.test( "setFromObject/BufferGeometry", ( assert ) => { + QUnit.test( 'setFromObject/BufferGeometry', ( assert ) => { var a = new Box3( zero3.clone(), one3.clone() ); var object = new Mesh( new BoxGeometry( 2, 2, 2 ) ); @@ -160,147 +160,147 @@ export default QUnit.module( 'Maths', () => { object.add( child ); a.setFromObject( object ); - assert.ok( a.min.equals( new Vector3( - 1, - 1, - 1 ) ), "Correct new minimum" ); - assert.ok( a.max.equals( new Vector3( 1, 1, 1 ) ), "Correct new maximum" ); + assert.ok( a.min.equals( new Vector3( - 1, - 1, - 1 ) ), 'Correct new minimum' ); + assert.ok( a.max.equals( new Vector3( 1, 1, 1 ) ), 'Correct new maximum' ); } ); - QUnit.test( "clone", ( assert ) => { + QUnit.test( 'clone', ( assert ) => { var a = new Box3( zero3.clone(), one3.clone() ); var b = a.clone(); - assert.ok( b.min.equals( zero3 ), "Passed!" ); - assert.ok( b.max.equals( one3 ), "Passed!" ); + assert.ok( b.min.equals( zero3 ), 'Passed!' ); + assert.ok( b.max.equals( one3 ), 'Passed!' ); a = new Box3(); var b = a.clone(); - assert.ok( b.min.equals( posInf3 ), "Passed!" ); - assert.ok( b.max.equals( negInf3 ), "Passed!" ); + assert.ok( b.min.equals( posInf3 ), 'Passed!' ); + assert.ok( b.max.equals( negInf3 ), 'Passed!' ); } ); - QUnit.test( "copy", ( assert ) => { + QUnit.test( 'copy', ( assert ) => { var a = new Box3( zero3.clone(), one3.clone() ); var b = new Box3().copy( a ); - assert.ok( b.min.equals( zero3 ), "Passed!" ); - assert.ok( b.max.equals( one3 ), "Passed!" ); + assert.ok( b.min.equals( zero3 ), 'Passed!' ); + assert.ok( b.max.equals( one3 ), 'Passed!' ); // ensure that it is a true copy a.min = zero3; a.max = one3; - assert.ok( b.min.equals( zero3 ), "Passed!" ); - assert.ok( b.max.equals( one3 ), "Passed!" ); + assert.ok( b.min.equals( zero3 ), 'Passed!' ); + assert.ok( b.max.equals( one3 ), 'Passed!' ); } ); - QUnit.test( "empty/makeEmpty", ( assert ) => { + QUnit.test( 'empty/makeEmpty', ( assert ) => { var a = new Box3(); - assert.ok( a.isEmpty(), "Passed!" ); + assert.ok( a.isEmpty(), 'Passed!' ); var a = new Box3( zero3.clone(), one3.clone() ); - assert.ok( ! a.isEmpty(), "Passed!" ); + assert.ok( ! a.isEmpty(), 'Passed!' ); a.makeEmpty(); - assert.ok( a.isEmpty(), "Passed!" ); + assert.ok( a.isEmpty(), 'Passed!' ); } ); - QUnit.test( "isEmpty", ( assert ) => { + QUnit.test( 'isEmpty', ( assert ) => { var a = new Box3( zero3.clone(), zero3.clone() ); - assert.ok( ! a.isEmpty(), "Passed!" ); + assert.ok( ! a.isEmpty(), 'Passed!' ); var a = new Box3( zero3.clone(), one3.clone() ); - assert.ok( ! a.isEmpty(), "Passed!" ); + assert.ok( ! a.isEmpty(), 'Passed!' ); var a = new Box3( two3.clone(), one3.clone() ); - assert.ok( a.isEmpty(), "Passed!" ); + assert.ok( a.isEmpty(), 'Passed!' ); var a = new Box3( posInf3.clone(), negInf3.clone() ); - assert.ok( a.isEmpty(), "Passed!" ); + assert.ok( a.isEmpty(), 'Passed!' ); } ); - QUnit.test( "getCenter", ( assert ) => { + QUnit.test( 'getCenter', ( assert ) => { var a = new Box3( zero3.clone(), zero3.clone() ); var center = new Vector3(); - assert.ok( a.getCenter( center ).equals( zero3 ), "Passed!" ); + assert.ok( a.getCenter( center ).equals( zero3 ), 'Passed!' ); var a = new Box3( zero3.clone(), one3.clone() ); var midpoint = one3.clone().multiplyScalar( 0.5 ); - assert.ok( a.getCenter( center ).equals( midpoint ), "Passed!" ); + assert.ok( a.getCenter( center ).equals( midpoint ), 'Passed!' ); } ); - QUnit.test( "getSize", ( assert ) => { + QUnit.test( 'getSize', ( assert ) => { var a = new Box3( zero3.clone(), zero3.clone() ); var size = new Vector3(); - assert.ok( a.getSize( size ).equals( zero3 ), "Passed!" ); + assert.ok( a.getSize( size ).equals( zero3 ), 'Passed!' ); var a = new Box3( zero3.clone(), one3.clone() ); - assert.ok( a.getSize( size ).equals( one3 ), "Passed!" ); + assert.ok( a.getSize( size ).equals( one3 ), 'Passed!' ); } ); - QUnit.test( "expandByPoint", ( assert ) => { + QUnit.test( 'expandByPoint', ( assert ) => { var a = new Box3( zero3.clone(), zero3.clone() ); var center = new Vector3(); var size = new Vector3(); a.expandByPoint( zero3 ); - assert.ok( a.getSize( size ).equals( zero3 ), "Passed!" ); + assert.ok( a.getSize( size ).equals( zero3 ), 'Passed!' ); a.expandByPoint( one3 ); - assert.ok( a.getSize( size ).equals( one3 ), "Passed!" ); + assert.ok( a.getSize( size ).equals( one3 ), 'Passed!' ); a.expandByPoint( one3.clone().negate() ); - assert.ok( a.getSize( size ).equals( one3.clone().multiplyScalar( 2 ) ), "Passed!" ); - assert.ok( a.getCenter( center ).equals( zero3 ), "Passed!" ); + assert.ok( a.getSize( size ).equals( one3.clone().multiplyScalar( 2 ) ), 'Passed!' ); + assert.ok( a.getCenter( center ).equals( zero3 ), 'Passed!' ); } ); - QUnit.test( "expandByVector", ( assert ) => { + QUnit.test( 'expandByVector', ( assert ) => { var a = new Box3( zero3.clone(), zero3.clone() ); var center = new Vector3(); var size = new Vector3(); a.expandByVector( zero3 ); - assert.ok( a.getSize( size ).equals( zero3 ), "Passed!" ); + assert.ok( a.getSize( size ).equals( zero3 ), 'Passed!' ); a.expandByVector( one3 ); - assert.ok( a.getSize( size ).equals( one3.clone().multiplyScalar( 2 ) ), "Passed!" ); - assert.ok( a.getCenter( center ).equals( zero3 ), "Passed!" ); + assert.ok( a.getSize( size ).equals( one3.clone().multiplyScalar( 2 ) ), 'Passed!' ); + assert.ok( a.getCenter( center ).equals( zero3 ), 'Passed!' ); } ); - QUnit.test( "expandByScalar", ( assert ) => { + QUnit.test( 'expandByScalar', ( assert ) => { var a = new Box3( zero3.clone(), zero3.clone() ); var center = new Vector3(); var size = new Vector3(); a.expandByScalar( 0 ); - assert.ok( a.getSize( size ).equals( zero3 ), "Passed!" ); + assert.ok( a.getSize( size ).equals( zero3 ), 'Passed!' ); a.expandByScalar( 1 ); - assert.ok( a.getSize( size ).equals( one3.clone().multiplyScalar( 2 ) ), "Passed!" ); - assert.ok( a.getCenter( center ).equals( zero3 ), "Passed!" ); + assert.ok( a.getSize( size ).equals( one3.clone().multiplyScalar( 2 ) ), 'Passed!' ); + assert.ok( a.getCenter( center ).equals( zero3 ), 'Passed!' ); } ); - QUnit.test( "expandByObject", ( assert ) => { + QUnit.test( 'expandByObject', ( assert ) => { var a = new Box3( zero3.clone(), one3.clone() ); var b = a.clone(); @@ -310,125 +310,125 @@ export default QUnit.module( 'Maths', () => { // just a bigger box to begin with a.expandByObject( bigger ); - assert.ok( a.min.equals( new Vector3( - 1, - 1, - 1 ) ), "Bigger box: correct new minimum" ); - assert.ok( a.max.equals( new Vector3( 1, 1, 1 ) ), "Bigger box: correct new maximum" ); + assert.ok( a.min.equals( new Vector3( - 1, - 1, - 1 ) ), 'Bigger box: correct new minimum' ); + assert.ok( a.max.equals( new Vector3( 1, 1, 1 ) ), 'Bigger box: correct new maximum' ); // a translated, bigger box a.copy( b ); bigger.translateX( 2 ); a.expandByObject( bigger ); - assert.ok( a.min.equals( new Vector3( 0, - 1, - 1 ) ), "Translated, bigger box: correct new minimum" ); - assert.ok( a.max.equals( new Vector3( 3, 1, 1 ) ), "Translated, bigger box: correct new maximum" ); + assert.ok( a.min.equals( new Vector3( 0, - 1, - 1 ) ), 'Translated, bigger box: correct new minimum' ); + assert.ok( a.max.equals( new Vector3( 3, 1, 1 ) ), 'Translated, bigger box: correct new maximum' ); // a translated, bigger box with child a.copy( b ); bigger.add( child ); a.expandByObject( bigger ); - assert.ok( a.min.equals( new Vector3( 0, - 1, - 1 ) ), "Translated, bigger box with child: correct new minimum" ); - assert.ok( a.max.equals( new Vector3( 3, 1, 1 ) ), "Translated, bigger box with child: correct new maximum" ); + assert.ok( a.min.equals( new Vector3( 0, - 1, - 1 ) ), 'Translated, bigger box with child: correct new minimum' ); + assert.ok( a.max.equals( new Vector3( 3, 1, 1 ) ), 'Translated, bigger box with child: correct new maximum' ); // a translated, bigger box with a translated child a.copy( b ); child.translateX( 2 ); a.expandByObject( bigger ); - assert.ok( a.min.equals( new Vector3( 0, - 1, - 1 ) ), "Translated, bigger box with translated child: correct new minimum" ); - assert.ok( a.max.equals( new Vector3( 4.5, 1, 1 ) ), "Translated, bigger box with translated child: correct new maximum" ); + assert.ok( a.min.equals( new Vector3( 0, - 1, - 1 ) ), 'Translated, bigger box with translated child: correct new minimum' ); + assert.ok( a.max.equals( new Vector3( 4.5, 1, 1 ) ), 'Translated, bigger box with translated child: correct new maximum' ); // a smaller box a.copy( b ); a.expandByObject( smaller ); - assert.ok( a.min.equals( new Vector3( - 0.25, - 0.25, - 0.25 ) ), "Smaller box: correct new minimum" ); - assert.ok( a.max.equals( new Vector3( 1, 1, 1 ) ), "Smaller box: correct new maximum" ); + assert.ok( a.min.equals( new Vector3( - 0.25, - 0.25, - 0.25 ) ), 'Smaller box: correct new minimum' ); + assert.ok( a.max.equals( new Vector3( 1, 1, 1 ) ), 'Smaller box: correct new maximum' ); // - assert.ok( new Box3().expandByObject( new Mesh() ).isEmpty() === true, "The AABB of a mesh with inital geometry is empty." ); + assert.ok( new Box3().expandByObject( new Mesh() ).isEmpty() === true, 'The AABB of a mesh with inital geometry is empty.' ); } ); - QUnit.test( "containsPoint", ( assert ) => { + QUnit.test( 'containsPoint', ( assert ) => { var a = new Box3( zero3.clone(), zero3.clone() ); - assert.ok( a.containsPoint( zero3 ), "Passed!" ); - assert.ok( ! a.containsPoint( one3 ), "Passed!" ); + assert.ok( a.containsPoint( zero3 ), 'Passed!' ); + assert.ok( ! a.containsPoint( one3 ), 'Passed!' ); a.expandByScalar( 1 ); - assert.ok( a.containsPoint( zero3 ), "Passed!" ); - assert.ok( a.containsPoint( one3 ), "Passed!" ); - assert.ok( a.containsPoint( one3.clone().negate() ), "Passed!" ); + assert.ok( a.containsPoint( zero3 ), 'Passed!' ); + assert.ok( a.containsPoint( one3 ), 'Passed!' ); + assert.ok( a.containsPoint( one3.clone().negate() ), 'Passed!' ); } ); - QUnit.test( "containsBox", ( assert ) => { + QUnit.test( 'containsBox', ( assert ) => { var a = new Box3( zero3.clone(), zero3.clone() ); var b = new Box3( zero3.clone(), one3.clone() ); var c = new Box3( one3.clone().negate(), one3.clone() ); - assert.ok( a.containsBox( a ), "Passed!" ); - assert.ok( ! a.containsBox( b ), "Passed!" ); - assert.ok( ! a.containsBox( c ), "Passed!" ); + assert.ok( a.containsBox( a ), 'Passed!' ); + assert.ok( ! a.containsBox( b ), 'Passed!' ); + assert.ok( ! a.containsBox( c ), 'Passed!' ); - assert.ok( b.containsBox( a ), "Passed!" ); - assert.ok( c.containsBox( a ), "Passed!" ); - assert.ok( ! b.containsBox( c ), "Passed!" ); + assert.ok( b.containsBox( a ), 'Passed!' ); + assert.ok( c.containsBox( a ), 'Passed!' ); + assert.ok( ! b.containsBox( c ), 'Passed!' ); } ); - QUnit.test( "getParameter", ( assert ) => { + QUnit.test( 'getParameter', ( assert ) => { var a = new Box3( zero3.clone(), one3.clone() ); var b = new Box3( one3.clone().negate(), one3.clone() ); var parameter = new Vector3(); a.getParameter( zero3, parameter ); - assert.ok( parameter.equals( zero3 ), "Passed!" ); + assert.ok( parameter.equals( zero3 ), 'Passed!' ); a.getParameter( one3, parameter ); - assert.ok( parameter.equals( one3 ), "Passed!" ); + assert.ok( parameter.equals( one3 ), 'Passed!' ); b.getParameter( one3.clone().negate(), parameter ); - assert.ok( parameter.equals( zero3 ), "Passed!" ); + assert.ok( parameter.equals( zero3 ), 'Passed!' ); b.getParameter( zero3, parameter ); - assert.ok( parameter.equals( new Vector3( 0.5, 0.5, 0.5 ) ), "Passed!" ); + assert.ok( parameter.equals( new Vector3( 0.5, 0.5, 0.5 ) ), 'Passed!' ); b.getParameter( one3, parameter ); - assert.ok( parameter.equals( one3 ), "Passed!" ); + assert.ok( parameter.equals( one3 ), 'Passed!' ); } ); - QUnit.test( "intersectsBox", ( assert ) => { + QUnit.test( 'intersectsBox', ( assert ) => { var a = new Box3( zero3.clone(), zero3.clone() ); var b = new Box3( zero3.clone(), one3.clone() ); var c = new Box3( one3.clone().negate(), one3.clone() ); - assert.ok( a.intersectsBox( a ), "Passed!" ); - assert.ok( a.intersectsBox( b ), "Passed!" ); - assert.ok( a.intersectsBox( c ), "Passed!" ); + assert.ok( a.intersectsBox( a ), 'Passed!' ); + assert.ok( a.intersectsBox( b ), 'Passed!' ); + assert.ok( a.intersectsBox( c ), 'Passed!' ); - assert.ok( b.intersectsBox( a ), "Passed!" ); - assert.ok( c.intersectsBox( a ), "Passed!" ); - assert.ok( b.intersectsBox( c ), "Passed!" ); + assert.ok( b.intersectsBox( a ), 'Passed!' ); + assert.ok( c.intersectsBox( a ), 'Passed!' ); + assert.ok( b.intersectsBox( c ), 'Passed!' ); b.translate( new Vector3( 2, 2, 2 ) ); - assert.ok( ! a.intersectsBox( b ), "Passed!" ); - assert.ok( ! b.intersectsBox( a ), "Passed!" ); - assert.ok( ! b.intersectsBox( c ), "Passed!" ); + assert.ok( ! a.intersectsBox( b ), 'Passed!' ); + assert.ok( ! b.intersectsBox( a ), 'Passed!' ); + assert.ok( ! b.intersectsBox( c ), 'Passed!' ); } ); - QUnit.test( "intersectsSphere", ( assert ) => { + QUnit.test( 'intersectsSphere', ( assert ) => { var a = new Box3( zero3.clone(), one3.clone() ); var b = new Sphere( zero3.clone(), 1 ); - assert.ok( a.intersectsSphere( b ), "Passed!" ); + assert.ok( a.intersectsSphere( b ), 'Passed!' ); b.translate( new Vector3( 2, 2, 2 ) ); - assert.ok( ! a.intersectsSphere( b ), "Passed!" ); + assert.ok( ! a.intersectsSphere( b ), 'Passed!' ); } ); - QUnit.test( "intersectsPlane", ( assert ) => { + QUnit.test( 'intersectsPlane', ( assert ) => { var a = new Box3( zero3.clone(), one3.clone() ); var b = new Plane( new Vector3( 0, 1, 0 ), 1 ); @@ -441,19 +441,19 @@ export default QUnit.module( 'Maths', () => { var i = new Plane( new Vector3( 1, 1, 1 ).normalize(), - 1.732 ); var j = new Plane( new Vector3( 1, 1, 1 ).normalize(), - 1.733 ); - assert.ok( ! a.intersectsPlane( b ), "Passed!" ); - assert.ok( ! a.intersectsPlane( c ), "Passed!" ); - assert.ok( ! a.intersectsPlane( d ), "Passed!" ); - assert.ok( ! a.intersectsPlane( e ), "Passed!" ); - assert.ok( a.intersectsPlane( f ), "Passed!" ); - assert.ok( a.intersectsPlane( g ), "Passed!" ); - assert.ok( a.intersectsPlane( h ), "Passed!" ); - assert.ok( a.intersectsPlane( i ), "Passed!" ); - assert.ok( ! a.intersectsPlane( j ), "Passed!" ); + assert.ok( ! a.intersectsPlane( b ), 'Passed!' ); + assert.ok( ! a.intersectsPlane( c ), 'Passed!' ); + assert.ok( ! a.intersectsPlane( d ), 'Passed!' ); + assert.ok( ! a.intersectsPlane( e ), 'Passed!' ); + assert.ok( a.intersectsPlane( f ), 'Passed!' ); + assert.ok( a.intersectsPlane( g ), 'Passed!' ); + assert.ok( a.intersectsPlane( h ), 'Passed!' ); + assert.ok( a.intersectsPlane( i ), 'Passed!' ); + assert.ok( ! a.intersectsPlane( j ), 'Passed!' ); } ); - QUnit.test( "intersectsTriangle", ( assert ) => { + QUnit.test( 'intersectsTriangle', ( assert ) => { var a = new Box3( one3.clone(), two3.clone() ); var b = new Triangle( new Vector3( 1.5, 1.5, 2.5 ), new Vector3( 2.5, 1.5, 1.5 ), new Vector3( 1.5, 2.5, 1.5 ) ); @@ -462,99 +462,99 @@ export default QUnit.module( 'Maths', () => { var e = new Triangle( new Vector3( 1.5, 1.8, 3 ), new Vector3( 3, 1.8, 1.5 ), new Vector3( 1.5, 2.5, 1.5 ) ); var f = new Triangle( new Vector3( 1.5, 2.5, 3 ), new Vector3( 3, 2.5, 1.5 ), new Vector3( 1.5, 2.5, 1.5 ) ); - assert.ok( a.intersectsTriangle( b ), "Passed!" ); - assert.ok( a.intersectsTriangle( c ), "Passed!" ); - assert.ok( a.intersectsTriangle( d ), "Passed!" ); - assert.ok( ! a.intersectsTriangle( e ), "Passed!" ); - assert.ok( ! a.intersectsTriangle( f ), "Passed!" ); + assert.ok( a.intersectsTriangle( b ), 'Passed!' ); + assert.ok( a.intersectsTriangle( c ), 'Passed!' ); + assert.ok( a.intersectsTriangle( d ), 'Passed!' ); + assert.ok( ! a.intersectsTriangle( e ), 'Passed!' ); + assert.ok( ! a.intersectsTriangle( f ), 'Passed!' ); } ); - QUnit.test( "clampPoint", ( assert ) => { + QUnit.test( 'clampPoint', ( assert ) => { var a = new Box3( zero3.clone(), zero3.clone() ); var b = new Box3( one3.clone().negate(), one3.clone() ); var point = new Vector3(); a.clampPoint( zero3, point ); - assert.ok( point.equals( zero3 ), "Passed!" ); + assert.ok( point.equals( zero3 ), 'Passed!' ); a.clampPoint( one3, point ); - assert.ok( point.equals( zero3 ), "Passed!" ); + assert.ok( point.equals( zero3 ), 'Passed!' ); a.clampPoint( one3.clone().negate(), point ); - assert.ok( point.equals( zero3 ), "Passed!" ); + assert.ok( point.equals( zero3 ), 'Passed!' ); b.clampPoint( new Vector3( 2, 2, 2 ), point ); - assert.ok( point.equals( one3 ), "Passed!" ); + assert.ok( point.equals( one3 ), 'Passed!' ); b.clampPoint( one3, point ); - assert.ok( point.equals( one3 ), "Passed!" ); + assert.ok( point.equals( one3 ), 'Passed!' ); b.clampPoint( zero3, point ); - assert.ok( point.equals( zero3 ), "Passed!" ); + assert.ok( point.equals( zero3 ), 'Passed!' ); b.clampPoint( one3.clone().negate(), point ); - assert.ok( point.equals( one3.clone().negate() ), "Passed!" ); + assert.ok( point.equals( one3.clone().negate() ), 'Passed!' ); b.clampPoint( new Vector3( - 2, - 2, - 2 ), point ); - assert.ok( point.equals( one3.clone().negate() ), "Passed!" ); + assert.ok( point.equals( one3.clone().negate() ), 'Passed!' ); } ); - QUnit.test( "distanceToPoint", ( assert ) => { + QUnit.test( 'distanceToPoint', ( assert ) => { var a = new Box3( zero3.clone(), zero3.clone() ); var b = new Box3( one3.clone().negate(), one3.clone() ); - assert.ok( a.distanceToPoint( new Vector3( 0, 0, 0 ) ) == 0, "Passed!" ); - assert.ok( a.distanceToPoint( new Vector3( 1, 1, 1 ) ) == Math.sqrt( 3 ), "Passed!" ); - assert.ok( a.distanceToPoint( new Vector3( - 1, - 1, - 1 ) ) == Math.sqrt( 3 ), "Passed!" ); + assert.ok( a.distanceToPoint( new Vector3( 0, 0, 0 ) ) == 0, 'Passed!' ); + assert.ok( a.distanceToPoint( new Vector3( 1, 1, 1 ) ) == Math.sqrt( 3 ), 'Passed!' ); + assert.ok( a.distanceToPoint( new Vector3( - 1, - 1, - 1 ) ) == Math.sqrt( 3 ), 'Passed!' ); - assert.ok( b.distanceToPoint( new Vector3( 2, 2, 2 ) ) == Math.sqrt( 3 ), "Passed!" ); - assert.ok( b.distanceToPoint( new Vector3( 1, 1, 1 ) ) == 0, "Passed!" ); - assert.ok( b.distanceToPoint( new Vector3( 0, 0, 0 ) ) == 0, "Passed!" ); - assert.ok( b.distanceToPoint( new Vector3( - 1, - 1, - 1 ) ) == 0, "Passed!" ); - assert.ok( b.distanceToPoint( new Vector3( - 2, - 2, - 2 ) ) == Math.sqrt( 3 ), "Passed!" ); + assert.ok( b.distanceToPoint( new Vector3( 2, 2, 2 ) ) == Math.sqrt( 3 ), 'Passed!' ); + assert.ok( b.distanceToPoint( new Vector3( 1, 1, 1 ) ) == 0, 'Passed!' ); + assert.ok( b.distanceToPoint( new Vector3( 0, 0, 0 ) ) == 0, 'Passed!' ); + assert.ok( b.distanceToPoint( new Vector3( - 1, - 1, - 1 ) ) == 0, 'Passed!' ); + assert.ok( b.distanceToPoint( new Vector3( - 2, - 2, - 2 ) ) == Math.sqrt( 3 ), 'Passed!' ); } ); - QUnit.test( "getBoundingSphere", ( assert ) => { + QUnit.test( 'getBoundingSphere', ( assert ) => { var a = new Box3( zero3.clone(), zero3.clone() ); var b = new Box3( zero3.clone(), one3.clone() ); var c = new Box3( one3.clone().negate(), one3.clone() ); var sphere = new Sphere(); - assert.ok( a.getBoundingSphere( sphere ).equals( new Sphere( zero3, 0 ) ), "Passed!" ); - assert.ok( b.getBoundingSphere( sphere ).equals( new Sphere( one3.clone().multiplyScalar( 0.5 ), Math.sqrt( 3 ) * 0.5 ) ), "Passed!" ); - assert.ok( c.getBoundingSphere( sphere ).equals( new Sphere( zero3, Math.sqrt( 12 ) * 0.5 ) ), "Passed!" ); + assert.ok( a.getBoundingSphere( sphere ).equals( new Sphere( zero3, 0 ) ), 'Passed!' ); + assert.ok( b.getBoundingSphere( sphere ).equals( new Sphere( one3.clone().multiplyScalar( 0.5 ), Math.sqrt( 3 ) * 0.5 ) ), 'Passed!' ); + assert.ok( c.getBoundingSphere( sphere ).equals( new Sphere( zero3, Math.sqrt( 12 ) * 0.5 ) ), 'Passed!' ); } ); - QUnit.test( "intersect", ( assert ) => { + QUnit.test( 'intersect', ( assert ) => { var a = new Box3( zero3.clone(), zero3.clone() ); var b = new Box3( zero3.clone(), one3.clone() ); var c = new Box3( one3.clone().negate(), one3.clone() ); - assert.ok( a.clone().intersect( a ).equals( a ), "Passed!" ); - assert.ok( a.clone().intersect( b ).equals( a ), "Passed!" ); - assert.ok( b.clone().intersect( b ).equals( b ), "Passed!" ); - assert.ok( a.clone().intersect( c ).equals( a ), "Passed!" ); - assert.ok( b.clone().intersect( c ).equals( b ), "Passed!" ); - assert.ok( c.clone().intersect( c ).equals( c ), "Passed!" ); + assert.ok( a.clone().intersect( a ).equals( a ), 'Passed!' ); + assert.ok( a.clone().intersect( b ).equals( a ), 'Passed!' ); + assert.ok( b.clone().intersect( b ).equals( b ), 'Passed!' ); + assert.ok( a.clone().intersect( c ).equals( a ), 'Passed!' ); + assert.ok( b.clone().intersect( c ).equals( b ), 'Passed!' ); + assert.ok( c.clone().intersect( c ).equals( c ), 'Passed!' ); } ); - QUnit.test( "union", ( assert ) => { + QUnit.test( 'union', ( assert ) => { var a = new Box3( zero3.clone(), zero3.clone() ); var b = new Box3( zero3.clone(), one3.clone() ); var c = new Box3( one3.clone().negate(), one3.clone() ); - assert.ok( a.clone().union( a ).equals( a ), "Passed!" ); - assert.ok( a.clone().union( b ).equals( b ), "Passed!" ); - assert.ok( a.clone().union( c ).equals( c ), "Passed!" ); - assert.ok( b.clone().union( c ).equals( c ), "Passed!" ); + assert.ok( a.clone().union( a ).equals( a ), 'Passed!' ); + assert.ok( a.clone().union( b ).equals( b ), 'Passed!' ); + assert.ok( a.clone().union( c ).equals( c ), 'Passed!' ); + assert.ok( b.clone().union( c ).equals( c ), 'Passed!' ); } ); - QUnit.test( "applyMatrix4", ( assert ) => { + QUnit.test( 'applyMatrix4', ( assert ) => { var a = new Box3( zero3.clone(), zero3.clone() ); var b = new Box3( zero3.clone(), one3.clone() ); @@ -564,53 +564,53 @@ export default QUnit.module( 'Maths', () => { var m = new Matrix4().makeTranslation( 1, - 2, 1 ); var t1 = new Vector3( 1, - 2, 1 ); - assert.ok( compareBox( a.clone().applyMatrix4( m ), a.clone().translate( t1 ) ), "Passed!" ); - assert.ok( compareBox( b.clone().applyMatrix4( m ), b.clone().translate( t1 ) ), "Passed!" ); - assert.ok( compareBox( c.clone().applyMatrix4( m ), c.clone().translate( t1 ) ), "Passed!" ); - assert.ok( compareBox( d.clone().applyMatrix4( m ), d.clone().translate( t1 ) ), "Passed!" ); + assert.ok( compareBox( a.clone().applyMatrix4( m ), a.clone().translate( t1 ) ), 'Passed!' ); + assert.ok( compareBox( b.clone().applyMatrix4( m ), b.clone().translate( t1 ) ), 'Passed!' ); + assert.ok( compareBox( c.clone().applyMatrix4( m ), c.clone().translate( t1 ) ), 'Passed!' ); + assert.ok( compareBox( d.clone().applyMatrix4( m ), d.clone().translate( t1 ) ), 'Passed!' ); } ); - QUnit.test( "translate", ( assert ) => { + QUnit.test( 'translate', ( assert ) => { var a = new Box3( zero3.clone(), zero3.clone() ); var b = new Box3( zero3.clone(), one3.clone() ); var c = new Box3( one3.clone().negate(), one3.clone() ); var d = new Box3( one3.clone().negate(), zero3.clone() ); - assert.ok( a.clone().translate( one3 ).equals( new Box3( one3, one3 ) ), "Passed!" ); - assert.ok( a.clone().translate( one3 ).translate( one3.clone().negate() ).equals( a ), "Passed!" ); - assert.ok( d.clone().translate( one3 ).equals( b ), "Passed!" ); - assert.ok( b.clone().translate( one3.clone().negate() ).equals( d ), "Passed!" ); + assert.ok( a.clone().translate( one3 ).equals( new Box3( one3, one3 ) ), 'Passed!' ); + assert.ok( a.clone().translate( one3 ).translate( one3.clone().negate() ).equals( a ), 'Passed!' ); + assert.ok( d.clone().translate( one3 ).equals( b ), 'Passed!' ); + assert.ok( b.clone().translate( one3.clone().negate() ).equals( d ), 'Passed!' ); } ); - QUnit.test( "equals", ( assert ) => { + QUnit.test( 'equals', ( assert ) => { var a = new Box3(); var b = new Box3(); - assert.ok( b.equals( a ), "Passed!" ); - assert.ok( a.equals( b ), "Passed!" ); + assert.ok( b.equals( a ), 'Passed!' ); + assert.ok( a.equals( b ), 'Passed!' ); a = new Box3( one3, two3 ); b = new Box3( one3, two3 ); - assert.ok( b.equals( a ), "Passed!" ); - assert.ok( a.equals( b ), "Passed!" ); + assert.ok( b.equals( a ), 'Passed!' ); + assert.ok( a.equals( b ), 'Passed!' ); a = new Box3( one3, two3 ); b = a.clone(); - assert.ok( b.equals( a ), "Passed!" ); - assert.ok( a.equals( b ), "Passed!" ); + assert.ok( b.equals( a ), 'Passed!' ); + assert.ok( a.equals( b ), 'Passed!' ); a = new Box3( one3, two3 ); b = new Box3( one3, one3 ); - assert.ok( ! b.equals( a ), "Passed!" ); - assert.ok( ! a.equals( b ), "Passed!" ); + assert.ok( ! b.equals( a ), 'Passed!' ); + assert.ok( ! a.equals( b ), 'Passed!' ); a = new Box3(); b = new Box3( one3, one3 ); - assert.ok( ! b.equals( a ), "Passed!" ); - assert.ok( ! a.equals( b ), "Passed!" ); + assert.ok( ! b.equals( a ), 'Passed!' ); + assert.ok( ! a.equals( b ), 'Passed!' ); } ); diff --git a/test/unit/src/math/Color.tests.js b/test/unit/src/math/Color.tests.js index 73608f49da544f..0cdd02fe38b4c6 100644 --- a/test/unit/src/math/Color.tests.js +++ b/test/unit/src/math/Color.tests.js @@ -9,41 +9,41 @@ export default QUnit.module( 'Maths', () => { QUnit.module( 'Color', () => { // INSTANCING - QUnit.test( "Instancing", ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { // default ctor var c = new Color(); - assert.ok( c.r, "Red: " + c.r ); - assert.ok( c.g, "Green: " + c.g ); - assert.ok( c.b, "Blue: " + c.b ); + assert.ok( c.r, 'Red: ' + c.r ); + assert.ok( c.g, 'Green: ' + c.g ); + assert.ok( c.b, 'Blue: ' + c.b ); // rgb ctor var c = new Color( 1, 1, 1 ); - assert.ok( c.r == 1, "Passed" ); - assert.ok( c.g == 1, "Passed" ); - assert.ok( c.b == 1, "Passed" ); + assert.ok( c.r == 1, 'Passed' ); + assert.ok( c.g == 1, 'Passed' ); + assert.ok( c.b == 1, 'Passed' ); } ); // EXPOSED CONSTANTS - QUnit.test( "Color.NAMES", ( assert ) => { + QUnit.test( 'Color.NAMES', ( assert ) => { - assert.ok( Color.NAMES.aliceblue == 0xF0F8FF, "Exposed Color.NAMES" ); + assert.ok( Color.NAMES.aliceblue == 0xF0F8FF, 'Exposed Color.NAMES' ); } ); // PUBLIC STUFF - QUnit.test( "isColor", ( assert ) => { + QUnit.test( 'isColor', ( assert ) => { var a = new Color(); - assert.ok( a.isColor === true, "Passed!" ); + assert.ok( a.isColor === true, 'Passed!' ); var b = new Object(); - assert.ok( ! b.isColor, "Passed!" ); + assert.ok( ! b.isColor, 'Passed!' ); } ); - QUnit.test( "set", ( assert ) => { + QUnit.test( 'set', ( assert ) => { var a = new Color(); var b = new Color( 0.5, 0, 0 ); @@ -51,228 +51,228 @@ export default QUnit.module( 'Maths', () => { var d = new Color( 0, 1.0, 0 ); a.set( b ); - assert.ok( a.equals( b ), "Set with Color instance" ); + assert.ok( a.equals( b ), 'Set with Color instance' ); a.set( 0xFF0000 ); - assert.ok( a.equals( c ), "Set with number" ); + assert.ok( a.equals( c ), 'Set with number' ); - a.set( "rgb(0,255,0)" ); - assert.ok( a.equals( d ), "Set with style" ); + a.set( 'rgb(0,255,0)' ); + assert.ok( a.equals( d ), 'Set with style' ); } ); - QUnit.test( "setScalar", ( assert ) => { + QUnit.test( 'setScalar', ( assert ) => { var c = new Color(); c.setScalar( 0.5 ); - assert.ok( c.r == 0.5, "Red: " + c.r ); - assert.ok( c.g == 0.5, "Green: " + c.g ); - assert.ok( c.b == 0.5, "Blue: " + c.b ); + assert.ok( c.r == 0.5, 'Red: ' + c.r ); + assert.ok( c.g == 0.5, 'Green: ' + c.g ); + assert.ok( c.b == 0.5, 'Blue: ' + c.b ); } ); - QUnit.test( "setHex", ( assert ) => { + QUnit.test( 'setHex', ( assert ) => { var c = new Color(); c.setHex( 0xFA8072 ); - assert.ok( c.getHex() == 0xFA8072, "Hex: " + c.getHex() ); - assert.ok( c.r == 0xFA / 0xFF, "Red: " + c.r ); - assert.ok( c.g == 0x80 / 0xFF, "Green: " + c.g ); - assert.ok( c.b == 0x72 / 0xFF, "Blue: " + c.b ); + assert.ok( c.getHex() == 0xFA8072, 'Hex: ' + c.getHex() ); + assert.ok( c.r == 0xFA / 0xFF, 'Red: ' + c.r ); + assert.ok( c.g == 0x80 / 0xFF, 'Green: ' + c.g ); + assert.ok( c.b == 0x72 / 0xFF, 'Blue: ' + c.b ); } ); - QUnit.test( "setRGB", ( assert ) => { + QUnit.test( 'setRGB', ( assert ) => { var c = new Color(); c.setRGB( 0.3, 0.5, 0.7 ); - assert.ok( c.r == 0.3, "Red: " + c.r ); - assert.ok( c.g == 0.5, "Green: " + c.g ); - assert.ok( c.b == 0.7, "Blue: " + c.b ); + assert.ok( c.r == 0.3, 'Red: ' + c.r ); + assert.ok( c.g == 0.5, 'Green: ' + c.g ); + assert.ok( c.b == 0.7, 'Blue: ' + c.b ); } ); - QUnit.test( "setHSL", ( assert ) => { + QUnit.test( 'setHSL', ( assert ) => { var c = new Color(); var hsl = { h: 0, s: 0, l: 0 }; c.setHSL( 0.75, 1.0, 0.25 ); c.getHSL( hsl ); - assert.ok( hsl.h == 0.75, "hue: " + hsl.h ); - assert.ok( hsl.s == 1.00, "saturation: " + hsl.s ); - assert.ok( hsl.l == 0.25, "lightness: " + hsl.l ); + assert.ok( hsl.h == 0.75, 'hue: ' + hsl.h ); + assert.ok( hsl.s == 1.00, 'saturation: ' + hsl.s ); + assert.ok( hsl.l == 0.25, 'lightness: ' + hsl.l ); } ); - QUnit.test( "setStyle", ( assert ) => { + QUnit.test( 'setStyle', ( assert ) => { var a = new Color(); var b = new Color( 8 / 255, 25 / 255, 178 / 255 ); - a.setStyle( "rgb(8,25,178)" ); - assert.ok( a.equals( b ), "Passed" ); + a.setStyle( 'rgb(8,25,178)' ); + assert.ok( a.equals( b ), 'Passed' ); b = new Color( 8 / 255, 25 / 255, 178 / 255 ); - a.setStyle( "rgba(8,25,178,200)" ); - assert.ok( a.equals( b ), "Passed" ); + a.setStyle( 'rgba(8,25,178,200)' ); + assert.ok( a.equals( b ), 'Passed' ); var hsl = { h: 0, s: 0, l: 0 }; - a.setStyle( "hsl(270,50%,75%)" ); + a.setStyle( 'hsl(270,50%,75%)' ); a.getHSL( hsl ); - assert.ok( hsl.h == 0.75, "hue: " + hsl.h ); - assert.ok( hsl.s == 0.5, "saturation: " + hsl.s ); - assert.ok( hsl.l == 0.75, "lightness: " + hsl.l ); + assert.ok( hsl.h == 0.75, 'hue: ' + hsl.h ); + assert.ok( hsl.s == 0.5, 'saturation: ' + hsl.s ); + assert.ok( hsl.l == 0.75, 'lightness: ' + hsl.l ); hsl = { h: 0, s: 0, l: 0 }; - a.setStyle( "hsl(270,50%,75%)" ); + a.setStyle( 'hsl(270,50%,75%)' ); a.getHSL( hsl ); - assert.ok( hsl.h == 0.75, "hue: " + hsl.h ); - assert.ok( hsl.s == 0.5, "saturation: " + hsl.s ); - assert.ok( hsl.l == 0.75, "lightness: " + hsl.l ); + assert.ok( hsl.h == 0.75, 'hue: ' + hsl.h ); + assert.ok( hsl.s == 0.5, 'saturation: ' + hsl.s ); + assert.ok( hsl.l == 0.75, 'lightness: ' + hsl.l ); - a.setStyle( "#F8A" ); - assert.ok( a.r == 0xFF / 255, "Red: " + a.r ); - assert.ok( a.g == 0x88 / 255, "Green: " + a.g ); - assert.ok( a.b == 0xAA / 255, "Blue: " + a.b ); + a.setStyle( '#F8A' ); + assert.ok( a.r == 0xFF / 255, 'Red: ' + a.r ); + assert.ok( a.g == 0x88 / 255, 'Green: ' + a.g ); + assert.ok( a.b == 0xAA / 255, 'Blue: ' + a.b ); - a.setStyle( "#F8ABC1" ); - assert.ok( a.r == 0xF8 / 255, "Red: " + a.r ); - assert.ok( a.g == 0xAB / 255, "Green: " + a.g ); - assert.ok( a.b == 0xC1 / 255, "Blue: " + a.b ); + a.setStyle( '#F8ABC1' ); + assert.ok( a.r == 0xF8 / 255, 'Red: ' + a.r ); + assert.ok( a.g == 0xAB / 255, 'Green: ' + a.g ); + assert.ok( a.b == 0xC1 / 255, 'Blue: ' + a.b ); - a.setStyle( "aliceblue" ); - assert.ok( a.r == 0xF0 / 255, "Red: " + a.r ); - assert.ok( a.g == 0xF8 / 255, "Green: " + a.g ); - assert.ok( a.b == 0xFF / 255, "Blue: " + a.b ); + a.setStyle( 'aliceblue' ); + assert.ok( a.r == 0xF0 / 255, 'Red: ' + a.r ); + assert.ok( a.g == 0xF8 / 255, 'Green: ' + a.g ); + assert.ok( a.b == 0xFF / 255, 'Blue: ' + a.b ); } ); - QUnit.test( "setColorName", ( assert ) => { + QUnit.test( 'setColorName', ( assert ) => { var c = new Color(); - var res = c.setColorName( "aliceblue" ); + var res = c.setColorName( 'aliceblue' ); - assert.ok( c.getHex() == 0xF0F8FF, "Hex: " + c.getHex() ); - assert.ok( c == res, "Returns Self" ); + assert.ok( c.getHex() == 0xF0F8FF, 'Hex: ' + c.getHex() ); + assert.ok( c == res, 'Returns Self' ); } ); - QUnit.test( "clone", ( assert ) => { + QUnit.test( 'clone', ( assert ) => { var c = new Color( 'teal' ); var c2 = c.clone(); - assert.ok( c2.getHex() == 0x008080, "Hex c2: " + c2.getHex() ); + assert.ok( c2.getHex() == 0x008080, 'Hex c2: ' + c2.getHex() ); } ); - QUnit.test( "copy", ( assert ) => { + QUnit.test( 'copy', ( assert ) => { var a = new Color( 'teal' ); var b = new Color(); b.copy( a ); - assert.ok( b.r == 0x00 / 255, "Red: " + b.r ); - assert.ok( b.g == 0x80 / 255, "Green: " + b.g ); - assert.ok( b.b == 0x80 / 255, "Blue: " + b.b ); + assert.ok( b.r == 0x00 / 255, 'Red: ' + b.r ); + assert.ok( b.g == 0x80 / 255, 'Green: ' + b.g ); + assert.ok( b.b == 0x80 / 255, 'Blue: ' + b.b ); } ); - QUnit.test( "copyGammaToLinear", ( assert ) => { + QUnit.test( 'copySRGBToLinear', ( assert ) => { var c = new Color(); var c2 = new Color(); c2.setRGB( 0.3, 0.5, 0.9 ); - c.copyGammaToLinear( c2 ); - assert.ok( c.r == 0.09, "Red c: " + c.r + " Red c2: " + c2.r ); - assert.ok( c.g == 0.25, "Green c: " + c.g + " Green c2: " + c2.g ); - assert.ok( c.b == 0.81, "Blue c: " + c.b + " Blue c2: " + c2.b ); + c.copySRGBToLinear( c2 ); + assert.numEqual( c.r, 0.09, 'Red c: ' + c.r + ' Red c2: ' + c2.r ); + assert.numEqual( c.g, 0.25, 'Green c: ' + c.g + ' Green c2: ' + c2.g ); + assert.numEqual( c.b, 0.81, 'Blue c: ' + c.b + ' Blue c2: ' + c2.b ); } ); - QUnit.test( "copyLinearToGamma", ( assert ) => { + QUnit.test( 'copyLinearToSRGB', ( assert ) => { var c = new Color(); var c2 = new Color(); c2.setRGB( 0.09, 0.25, 0.81 ); - c.copyLinearToGamma( c2 ); - assert.ok( c.r == 0.3, "Red c: " + c.r + " Red c2: " + c2.r ); - assert.ok( c.g == 0.5, "Green c: " + c.g + " Green c2: " + c2.g ); - assert.ok( c.b == 0.9, "Blue c: " + c.b + " Blue c2: " + c2.b ); + c.copyLinearToSRGB( c2 ); + assert.numEqual( c.r, 0.3, 'Red c: ' + c.r + ' Red c2: ' + c2.r ); + assert.numEqual( c.g, 0.5, 'Green c: ' + c.g + ' Green c2: ' + c2.g ); + assert.numEqual( c.b, 0.9, 'Blue c: ' + c.b + ' Blue c2: ' + c2.b ); } ); - QUnit.test( "convertGammaToLinear", ( assert ) => { + QUnit.test( 'convertSRGBToLinear', ( assert ) => { var c = new Color(); c.setRGB( 0.3, 0.5, 0.9 ); - c.convertGammaToLinear(); - assert.ok( c.r == 0.09, "Red: " + c.r ); - assert.ok( c.g == 0.25, "Green: " + c.g ); - assert.ok( c.b == 0.81, "Blue: " + c.b ); + c.convertSRGBToLinear(); + assert.numEqual( c.r, 0.09, 'Red: ' + c.r ); + assert.numEqual( c.g, 0.25, 'Green: ' + c.g ); + assert.numEqual( c.b, 0.81, 'Blue: ' + c.b ); } ); - QUnit.test( "convertLinearToGamma", ( assert ) => { + QUnit.test( 'convertLinearToSRGB', ( assert ) => { var c = new Color(); c.setRGB( 4, 9, 16 ); - c.convertLinearToGamma(); - assert.ok( c.r == 2, "Red: " + c.r ); - assert.ok( c.g == 3, "Green: " + c.g ); - assert.ok( c.b == 4, "Blue: " + c.b ); + c.convertLinearToSRGB(); + assert.numEqual( c.r, 1.82, 'Red: ' + c.r ); + assert.numEqual( c.g, 2.58, 'Green: ' + c.g ); + assert.numEqual( c.b, 3.29, 'Blue: ' + c.b ); } ); - QUnit.test( "getHex", ( assert ) => { + QUnit.test( 'getHex', ( assert ) => { var c = new Color( 'red' ); var res = c.getHex(); - assert.ok( res == 0xFF0000, "Hex: " + res ); + assert.ok( res == 0xFF0000, 'Hex: ' + res ); } ); - QUnit.test( "getHexString", ( assert ) => { + QUnit.test( 'getHexString', ( assert ) => { var c = new Color( 'tomato' ); var res = c.getHexString(); - assert.ok( res == 'ff6347', "Hex: " + res ); + assert.ok( res == 'ff6347', 'Hex: ' + res ); } ); - QUnit.test( "getHSL", ( assert ) => { + QUnit.test( 'getHSL', ( assert ) => { var c = new Color( 0x80ffff ); var hsl = { h: 0, s: 0, l: 0 }; c.getHSL( hsl ); - assert.ok( hsl.h == 0.5, "hue: " + hsl.h ); - assert.ok( hsl.s == 1.0, "saturation: " + hsl.s ); - assert.ok( ( Math.round( parseFloat( hsl.l ) * 100 ) / 100 ) == 0.75, "lightness: " + hsl.l ); + assert.ok( hsl.h == 0.5, 'hue: ' + hsl.h ); + assert.ok( hsl.s == 1.0, 'saturation: ' + hsl.s ); + assert.ok( ( Math.round( parseFloat( hsl.l ) * 100 ) / 100 ) == 0.75, 'lightness: ' + hsl.l ); } ); - QUnit.test( "getStyle", ( assert ) => { + QUnit.test( 'getStyle', ( assert ) => { var c = new Color( 'plum' ); var res = c.getStyle(); - assert.ok( res == 'rgb(221,160,221)', "style: " + res ); + assert.ok( res == 'rgb(221,160,221)', 'style: ' + res ); } ); - QUnit.test( "offsetHSL", ( assert ) => { + QUnit.test( 'offsetHSL', ( assert ) => { - var a = new Color( "hsl(120,50%,50%)" ); + var a = new Color( 'hsl(120,50%,50%)' ); var b = new Color( 0.36, 0.84, 0.648 ); a.offsetHSL( 0.1, 0.1, 0.1 ); - assert.ok( Math.abs( a.r - b.r ) <= eps, "Check r" ); - assert.ok( Math.abs( a.g - b.g ) <= eps, "Check g" ); - assert.ok( Math.abs( a.b - b.b ) <= eps, "Check b" ); + assert.ok( Math.abs( a.r - b.r ) <= eps, 'Check r' ); + assert.ok( Math.abs( a.g - b.g ) <= eps, 'Check g' ); + assert.ok( Math.abs( a.b - b.b ) <= eps, 'Check b' ); } ); - QUnit.test( "add", ( assert ) => { + QUnit.test( 'add', ( assert ) => { var a = new Color( 0x0000FF ); var b = new Color( 0xFF0000 ); @@ -280,11 +280,11 @@ export default QUnit.module( 'Maths', () => { a.add( b ); - assert.ok( a.equals( c ), "Check new value" ); + assert.ok( a.equals( c ), 'Check new value' ); } ); - QUnit.test( "addColors", ( assert ) => { + QUnit.test( 'addColors', ( assert ) => { var a = new Color( 0x0000FF ); var b = new Color( 0xFF0000 ); @@ -293,195 +293,195 @@ export default QUnit.module( 'Maths', () => { d.addColors( a, b ); - assert.ok( d.equals( c ), "Passed" ); + assert.ok( d.equals( c ), 'Passed' ); } ); - QUnit.test( "addScalar", ( assert ) => { + QUnit.test( 'addScalar', ( assert ) => { var a = new Color( 0.1, 0.0, 0.0 ); var b = new Color( 0.6, 0.5, 0.5 ); a.addScalar( 0.5 ); - assert.ok( a.equals( b ), "Check new value" ); + assert.ok( a.equals( b ), 'Check new value' ); } ); - QUnit.test( "sub", ( assert ) => { + QUnit.test( 'sub', ( assert ) => { var a = new Color( 0x0000CC ); var b = new Color( 0xFF0000 ); var c = new Color( 0x0000AA ); a.sub( b ); - assert.strictEqual( a.getHex(), 0xCC, "Difference too large" ); + assert.strictEqual( a.getHex(), 0xCC, 'Difference too large' ); a.sub( c ); - assert.strictEqual( a.getHex(), 0x22, "Difference fine" ); + assert.strictEqual( a.getHex(), 0x22, 'Difference fine' ); } ); - QUnit.test( "multiply", ( assert ) => { + QUnit.test( 'multiply', ( assert ) => { var a = new Color( 1, 0, 0.5 ); var b = new Color( 0.5, 1, 0.5 ); var c = new Color( 0.5, 0, 0.25 ); a.multiply( b ); - assert.ok( a.equals( c ), "Check new value" ); + assert.ok( a.equals( c ), 'Check new value' ); } ); - QUnit.test( "multiplyScalar", ( assert ) => { + QUnit.test( 'multiplyScalar', ( assert ) => { var a = new Color( 0.25, 0, 0.5 ); var b = new Color( 0.5, 0, 1 ); a.multiplyScalar( 2 ); - assert.ok( a.equals( b ), "Check new value" ); + assert.ok( a.equals( b ), 'Check new value' ); } ); - QUnit.test( "copyHex", ( assert ) => { + QUnit.test( 'copyHex', ( assert ) => { var c = new Color(); var c2 = new Color( 0xF5FFFA ); c.copy( c2 ); - assert.ok( c.getHex() == c2.getHex(), "Hex c: " + c.getHex() + " Hex c2: " + c2.getHex() ); + assert.ok( c.getHex() == c2.getHex(), 'Hex c: ' + c.getHex() + ' Hex c2: ' + c2.getHex() ); } ); - QUnit.test( "copyColorString", ( assert ) => { + QUnit.test( 'copyColorString', ( assert ) => { var c = new Color(); var c2 = new Color( 'ivory' ); c.copy( c2 ); - assert.ok( c.getHex() == c2.getHex(), "Hex c: " + c.getHex() + " Hex c2: " + c2.getHex() ); + assert.ok( c.getHex() == c2.getHex(), 'Hex c: ' + c.getHex() + ' Hex c2: ' + c2.getHex() ); } ); - QUnit.test( "lerp", ( assert ) => { + QUnit.test( 'lerp', ( assert ) => { var c = new Color(); var c2 = new Color(); c.setRGB( 0, 0, 0 ); c.lerp( c2, 0.2 ); - assert.ok( c.r == 0.2, "Red: " + c.r ); - assert.ok( c.g == 0.2, "Green: " + c.g ); - assert.ok( c.b == 0.2, "Blue: " + c.b ); + assert.ok( c.r == 0.2, 'Red: ' + c.r ); + assert.ok( c.g == 0.2, 'Green: ' + c.g ); + assert.ok( c.b == 0.2, 'Blue: ' + c.b ); } ); - QUnit.test( "equals", ( assert ) => { + QUnit.test( 'equals', ( assert ) => { var a = new Color( 0.5, 0.0, 1.0 ); var b = new Color( 0.5, 1.0, 0.0 ); - assert.strictEqual( a.r, b.r, "Components: r is equal" ); - assert.notStrictEqual( a.g, b.g, "Components: g is not equal" ); - assert.notStrictEqual( a.b, b.b, "Components: b is not equal" ); + assert.strictEqual( a.r, b.r, 'Components: r is equal' ); + assert.notStrictEqual( a.g, b.g, 'Components: g is not equal' ); + assert.notStrictEqual( a.b, b.b, 'Components: b is not equal' ); - assert.notOk( a.equals( b ), "equals(): a not equal b" ); - assert.notOk( b.equals( a ), "equals(): b not equal a" ); + assert.notOk( a.equals( b ), 'equals(): a not equal b' ); + assert.notOk( b.equals( a ), 'equals(): b not equal a' ); a.copy( b ); - assert.strictEqual( a.r, b.r, "Components after copy(): r is equal" ); - assert.strictEqual( a.g, b.g, "Components after copy(): g is equal" ); - assert.strictEqual( a.b, b.b, "Components after copy(): b is equal" ); + assert.strictEqual( a.r, b.r, 'Components after copy(): r is equal' ); + assert.strictEqual( a.g, b.g, 'Components after copy(): g is equal' ); + assert.strictEqual( a.b, b.b, 'Components after copy(): b is equal' ); - assert.ok( a.equals( b ), "equals() after copy(): a equals b" ); - assert.ok( b.equals( a ), "equals() after copy(): b equals a" ); + assert.ok( a.equals( b ), 'equals() after copy(): a equals b' ); + assert.ok( b.equals( a ), 'equals() after copy(): b equals a' ); } ); - QUnit.test( "fromArray", ( assert ) => { + QUnit.test( 'fromArray', ( assert ) => { var a = new Color(); var array = [ 0.5, 0.6, 0.7, 0, 1, 0 ]; a.fromArray( array ); - assert.strictEqual( a.r, 0.5, "No offset: check r" ); - assert.strictEqual( a.g, 0.6, "No offset: check g" ); - assert.strictEqual( a.b, 0.7, "No offset: check b" ); + assert.strictEqual( a.r, 0.5, 'No offset: check r' ); + assert.strictEqual( a.g, 0.6, 'No offset: check g' ); + assert.strictEqual( a.b, 0.7, 'No offset: check b' ); a.fromArray( array, 3 ); - assert.strictEqual( a.r, 0, "With offset: check r" ); - assert.strictEqual( a.g, 1, "With offset: check g" ); - assert.strictEqual( a.b, 0, "With offset: check b" ); + assert.strictEqual( a.r, 0, 'With offset: check r' ); + assert.strictEqual( a.g, 1, 'With offset: check g' ); + assert.strictEqual( a.b, 0, 'With offset: check b' ); } ); - QUnit.test( "toArray", ( assert ) => { + QUnit.test( 'toArray', ( assert ) => { var r = 0.5, g = 1.0, b = 0.0; var a = new Color( r, g, b ); var array = a.toArray(); - assert.strictEqual( array[ 0 ], r, "No array, no offset: check r" ); - assert.strictEqual( array[ 1 ], g, "No array, no offset: check g" ); - assert.strictEqual( array[ 2 ], b, "No array, no offset: check b" ); + assert.strictEqual( array[ 0 ], r, 'No array, no offset: check r' ); + assert.strictEqual( array[ 1 ], g, 'No array, no offset: check g' ); + assert.strictEqual( array[ 2 ], b, 'No array, no offset: check b' ); var array = []; a.toArray( array ); - assert.strictEqual( array[ 0 ], r, "With array, no offset: check r" ); - assert.strictEqual( array[ 1 ], g, "With array, no offset: check g" ); - assert.strictEqual( array[ 2 ], b, "With array, no offset: check b" ); + assert.strictEqual( array[ 0 ], r, 'With array, no offset: check r' ); + assert.strictEqual( array[ 1 ], g, 'With array, no offset: check g' ); + assert.strictEqual( array[ 2 ], b, 'With array, no offset: check b' ); var array = []; a.toArray( array, 1 ); - assert.strictEqual( array[ 0 ], undefined, "With array and offset: check [0]" ); - assert.strictEqual( array[ 1 ], r, "With array and offset: check r" ); - assert.strictEqual( array[ 2 ], g, "With array and offset: check g" ); - assert.strictEqual( array[ 3 ], b, "With array and offset: check b" ); + assert.strictEqual( array[ 0 ], undefined, 'With array and offset: check [0]' ); + assert.strictEqual( array[ 1 ], r, 'With array and offset: check r' ); + assert.strictEqual( array[ 2 ], g, 'With array and offset: check g' ); + assert.strictEqual( array[ 3 ], b, 'With array and offset: check b' ); } ); - QUnit.test( "toJSON", ( assert ) => { + QUnit.test( 'toJSON', ( assert ) => { var a = new Color( 0.0, 0.0, 0.0 ); var b = new Color( 0.0, 0.5, 0.0 ); var c = new Color( 1.0, 0.0, 0.0 ); var d = new Color( 1.0, 1.0, 1.0 ); - assert.strictEqual( a.toJSON(), 0x000000, "Check black" ); - assert.strictEqual( b.toJSON(), 0x007F00, "Check half-blue" ); - assert.strictEqual( c.toJSON(), 0xFF0000, "Check red" ); - assert.strictEqual( d.toJSON(), 0xFFFFFF, "Check white" ); + assert.strictEqual( a.toJSON(), 0x000000, 'Check black' ); + assert.strictEqual( b.toJSON(), 0x007F00, 'Check half-blue' ); + assert.strictEqual( c.toJSON(), 0xFF0000, 'Check red' ); + assert.strictEqual( d.toJSON(), 0xFFFFFF, 'Check white' ); } ); // OTHERS - QUnit.test( "setWithNum", ( assert ) => { + QUnit.test( 'setWithNum', ( assert ) => { var c = new Color(); c.set( 0xFF0000 ); - assert.ok( c.r == 1, "Red: " + c.r ); - assert.ok( c.g === 0, "Green: " + c.g ); - assert.ok( c.b === 0, "Blue: " + c.b ); + assert.ok( c.r == 1, 'Red: ' + c.r ); + assert.ok( c.g === 0, 'Green: ' + c.g ); + assert.ok( c.b === 0, 'Blue: ' + c.b ); } ); - QUnit.test( "setWithString", ( assert ) => { + QUnit.test( 'setWithString', ( assert ) => { var c = new Color(); c.set( 'silver' ); - assert.ok( c.getHex() == 0xC0C0C0, "Hex c: " + c.getHex() ); + assert.ok( c.getHex() == 0xC0C0C0, 'Hex c: ' + c.getHex() ); } ); - QUnit.test( "setStyleRGBRed", ( assert ) => { + QUnit.test( 'setStyleRGBRed', ( assert ) => { var c = new Color(); c.setStyle( 'rgb(255,0,0)' ); - assert.ok( c.r == 1, "Red: " + c.r ); - assert.ok( c.g === 0, "Green: " + c.g ); - assert.ok( c.b === 0, "Blue: " + c.b ); + assert.ok( c.r == 1, 'Red: ' + c.r ); + assert.ok( c.g === 0, 'Green: ' + c.g ); + assert.ok( c.b === 0, 'Blue: ' + c.b ); } ); - QUnit.test( "setStyleRGBARed", ( assert ) => { + QUnit.test( 'setStyleRGBARed', ( assert ) => { var c = new Color(); @@ -489,43 +489,43 @@ export default QUnit.module( 'Maths', () => { c.setStyle( 'rgba(255,0,0,0.5)' ); console.level = CONSOLE_LEVEL.DEFAULT; - assert.ok( c.r == 1, "Red: " + c.r ); - assert.ok( c.g === 0, "Green: " + c.g ); - assert.ok( c.b === 0, "Blue: " + c.b ); + assert.ok( c.r == 1, 'Red: ' + c.r ); + assert.ok( c.g === 0, 'Green: ' + c.g ); + assert.ok( c.b === 0, 'Blue: ' + c.b ); } ); - QUnit.test( "setStyleRGBRedWithSpaces", ( assert ) => { + QUnit.test( 'setStyleRGBRedWithSpaces', ( assert ) => { var c = new Color(); c.setStyle( 'rgb( 255 , 0, 0 )' ); - assert.ok( c.r == 1, "Red: " + c.r ); - assert.ok( c.g === 0, "Green: " + c.g ); - assert.ok( c.b === 0, "Blue: " + c.b ); + assert.ok( c.r == 1, 'Red: ' + c.r ); + assert.ok( c.g === 0, 'Green: ' + c.g ); + assert.ok( c.b === 0, 'Blue: ' + c.b ); } ); - QUnit.test( "setStyleRGBARedWithSpaces", ( assert ) => { + QUnit.test( 'setStyleRGBARedWithSpaces', ( assert ) => { var c = new Color(); c.setStyle( 'rgba( 255, 0, 0 , 1 )' ); - assert.ok( c.r == 1, "Red: " + c.r ); - assert.ok( c.g === 0, "Green: " + c.g ); - assert.ok( c.b === 0, "Blue: " + c.b ); + assert.ok( c.r == 1, 'Red: ' + c.r ); + assert.ok( c.g === 0, 'Green: ' + c.g ); + assert.ok( c.b === 0, 'Blue: ' + c.b ); } ); - QUnit.test( "setStyleRGBPercent", ( assert ) => { + QUnit.test( 'setStyleRGBPercent', ( assert ) => { var c = new Color(); c.setStyle( 'rgb(100%,50%,10%)' ); - assert.ok( c.r == 1, "Red: " + c.r ); - assert.ok( c.g == 0.5, "Green: " + c.g ); - assert.ok( c.b == 0.1, "Blue: " + c.b ); + assert.ok( c.r == 1, 'Red: ' + c.r ); + assert.ok( c.g == 0.5, 'Green: ' + c.g ); + assert.ok( c.b == 0.1, 'Blue: ' + c.b ); } ); - QUnit.test( "setStyleRGBAPercent", ( assert ) => { + QUnit.test( 'setStyleRGBAPercent', ( assert ) => { var c = new Color(); @@ -533,23 +533,23 @@ export default QUnit.module( 'Maths', () => { c.setStyle( 'rgba(100%,50%,10%, 0.5)' ); console.level = CONSOLE_LEVEL.DEFAULT; - assert.ok( c.r == 1, "Red: " + c.r ); - assert.ok( c.g == 0.5, "Green: " + c.g ); - assert.ok( c.b == 0.1, "Blue: " + c.b ); + assert.ok( c.r == 1, 'Red: ' + c.r ); + assert.ok( c.g == 0.5, 'Green: ' + c.g ); + assert.ok( c.b == 0.1, 'Blue: ' + c.b ); } ); - QUnit.test( "setStyleRGBPercentWithSpaces", ( assert ) => { + QUnit.test( 'setStyleRGBPercentWithSpaces', ( assert ) => { var c = new Color(); c.setStyle( 'rgb( 100% ,50% , 10% )' ); - assert.ok( c.r == 1, "Red: " + c.r ); - assert.ok( c.g == 0.5, "Green: " + c.g ); - assert.ok( c.b == 0.1, "Blue: " + c.b ); + assert.ok( c.r == 1, 'Red: ' + c.r ); + assert.ok( c.g == 0.5, 'Green: ' + c.g ); + assert.ok( c.b == 0.1, 'Blue: ' + c.b ); } ); - QUnit.test( "setStyleRGBAPercentWithSpaces", ( assert ) => { + QUnit.test( 'setStyleRGBAPercentWithSpaces', ( assert ) => { var c = new Color(); @@ -557,23 +557,23 @@ export default QUnit.module( 'Maths', () => { c.setStyle( 'rgba( 100% ,50% , 10%, 0.5 )' ); console.level = CONSOLE_LEVEL.DEFAULT; - assert.ok( c.r == 1, "Red: " + c.r ); - assert.ok( c.g == 0.5, "Green: " + c.g ); - assert.ok( c.b == 0.1, "Blue: " + c.b ); + assert.ok( c.r == 1, 'Red: ' + c.r ); + assert.ok( c.g == 0.5, 'Green: ' + c.g ); + assert.ok( c.b == 0.1, 'Blue: ' + c.b ); } ); - QUnit.test( "setStyleHSLRed", ( assert ) => { + QUnit.test( 'setStyleHSLRed', ( assert ) => { var c = new Color(); c.setStyle( 'hsl(360,100%,50%)' ); - assert.ok( c.r == 1, "Red: " + c.r ); - assert.ok( c.g === 0, "Green: " + c.g ); - assert.ok( c.b === 0, "Blue: " + c.b ); + assert.ok( c.r == 1, 'Red: ' + c.r ); + assert.ok( c.g === 0, 'Green: ' + c.g ); + assert.ok( c.b === 0, 'Blue: ' + c.b ); } ); - QUnit.test( "setStyleHSLARed", ( assert ) => { + QUnit.test( 'setStyleHSLARed', ( assert ) => { var c = new Color(); @@ -581,23 +581,23 @@ export default QUnit.module( 'Maths', () => { c.setStyle( 'hsla(360,100%,50%,0.5)' ); console.level = CONSOLE_LEVEL.DEFAULT; - assert.ok( c.r == 1, "Red: " + c.r ); - assert.ok( c.g === 0, "Green: " + c.g ); - assert.ok( c.b === 0, "Blue: " + c.b ); + assert.ok( c.r == 1, 'Red: ' + c.r ); + assert.ok( c.g === 0, 'Green: ' + c.g ); + assert.ok( c.b === 0, 'Blue: ' + c.b ); } ); - QUnit.test( "setStyleHSLRedWithSpaces", ( assert ) => { + QUnit.test( 'setStyleHSLRedWithSpaces', ( assert ) => { var c = new Color(); c.setStyle( 'hsl(360, 100% , 50% )' ); - assert.ok( c.r == 1, "Red: " + c.r ); - assert.ok( c.g === 0, "Green: " + c.g ); - assert.ok( c.b === 0, "Blue: " + c.b ); + assert.ok( c.r == 1, 'Red: ' + c.r ); + assert.ok( c.g === 0, 'Green: ' + c.g ); + assert.ok( c.b === 0, 'Blue: ' + c.b ); } ); - QUnit.test( "setStyleHSLARedWithSpaces", ( assert ) => { + QUnit.test( 'setStyleHSLARedWithSpaces', ( assert ) => { var c = new Color(); @@ -605,49 +605,49 @@ export default QUnit.module( 'Maths', () => { c.setStyle( 'hsla( 360, 100% , 50%, 0.5 )' ); console.level = CONSOLE_LEVEL.DEFAULT; - assert.ok( c.r == 1, "Red: " + c.r ); - assert.ok( c.g === 0, "Green: " + c.g ); - assert.ok( c.b === 0, "Blue: " + c.b ); + assert.ok( c.r == 1, 'Red: ' + c.r ); + assert.ok( c.g === 0, 'Green: ' + c.g ); + assert.ok( c.b === 0, 'Blue: ' + c.b ); } ); - QUnit.test( "setStyleHexSkyBlue", ( assert ) => { + QUnit.test( 'setStyleHexSkyBlue', ( assert ) => { var c = new Color(); c.setStyle( '#87CEEB' ); - assert.ok( c.getHex() == 0x87CEEB, "Hex c: " + c.getHex() ); + assert.ok( c.getHex() == 0x87CEEB, 'Hex c: ' + c.getHex() ); } ); - QUnit.test( "setStyleHexSkyBlueMixed", ( assert ) => { + QUnit.test( 'setStyleHexSkyBlueMixed', ( assert ) => { var c = new Color(); c.setStyle( '#87cEeB' ); - assert.ok( c.getHex() == 0x87CEEB, "Hex c: " + c.getHex() ); + assert.ok( c.getHex() == 0x87CEEB, 'Hex c: ' + c.getHex() ); } ); - QUnit.test( "setStyleHex2Olive", ( assert ) => { + QUnit.test( 'setStyleHex2Olive', ( assert ) => { var c = new Color(); c.setStyle( '#F00' ); - assert.ok( c.getHex() == 0xFF0000, "Hex c: " + c.getHex() ); + assert.ok( c.getHex() == 0xFF0000, 'Hex c: ' + c.getHex() ); } ); - QUnit.test( "setStyleHex2OliveMixed", ( assert ) => { + QUnit.test( 'setStyleHex2OliveMixed', ( assert ) => { var c = new Color(); c.setStyle( '#f00' ); - assert.ok( c.getHex() == 0xFF0000, "Hex c: " + c.getHex() ); + assert.ok( c.getHex() == 0xFF0000, 'Hex c: ' + c.getHex() ); } ); - QUnit.test( "setStyleColorName", ( assert ) => { + QUnit.test( 'setStyleColorName', ( assert ) => { var c = new Color(); c.setStyle( 'powderblue' ); - assert.ok( c.getHex() == 0xB0E0E6, "Hex c: " + c.getHex() ); + assert.ok( c.getHex() == 0xB0E0E6, 'Hex c: ' + c.getHex() ); } ); diff --git a/test/unit/src/math/Cylindrical.tests.js b/test/unit/src/math/Cylindrical.tests.js index 9f91c3c53abf93..2a1e3e72382fca 100644 --- a/test/unit/src/math/Cylindrical.tests.js +++ b/test/unit/src/math/Cylindrical.tests.js @@ -9,26 +9,26 @@ export default QUnit.module( 'Maths', () => { QUnit.module( 'Cylindrical', () => { // INSTANCING - QUnit.test( "Instancing", ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { var a = new Cylindrical(); var radius = 10.0; var theta = Math.PI; var y = 5; - assert.strictEqual( a.radius, 1.0, "Default values: check radius" ); - assert.strictEqual( a.theta, 0, "Default values: check theta" ); - assert.strictEqual( a.y, 0, "Default values: check y" ); + assert.strictEqual( a.radius, 1.0, 'Default values: check radius' ); + assert.strictEqual( a.theta, 0, 'Default values: check theta' ); + assert.strictEqual( a.y, 0, 'Default values: check y' ); var a = new Cylindrical( radius, theta, y ); - assert.strictEqual( a.radius, radius, "Custom values: check radius" ); - assert.strictEqual( a.theta, theta, "Custom values: check theta" ); - assert.strictEqual( a.y, y, "Custom values: check y" ); + assert.strictEqual( a.radius, radius, 'Custom values: check radius' ); + assert.strictEqual( a.theta, theta, 'Custom values: check theta' ); + assert.strictEqual( a.y, y, 'Custom values: check y' ); } ); // PUBLIC STUFF - QUnit.test( "set", ( assert ) => { + QUnit.test( 'set', ( assert ) => { var a = new Cylindrical(); var radius = 10.0; @@ -36,13 +36,13 @@ export default QUnit.module( 'Maths', () => { var y = 5; a.set( radius, theta, y ); - assert.strictEqual( a.radius, radius, "Check radius" ); - assert.strictEqual( a.theta, theta, "Check theta" ); - assert.strictEqual( a.y, y, "Check y" ); + assert.strictEqual( a.radius, radius, 'Check radius' ); + assert.strictEqual( a.theta, theta, 'Check theta' ); + assert.strictEqual( a.y, y, 'Check y' ); } ); - QUnit.test( "clone", ( assert ) => { + QUnit.test( 'clone', ( assert ) => { var radius = 10.0; var theta = Math.PI; @@ -50,14 +50,14 @@ export default QUnit.module( 'Maths', () => { var a = new Cylindrical( radius, theta, y ); var b = a.clone(); - assert.propEqual( a, b, "Check a and b are equal after clone()" ); + assert.propEqual( a, b, 'Check a and b are equal after clone()' ); a.radius = 1; - assert.notPropEqual( a, b, "Check a and b are not equal after modification" ); + assert.notPropEqual( a, b, 'Check a and b are not equal after modification' ); } ); - QUnit.test( "copy", ( assert ) => { + QUnit.test( 'copy', ( assert ) => { var radius = 10.0; var theta = Math.PI; @@ -65,14 +65,14 @@ export default QUnit.module( 'Maths', () => { var a = new Cylindrical( radius, theta, y ); var b = new Cylindrical().copy( a ); - assert.propEqual( a, b, "Check a and b are equal after copy()" ); + assert.propEqual( a, b, 'Check a and b are equal after copy()' ); a.radius = 1; - assert.notPropEqual( a, b, "Check a and b are not equal after modification" ); + assert.notPropEqual( a, b, 'Check a and b are not equal after modification' ); } ); - QUnit.test( "setFromVector3", ( assert ) => { + QUnit.test( 'setFromVector3', ( assert ) => { var a = new Cylindrical( 1, 1, 1 ); var b = new Vector3( 0, 0, 0 ); @@ -80,14 +80,14 @@ export default QUnit.module( 'Maths', () => { var expected = new Cylindrical( Math.sqrt( 9 + 9 ), Math.atan2( 3, - 3 ), - 1 ); a.setFromVector3( b ); - assert.strictEqual( a.radius, 0, "Zero-length vector: check radius" ); - assert.strictEqual( a.theta, 0, "Zero-length vector: check theta" ); - assert.strictEqual( a.y, 0, "Zero-length vector: check y" ); + assert.strictEqual( a.radius, 0, 'Zero-length vector: check radius' ); + assert.strictEqual( a.theta, 0, 'Zero-length vector: check theta' ); + assert.strictEqual( a.y, 0, 'Zero-length vector: check y' ); a.setFromVector3( c ); - assert.ok( Math.abs( a.radius - expected.radius ) <= eps, "Normal vector: check radius" ); - assert.ok( Math.abs( a.theta - expected.theta ) <= eps, "Normal vector: check theta" ); - assert.ok( Math.abs( a.y - expected.y ) <= eps, "Normal vector: check y" ); + assert.ok( Math.abs( a.radius - expected.radius ) <= eps, 'Normal vector: check radius' ); + assert.ok( Math.abs( a.theta - expected.theta ) <= eps, 'Normal vector: check theta' ); + assert.ok( Math.abs( a.y - expected.y ) <= eps, 'Normal vector: check y' ); } ); diff --git a/test/unit/src/math/Euler.tests.js b/test/unit/src/math/Euler.tests.js index d543bd62e386a8..20e17d7ab990e7 100644 --- a/test/unit/src/math/Euler.tests.js +++ b/test/unit/src/math/Euler.tests.js @@ -6,9 +6,9 @@ import { Quaternion } from '../../../../src/math/Quaternion'; import { Vector3 } from '../../../../src/math/Vector3'; import { x, y, z } from './Constants.tests'; -const eulerZero = new Euler( 0, 0, 0, "XYZ" ); -const eulerAxyz = new Euler( 1, 0, 0, "XYZ" ); -const eulerAzyx = new Euler( 0, 1, 0, "ZYX" ); +const eulerZero = new Euler( 0, 0, 0, 'XYZ' ); +const eulerAxyz = new Euler( 1, 0, 0, 'XYZ' ); +const eulerAzyx = new Euler( 0, 1, 0, 'ZYX' ); function matrixEquals4( a, b, tolerance ) { @@ -57,47 +57,47 @@ export default QUnit.module( 'Maths', () => { QUnit.module( 'Euler', () => { // INSTANCING - QUnit.test( "Instancing", ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { var a = new Euler(); - assert.ok( a.equals( eulerZero ), "Passed!" ); - assert.ok( ! a.equals( eulerAxyz ), "Passed!" ); - assert.ok( ! a.equals( eulerAzyx ), "Passed!" ); + assert.ok( a.equals( eulerZero ), 'Passed!' ); + assert.ok( ! a.equals( eulerAxyz ), 'Passed!' ); + assert.ok( ! a.equals( eulerAzyx ), 'Passed!' ); } ); // STATIC STUFF - QUnit.test( "RotationOrders", ( assert ) => { + QUnit.test( 'RotationOrders', ( assert ) => { - assert.ok( Array.isArray( Euler.RotationOrders ), "Passed!" ); - assert.deepEqual( Euler.RotationOrders, [ 'XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ], "Passed!" ); + assert.ok( Array.isArray( Euler.RotationOrders ), 'Passed!' ); + assert.deepEqual( Euler.RotationOrders, [ 'XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ], 'Passed!' ); } ); - QUnit.test( "DefaultOrder", ( assert ) => { + QUnit.test( 'DefaultOrder', ( assert ) => { - assert.equal( Euler.DefaultOrder, "XYZ", "Passed!" ); + assert.equal( Euler.DefaultOrder, 'XYZ', 'Passed!' ); } ); // PROPERTIES STUFF - QUnit.test( "x", ( assert ) => { + QUnit.test( 'x', ( assert ) => { var a = new Euler(); - assert.ok( a.x === 0, "Passed!" ); + assert.ok( a.x === 0, 'Passed!' ); a = new Euler( 1, 2, 3 ); - assert.ok( a.x === 1, "Passed!" ); + assert.ok( a.x === 1, 'Passed!' ); - a = new Euler( 4, 5, 6, "XYZ" ); - assert.ok( a.x === 4, "Passed!" ); + a = new Euler( 4, 5, 6, 'XYZ' ); + assert.ok( a.x === 4, 'Passed!' ); - a = new Euler( 7, 8, 9, "XYZ" ); + a = new Euler( 7, 8, 9, 'XYZ' ); a.x = 10; - assert.ok( a.x === 10, "Passed!" ); + assert.ok( a.x === 10, 'Passed!' ); - a = new Euler( 11, 12, 13, "XYZ" ); + a = new Euler( 11, 12, 13, 'XYZ' ); var b = false; a._onChange( function () { @@ -105,28 +105,28 @@ export default QUnit.module( 'Maths', () => { } ); a.x = 14; - assert.ok( b, "Passed!" ); - assert.ok( a.x === 14, "Passed!" ); + assert.ok( b, 'Passed!' ); + assert.ok( a.x === 14, 'Passed!' ); } ); - QUnit.test( "y", ( assert ) => { + QUnit.test( 'y', ( assert ) => { var a = new Euler(); - assert.ok( a.y === 0, "Passed!" ); + assert.ok( a.y === 0, 'Passed!' ); a = new Euler( 1, 2, 3 ); - assert.ok( a.y === 2, "Passed!" ); + assert.ok( a.y === 2, 'Passed!' ); - a = new Euler( 4, 5, 6, "XYZ" ); - assert.ok( a.y === 5, "Passed!" ); + a = new Euler( 4, 5, 6, 'XYZ' ); + assert.ok( a.y === 5, 'Passed!' ); - a = new Euler( 7, 8, 9, "XYZ" ); + a = new Euler( 7, 8, 9, 'XYZ' ); a.y = 10; - assert.ok( a.y === 10, "Passed!" ); + assert.ok( a.y === 10, 'Passed!' ); - a = new Euler( 11, 12, 13, "XYZ" ); + a = new Euler( 11, 12, 13, 'XYZ' ); var b = false; a._onChange( function () { @@ -134,28 +134,28 @@ export default QUnit.module( 'Maths', () => { } ); a.y = 14; - assert.ok( b, "Passed!" ); - assert.ok( a.y === 14, "Passed!" ); + assert.ok( b, 'Passed!' ); + assert.ok( a.y === 14, 'Passed!' ); } ); - QUnit.test( "z", ( assert ) => { + QUnit.test( 'z', ( assert ) => { var a = new Euler(); - assert.ok( a.z === 0, "Passed!" ); + assert.ok( a.z === 0, 'Passed!' ); a = new Euler( 1, 2, 3 ); - assert.ok( a.z === 3, "Passed!" ); + assert.ok( a.z === 3, 'Passed!' ); - a = new Euler( 4, 5, 6, "XYZ" ); - assert.ok( a.z === 6, "Passed!" ); + a = new Euler( 4, 5, 6, 'XYZ' ); + assert.ok( a.z === 6, 'Passed!' ); - a = new Euler( 7, 8, 9, "XYZ" ); + a = new Euler( 7, 8, 9, 'XYZ' ); a.z = 10; - assert.ok( a.z === 10, "Passed!" ); + assert.ok( a.z === 10, 'Passed!' ); - a = new Euler( 11, 12, 13, "XYZ" ); + a = new Euler( 11, 12, 13, 'XYZ' ); var b = false; a._onChange( function () { @@ -163,86 +163,86 @@ export default QUnit.module( 'Maths', () => { } ); a.z = 14; - assert.ok( b, "Passed!" ); - assert.ok( a.z === 14, "Passed!" ); + assert.ok( b, 'Passed!' ); + assert.ok( a.z === 14, 'Passed!' ); } ); - QUnit.test( "order", ( assert ) => { + QUnit.test( 'order', ( assert ) => { var a = new Euler(); - assert.ok( a.order === Euler.DefaultOrder, "Passed!" ); + assert.ok( a.order === Euler.DefaultOrder, 'Passed!' ); a = new Euler( 1, 2, 3 ); - assert.ok( a.order === Euler.DefaultOrder, "Passed!" ); + assert.ok( a.order === Euler.DefaultOrder, 'Passed!' ); - a = new Euler( 4, 5, 6, "YZX" ); - assert.ok( a.order === "YZX", "Passed!" ); + a = new Euler( 4, 5, 6, 'YZX' ); + assert.ok( a.order === 'YZX', 'Passed!' ); - a = new Euler( 7, 8, 9, "YZX" ); - a.order = "ZXY"; - assert.ok( a.order === "ZXY", "Passed!" ); + a = new Euler( 7, 8, 9, 'YZX' ); + a.order = 'ZXY'; + assert.ok( a.order === 'ZXY', 'Passed!' ); - a = new Euler( 11, 12, 13, "YZX" ); + a = new Euler( 11, 12, 13, 'YZX' ); var b = false; a._onChange( function () { b = true; } ); - a.order = "ZXY"; - assert.ok( b, "Passed!" ); - assert.ok( a.order === "ZXY", "Passed!" ); + a.order = 'ZXY'; + assert.ok( b, 'Passed!' ); + assert.ok( a.order === 'ZXY', 'Passed!' ); } ); // PUBLIC STUFF - QUnit.test( "isEuler", ( assert ) => { + QUnit.test( 'isEuler', ( assert ) => { var a = new Euler(); - assert.ok( a.isEuler, "Passed!" ); + assert.ok( a.isEuler, 'Passed!' ); var b = new Vector3(); - assert.ok( ! b.isEuler, "Passed!" ); + assert.ok( ! b.isEuler, 'Passed!' ); } ); - QUnit.test( "set/setFromVector3/toVector3", ( assert ) => { + QUnit.test( 'set/setFromVector3/toVector3', ( assert ) => { var a = new Euler(); - a.set( 0, 1, 0, "ZYX" ); - assert.ok( a.equals( eulerAzyx ), "Passed!" ); - assert.ok( ! a.equals( eulerAxyz ), "Passed!" ); - assert.ok( ! a.equals( eulerZero ), "Passed!" ); + a.set( 0, 1, 0, 'ZYX' ); + assert.ok( a.equals( eulerAzyx ), 'Passed!' ); + assert.ok( ! a.equals( eulerAxyz ), 'Passed!' ); + assert.ok( ! a.equals( eulerZero ), 'Passed!' ); var vec = new Vector3( 0, 1, 0 ); - var b = new Euler().setFromVector3( vec, "ZYX" ); - assert.ok( a.equals( b ), "Passed!" ); + var b = new Euler().setFromVector3( vec, 'ZYX' ); + assert.ok( a.equals( b ), 'Passed!' ); var c = b.toVector3(); - assert.ok( c.equals( vec ), "Passed!" ); + assert.ok( c.equals( vec ), 'Passed!' ); } ); - QUnit.test( "clone/copy/equals", ( assert ) => { + QUnit.test( 'clone/copy/equals', ( assert ) => { var a = eulerAxyz.clone(); - assert.ok( a.equals( eulerAxyz ), "Passed!" ); - assert.ok( ! a.equals( eulerZero ), "Passed!" ); - assert.ok( ! a.equals( eulerAzyx ), "Passed!" ); + assert.ok( a.equals( eulerAxyz ), 'Passed!' ); + assert.ok( ! a.equals( eulerZero ), 'Passed!' ); + assert.ok( ! a.equals( eulerAzyx ), 'Passed!' ); a.copy( eulerAzyx ); - assert.ok( a.equals( eulerAzyx ), "Passed!" ); - assert.ok( ! a.equals( eulerAxyz ), "Passed!" ); - assert.ok( ! a.equals( eulerZero ), "Passed!" ); + assert.ok( a.equals( eulerAzyx ), 'Passed!' ); + assert.ok( ! a.equals( eulerAxyz ), 'Passed!' ); + assert.ok( ! a.equals( eulerZero ), 'Passed!' ); } ); - QUnit.test( "Quaternion.setFromEuler/Euler.fromQuaternion", ( assert ) => { + QUnit.test( 'Quaternion.setFromEuler/Euler.fromQuaternion', ( assert ) => { var testValues = [ eulerZero, eulerAxyz, eulerAzyx ]; for ( var i = 0; i < testValues.length; i ++ ) { @@ -252,13 +252,13 @@ export default QUnit.module( 'Maths', () => { var v2 = new Euler().setFromQuaternion( q, v.order ); var q2 = new Quaternion().setFromEuler( v2 ); - assert.ok( quatEquals( q, q2 ), "Passed!" ); + assert.ok( quatEquals( q, q2 ), 'Passed!' ); } } ); - QUnit.test( "Matrix4.setFromEuler/Euler.fromRotationMatrix", ( assert ) => { + QUnit.test( 'Matrix4.setFromEuler/Euler.fromRotationMatrix', ( assert ) => { var testValues = [ eulerZero, eulerAxyz, eulerAzyx ]; for ( var i = 0; i < testValues.length; i ++ ) { @@ -268,13 +268,13 @@ export default QUnit.module( 'Maths', () => { var v2 = new Euler().setFromRotationMatrix( m, v.order ); var m2 = new Matrix4().makeRotationFromEuler( v2 ); - assert.ok( matrixEquals4( m, m2, 0.0001 ), "Passed!" ); + assert.ok( matrixEquals4( m, m2, 0.0001 ), 'Passed!' ); } } ); - QUnit.test( "reorder", ( assert ) => { + QUnit.test( 'reorder', ( assert ) => { var testValues = [ eulerZero, eulerAxyz, eulerAzyx ]; for ( var i = 0; i < testValues.length; i ++ ) { @@ -284,129 +284,132 @@ export default QUnit.module( 'Maths', () => { v.reorder( 'YZX' ); var q2 = new Quaternion().setFromEuler( v ); - assert.ok( quatEquals( q, q2 ), "Passed!" ); + assert.ok( quatEquals( q, q2 ), 'Passed!' ); v.reorder( 'ZXY' ); var q3 = new Quaternion().setFromEuler( v ); - assert.ok( quatEquals( q, q3 ), "Passed!" ); + assert.ok( quatEquals( q, q3 ), 'Passed!' ); } } ); - QUnit.test( "set/get properties, check callbacks", ( assert ) => { + QUnit.test( 'set/get properties, check callbacks', ( assert ) => { var a = new Euler(); a._onChange( function () { - assert.step( "set: onChange called" ); + assert.step( 'set: onChange called' ); } ); a.x = 1; a.y = 2; a.z = 3; - a.order = "ZYX"; + a.order = 'ZYX'; - assert.strictEqual( a.x, 1, "get: check x" ); - assert.strictEqual( a.y, 2, "get: check y" ); - assert.strictEqual( a.z, 3, "get: check z" ); - assert.strictEqual( a.order, "ZYX", "get: check order" ); + assert.strictEqual( a.x, 1, 'get: check x' ); + assert.strictEqual( a.y, 2, 'get: check y' ); + assert.strictEqual( a.z, 3, 'get: check z' ); + assert.strictEqual( a.order, 'ZYX', 'get: check order' ); - assert.verifySteps( Array( 4 ).fill( "set: onChange called" ) ); + assert.verifySteps( Array( 4 ).fill( 'set: onChange called' ) ); } ); - QUnit.test( "clone/copy, check callbacks", ( assert ) => { + QUnit.test( 'clone/copy, check callbacks', ( assert ) => { - var a = new Euler( 1, 2, 3, "ZXY" ); - var b = new Euler( 4, 5, 6, "XZY" ); + var a = new Euler( 1, 2, 3, 'ZXY' ); + var b = new Euler( 4, 5, 6, 'XZY' ); var cbSucceed = function () { assert.ok( true ); - assert.step( "onChange called" ); + assert.step( 'onChange called' ); }; + var cbFail = function () { assert.ok( false ); }; + a._onChange( cbFail ); b._onChange( cbFail ); // clone doesn't trigger onChange a = b.clone(); - assert.ok( a.equals( b ), "clone: check if a equals b" ); + assert.ok( a.equals( b ), 'clone: check if a equals b' ); // copy triggers onChange once - a = new Euler( 1, 2, 3, "ZXY" ); + a = new Euler( 1, 2, 3, 'ZXY' ); a._onChange( cbSucceed ); a.copy( b ); - assert.ok( a.equals( b ), "copy: check if a equals b" ); - assert.verifySteps( [ "onChange called" ] ); + assert.ok( a.equals( b ), 'copy: check if a equals b' ); + assert.verifySteps( [ 'onChange called' ] ); } ); - QUnit.test( "toArray", ( assert ) => { + QUnit.test( 'toArray', ( assert ) => { - var order = "YXZ"; + var order = 'YXZ'; var a = new Euler( x, y, z, order ); var array = a.toArray(); - assert.strictEqual( array[ 0 ], x, "No array, no offset: check x" ); - assert.strictEqual( array[ 1 ], y, "No array, no offset: check y" ); - assert.strictEqual( array[ 2 ], z, "No array, no offset: check z" ); - assert.strictEqual( array[ 3 ], order, "No array, no offset: check order" ); + assert.strictEqual( array[ 0 ], x, 'No array, no offset: check x' ); + assert.strictEqual( array[ 1 ], y, 'No array, no offset: check y' ); + assert.strictEqual( array[ 2 ], z, 'No array, no offset: check z' ); + assert.strictEqual( array[ 3 ], order, 'No array, no offset: check order' ); var array = []; a.toArray( array ); - assert.strictEqual( array[ 0 ], x, "With array, no offset: check x" ); - assert.strictEqual( array[ 1 ], y, "With array, no offset: check y" ); - assert.strictEqual( array[ 2 ], z, "With array, no offset: check z" ); - assert.strictEqual( array[ 3 ], order, "With array, no offset: check order" ); + assert.strictEqual( array[ 0 ], x, 'With array, no offset: check x' ); + assert.strictEqual( array[ 1 ], y, 'With array, no offset: check y' ); + assert.strictEqual( array[ 2 ], z, 'With array, no offset: check z' ); + assert.strictEqual( array[ 3 ], order, 'With array, no offset: check order' ); var array = []; a.toArray( array, 1 ); - assert.strictEqual( array[ 0 ], undefined, "With array and offset: check [0]" ); - assert.strictEqual( array[ 1 ], x, "With array and offset: check x" ); - assert.strictEqual( array[ 2 ], y, "With array and offset: check y" ); - assert.strictEqual( array[ 3 ], z, "With array and offset: check z" ); - assert.strictEqual( array[ 4 ], order, "With array and offset: check order" ); + assert.strictEqual( array[ 0 ], undefined, 'With array and offset: check [0]' ); + assert.strictEqual( array[ 1 ], x, 'With array and offset: check x' ); + assert.strictEqual( array[ 2 ], y, 'With array and offset: check y' ); + assert.strictEqual( array[ 3 ], z, 'With array and offset: check z' ); + assert.strictEqual( array[ 4 ], order, 'With array and offset: check order' ); } ); - QUnit.test( "fromArray", ( assert ) => { + QUnit.test( 'fromArray', ( assert ) => { var a = new Euler(); var array = [ x, y, z ]; var cb = function () { - assert.step( "onChange called" ); + assert.step( 'onChange called' ); }; + a._onChange( cb ); a.fromArray( array ); - assert.strictEqual( a.x, x, "No order: check x" ); - assert.strictEqual( a.y, y, "No order: check y" ); - assert.strictEqual( a.z, z, "No order: check z" ); - assert.strictEqual( a.order, "XYZ", "No order: check order" ); + assert.strictEqual( a.x, x, 'No order: check x' ); + assert.strictEqual( a.y, y, 'No order: check y' ); + assert.strictEqual( a.z, z, 'No order: check z' ); + assert.strictEqual( a.order, 'XYZ', 'No order: check order' ); a = new Euler(); - array = [ x, y, z, "ZXY" ]; + array = [ x, y, z, 'ZXY' ]; a._onChange( cb ); a.fromArray( array ); - assert.strictEqual( a.x, x, "With order: check x" ); - assert.strictEqual( a.y, y, "With order: check y" ); - assert.strictEqual( a.z, z, "With order: check z" ); - assert.strictEqual( a.order, "ZXY", "With order: check order" ); + assert.strictEqual( a.x, x, 'With order: check x' ); + assert.strictEqual( a.y, y, 'With order: check y' ); + assert.strictEqual( a.z, z, 'With order: check z' ); + assert.strictEqual( a.order, 'ZXY', 'With order: check order' ); - assert.verifySteps( Array( 2 ).fill( "onChange called" ) ); + assert.verifySteps( Array( 2 ).fill( 'onChange called' ) ); } ); - QUnit.test( "_onChange", ( assert ) => { + QUnit.test( '_onChange', ( assert ) => { var f = function () { @@ -414,29 +417,29 @@ export default QUnit.module( 'Maths', () => { }; - var a = new Euler( 11, 12, 13, "XYZ" ); + var a = new Euler( 11, 12, 13, 'XYZ' ); a._onChange( f ); - assert.ok( a._onChangeCallback === f, "Passed!" ); + assert.ok( a._onChangeCallback === f, 'Passed!' ); } ); - QUnit.test( "_onChangeCallback", ( assert ) => { + QUnit.test( '_onChangeCallback', ( assert ) => { var b = false; - var a = new Euler( 11, 12, 13, "XYZ" ); + var a = new Euler( 11, 12, 13, 'XYZ' ); var f = function () { b = true; - assert.ok( a === this, "Passed!" ); + assert.ok( a === this, 'Passed!' ); }; a._onChangeCallback = f; - assert.ok( a._onChangeCallback === f, "Passed!" ); + assert.ok( a._onChangeCallback === f, 'Passed!' ); a._onChangeCallback(); - assert.ok( b, "Passed!" ); + assert.ok( b, 'Passed!' ); } ); diff --git a/test/unit/src/math/Frustum.tests.js b/test/unit/src/math/Frustum.tests.js index 1437bd0421b5fc..ac79d887b72ae6 100644 --- a/test/unit/src/math/Frustum.tests.js +++ b/test/unit/src/math/Frustum.tests.js @@ -29,17 +29,17 @@ export default QUnit.module( 'Maths', () => { QUnit.module( 'Frustum', () => { // INSTANCING - QUnit.test( "Instancing", ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { var a = new Frustum(); - assert.ok( a.planes !== undefined, "Passed!" ); - assert.ok( a.planes.length === 6, "Passed!" ); + assert.ok( a.planes !== undefined, 'Passed!' ); + assert.ok( a.planes.length === 6, 'Passed!' ); var pDefault = new Plane(); for ( var i = 0; i < 6; i ++ ) { - assert.ok( a.planes[ i ].equals( pDefault ), "Passed!" ); + assert.ok( a.planes[ i ].equals( pDefault ), 'Passed!' ); } @@ -51,17 +51,17 @@ export default QUnit.module( 'Maths', () => { var p5 = new Plane( unit3, 5 ); var a = new Frustum( p0, p1, p2, p3, p4, p5 ); - assert.ok( a.planes[ 0 ].equals( p0 ), "Passed!" ); - assert.ok( a.planes[ 1 ].equals( p1 ), "Passed!" ); - assert.ok( a.planes[ 2 ].equals( p2 ), "Passed!" ); - assert.ok( a.planes[ 3 ].equals( p3 ), "Passed!" ); - assert.ok( a.planes[ 4 ].equals( p4 ), "Passed!" ); - assert.ok( a.planes[ 5 ].equals( p5 ), "Passed!" ); + assert.ok( a.planes[ 0 ].equals( p0 ), 'Passed!' ); + assert.ok( a.planes[ 1 ].equals( p1 ), 'Passed!' ); + assert.ok( a.planes[ 2 ].equals( p2 ), 'Passed!' ); + assert.ok( a.planes[ 3 ].equals( p3 ), 'Passed!' ); + assert.ok( a.planes[ 4 ].equals( p4 ), 'Passed!' ); + assert.ok( a.planes[ 5 ].equals( p5 ), 'Passed!' ); } ); // PUBLIC STUFF - QUnit.test( "set", ( assert ) => { + QUnit.test( 'set', ( assert ) => { var a = new Frustum(); var p0 = new Plane( unit3, - 1 ); @@ -73,16 +73,16 @@ export default QUnit.module( 'Maths', () => { a.set( p0, p1, p2, p3, p4, p5 ); - assert.ok( a.planes[ 0 ].equals( p0 ), "Check plane #0" ); - assert.ok( a.planes[ 1 ].equals( p1 ), "Check plane #1" ); - assert.ok( a.planes[ 2 ].equals( p2 ), "Check plane #2" ); - assert.ok( a.planes[ 3 ].equals( p3 ), "Check plane #3" ); - assert.ok( a.planes[ 4 ].equals( p4 ), "Check plane #4" ); - assert.ok( a.planes[ 5 ].equals( p5 ), "Check plane #5" ); + assert.ok( a.planes[ 0 ].equals( p0 ), 'Check plane #0' ); + assert.ok( a.planes[ 1 ].equals( p1 ), 'Check plane #1' ); + assert.ok( a.planes[ 2 ].equals( p2 ), 'Check plane #2' ); + assert.ok( a.planes[ 3 ].equals( p3 ), 'Check plane #3' ); + assert.ok( a.planes[ 4 ].equals( p4 ), 'Check plane #4' ); + assert.ok( a.planes[ 5 ].equals( p5 ), 'Check plane #5' ); } ); - QUnit.test( "clone", ( assert ) => { + QUnit.test( 'clone', ( assert ) => { var p0 = new Plane( unit3, - 1 ); var p1 = new Plane( unit3, 1 ); @@ -93,20 +93,20 @@ export default QUnit.module( 'Maths', () => { var b = new Frustum( p0, p1, p2, p3, p4, p5 ); var a = b.clone(); - assert.ok( a.planes[ 0 ].equals( p0 ), "Passed!" ); - assert.ok( a.planes[ 1 ].equals( p1 ), "Passed!" ); - assert.ok( a.planes[ 2 ].equals( p2 ), "Passed!" ); - assert.ok( a.planes[ 3 ].equals( p3 ), "Passed!" ); - assert.ok( a.planes[ 4 ].equals( p4 ), "Passed!" ); - assert.ok( a.planes[ 5 ].equals( p5 ), "Passed!" ); + assert.ok( a.planes[ 0 ].equals( p0 ), 'Passed!' ); + assert.ok( a.planes[ 1 ].equals( p1 ), 'Passed!' ); + assert.ok( a.planes[ 2 ].equals( p2 ), 'Passed!' ); + assert.ok( a.planes[ 3 ].equals( p3 ), 'Passed!' ); + assert.ok( a.planes[ 4 ].equals( p4 ), 'Passed!' ); + assert.ok( a.planes[ 5 ].equals( p5 ), 'Passed!' ); // ensure it is a true copy by modifying source a.planes[ 0 ].copy( p1 ); - assert.ok( b.planes[ 0 ].equals( p0 ), "Passed!" ); + assert.ok( b.planes[ 0 ].equals( p0 ), 'Passed!' ); } ); - QUnit.test( "copy", ( assert ) => { + QUnit.test( 'copy', ( assert ) => { var p0 = new Plane( unit3, - 1 ); var p1 = new Plane( unit3, 1 ); @@ -117,90 +117,90 @@ export default QUnit.module( 'Maths', () => { var b = new Frustum( p0, p1, p2, p3, p4, p5 ); var a = new Frustum().copy( b ); - assert.ok( a.planes[ 0 ].equals( p0 ), "Passed!" ); - assert.ok( a.planes[ 1 ].equals( p1 ), "Passed!" ); - assert.ok( a.planes[ 2 ].equals( p2 ), "Passed!" ); - assert.ok( a.planes[ 3 ].equals( p3 ), "Passed!" ); - assert.ok( a.planes[ 4 ].equals( p4 ), "Passed!" ); - assert.ok( a.planes[ 5 ].equals( p5 ), "Passed!" ); + assert.ok( a.planes[ 0 ].equals( p0 ), 'Passed!' ); + assert.ok( a.planes[ 1 ].equals( p1 ), 'Passed!' ); + assert.ok( a.planes[ 2 ].equals( p2 ), 'Passed!' ); + assert.ok( a.planes[ 3 ].equals( p3 ), 'Passed!' ); + assert.ok( a.planes[ 4 ].equals( p4 ), 'Passed!' ); + assert.ok( a.planes[ 5 ].equals( p5 ), 'Passed!' ); // ensure it is a true copy by modifying source b.planes[ 0 ] = p1; - assert.ok( a.planes[ 0 ].equals( p0 ), "Passed!" ); + assert.ok( a.planes[ 0 ].equals( p0 ), 'Passed!' ); } ); - QUnit.test( "setFromProjectionMatrix/makeOrthographic/containsPoint", ( assert ) => { + QUnit.test( 'setFromProjectionMatrix/makeOrthographic/containsPoint', ( assert ) => { var m = new Matrix4().makeOrthographic( - 1, 1, - 1, 1, 1, 100 ); var a = new Frustum().setFromProjectionMatrix( m ); - assert.ok( ! a.containsPoint( new Vector3( 0, 0, 0 ) ), "Passed!" ); - assert.ok( a.containsPoint( new Vector3( 0, 0, - 50 ) ), "Passed!" ); - assert.ok( a.containsPoint( new Vector3( 0, 0, - 1.001 ) ), "Passed!" ); - assert.ok( a.containsPoint( new Vector3( - 1, - 1, - 1.001 ) ), "Passed!" ); - assert.ok( ! a.containsPoint( new Vector3( - 1.1, - 1.1, - 1.001 ) ), "Passed!" ); - assert.ok( a.containsPoint( new Vector3( 1, 1, - 1.001 ) ), "Passed!" ); - assert.ok( ! a.containsPoint( new Vector3( 1.1, 1.1, - 1.001 ) ), "Passed!" ); - assert.ok( a.containsPoint( new Vector3( 0, 0, - 100 ) ), "Passed!" ); - assert.ok( a.containsPoint( new Vector3( - 1, - 1, - 100 ) ), "Passed!" ); - assert.ok( ! a.containsPoint( new Vector3( - 1.1, - 1.1, - 100.1 ) ), "Passed!" ); - assert.ok( a.containsPoint( new Vector3( 1, 1, - 100 ) ), "Passed!" ); - assert.ok( ! a.containsPoint( new Vector3( 1.1, 1.1, - 100.1 ) ), "Passed!" ); - assert.ok( ! a.containsPoint( new Vector3( 0, 0, - 101 ) ), "Passed!" ); + assert.ok( ! a.containsPoint( new Vector3( 0, 0, 0 ) ), 'Passed!' ); + assert.ok( a.containsPoint( new Vector3( 0, 0, - 50 ) ), 'Passed!' ); + assert.ok( a.containsPoint( new Vector3( 0, 0, - 1.001 ) ), 'Passed!' ); + assert.ok( a.containsPoint( new Vector3( - 1, - 1, - 1.001 ) ), 'Passed!' ); + assert.ok( ! a.containsPoint( new Vector3( - 1.1, - 1.1, - 1.001 ) ), 'Passed!' ); + assert.ok( a.containsPoint( new Vector3( 1, 1, - 1.001 ) ), 'Passed!' ); + assert.ok( ! a.containsPoint( new Vector3( 1.1, 1.1, - 1.001 ) ), 'Passed!' ); + assert.ok( a.containsPoint( new Vector3( 0, 0, - 100 ) ), 'Passed!' ); + assert.ok( a.containsPoint( new Vector3( - 1, - 1, - 100 ) ), 'Passed!' ); + assert.ok( ! a.containsPoint( new Vector3( - 1.1, - 1.1, - 100.1 ) ), 'Passed!' ); + assert.ok( a.containsPoint( new Vector3( 1, 1, - 100 ) ), 'Passed!' ); + assert.ok( ! a.containsPoint( new Vector3( 1.1, 1.1, - 100.1 ) ), 'Passed!' ); + assert.ok( ! a.containsPoint( new Vector3( 0, 0, - 101 ) ), 'Passed!' ); } ); - QUnit.test( "setFromProjectionMatrix/makePerspective/containsPoint", ( assert ) => { + QUnit.test( 'setFromProjectionMatrix/makePerspective/containsPoint', ( assert ) => { var m = new Matrix4().makePerspective( - 1, 1, 1, - 1, 1, 100 ); var a = new Frustum().setFromProjectionMatrix( m ); - assert.ok( ! a.containsPoint( new Vector3( 0, 0, 0 ) ), "Passed!" ); - assert.ok( a.containsPoint( new Vector3( 0, 0, - 50 ) ), "Passed!" ); - assert.ok( a.containsPoint( new Vector3( 0, 0, - 1.001 ) ), "Passed!" ); - assert.ok( a.containsPoint( new Vector3( - 1, - 1, - 1.001 ) ), "Passed!" ); - assert.ok( ! a.containsPoint( new Vector3( - 1.1, - 1.1, - 1.001 ) ), "Passed!" ); - assert.ok( a.containsPoint( new Vector3( 1, 1, - 1.001 ) ), "Passed!" ); - assert.ok( ! a.containsPoint( new Vector3( 1.1, 1.1, - 1.001 ) ), "Passed!" ); - assert.ok( a.containsPoint( new Vector3( 0, 0, - 99.999 ) ), "Passed!" ); - assert.ok( a.containsPoint( new Vector3( - 99.999, - 99.999, - 99.999 ) ), "Passed!" ); - assert.ok( ! a.containsPoint( new Vector3( - 100.1, - 100.1, - 100.1 ) ), "Passed!" ); - assert.ok( a.containsPoint( new Vector3( 99.999, 99.999, - 99.999 ) ), "Passed!" ); - assert.ok( ! a.containsPoint( new Vector3( 100.1, 100.1, - 100.1 ) ), "Passed!" ); - assert.ok( ! a.containsPoint( new Vector3( 0, 0, - 101 ) ), "Passed!" ); + assert.ok( ! a.containsPoint( new Vector3( 0, 0, 0 ) ), 'Passed!' ); + assert.ok( a.containsPoint( new Vector3( 0, 0, - 50 ) ), 'Passed!' ); + assert.ok( a.containsPoint( new Vector3( 0, 0, - 1.001 ) ), 'Passed!' ); + assert.ok( a.containsPoint( new Vector3( - 1, - 1, - 1.001 ) ), 'Passed!' ); + assert.ok( ! a.containsPoint( new Vector3( - 1.1, - 1.1, - 1.001 ) ), 'Passed!' ); + assert.ok( a.containsPoint( new Vector3( 1, 1, - 1.001 ) ), 'Passed!' ); + assert.ok( ! a.containsPoint( new Vector3( 1.1, 1.1, - 1.001 ) ), 'Passed!' ); + assert.ok( a.containsPoint( new Vector3( 0, 0, - 99.999 ) ), 'Passed!' ); + assert.ok( a.containsPoint( new Vector3( - 99.999, - 99.999, - 99.999 ) ), 'Passed!' ); + assert.ok( ! a.containsPoint( new Vector3( - 100.1, - 100.1, - 100.1 ) ), 'Passed!' ); + assert.ok( a.containsPoint( new Vector3( 99.999, 99.999, - 99.999 ) ), 'Passed!' ); + assert.ok( ! a.containsPoint( new Vector3( 100.1, 100.1, - 100.1 ) ), 'Passed!' ); + assert.ok( ! a.containsPoint( new Vector3( 0, 0, - 101 ) ), 'Passed!' ); } ); - QUnit.test( "setFromProjectionMatrix/makePerspective/intersectsSphere", ( assert ) => { + QUnit.test( 'setFromProjectionMatrix/makePerspective/intersectsSphere', ( assert ) => { var m = new Matrix4().makePerspective( - 1, 1, 1, - 1, 1, 100 ); var a = new Frustum().setFromProjectionMatrix( m ); - assert.ok( ! a.intersectsSphere( new Sphere( new Vector3( 0, 0, 0 ), 0 ) ), "Passed!" ); - assert.ok( ! a.intersectsSphere( new Sphere( new Vector3( 0, 0, 0 ), 0.9 ) ), "Passed!" ); - assert.ok( a.intersectsSphere( new Sphere( new Vector3( 0, 0, 0 ), 1.1 ) ), "Passed!" ); - assert.ok( a.intersectsSphere( new Sphere( new Vector3( 0, 0, - 50 ), 0 ) ), "Passed!" ); - assert.ok( a.intersectsSphere( new Sphere( new Vector3( 0, 0, - 1.001 ), 0 ) ), "Passed!" ); - assert.ok( a.intersectsSphere( new Sphere( new Vector3( - 1, - 1, - 1.001 ), 0 ) ), "Passed!" ); - assert.ok( ! a.intersectsSphere( new Sphere( new Vector3( - 1.1, - 1.1, - 1.001 ), 0 ) ), "Passed!" ); - assert.ok( a.intersectsSphere( new Sphere( new Vector3( - 1.1, - 1.1, - 1.001 ), 0.5 ) ), "Passed!" ); - assert.ok( a.intersectsSphere( new Sphere( new Vector3( 1, 1, - 1.001 ), 0 ) ), "Passed!" ); - assert.ok( ! a.intersectsSphere( new Sphere( new Vector3( 1.1, 1.1, - 1.001 ), 0 ) ), "Passed!" ); - assert.ok( a.intersectsSphere( new Sphere( new Vector3( 1.1, 1.1, - 1.001 ), 0.5 ) ), "Passed!" ); - assert.ok( a.intersectsSphere( new Sphere( new Vector3( 0, 0, - 99.999 ), 0 ) ), "Passed!" ); - assert.ok( a.intersectsSphere( new Sphere( new Vector3( - 99.999, - 99.999, - 99.999 ), 0 ) ), "Passed!" ); - assert.ok( ! a.intersectsSphere( new Sphere( new Vector3( - 100.1, - 100.1, - 100.1 ), 0 ) ), "Passed!" ); - assert.ok( a.intersectsSphere( new Sphere( new Vector3( - 100.1, - 100.1, - 100.1 ), 0.5 ) ), "Passed!" ); - assert.ok( a.intersectsSphere( new Sphere( new Vector3( 99.999, 99.999, - 99.999 ), 0 ) ), "Passed!" ); - assert.ok( ! a.intersectsSphere( new Sphere( new Vector3( 100.1, 100.1, - 100.1 ), 0 ) ), "Passed!" ); - assert.ok( a.intersectsSphere( new Sphere( new Vector3( 100.1, 100.1, - 100.1 ), 0.2 ) ), "Passed!" ); - assert.ok( ! a.intersectsSphere( new Sphere( new Vector3( 0, 0, - 101 ), 0 ) ), "Passed!" ); - assert.ok( a.intersectsSphere( new Sphere( new Vector3( 0, 0, - 101 ), 1.1 ) ), "Passed!" ); + assert.ok( ! a.intersectsSphere( new Sphere( new Vector3( 0, 0, 0 ), 0 ) ), 'Passed!' ); + assert.ok( ! a.intersectsSphere( new Sphere( new Vector3( 0, 0, 0 ), 0.9 ) ), 'Passed!' ); + assert.ok( a.intersectsSphere( new Sphere( new Vector3( 0, 0, 0 ), 1.1 ) ), 'Passed!' ); + assert.ok( a.intersectsSphere( new Sphere( new Vector3( 0, 0, - 50 ), 0 ) ), 'Passed!' ); + assert.ok( a.intersectsSphere( new Sphere( new Vector3( 0, 0, - 1.001 ), 0 ) ), 'Passed!' ); + assert.ok( a.intersectsSphere( new Sphere( new Vector3( - 1, - 1, - 1.001 ), 0 ) ), 'Passed!' ); + assert.ok( ! a.intersectsSphere( new Sphere( new Vector3( - 1.1, - 1.1, - 1.001 ), 0 ) ), 'Passed!' ); + assert.ok( a.intersectsSphere( new Sphere( new Vector3( - 1.1, - 1.1, - 1.001 ), 0.5 ) ), 'Passed!' ); + assert.ok( a.intersectsSphere( new Sphere( new Vector3( 1, 1, - 1.001 ), 0 ) ), 'Passed!' ); + assert.ok( ! a.intersectsSphere( new Sphere( new Vector3( 1.1, 1.1, - 1.001 ), 0 ) ), 'Passed!' ); + assert.ok( a.intersectsSphere( new Sphere( new Vector3( 1.1, 1.1, - 1.001 ), 0.5 ) ), 'Passed!' ); + assert.ok( a.intersectsSphere( new Sphere( new Vector3( 0, 0, - 99.999 ), 0 ) ), 'Passed!' ); + assert.ok( a.intersectsSphere( new Sphere( new Vector3( - 99.999, - 99.999, - 99.999 ), 0 ) ), 'Passed!' ); + assert.ok( ! a.intersectsSphere( new Sphere( new Vector3( - 100.1, - 100.1, - 100.1 ), 0 ) ), 'Passed!' ); + assert.ok( a.intersectsSphere( new Sphere( new Vector3( - 100.1, - 100.1, - 100.1 ), 0.5 ) ), 'Passed!' ); + assert.ok( a.intersectsSphere( new Sphere( new Vector3( 99.999, 99.999, - 99.999 ), 0 ) ), 'Passed!' ); + assert.ok( ! a.intersectsSphere( new Sphere( new Vector3( 100.1, 100.1, - 100.1 ), 0 ) ), 'Passed!' ); + assert.ok( a.intersectsSphere( new Sphere( new Vector3( 100.1, 100.1, - 100.1 ), 0.2 ) ), 'Passed!' ); + assert.ok( ! a.intersectsSphere( new Sphere( new Vector3( 0, 0, - 101 ), 0 ) ), 'Passed!' ); + assert.ok( a.intersectsSphere( new Sphere( new Vector3( 0, 0, - 101 ), 1.1 ) ), 'Passed!' ); } ); - QUnit.test( "intersectsObject", ( assert ) => { + QUnit.test( 'intersectsObject', ( assert ) => { var m = new Matrix4().makePerspective( - 1, 1, 1, - 1, 1, 100 ); var a = new Frustum().setFromProjectionMatrix( m ); @@ -208,23 +208,23 @@ export default QUnit.module( 'Maths', () => { var intersects; intersects = a.intersectsObject( object ); - assert.notOk( intersects, "No intersection" ); + assert.notOk( intersects, 'No intersection' ); object.position.set( - 1, - 1, - 1 ); object.updateMatrixWorld(); intersects = a.intersectsObject( object ); - assert.ok( intersects, "Successful intersection" ); + assert.ok( intersects, 'Successful intersection' ); object.position.set( 1, 1, 1 ); object.updateMatrixWorld(); intersects = a.intersectsObject( object ); - assert.notOk( intersects, "No intersection" ); + assert.notOk( intersects, 'No intersection' ); } ); - QUnit.test( "intersectsSprite", ( assert ) => { + QUnit.test( 'intersectsSprite', ( assert ) => { var m = new Matrix4().makePerspective( - 1, 1, 1, - 1, 1, 100 ); var a = new Frustum().setFromProjectionMatrix( m ); @@ -232,23 +232,23 @@ export default QUnit.module( 'Maths', () => { var intersects; intersects = a.intersectsSprite( sprite ); - assert.notOk( intersects, "No intersection" ); + assert.notOk( intersects, 'No intersection' ); sprite.position.set( - 1, - 1, - 1 ); sprite.updateMatrixWorld(); intersects = a.intersectsSprite( sprite ); - assert.ok( intersects, "Successful intersection" ); + assert.ok( intersects, 'Successful intersection' ); } ); - QUnit.todo( "intersectsSphere", ( assert ) => { + QUnit.todo( 'intersectsSphere', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "intersectsBox", ( assert ) => { + QUnit.test( 'intersectsBox', ( assert ) => { var m = new Matrix4().makePerspective( - 1, 1, 1, - 1, 1, 100 ); var a = new Frustum().setFromProjectionMatrix( m ); @@ -256,19 +256,19 @@ export default QUnit.module( 'Maths', () => { var intersects; intersects = a.intersectsBox( box ); - assert.notOk( intersects, "No intersection" ); + assert.notOk( intersects, 'No intersection' ); // add eps so that we prevent box touching the frustum, which might intersect depending on floating point numerics box.translate( new Vector3( - 1 - eps, - 1 - eps, - 1 - eps ) ); intersects = a.intersectsBox( box ); - assert.ok( intersects, "Successful intersection" ); + assert.ok( intersects, 'Successful intersection' ); } ); - QUnit.todo( "containsPoint", ( assert ) => { + QUnit.todo( 'containsPoint', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/math/Interpolant.tests.js b/test/unit/src/math/Interpolant.tests.js index 9af699d49d6a44..69fc1c53014abf 100644 --- a/test/unit/src/math/Interpolant.tests.js +++ b/test/unit/src/math/Interpolant.tests.js @@ -97,31 +97,31 @@ export default QUnit.module( 'Maths', () => { // Tests // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "evaluate", ( assert ) => { + QUnit.todo( 'evaluate', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PRIVATE STUFF - QUnit.test( "copySampleValue_", ( assert ) => { + QUnit.test( 'copySampleValue_', ( assert ) => { var interpolant = new Mock( null, [ 1, 11, 2, 22, 3, 33 ], 2, [] ); - assert.deepEqual( interpolant.copySampleValue_( 0 ), [ 1, 11 ], "sample fetch (0)" ); - assert.deepEqual( interpolant.copySampleValue_( 1 ), [ 2, 22 ], "sample fetch (1)" ); - assert.deepEqual( interpolant.copySampleValue_( 2 ), [ 3, 33 ], "first sample (2)" ); + assert.deepEqual( interpolant.copySampleValue_( 0 ), [ 1, 11 ], 'sample fetch (0)' ); + assert.deepEqual( interpolant.copySampleValue_( 1 ), [ 2, 22 ], 'sample fetch (1)' ); + assert.deepEqual( interpolant.copySampleValue_( 2 ), [ 3, 33 ], 'first sample (2)' ); } ); - QUnit.test( "evaluate -> intervalChanged_ / interpolate_", ( assert ) => { + QUnit.test( 'evaluate -> intervalChanged_ / interpolate_', ( assert ) => { var actual, expect; @@ -144,7 +144,7 @@ export default QUnit.module( 'Maths', () => { }; assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - assert.ok( Mock.calls.length === 2, "no further calls" ); + assert.ok( Mock.calls.length === 2, 'no further calls' ); Mock.calls = []; interpolant.evaluate( 12 ); // same interval @@ -156,7 +156,7 @@ export default QUnit.module( 'Maths', () => { }; assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - assert.ok( Mock.calls.length === 1, "no further calls" ); + assert.ok( Mock.calls.length === 1, 'no further calls' ); Mock.calls = []; interpolant.evaluate( 22 ); // step forward @@ -194,7 +194,7 @@ export default QUnit.module( 'Maths', () => { }; assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - assert.ok( Mock.calls.length === 2, "no further calls" ); + assert.ok( Mock.calls.length === 2, 'no further calls' ); Mock.calls = []; interpolant.evaluate( 20 ); // same interval @@ -206,7 +206,7 @@ export default QUnit.module( 'Maths', () => { }; assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - assert.ok( Mock.calls.length === 1, "no further calls" ); + assert.ok( Mock.calls.length === 1, 'no further calls' ); Mock.calls = []; interpolant.evaluate( 43 ); // two steps forward @@ -225,7 +225,7 @@ export default QUnit.module( 'Maths', () => { }; assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - assert.ok( Mock.calls.length === 2, "no further calls" ); + assert.ok( Mock.calls.length === 2, 'no further calls' ); Mock.calls = []; interpolant.evaluate( 12 ); // two steps back @@ -244,7 +244,7 @@ export default QUnit.module( 'Maths', () => { }; assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - assert.ok( Mock.calls.length === 2, "no further calls" ); + assert.ok( Mock.calls.length === 2, 'no further calls' ); Mock.calls = []; interpolant.evaluate( 77 ); // random access @@ -263,7 +263,7 @@ export default QUnit.module( 'Maths', () => { }; assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - assert.ok( Mock.calls.length === 2, "no further calls" ); + assert.ok( Mock.calls.length === 2, 'no further calls' ); Mock.calls = []; interpolant.evaluate( 80 ); // same interval @@ -275,7 +275,7 @@ export default QUnit.module( 'Maths', () => { }; assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - assert.ok( Mock.calls.length === 1, "no further calls" ); + assert.ok( Mock.calls.length === 1, 'no further calls' ); Mock.calls = []; interpolant.evaluate( 36 ); // random access @@ -294,7 +294,7 @@ export default QUnit.module( 'Maths', () => { }; assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - assert.ok( Mock.calls.length === 2, "no further calls" ); + assert.ok( Mock.calls.length === 2, 'no further calls' ); Mock.calls = []; interpolant.evaluate( 24 ); // fast reset / loop (2nd) @@ -313,7 +313,7 @@ export default QUnit.module( 'Maths', () => { }; assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - assert.ok( Mock.calls.length === 2, "no further calls" ); + assert.ok( Mock.calls.length === 2, 'no further calls' ); Mock.calls = []; interpolant.evaluate( 16 ); // fast reset / loop (2nd) @@ -332,11 +332,11 @@ export default QUnit.module( 'Maths', () => { }; assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - assert.ok( Mock.calls.length === 2, "no further calls" ); + assert.ok( Mock.calls.length === 2, 'no further calls' ); } ); - QUnit.test( "evaulate -> beforeStart_ [once]", ( assert ) => { + QUnit.test( 'evaulate -> beforeStart_ [once]', ( assert ) => { var actual, expect; @@ -352,7 +352,7 @@ export default QUnit.module( 'Maths', () => { }; assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - assert.ok( Mock.calls.length === 1, "no further calls" ); + assert.ok( Mock.calls.length === 1, 'no further calls' ); // Check operation resumes normally and intervalChanged gets called Mock.calls = []; @@ -372,7 +372,7 @@ export default QUnit.module( 'Maths', () => { }; assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - assert.ok( Mock.calls.length === 2, "no further calls" ); + assert.ok( Mock.calls.length === 2, 'no further calls' ); // Back off-bounds Mock.calls = []; @@ -385,11 +385,11 @@ export default QUnit.module( 'Maths', () => { }; assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - assert.ok( Mock.calls.length === 1, "no further calls" ); + assert.ok( Mock.calls.length === 1, 'no further calls' ); } ); - QUnit.test( "evaluate -> beforeStart_ [twice]", ( assert ) => { + QUnit.test( 'evaluate -> beforeStart_ [twice]', ( assert ) => { var actual, expect; @@ -405,7 +405,7 @@ export default QUnit.module( 'Maths', () => { }; assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - assert.ok( Mock.calls.length === 1, "no further calls" ); + assert.ok( Mock.calls.length === 1, 'no further calls' ); Mock.calls = []; // again - consider changed state interpolant.evaluate( 10 ); @@ -417,7 +417,7 @@ export default QUnit.module( 'Maths', () => { }; assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - assert.ok( Mock.calls.length === 1, "no further calls" ); + assert.ok( Mock.calls.length === 1, 'no further calls' ); // Check operation resumes normally and intervalChanged gets called Mock.calls = []; @@ -437,11 +437,11 @@ export default QUnit.module( 'Maths', () => { }; assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - assert.ok( Mock.calls.length === 2, "no further calls" ); + assert.ok( Mock.calls.length === 2, 'no further calls' ); } ); - QUnit.test( "evaluate -> afterEnd_ [once]", ( assert ) => { + QUnit.test( 'evaluate -> afterEnd_ [once]', ( assert ) => { var actual, expect; @@ -457,7 +457,7 @@ export default QUnit.module( 'Maths', () => { }; assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - assert.ok( Mock.calls.length === 1, "no further calls" ); + assert.ok( Mock.calls.length === 1, 'no further calls' ); // Check operation resumes normally and intervalChanged gets called Mock.calls = []; @@ -477,7 +477,7 @@ export default QUnit.module( 'Maths', () => { }; assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - assert.ok( Mock.calls.length === 2, "no further calls" ); + assert.ok( Mock.calls.length === 2, 'no further calls' ); // Back off-bounds Mock.calls = []; @@ -490,11 +490,11 @@ export default QUnit.module( 'Maths', () => { }; assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - assert.ok( Mock.calls.length === 1, "no further calls" ); + assert.ok( Mock.calls.length === 1, 'no further calls' ); } ); - QUnit.test( "evaluate -> afterEnd_ [twice]", ( assert ) => { + QUnit.test( 'evaluate -> afterEnd_ [twice]', ( assert ) => { var actual, expect; @@ -510,7 +510,7 @@ export default QUnit.module( 'Maths', () => { }; assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - assert.ok( Mock.calls.length === 1, "no further calls" ); + assert.ok( Mock.calls.length === 1, 'no further calls' ); Mock.calls = []; // again - consider changed state interpolant.evaluate( 33 ); @@ -522,7 +522,7 @@ export default QUnit.module( 'Maths', () => { }; assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - assert.ok( Mock.calls.length === 1, "no further calls" ); + assert.ok( Mock.calls.length === 1, 'no further calls' ); // Check operation resumes normally and intervalChanged gets called Mock.calls = []; @@ -542,7 +542,7 @@ export default QUnit.module( 'Maths', () => { }; assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - assert.ok( Mock.calls.length === 2, "no further calls" ); + assert.ok( Mock.calls.length === 2, 'no further calls' ); } ); diff --git a/test/unit/src/math/Line3.tests.js b/test/unit/src/math/Line3.tests.js index b18898187f4c18..5fc50e28e06700 100644 --- a/test/unit/src/math/Line3.tests.js +++ b/test/unit/src/math/Line3.tests.js @@ -18,154 +18,154 @@ export default QUnit.module( 'Maths', () => { QUnit.module( 'Line3', () => { // INSTANCING - QUnit.test( "Instancing", ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { var a = new Line3(); - assert.ok( a.start.equals( zero3 ), "Passed!" ); - assert.ok( a.end.equals( zero3 ), "Passed!" ); + assert.ok( a.start.equals( zero3 ), 'Passed!' ); + assert.ok( a.end.equals( zero3 ), 'Passed!' ); var a = new Line3( two3.clone(), one3.clone() ); - assert.ok( a.start.equals( two3 ), "Passed!" ); - assert.ok( a.end.equals( one3 ), "Passed!" ); + assert.ok( a.start.equals( two3 ), 'Passed!' ); + assert.ok( a.end.equals( one3 ), 'Passed!' ); } ); // PUBLIC STUFF - QUnit.test( "set", ( assert ) => { + QUnit.test( 'set', ( assert ) => { var a = new Line3(); a.set( one3, one3 ); - assert.ok( a.start.equals( one3 ), "Passed!" ); - assert.ok( a.end.equals( one3 ), "Passed!" ); + assert.ok( a.start.equals( one3 ), 'Passed!' ); + assert.ok( a.end.equals( one3 ), 'Passed!' ); } ); - QUnit.test( "copy/equals", ( assert ) => { + QUnit.test( 'copy/equals', ( assert ) => { var a = new Line3( zero3.clone(), one3.clone() ); var b = new Line3().copy( a ); - assert.ok( b.start.equals( zero3 ), "Passed!" ); - assert.ok( b.end.equals( one3 ), "Passed!" ); + assert.ok( b.start.equals( zero3 ), 'Passed!' ); + assert.ok( b.end.equals( one3 ), 'Passed!' ); // ensure that it is a true copy a.start = zero3; a.end = one3; - assert.ok( b.start.equals( zero3 ), "Passed!" ); - assert.ok( b.end.equals( one3 ), "Passed!" ); + assert.ok( b.start.equals( zero3 ), 'Passed!' ); + assert.ok( b.end.equals( one3 ), 'Passed!' ); } ); - QUnit.test( "clone/equal", ( assert ) => { + QUnit.test( 'clone/equal', ( assert ) => { var a = new Line3(); var b = new Line3( zero3, new Vector3( 1, 1, 1 ) ); var c = new Line3( zero3, new Vector3( 1, 1, 0 ) ); - assert.notOk( a.equals( b ), "Check a and b aren't equal" ); - assert.notOk( a.equals( c ), "Check a and c aren't equal" ); - assert.notOk( b.equals( c ), "Check b and c aren't equal" ); + assert.notOk( a.equals( b ), 'Check a and b aren\'t equal' ); + assert.notOk( a.equals( c ), 'Check a and c aren\'t equal' ); + assert.notOk( b.equals( c ), 'Check b and c aren\'t equal' ); var a = b.clone(); - assert.ok( a.equals( b ), "Check a and b are equal after clone()" ); - assert.notOk( a.equals( c ), "Check a and c aren't equal after clone()" ); + assert.ok( a.equals( b ), 'Check a and b are equal after clone()' ); + assert.notOk( a.equals( c ), 'Check a and c aren\'t equal after clone()' ); a.set( zero3, zero3 ); - assert.notOk( a.equals( b ), "Check a and b are not equal after modification" ); + assert.notOk( a.equals( b ), 'Check a and b are not equal after modification' ); } ); - QUnit.test( "getCenter", ( assert ) => { + QUnit.test( 'getCenter', ( assert ) => { var center = new Vector3(); var a = new Line3( zero3.clone(), two3.clone() ); - assert.ok( a.getCenter( center ).equals( one3.clone() ), "Passed" ); + assert.ok( a.getCenter( center ).equals( one3.clone() ), 'Passed' ); } ); - QUnit.test( "delta", ( assert ) => { + QUnit.test( 'delta', ( assert ) => { var delta = new Vector3(); var a = new Line3( zero3.clone(), two3.clone() ); - assert.ok( a.delta( delta ).equals( two3.clone() ), "Passed" ); + assert.ok( a.delta( delta ).equals( two3.clone() ), 'Passed' ); } ); - QUnit.test( "distanceSq", ( assert ) => { + QUnit.test( 'distanceSq', ( assert ) => { var a = new Line3( zero3, zero3 ); var b = new Line3( zero3, one3 ); var c = new Line3( one3.clone().negate(), one3 ); var d = new Line3( two3.clone().multiplyScalar( - 2 ), two3.clone().negate() ); - assert.numEqual( a.distanceSq(), 0, "Check squared distance for zero-length line" ); - assert.numEqual( b.distanceSq(), 3, "Check squared distance for simple line" ); - assert.numEqual( c.distanceSq(), 12, "Check squared distance for negative to positive endpoints" ); - assert.numEqual( d.distanceSq(), 12, "Check squared distance for negative to negative endpoints" ); + assert.numEqual( a.distanceSq(), 0, 'Check squared distance for zero-length line' ); + assert.numEqual( b.distanceSq(), 3, 'Check squared distance for simple line' ); + assert.numEqual( c.distanceSq(), 12, 'Check squared distance for negative to positive endpoints' ); + assert.numEqual( d.distanceSq(), 12, 'Check squared distance for negative to negative endpoints' ); } ); - QUnit.test( "distance", ( assert ) => { + QUnit.test( 'distance', ( assert ) => { var a = new Line3( zero3, zero3 ); var b = new Line3( zero3, one3 ); var c = new Line3( one3.clone().negate(), one3 ); var d = new Line3( two3.clone().multiplyScalar( - 2 ), two3.clone().negate() ); - assert.numEqual( a.distance(), 0, "Check distance for zero-length line" ); - assert.numEqual( b.distance(), Math.sqrt( 3 ), "Check distance for simple line" ); - assert.numEqual( c.distance(), Math.sqrt( 12 ), "Check distance for negative to positive endpoints" ); - assert.numEqual( d.distance(), Math.sqrt( 12 ), "Check distance for negative to negative endpoints" ); + assert.numEqual( a.distance(), 0, 'Check distance for zero-length line' ); + assert.numEqual( b.distance(), Math.sqrt( 3 ), 'Check distance for simple line' ); + assert.numEqual( c.distance(), Math.sqrt( 12 ), 'Check distance for negative to positive endpoints' ); + assert.numEqual( d.distance(), Math.sqrt( 12 ), 'Check distance for negative to negative endpoints' ); } ); - QUnit.test( "at", ( assert ) => { + QUnit.test( 'at', ( assert ) => { var a = new Line3( one3.clone(), new Vector3( 1, 1, 2 ) ); var point = new Vector3(); a.at( - 1, point ); - assert.ok( point.distanceTo( new Vector3( 1, 1, 0 ) ) < 0.0001, "Passed!" ); + assert.ok( point.distanceTo( new Vector3( 1, 1, 0 ) ) < 0.0001, 'Passed!' ); a.at( 0, point ); - assert.ok( point.distanceTo( one3.clone() ) < 0.0001, "Passed!" ); + assert.ok( point.distanceTo( one3.clone() ) < 0.0001, 'Passed!' ); a.at( 1, point ); - assert.ok( point.distanceTo( new Vector3( 1, 1, 2 ) ) < 0.0001, "Passed!" ); + assert.ok( point.distanceTo( new Vector3( 1, 1, 2 ) ) < 0.0001, 'Passed!' ); a.at( 2, point ); - assert.ok( point.distanceTo( new Vector3( 1, 1, 3 ) ) < 0.0001, "Passed!" ); + assert.ok( point.distanceTo( new Vector3( 1, 1, 3 ) ) < 0.0001, 'Passed!' ); } ); - QUnit.test( "closestPointToPoint/closestPointToPointParameter", ( assert ) => { + QUnit.test( 'closestPointToPoint/closestPointToPointParameter', ( assert ) => { var a = new Line3( one3.clone(), new Vector3( 1, 1, 2 ) ); var point = new Vector3(); // nearby the ray - assert.ok( a.closestPointToPointParameter( zero3.clone(), true ) == 0, "Passed!" ); + assert.ok( a.closestPointToPointParameter( zero3.clone(), true ) == 0, 'Passed!' ); a.closestPointToPoint( zero3.clone(), true, point ); - assert.ok( point.distanceTo( new Vector3( 1, 1, 1 ) ) < 0.0001, "Passed!" ); + assert.ok( point.distanceTo( new Vector3( 1, 1, 1 ) ) < 0.0001, 'Passed!' ); // nearby the ray - assert.ok( a.closestPointToPointParameter( zero3.clone(), false ) == - 1, "Passed!" ); + assert.ok( a.closestPointToPointParameter( zero3.clone(), false ) == - 1, 'Passed!' ); a.closestPointToPoint( zero3.clone(), false, point ); - assert.ok( point.distanceTo( new Vector3( 1, 1, 0 ) ) < 0.0001, "Passed!" ); + assert.ok( point.distanceTo( new Vector3( 1, 1, 0 ) ) < 0.0001, 'Passed!' ); // nearby the ray - assert.ok( a.closestPointToPointParameter( new Vector3( 1, 1, 5 ), true ) == 1, "Passed!" ); + assert.ok( a.closestPointToPointParameter( new Vector3( 1, 1, 5 ), true ) == 1, 'Passed!' ); a.closestPointToPoint( new Vector3( 1, 1, 5 ), true, point ); - assert.ok( point.distanceTo( new Vector3( 1, 1, 2 ) ) < 0.0001, "Passed!" ); + assert.ok( point.distanceTo( new Vector3( 1, 1, 2 ) ) < 0.0001, 'Passed!' ); // exactly on the ray - assert.ok( a.closestPointToPointParameter( one3.clone(), true ) == 0, "Passed!" ); + assert.ok( a.closestPointToPointParameter( one3.clone(), true ) == 0, 'Passed!' ); a.closestPointToPoint( one3.clone(), true, point ); - assert.ok( point.distanceTo( one3.clone() ) < 0.0001, "Passed!" ); + assert.ok( point.distanceTo( one3.clone() ) < 0.0001, 'Passed!' ); } ); - QUnit.test( "applyMatrix4", ( assert ) => { + QUnit.test( 'applyMatrix4', ( assert ) => { var a = new Line3( zero3.clone(), two3.clone() ); var b = new Vector4( two3.x, two3.y, two3.z, 1 ); @@ -173,8 +173,8 @@ export default QUnit.module( 'Maths', () => { var v = new Vector3( x, y, z ); a.applyMatrix4( m ); - assert.ok( a.start.equals( v ), "Translation: check start" ); - assert.ok( a.end.equals( new Vector3( 2 + x, 2 + y, 2 + z ) ), "Translation: check start" ); + assert.ok( a.start.equals( v ), 'Translation: check start' ); + assert.ok( a.end.equals( new Vector3( 2 + x, 2 + y, 2 + z ) ), 'Translation: check start' ); // reset starting conditions a.set( zero3.clone(), two3.clone() ); @@ -183,10 +183,10 @@ export default QUnit.module( 'Maths', () => { a.applyMatrix4( m ); b.applyMatrix4( m ); - assert.ok( a.start.equals( zero3 ), "Rotation: check start" ); - assert.numEqual( a.end.x, b.x / b.w, "Rotation: check end.x" ); - assert.numEqual( a.end.y, b.y / b.w, "Rotation: check end.y" ); - assert.numEqual( a.end.z, b.z / b.w, "Rotation: check end.z" ); + assert.ok( a.start.equals( zero3 ), 'Rotation: check start' ); + assert.numEqual( a.end.x, b.x / b.w, 'Rotation: check end.x' ); + assert.numEqual( a.end.y, b.y / b.w, 'Rotation: check end.y' ); + assert.numEqual( a.end.z, b.z / b.w, 'Rotation: check end.z' ); // reset starting conditions a.set( zero3.clone(), two3.clone() ); @@ -196,18 +196,18 @@ export default QUnit.module( 'Maths', () => { a.applyMatrix4( m ); b.applyMatrix4( m ); - assert.ok( a.start.equals( v ), "Both: check start" ); - assert.numEqual( a.end.x, b.x / b.w, "Both: check end.x" ); - assert.numEqual( a.end.y, b.y / b.w, "Both: check end.y" ); - assert.numEqual( a.end.z, b.z / b.w, "Both: check end.z" ); + assert.ok( a.start.equals( v ), 'Both: check start' ); + assert.numEqual( a.end.x, b.x / b.w, 'Both: check end.x' ); + assert.numEqual( a.end.y, b.y / b.w, 'Both: check end.y' ); + assert.numEqual( a.end.z, b.z / b.w, 'Both: check end.z' ); } ); - QUnit.test( "equals", ( assert ) => { + QUnit.test( 'equals', ( assert ) => { var a = new Line3( zero3.clone(), zero3.clone() ); var b = new Line3(); - assert.ok( a.equals( b ), "Passed" ); + assert.ok( a.equals( b ), 'Passed' ); } ); diff --git a/test/unit/src/math/Matrix3.tests.js b/test/unit/src/math/Matrix3.tests.js index 8f3612ff9c9b13..78a266dd9bbca7 100644 --- a/test/unit/src/math/Matrix3.tests.js +++ b/test/unit/src/math/Matrix3.tests.js @@ -51,10 +51,10 @@ export default QUnit.module( 'Maths', () => { QUnit.module( 'Matrix3', () => { // INSTANCING - QUnit.test( "Instancing", ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { var a = new Matrix3(); - assert.ok( a.determinant() == 1, "Passed!" ); + assert.ok( a.determinant() == 1, 'Passed!' ); var b = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); assert.ok( b.elements[ 0 ] == 0 ); @@ -67,25 +67,25 @@ export default QUnit.module( 'Maths', () => { assert.ok( b.elements[ 7 ] == 5 ); assert.ok( b.elements[ 8 ] == 8 ); - assert.ok( ! matrixEquals3( a, b ), "Passed!" ); + assert.ok( ! matrixEquals3( a, b ), 'Passed!' ); } ); // PUBLIC STUFF - QUnit.test( "isMatrix3", ( assert ) => { + QUnit.test( 'isMatrix3', ( assert ) => { var a = new Matrix3(); - assert.ok( a.isMatrix3 === true, "Passed!" ); + assert.ok( a.isMatrix3 === true, 'Passed!' ); var b = new Matrix4(); - assert.ok( ! b.isMatrix3, "Passed!" ); + assert.ok( ! b.isMatrix3, 'Passed!' ); } ); - QUnit.test( "set", ( assert ) => { + QUnit.test( 'set', ( assert ) => { var b = new Matrix3(); - assert.ok( b.determinant() == 1, "Passed!" ); + assert.ok( b.determinant() == 1, 'Passed!' ); b.set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); assert.ok( b.elements[ 0 ] == 0 ); @@ -100,7 +100,7 @@ export default QUnit.module( 'Maths', () => { } ); - QUnit.test( "identity", ( assert ) => { + QUnit.test( 'identity', ( assert ) => { var b = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); assert.ok( b.elements[ 0 ] == 0 ); @@ -114,40 +114,40 @@ export default QUnit.module( 'Maths', () => { assert.ok( b.elements[ 8 ] == 8 ); var a = new Matrix3(); - assert.ok( ! matrixEquals3( a, b ), "Passed!" ); + assert.ok( ! matrixEquals3( a, b ), 'Passed!' ); b.identity(); - assert.ok( matrixEquals3( a, b ), "Passed!" ); + assert.ok( matrixEquals3( a, b ), 'Passed!' ); } ); - QUnit.test( "clone", ( assert ) => { + QUnit.test( 'clone', ( assert ) => { var a = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); var b = a.clone(); - assert.ok( matrixEquals3( a, b ), "Passed!" ); + assert.ok( matrixEquals3( a, b ), 'Passed!' ); // ensure that it is a true copy a.elements[ 0 ] = 2; - assert.ok( ! matrixEquals3( a, b ), "Passed!" ); + assert.ok( ! matrixEquals3( a, b ), 'Passed!' ); } ); - QUnit.test( "copy", ( assert ) => { + QUnit.test( 'copy', ( assert ) => { var a = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); var b = new Matrix3().copy( a ); - assert.ok( matrixEquals3( a, b ), "Passed!" ); + assert.ok( matrixEquals3( a, b ), 'Passed!' ); // ensure that it is a true copy a.elements[ 0 ] = 2; - assert.ok( ! matrixEquals3( a, b ), "Passed!" ); + assert.ok( ! matrixEquals3( a, b ), 'Passed!' ); } ); - QUnit.test( "setFromMatrix4", ( assert ) => { + QUnit.test( 'setFromMatrix4', ( assert ) => { var a = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); @@ -158,7 +158,7 @@ export default QUnit.module( 'Maths', () => { } ); - QUnit.test( "multiply/premultiply", ( assert ) => { + QUnit.test( 'multiply/premultiply', ( assert ) => { // both simply just wrap multiplyMatrices var a = new Matrix3().set( 2, 3, 5, 7, 11, 13, 17, 19, 23 ); @@ -167,15 +167,15 @@ export default QUnit.module( 'Maths', () => { var expectedPremultiply = [ 904, 1182, 1556, 1131, 1489, 1967, 1399, 1845, 2435 ]; a.multiply( b ); - assert.deepEqual( a.elements, expectedMultiply, "multiply: check result" ); + assert.deepEqual( a.elements, expectedMultiply, 'multiply: check result' ); a.set( 2, 3, 5, 7, 11, 13, 17, 19, 23 ); a.premultiply( b ); - assert.deepEqual( a.elements, expectedPremultiply, "premultiply: check result" ); + assert.deepEqual( a.elements, expectedPremultiply, 'premultiply: check result' ); } ); - QUnit.test( "multiplyMatrices", ( assert ) => { + QUnit.test( 'multiplyMatrices', ( assert ) => { // Reference: // @@ -210,7 +210,7 @@ export default QUnit.module( 'Maths', () => { } ); - QUnit.test( "multiplyScalar", ( assert ) => { + QUnit.test( 'multiplyScalar', ( assert ) => { var b = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); assert.ok( b.elements[ 0 ] == 0 ); @@ -236,24 +236,24 @@ export default QUnit.module( 'Maths', () => { } ); - QUnit.test( "determinant", ( assert ) => { + QUnit.test( 'determinant', ( assert ) => { var a = new Matrix3(); - assert.ok( a.determinant() == 1, "Passed!" ); + assert.ok( a.determinant() == 1, 'Passed!' ); a.elements[ 0 ] = 2; - assert.ok( a.determinant() == 2, "Passed!" ); + assert.ok( a.determinant() == 2, 'Passed!' ); a.elements[ 0 ] = 0; - assert.ok( a.determinant() == 0, "Passed!" ); + assert.ok( a.determinant() == 0, 'Passed!' ); // calculated via http://www.euclideanspace.com/maths/algebra/matrix/functions/determinant/threeD/index.htm a.set( 2, 3, 4, 5, 13, 7, 8, 9, 11 ); - assert.ok( a.determinant() == - 73, "Passed!" ); + assert.ok( a.determinant() == - 73, 'Passed!' ); } ); - QUnit.test( "invert", ( assert ) => { + QUnit.test( 'invert', ( assert ) => { var zero = new Matrix3().set( 0, 0, 0, 0, 0, 0, 0, 0, 0 ); var identity4 = new Matrix4(); @@ -261,7 +261,7 @@ export default QUnit.module( 'Maths', () => { var b = new Matrix3(); b.copy( a ).invert(); - assert.ok( matrixEquals3( b, zero ), "Matrix a is zero matrix" ); + assert.ok( matrixEquals3( b, zero ), 'Matrix a is zero matrix' ); var testMatrices = [ new Matrix4().makeRotationX( 0.3 ), @@ -284,32 +284,32 @@ export default QUnit.module( 'Maths', () => { var mInverse = toMatrix4( mInverse3 ); // the determinant of the inverse should be the reciprocal - assert.ok( Math.abs( a.determinant() * mInverse3.determinant() - 1 ) < 0.0001, "Passed!" ); - assert.ok( Math.abs( m.determinant() * mInverse.determinant() - 1 ) < 0.0001, "Passed!" ); + assert.ok( Math.abs( a.determinant() * mInverse3.determinant() - 1 ) < 0.0001, 'Passed!' ); + assert.ok( Math.abs( m.determinant() * mInverse.determinant() - 1 ) < 0.0001, 'Passed!' ); var mProduct = new Matrix4().multiplyMatrices( m, mInverse ); - assert.ok( Math.abs( mProduct.determinant() - 1 ) < 0.0001, "Passed!" ); - assert.ok( matrixEquals3( mProduct, identity4 ), "Passed!" ); + assert.ok( Math.abs( mProduct.determinant() - 1 ) < 0.0001, 'Passed!' ); + assert.ok( matrixEquals3( mProduct, identity4 ), 'Passed!' ); } } ); - QUnit.test( "transpose", ( assert ) => { + QUnit.test( 'transpose', ( assert ) => { var a = new Matrix3(); var b = a.clone().transpose(); - assert.ok( matrixEquals3( a, b ), "Passed!" ); + assert.ok( matrixEquals3( a, b ), 'Passed!' ); var b = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); var c = b.clone().transpose(); - assert.ok( ! matrixEquals3( b, c ), "Passed!" ); + assert.ok( ! matrixEquals3( b, c ), 'Passed!' ); c.transpose(); - assert.ok( matrixEquals3( b, c ), "Passed!" ); + assert.ok( matrixEquals3( b, c ), 'Passed!' ); } ); - QUnit.test( "getNormalMatrix", ( assert ) => { + QUnit.test( 'getNormalMatrix', ( assert ) => { var a = new Matrix3(); var b = new Matrix4().set( @@ -325,11 +325,11 @@ export default QUnit.module( 'Maths', () => { ); a.getNormalMatrix( b ); - assert.ok( matrixEquals3( a, expected ), "Check resulting Matrix3" ); + assert.ok( matrixEquals3( a, expected ), 'Check resulting Matrix3' ); } ); - QUnit.test( "transposeIntoArray", ( assert ) => { + QUnit.test( 'transposeIntoArray', ( assert ) => { var a = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); var b = []; @@ -348,7 +348,7 @@ export default QUnit.module( 'Maths', () => { } ); - QUnit.test( "setUvTransform", ( assert ) => { + QUnit.test( 'setUvTransform', ( assert ) => { var a = new Matrix3().set( 0.1767766952966369, 0.17677669529663687, 0.32322330470336313, @@ -385,12 +385,12 @@ export default QUnit.module( 'Maths', () => { .translate( params.centerX, params.centerY ) .translate( params.offsetX, params.offsetY ); - assert.ok( matrixEquals3( a, expected ), "Check direct method" ); - assert.ok( matrixEquals3( b, expected ), "Check indirect method" ); + assert.ok( matrixEquals3( a, expected ), 'Check direct method' ); + assert.ok( matrixEquals3( b, expected ), 'Check indirect method' ); } ); - QUnit.test( "scale", ( assert ) => { + QUnit.test( 'scale', ( assert ) => { var a = new Matrix3().set( 1, 2, 3, 4, 5, 6, 7, 8, 9 ); var expected = new Matrix3().set( @@ -400,11 +400,11 @@ export default QUnit.module( 'Maths', () => { ); a.scale( 0.25, 0.25 ); - assert.ok( matrixEquals3( a, expected ), "Check scaling result" ); + assert.ok( matrixEquals3( a, expected ), 'Check scaling result' ); } ); - QUnit.test( "rotate", ( assert ) => { + QUnit.test( 'rotate', ( assert ) => { var a = new Matrix3().set( 1, 2, 3, 4, 5, 6, 7, 8, 9 ); var expected = new Matrix3().set( @@ -414,35 +414,35 @@ export default QUnit.module( 'Maths', () => { ); a.rotate( Math.PI / 4 ); - assert.ok( matrixEquals3( a, expected ), "Check rotated result" ); + assert.ok( matrixEquals3( a, expected ), 'Check rotated result' ); } ); - QUnit.test( "translate", ( assert ) => { + QUnit.test( 'translate', ( assert ) => { var a = new Matrix3().set( 1, 2, 3, 4, 5, 6, 7, 8, 9 ); var expected = new Matrix3().set( 22, 26, 30, 53, 61, 69, 7, 8, 9 ); a.translate( 3, 7 ); - assert.ok( matrixEquals3( a, expected ), "Check translation result" ); + assert.ok( matrixEquals3( a, expected ), 'Check translation result' ); } ); - QUnit.test( "equals", ( assert ) => { + QUnit.test( 'equals', ( assert ) => { var a = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); var b = new Matrix3().set( 0, - 1, 2, 3, 4, 5, 6, 7, 8 ); - assert.notOk( a.equals( b ), "Check that a does not equal b" ); - assert.notOk( b.equals( a ), "Check that b does not equal a" ); + assert.notOk( a.equals( b ), 'Check that a does not equal b' ); + assert.notOk( b.equals( a ), 'Check that b does not equal a' ); a.copy( b ); - assert.ok( a.equals( b ), "Check that a equals b after copy()" ); - assert.ok( b.equals( a ), "Check that b equals a after copy()" ); + assert.ok( a.equals( b ), 'Check that a equals b after copy()' ); + assert.ok( b.equals( a ), 'Check that b equals a after copy()' ); } ); - QUnit.test( "fromArray", ( assert ) => { + QUnit.test( 'fromArray', ( assert ) => { var b = new Matrix3(); b.fromArray( [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ] ); @@ -472,22 +472,22 @@ export default QUnit.module( 'Maths', () => { } ); - QUnit.test( "toArray", ( assert ) => { + QUnit.test( 'toArray', ( assert ) => { var a = new Matrix3().set( 1, 2, 3, 4, 5, 6, 7, 8, 9 ); var noOffset = [ 1, 4, 7, 2, 5, 8, 3, 6, 9 ]; var withOffset = [ undefined, 1, 4, 7, 2, 5, 8, 3, 6, 9 ]; var array = a.toArray(); - assert.deepEqual( array, noOffset, "No array, no offset" ); + assert.deepEqual( array, noOffset, 'No array, no offset' ); var array = []; a.toArray( array ); - assert.deepEqual( array, noOffset, "With array, no offset" ); + assert.deepEqual( array, noOffset, 'With array, no offset' ); var array = []; a.toArray( array, 1 ); - assert.deepEqual( array, withOffset, "With array, with offset" ); + assert.deepEqual( array, withOffset, 'With array, with offset' ); } ); diff --git a/test/unit/src/math/Matrix4.tests.js b/test/unit/src/math/Matrix4.tests.js index bda9c41bc90795..1d4e2b61df583b 100644 --- a/test/unit/src/math/Matrix4.tests.js +++ b/test/unit/src/math/Matrix4.tests.js @@ -47,10 +47,10 @@ export default QUnit.module( 'Maths', () => { QUnit.module( 'Matrix4', () => { // INSTANCING - QUnit.test( "Instancing", ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { var a = new Matrix4(); - assert.ok( a.determinant() == 1, "Passed!" ); + assert.ok( a.determinant() == 1, 'Passed!' ); var b = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); assert.ok( b.elements[ 0 ] == 0 ); @@ -70,25 +70,25 @@ export default QUnit.module( 'Maths', () => { assert.ok( b.elements[ 14 ] == 11 ); assert.ok( b.elements[ 15 ] == 15 ); - assert.ok( ! matrixEquals4( a, b ), "Passed!" ); + assert.ok( ! matrixEquals4( a, b ), 'Passed!' ); } ); // PUBLIC STUFF - QUnit.test( "isMatrix4", ( assert ) => { + QUnit.test( 'isMatrix4', ( assert ) => { var a = new Matrix4(); - assert.ok( a.isMatrix4 === true, "Passed!" ); + assert.ok( a.isMatrix4 === true, 'Passed!' ); var b = new Vector3(); - assert.ok( ! b.isMatrix4, "Passed!" ); + assert.ok( ! b.isMatrix4, 'Passed!' ); } ); - QUnit.test( "set", ( assert ) => { + QUnit.test( 'set', ( assert ) => { var b = new Matrix4(); - assert.ok( b.determinant() == 1, "Passed!" ); + assert.ok( b.determinant() == 1, 'Passed!' ); b.set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); assert.ok( b.elements[ 0 ] == 0 ); @@ -110,7 +110,7 @@ export default QUnit.module( 'Maths', () => { } ); - QUnit.test( "identity", ( assert ) => { + QUnit.test( 'identity', ( assert ) => { var b = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); assert.ok( b.elements[ 0 ] == 0 ); @@ -131,40 +131,40 @@ export default QUnit.module( 'Maths', () => { assert.ok( b.elements[ 15 ] == 15 ); var a = new Matrix4(); - assert.ok( ! matrixEquals4( a, b ), "Passed!" ); + assert.ok( ! matrixEquals4( a, b ), 'Passed!' ); b.identity(); - assert.ok( matrixEquals4( a, b ), "Passed!" ); + assert.ok( matrixEquals4( a, b ), 'Passed!' ); } ); - QUnit.test( "clone", ( assert ) => { + QUnit.test( 'clone', ( assert ) => { var a = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); var b = a.clone(); - assert.ok( matrixEquals4( a, b ), "Passed!" ); + assert.ok( matrixEquals4( a, b ), 'Passed!' ); // ensure that it is a true copy a.elements[ 0 ] = 2; - assert.ok( ! matrixEquals4( a, b ), "Passed!" ); + assert.ok( ! matrixEquals4( a, b ), 'Passed!' ); } ); - QUnit.test( "copy", ( assert ) => { + QUnit.test( 'copy', ( assert ) => { var a = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); var b = new Matrix4().copy( a ); - assert.ok( matrixEquals4( a, b ), "Passed!" ); + assert.ok( matrixEquals4( a, b ), 'Passed!' ); // ensure that it is a true copy a.elements[ 0 ] = 2; - assert.ok( ! matrixEquals4( a, b ), "Passed!" ); + assert.ok( ! matrixEquals4( a, b ), 'Passed!' ); } ); - QUnit.test( "setFromMatrix4", ( assert ) => { + QUnit.test( 'setFromMatrix4', ( assert ) => { var a = new Matrix3().set( 0, 1, 2, @@ -183,24 +183,24 @@ export default QUnit.module( 'Maths', () => { } ); - QUnit.test( "copyPosition", ( assert ) => { + QUnit.test( 'copyPosition', ( assert ) => { var a = new Matrix4().set( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ); var b = new Matrix4().set( 1, 2, 3, 0, 5, 6, 7, 0, 9, 10, 11, 0, 13, 14, 15, 16 ); - assert.notOk( matrixEquals4( a, b ), "a and b initially not equal" ); + assert.notOk( matrixEquals4( a, b ), 'a and b initially not equal' ); b.copyPosition( a ); - assert.ok( matrixEquals4( a, b ), "a and b equal after copyPosition()" ); + assert.ok( matrixEquals4( a, b ), 'a and b equal after copyPosition()' ); } ); - QUnit.test( "makeBasis/extractBasis", ( assert ) => { + QUnit.test( 'makeBasis/extractBasis', ( assert ) => { var identityBasis = [ new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ) ]; var a = new Matrix4().makeBasis( identityBasis[ 0 ], identityBasis[ 1 ], identityBasis[ 2 ] ); var identity = new Matrix4(); - assert.ok( matrixEquals4( a, identity ), "Passed!" ); + assert.ok( matrixEquals4( a, identity ), 'Passed!' ); var testBases = [[ new Vector3( 0, 1, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ) ]]; for ( var i = 0; i < testBases.length; i ++ ) { @@ -212,7 +212,7 @@ export default QUnit.module( 'Maths', () => { // check what goes in, is what comes out. for ( var j = 0; j < outBasis.length; j ++ ) { - assert.ok( outBasis[ j ].equals( testBasis[ j ] ), "Passed!" ); + assert.ok( outBasis[ j ].equals( testBasis[ j ] ), 'Passed!' ); } @@ -223,10 +223,11 @@ export default QUnit.module( 'Maths', () => { outBasis[ j ].applyMatrix4( b ); } + // did the multiply method of basis extraction work? for ( var j = 0; j < outBasis.length; j ++ ) { - assert.ok( outBasis[ j ].equals( testBasis[ j ] ), "Passed!" ); + assert.ok( outBasis[ j ].equals( testBasis[ j ] ), 'Passed!' ); } @@ -234,14 +235,14 @@ export default QUnit.module( 'Maths', () => { } ); - QUnit.test( "makeRotationFromEuler/extractRotation", ( assert ) => { + QUnit.test( 'makeRotationFromEuler/extractRotation', ( assert ) => { var testValues = [ - new Euler( 0, 0, 0, "XYZ" ), - new Euler( 1, 0, 0, "XYZ" ), - new Euler( 0, 1, 0, "ZYX" ), - new Euler( 0, 0, 0.5, "YZX" ), - new Euler( 0, 0, - 0.5, "YZX" ) + new Euler( 0, 0, 0, 'XYZ' ), + new Euler( 1, 0, 0, 'XYZ' ), + new Euler( 0, 1, 0, 'ZYX' ), + new Euler( 0, 0, 0.5, 'YZX' ), + new Euler( 0, 0, - 0.5, 'YZX' ) ]; for ( var i = 0; i < testValues.length; i ++ ) { @@ -253,20 +254,20 @@ export default QUnit.module( 'Maths', () => { var v2 = new Euler().setFromRotationMatrix( m, v.order ); var m2 = new Matrix4().makeRotationFromEuler( v2 ); - assert.ok( matrixEquals4( m, m2, eps ), "makeRotationFromEuler #" + i + ": original and Euler-derived matrices are equal" ); - assert.ok( eulerEquals( v, v2, eps ), "makeRotationFromEuler #" + i + ": original and matrix-derived Eulers are equal" ); + assert.ok( matrixEquals4( m, m2, eps ), 'makeRotationFromEuler #' + i + ': original and Euler-derived matrices are equal' ); + assert.ok( eulerEquals( v, v2, eps ), 'makeRotationFromEuler #' + i + ': original and matrix-derived Eulers are equal' ); var m3 = new Matrix4().extractRotation( m2 ); var v3 = new Euler().setFromRotationMatrix( m3, v.order ); - assert.ok( matrixEquals4( m, m3, eps ), "extractRotation #" + i + ": original and extracted matrices are equal" ); - assert.ok( eulerEquals( v, v3, eps ), "extractRotation #" + i + ": original and extracted Eulers are equal" ); + assert.ok( matrixEquals4( m, m3, eps ), 'extractRotation #' + i + ': original and extracted matrices are equal' ); + assert.ok( eulerEquals( v, v3, eps ), 'extractRotation #' + i + ': original and extracted Eulers are equal' ); } } ); - QUnit.test( "lookAt", ( assert ) => { + QUnit.test( 'lookAt', ( assert ) => { var a = new Matrix4(); var expected = new Matrix4().identity(); @@ -276,12 +277,12 @@ export default QUnit.module( 'Maths', () => { a.lookAt( eye, target, up ); var rotation = new Euler().setFromRotationMatrix( a ); - assert.numEqual( rotation.x * ( 180 / Math.PI ), 45, "Check the rotation" ); + assert.numEqual( rotation.x * ( 180 / Math.PI ), 45, 'Check the rotation' ); // eye and target are in the same position eye.copy( target ); a.lookAt( eye, target, up ); - assert.ok( matrixEquals4( a, expected ), "Check the result for eye == target" ); + assert.ok( matrixEquals4( a, expected ), 'Check the result for eye == target' ); // up and z are parallel eye.set( 0, 1, 0 ); @@ -293,11 +294,11 @@ export default QUnit.module( 'Maths', () => { 0, - 1, 0.0001, 0, 0, 0, 0, 1 ); - assert.ok( matrixEquals4( a, expected ), "Check the result for when up and z are parallel" ); + assert.ok( matrixEquals4( a, expected ), 'Check the result for when up and z are parallel' ); } ); - QUnit.test( "multiply", ( assert ) => { + QUnit.test( 'multiply', ( assert ) => { var lhs = new Matrix4().set( 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53 ); var rhs = new Matrix4().set( 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131 ); @@ -323,7 +324,7 @@ export default QUnit.module( 'Maths', () => { } ); - QUnit.test( "premultiply", ( assert ) => { + QUnit.test( 'premultiply', ( assert ) => { var lhs = new Matrix4().set( 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53 ); var rhs = new Matrix4().set( 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131 ); @@ -350,7 +351,7 @@ export default QUnit.module( 'Maths', () => { } ); - QUnit.test( "multiplyMatrices", ( assert ) => { + QUnit.test( 'multiplyMatrices', ( assert ) => { // Reference: // @@ -393,7 +394,7 @@ export default QUnit.module( 'Maths', () => { } ); - QUnit.test( "multiplyScalar", ( assert ) => { + QUnit.test( 'multiplyScalar', ( assert ) => { var b = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); assert.ok( b.elements[ 0 ] == 0 ); @@ -433,49 +434,49 @@ export default QUnit.module( 'Maths', () => { } ); - QUnit.test( "determinant", ( assert ) => { + QUnit.test( 'determinant', ( assert ) => { var a = new Matrix4(); - assert.ok( a.determinant() == 1, "Passed!" ); + assert.ok( a.determinant() == 1, 'Passed!' ); a.elements[ 0 ] = 2; - assert.ok( a.determinant() == 2, "Passed!" ); + assert.ok( a.determinant() == 2, 'Passed!' ); a.elements[ 0 ] = 0; - assert.ok( a.determinant() == 0, "Passed!" ); + assert.ok( a.determinant() == 0, 'Passed!' ); // calculated via http://www.euclideanspace.com/maths/algebra/matrix/functions/determinant/fourD/index.htm a.set( 2, 3, 4, 5, - 1, - 21, - 3, - 4, 6, 7, 8, 10, - 8, - 9, - 10, - 12 ); - assert.ok( a.determinant() == 76, "Passed!" ); + assert.ok( a.determinant() == 76, 'Passed!' ); } ); - QUnit.test( "transpose", ( assert ) => { + QUnit.test( 'transpose', ( assert ) => { var a = new Matrix4(); var b = a.clone().transpose(); - assert.ok( matrixEquals4( a, b ), "Passed!" ); + assert.ok( matrixEquals4( a, b ), 'Passed!' ); var b = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); var c = b.clone().transpose(); - assert.ok( ! matrixEquals4( b, c ), "Passed!" ); + assert.ok( ! matrixEquals4( b, c ), 'Passed!' ); c.transpose(); - assert.ok( matrixEquals4( b, c ), "Passed!" ); + assert.ok( matrixEquals4( b, c ), 'Passed!' ); } ); - QUnit.test( "setPosition", ( assert ) => { + QUnit.test( 'setPosition', ( assert ) => { var a = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); var b = new Vector3( - 1, - 2, - 3 ); var c = new Matrix4().set( 0, 1, 2, - 1, 4, 5, 6, - 2, 8, 9, 10, - 3, 12, 13, 14, 15 ); a.setPosition( b ); - assert.ok( matrixEquals4( a, c ), "Passed!" ); + assert.ok( matrixEquals4( a, c ), 'Passed!' ); } ); - QUnit.test( "invert", ( assert ) => { + QUnit.test( 'invert', ( assert ) => { var zero = new Matrix4().set( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); var identity = new Matrix4(); @@ -484,7 +485,7 @@ export default QUnit.module( 'Maths', () => { var b = new Matrix4().set( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); a.copy( b ).invert(); - assert.ok( matrixEquals4( a, zero ), "Passed!" ); + assert.ok( matrixEquals4( a, zero ), 'Passed!' ); var testMatrices = [ @@ -510,64 +511,64 @@ export default QUnit.module( 'Maths', () => { mSelfInverse.copy( mSelfInverse ).invert(); // self-inverse should the same as inverse - assert.ok( matrixEquals4( mSelfInverse, mInverse ), "Passed!" ); + assert.ok( matrixEquals4( mSelfInverse, mInverse ), 'Passed!' ); // the determinant of the inverse should be the reciprocal - assert.ok( Math.abs( m.determinant() * mInverse.determinant() - 1 ) < 0.0001, "Passed!" ); + assert.ok( Math.abs( m.determinant() * mInverse.determinant() - 1 ) < 0.0001, 'Passed!' ); var mProduct = new Matrix4().multiplyMatrices( m, mInverse ); // the determinant of the identity matrix is 1 - assert.ok( Math.abs( mProduct.determinant() - 1 ) < 0.0001, "Passed!" ); - assert.ok( matrixEquals4( mProduct, identity ), "Passed!" ); + assert.ok( Math.abs( mProduct.determinant() - 1 ) < 0.0001, 'Passed!' ); + assert.ok( matrixEquals4( mProduct, identity ), 'Passed!' ); } } ); - QUnit.test( "scale", ( assert ) => { + QUnit.test( 'scale', ( assert ) => { var a = new Matrix4().set( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ); var b = new Vector3( 2, 3, 4 ); var c = new Matrix4().set( 2, 6, 12, 4, 10, 18, 28, 8, 18, 30, 44, 12, 26, 42, 60, 16 ); a.scale( b ); - assert.ok( matrixEquals4( a, c ), "Passed!" ); + assert.ok( matrixEquals4( a, c ), 'Passed!' ); } ); - QUnit.test( "getMaxScaleOnAxis", ( assert ) => { + QUnit.test( 'getMaxScaleOnAxis', ( assert ) => { var a = new Matrix4().set( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ); var expected = Math.sqrt( 3 * 3 + 7 * 7 + 11 * 11 ); - assert.ok( Math.abs( a.getMaxScaleOnAxis() - expected ) <= eps, "Check result" ); + assert.ok( Math.abs( a.getMaxScaleOnAxis() - expected ) <= eps, 'Check result' ); } ); - QUnit.test( "makeTranslation", ( assert ) => { + QUnit.test( 'makeTranslation', ( assert ) => { var a = new Matrix4(); var b = new Vector3( 2, 3, 4 ); var c = new Matrix4().set( 1, 0, 0, 2, 0, 1, 0, 3, 0, 0, 1, 4, 0, 0, 0, 1 ); a.makeTranslation( b.x, b.y, b.z ); - assert.ok( matrixEquals4( a, c ), "Passed!" ); + assert.ok( matrixEquals4( a, c ), 'Passed!' ); } ); - QUnit.test( "makeRotationX", ( assert ) => { + QUnit.test( 'makeRotationX', ( assert ) => { var a = new Matrix4(); var b = Math.sqrt( 3 ) / 2; var c = new Matrix4().set( 1, 0, 0, 0, 0, b, - 0.5, 0, 0, 0.5, b, 0, 0, 0, 0, 1 ); a.makeRotationX( Math.PI / 6 ); - assert.ok( matrixEquals4( a, c ), "Passed!" ); + assert.ok( matrixEquals4( a, c ), 'Passed!' ); } ); - QUnit.test( "makeRotationY", ( assert ) => { + QUnit.test( 'makeRotationY', ( assert ) => { var a = new Matrix4(); @@ -575,11 +576,11 @@ export default QUnit.module( 'Maths', () => { var c = new Matrix4().set( b, 0, 0.5, 0, 0, 1, 0, 0, - 0.5, 0, b, 0, 0, 0, 0, 1 ); a.makeRotationY( Math.PI / 6 ); - assert.ok( matrixEquals4( a, c ), "Passed!" ); + assert.ok( matrixEquals4( a, c ), 'Passed!' ); } ); - QUnit.test( "makeRotationZ", ( assert ) => { + QUnit.test( 'makeRotationZ', ( assert ) => { var a = new Matrix4(); @@ -587,11 +588,11 @@ export default QUnit.module( 'Maths', () => { var c = new Matrix4().set( b, - 0.5, 0, 0, 0.5, b, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ); a.makeRotationZ( Math.PI / 6 ); - assert.ok( matrixEquals4( a, c ), "Passed!" ); + assert.ok( matrixEquals4( a, c ), 'Passed!' ); } ); - QUnit.test( "makeRotationAxis", ( assert ) => { + QUnit.test( 'makeRotationAxis', ( assert ) => { var axis = new Vector3( 1.5, 0.0, 1.0 ).normalize(); var radians = MathUtils.degToRad( 45 ); @@ -604,31 +605,31 @@ export default QUnit.module( 'Maths', () => { 0, 0, 0, 1 ); - assert.ok( matrixEquals4( a, expected ), "Check numeric result" ); + assert.ok( matrixEquals4( a, expected ), 'Check numeric result' ); } ); - QUnit.test( "makeScale", ( assert ) => { + QUnit.test( 'makeScale', ( assert ) => { var a = new Matrix4(); var c = new Matrix4().set( 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 4, 0, 0, 0, 0, 1 ); a.makeScale( 2, 3, 4 ); - assert.ok( matrixEquals4( a, c ), "Passed!" ); + assert.ok( matrixEquals4( a, c ), 'Passed!' ); } ); - QUnit.test( "makeShear", ( assert ) => { + QUnit.test( 'makeShear', ( assert ) => { var a = new Matrix4(); var c = new Matrix4().set( 1, 3, 5, 0, 1, 1, 6, 0, 2, 4, 1, 0, 0, 0, 0, 1 ); a.makeShear( 1, 2, 3, 4, 5, 6 ); - assert.ok( matrixEquals4( a, c ), "Passed!" ); + assert.ok( matrixEquals4( a, c ), 'Passed!' ); } ); - QUnit.test( "compose/decompose", ( assert ) => { + QUnit.test( 'compose/decompose', ( assert ) => { var tValues = [ new Vector3(), @@ -692,7 +693,7 @@ export default QUnit.module( 'Maths', () => { } */ - assert.ok( matrixEquals4( m, m2 ), "Passed!" ); + assert.ok( matrixEquals4( m, m2 ), 'Passed!' ); } @@ -702,7 +703,7 @@ export default QUnit.module( 'Maths', () => { } ); - QUnit.test( "makePerspective", ( assert ) => { + QUnit.test( 'makePerspective', ( assert ) => { var a = new Matrix4().makePerspective( - 1, 1, - 1, 1, 1, 100 ); var expected = new Matrix4().set( @@ -711,11 +712,11 @@ export default QUnit.module( 'Maths', () => { 0, 0, - 101 / 99, - 200 / 99, 0, 0, - 1, 0 ); - assert.ok( matrixEquals4( a, expected ), "Check result" ); + assert.ok( matrixEquals4( a, expected ), 'Check result' ); } ); - QUnit.test( "makeOrthographic", ( assert ) => { + QUnit.test( 'makeOrthographic', ( assert ) => { var a = new Matrix4().makeOrthographic( - 1, 1, - 1, 1, 1, 100 ); var expected = new Matrix4().set( @@ -725,50 +726,50 @@ export default QUnit.module( 'Maths', () => { 0, 0, 0, 1 ); - assert.ok( matrixEquals4( a, expected ), "Check result" ); + assert.ok( matrixEquals4( a, expected ), 'Check result' ); } ); - QUnit.test( "equals", ( assert ) => { + QUnit.test( 'equals', ( assert ) => { var a = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ); var b = new Matrix4().set( 0, - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ); - assert.notOk( a.equals( b ), "Check that a does not equal b" ); - assert.notOk( b.equals( a ), "Check that b does not equal a" ); + assert.notOk( a.equals( b ), 'Check that a does not equal b' ); + assert.notOk( b.equals( a ), 'Check that b does not equal a' ); a.copy( b ); - assert.ok( a.equals( b ), "Check that a equals b after copy()" ); - assert.ok( b.equals( a ), "Check that b equals a after copy()" ); + assert.ok( a.equals( b ), 'Check that a equals b after copy()' ); + assert.ok( b.equals( a ), 'Check that b equals a after copy()' ); } ); - QUnit.test( "fromArray", ( assert ) => { + QUnit.test( 'fromArray', ( assert ) => { var a = new Matrix4(); var b = new Matrix4().set( 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16 ); a.fromArray( [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ] ); - assert.ok( a.equals( b ), "Passed" ); + assert.ok( a.equals( b ), 'Passed' ); } ); - QUnit.test( "toArray", ( assert ) => { + QUnit.test( 'toArray', ( assert ) => { var a = new Matrix4().set( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ); var noOffset = [ 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16 ]; var withOffset = [ undefined, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16 ]; var array = a.toArray(); - assert.deepEqual( array, noOffset, "No array, no offset" ); + assert.deepEqual( array, noOffset, 'No array, no offset' ); var array = []; a.toArray( array ); - assert.deepEqual( array, noOffset, "With array, no offset" ); + assert.deepEqual( array, noOffset, 'With array, no offset' ); var array = []; a.toArray( array, 1 ); - assert.deepEqual( array, withOffset, "With array, with offset" ); + assert.deepEqual( array, withOffset, 'With array, with offset' ); } ); diff --git a/test/unit/src/math/Plane.tests.js b/test/unit/src/math/Plane.tests.js index b63ad711d6e89b..4cdda9449bd357 100644 --- a/test/unit/src/math/Plane.tests.js +++ b/test/unit/src/math/Plane.tests.js @@ -28,83 +28,83 @@ export default QUnit.module( 'Maths', () => { QUnit.module( 'Plane', () => { // INSTANCING - QUnit.test( "Instancing", ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { var a = new Plane(); - assert.ok( a.normal.x == 1, "Passed!" ); - assert.ok( a.normal.y == 0, "Passed!" ); - assert.ok( a.normal.z == 0, "Passed!" ); - assert.ok( a.constant == 0, "Passed!" ); + assert.ok( a.normal.x == 1, 'Passed!' ); + assert.ok( a.normal.y == 0, 'Passed!' ); + assert.ok( a.normal.z == 0, 'Passed!' ); + assert.ok( a.constant == 0, 'Passed!' ); var a = new Plane( one3.clone(), 0 ); - assert.ok( a.normal.x == 1, "Passed!" ); - assert.ok( a.normal.y == 1, "Passed!" ); - assert.ok( a.normal.z == 1, "Passed!" ); - assert.ok( a.constant == 0, "Passed!" ); + assert.ok( a.normal.x == 1, 'Passed!' ); + assert.ok( a.normal.y == 1, 'Passed!' ); + assert.ok( a.normal.z == 1, 'Passed!' ); + assert.ok( a.constant == 0, 'Passed!' ); var a = new Plane( one3.clone(), 1 ); - assert.ok( a.normal.x == 1, "Passed!" ); - assert.ok( a.normal.y == 1, "Passed!" ); - assert.ok( a.normal.z == 1, "Passed!" ); - assert.ok( a.constant == 1, "Passed!" ); + assert.ok( a.normal.x == 1, 'Passed!' ); + assert.ok( a.normal.y == 1, 'Passed!' ); + assert.ok( a.normal.z == 1, 'Passed!' ); + assert.ok( a.constant == 1, 'Passed!' ); } ); // PUBLIC STUFF - QUnit.test( "isPlane", ( assert ) => { + QUnit.test( 'isPlane', ( assert ) => { var a = new Plane(); - assert.ok( a.isPlane === true, "Passed!" ); + assert.ok( a.isPlane === true, 'Passed!' ); var b = new Vector3(); - assert.ok( ! b.isPlane, "Passed!" ); + assert.ok( ! b.isPlane, 'Passed!' ); } ); - QUnit.test( "set", ( assert ) => { + QUnit.test( 'set', ( assert ) => { var a = new Plane(); - assert.ok( a.normal.x == 1, "Passed!" ); - assert.ok( a.normal.y == 0, "Passed!" ); - assert.ok( a.normal.z == 0, "Passed!" ); - assert.ok( a.constant == 0, "Passed!" ); + assert.ok( a.normal.x == 1, 'Passed!' ); + assert.ok( a.normal.y == 0, 'Passed!' ); + assert.ok( a.normal.z == 0, 'Passed!' ); + assert.ok( a.constant == 0, 'Passed!' ); var b = a.clone().set( new Vector3( x, y, z ), w ); - assert.ok( b.normal.x == x, "Passed!" ); - assert.ok( b.normal.y == y, "Passed!" ); - assert.ok( b.normal.z == z, "Passed!" ); - assert.ok( b.constant == w, "Passed!" ); + assert.ok( b.normal.x == x, 'Passed!' ); + assert.ok( b.normal.y == y, 'Passed!' ); + assert.ok( b.normal.z == z, 'Passed!' ); + assert.ok( b.constant == w, 'Passed!' ); } ); - QUnit.test( "setComponents", ( assert ) => { + QUnit.test( 'setComponents', ( assert ) => { var a = new Plane(); - assert.ok( a.normal.x == 1, "Passed!" ); - assert.ok( a.normal.y == 0, "Passed!" ); - assert.ok( a.normal.z == 0, "Passed!" ); - assert.ok( a.constant == 0, "Passed!" ); + assert.ok( a.normal.x == 1, 'Passed!' ); + assert.ok( a.normal.y == 0, 'Passed!' ); + assert.ok( a.normal.z == 0, 'Passed!' ); + assert.ok( a.constant == 0, 'Passed!' ); var b = a.clone().setComponents( x, y, z, w ); - assert.ok( b.normal.x == x, "Passed!" ); - assert.ok( b.normal.y == y, "Passed!" ); - assert.ok( b.normal.z == z, "Passed!" ); - assert.ok( b.constant == w, "Passed!" ); + assert.ok( b.normal.x == x, 'Passed!' ); + assert.ok( b.normal.y == y, 'Passed!' ); + assert.ok( b.normal.z == z, 'Passed!' ); + assert.ok( b.constant == w, 'Passed!' ); } ); - QUnit.test( "setFromNormalAndCoplanarPoint", ( assert ) => { + QUnit.test( 'setFromNormalAndCoplanarPoint', ( assert ) => { var normal = one3.clone().normalize(); var a = new Plane().setFromNormalAndCoplanarPoint( normal, zero3 ); - assert.ok( a.normal.equals( normal ), "Passed!" ); - assert.ok( a.constant == 0, "Passed!" ); + assert.ok( a.normal.equals( normal ), 'Passed!' ); + assert.ok( a.constant == 0, 'Passed!' ); } ); - QUnit.test( "setFromCoplanarPoints", ( assert ) => { + QUnit.test( 'setFromCoplanarPoints', ( assert ) => { var a = new Plane(); var v1 = new Vector3( 2.0, 0.5, 0.25 ); @@ -115,127 +115,127 @@ export default QUnit.module( 'Maths', () => { a.setFromCoplanarPoints( v1, v2, v3 ); - assert.ok( a.normal.equals( normal ), "Check normal" ); - assert.strictEqual( a.constant, constant, "Check constant" ); + assert.ok( a.normal.equals( normal ), 'Check normal' ); + assert.strictEqual( a.constant, constant, 'Check constant' ); } ); - QUnit.test( "clone", ( assert ) => { + QUnit.test( 'clone', ( assert ) => { var a = new Plane( new Vector3( 2.0, 0.5, 0.25 ) ); var b = a.clone(); - assert.ok( a.equals( b ), "clones are equal" ); + assert.ok( a.equals( b ), 'clones are equal' ); } ); - QUnit.test( "copy", ( assert ) => { + QUnit.test( 'copy', ( assert ) => { var a = new Plane( new Vector3( x, y, z ), w ); var b = new Plane().copy( a ); - assert.ok( b.normal.x == x, "Passed!" ); - assert.ok( b.normal.y == y, "Passed!" ); - assert.ok( b.normal.z == z, "Passed!" ); - assert.ok( b.constant == w, "Passed!" ); + assert.ok( b.normal.x == x, 'Passed!' ); + assert.ok( b.normal.y == y, 'Passed!' ); + assert.ok( b.normal.z == z, 'Passed!' ); + assert.ok( b.constant == w, 'Passed!' ); // ensure that it is a true copy a.normal.x = 0; a.normal.y = - 1; a.normal.z = - 2; a.constant = - 3; - assert.ok( b.normal.x == x, "Passed!" ); - assert.ok( b.normal.y == y, "Passed!" ); - assert.ok( b.normal.z == z, "Passed!" ); - assert.ok( b.constant == w, "Passed!" ); + assert.ok( b.normal.x == x, 'Passed!' ); + assert.ok( b.normal.y == y, 'Passed!' ); + assert.ok( b.normal.z == z, 'Passed!' ); + assert.ok( b.constant == w, 'Passed!' ); } ); - QUnit.test( "normalize", ( assert ) => { + QUnit.test( 'normalize', ( assert ) => { var a = new Plane( new Vector3( 2, 0, 0 ), 2 ); a.normalize(); - assert.ok( a.normal.length() == 1, "Passed!" ); - assert.ok( a.normal.equals( new Vector3( 1, 0, 0 ) ), "Passed!" ); - assert.ok( a.constant == 1, "Passed!" ); + assert.ok( a.normal.length() == 1, 'Passed!' ); + assert.ok( a.normal.equals( new Vector3( 1, 0, 0 ) ), 'Passed!' ); + assert.ok( a.constant == 1, 'Passed!' ); } ); - QUnit.test( "negate/distanceToPoint", ( assert ) => { + QUnit.test( 'negate/distanceToPoint', ( assert ) => { var a = new Plane( new Vector3( 2, 0, 0 ), - 2 ); a.normalize(); - assert.ok( a.distanceToPoint( new Vector3( 4, 0, 0 ) ) === 3, "Passed!" ); - assert.ok( a.distanceToPoint( new Vector3( 1, 0, 0 ) ) === 0, "Passed!" ); + assert.ok( a.distanceToPoint( new Vector3( 4, 0, 0 ) ) === 3, 'Passed!' ); + assert.ok( a.distanceToPoint( new Vector3( 1, 0, 0 ) ) === 0, 'Passed!' ); a.negate(); - assert.ok( a.distanceToPoint( new Vector3( 4, 0, 0 ) ) === - 3, "Passed!" ); - assert.ok( a.distanceToPoint( new Vector3( 1, 0, 0 ) ) === 0, "Passed!" ); + assert.ok( a.distanceToPoint( new Vector3( 4, 0, 0 ) ) === - 3, 'Passed!' ); + assert.ok( a.distanceToPoint( new Vector3( 1, 0, 0 ) ) === 0, 'Passed!' ); } ); - QUnit.test( "distanceToPoint", ( assert ) => { + QUnit.test( 'distanceToPoint', ( assert ) => { var a = new Plane( new Vector3( 2, 0, 0 ), - 2 ); var point = new Vector3(); a.normalize().projectPoint( zero3.clone(), point ); - assert.ok( a.distanceToPoint( point ) === 0, "Passed!" ); - assert.ok( a.distanceToPoint( new Vector3( 4, 0, 0 ) ) === 3, "Passed!" ); + assert.ok( a.distanceToPoint( point ) === 0, 'Passed!' ); + assert.ok( a.distanceToPoint( new Vector3( 4, 0, 0 ) ) === 3, 'Passed!' ); } ); - QUnit.test( "distanceToSphere", ( assert ) => { + QUnit.test( 'distanceToSphere', ( assert ) => { var a = new Plane( new Vector3( 1, 0, 0 ), 0 ); var b = new Sphere( new Vector3( 2, 0, 0 ), 1 ); - assert.ok( a.distanceToSphere( b ) === 1, "Passed!" ); + assert.ok( a.distanceToSphere( b ) === 1, 'Passed!' ); a.set( new Vector3( 1, 0, 0 ), 2 ); - assert.ok( a.distanceToSphere( b ) === 3, "Passed!" ); + assert.ok( a.distanceToSphere( b ) === 3, 'Passed!' ); a.set( new Vector3( 1, 0, 0 ), - 2 ); - assert.ok( a.distanceToSphere( b ) === - 1, "Passed!" ); + assert.ok( a.distanceToSphere( b ) === - 1, 'Passed!' ); } ); - QUnit.test( "projectPoint", ( assert ) => { + QUnit.test( 'projectPoint', ( assert ) => { var a = new Plane( new Vector3( 1, 0, 0 ), 0 ); var point = new Vector3(); a.projectPoint( new Vector3( 10, 0, 0 ), point ); - assert.ok( point.equals( zero3 ), "Passed!" ); + assert.ok( point.equals( zero3 ), 'Passed!' ); a.projectPoint( new Vector3( - 10, 0, 0 ), point ); - assert.ok( point.equals( zero3 ), "Passed!" ); + assert.ok( point.equals( zero3 ), 'Passed!' ); var a = new Plane( new Vector3( 0, 1, 0 ), - 1 ); a.projectPoint( new Vector3( 0, 0, 0 ), point ); - assert.ok( point.equals( new Vector3( 0, 1, 0 ) ), "Passed!" ); + assert.ok( point.equals( new Vector3( 0, 1, 0 ) ), 'Passed!' ); a.projectPoint( new Vector3( 0, 1, 0 ), point ); - assert.ok( point.equals( new Vector3( 0, 1, 0 ) ), "Passed!" ); + assert.ok( point.equals( new Vector3( 0, 1, 0 ) ), 'Passed!' ); } ); - QUnit.test( "isInterestionLine/intersectLine", ( assert ) => { + QUnit.test( 'isInterestionLine/intersectLine', ( assert ) => { var a = new Plane( new Vector3( 1, 0, 0 ), 0 ); var point = new Vector3(); var l1 = new Line3( new Vector3( - 10, 0, 0 ), new Vector3( 10, 0, 0 ) ); a.intersectLine( l1, point ); - assert.ok( point.equals( new Vector3( 0, 0, 0 ) ), "Passed!" ); + assert.ok( point.equals( new Vector3( 0, 0, 0 ) ), 'Passed!' ); var a = new Plane( new Vector3( 1, 0, 0 ), - 3 ); a.intersectLine( l1, point ); - assert.ok( point.equals( new Vector3( 3, 0, 0 ) ), "Passed!" ); + assert.ok( point.equals( new Vector3( 3, 0, 0 ) ), 'Passed!' ); } ); - QUnit.test( "intersectsBox", ( assert ) => { + QUnit.test( 'intersectsBox', ( assert ) => { var a = new Box3( zero3.clone(), one3.clone() ); var b = new Plane( new Vector3( 0, 1, 0 ), 1 ); @@ -248,81 +248,81 @@ export default QUnit.module( 'Maths', () => { var i = new Plane( new Vector3( 1, 1, 1 ).normalize(), - 1.732 ); var j = new Plane( new Vector3( 1, 1, 1 ).normalize(), - 1.733 ); - assert.ok( ! b.intersectsBox( a ), "Passed!" ); - assert.ok( ! c.intersectsBox( a ), "Passed!" ); - assert.ok( ! d.intersectsBox( a ), "Passed!" ); - assert.ok( ! e.intersectsBox( a ), "Passed!" ); - assert.ok( f.intersectsBox( a ), "Passed!" ); - assert.ok( g.intersectsBox( a ), "Passed!" ); - assert.ok( h.intersectsBox( a ), "Passed!" ); - assert.ok( i.intersectsBox( a ), "Passed!" ); - assert.ok( ! j.intersectsBox( a ), "Passed!" ); + assert.ok( ! b.intersectsBox( a ), 'Passed!' ); + assert.ok( ! c.intersectsBox( a ), 'Passed!' ); + assert.ok( ! d.intersectsBox( a ), 'Passed!' ); + assert.ok( ! e.intersectsBox( a ), 'Passed!' ); + assert.ok( f.intersectsBox( a ), 'Passed!' ); + assert.ok( g.intersectsBox( a ), 'Passed!' ); + assert.ok( h.intersectsBox( a ), 'Passed!' ); + assert.ok( i.intersectsBox( a ), 'Passed!' ); + assert.ok( ! j.intersectsBox( a ), 'Passed!' ); } ); - QUnit.test( "intersectsSphere", ( assert ) => { + QUnit.test( 'intersectsSphere', ( assert ) => { var a = new Sphere( zero3.clone(), 1 ); var b = new Plane( new Vector3( 0, 1, 0 ), 1 ); var c = new Plane( new Vector3( 0, 1, 0 ), 1.25 ); var d = new Plane( new Vector3( 0, - 1, 0 ), 1.25 ); - assert.ok( b.intersectsSphere( a ), "Passed!" ); - assert.ok( ! c.intersectsSphere( a ), "Passed!" ); - assert.ok( ! d.intersectsSphere( a ), "Passed!" ); + assert.ok( b.intersectsSphere( a ), 'Passed!' ); + assert.ok( ! c.intersectsSphere( a ), 'Passed!' ); + assert.ok( ! d.intersectsSphere( a ), 'Passed!' ); } ); - QUnit.test( "coplanarPoint", ( assert ) => { + QUnit.test( 'coplanarPoint', ( assert ) => { var point = new Vector3(); var a = new Plane( new Vector3( 1, 0, 0 ), 0 ); a.coplanarPoint( point ); - assert.ok( a.distanceToPoint( point ) === 0, "Passed!" ); + assert.ok( a.distanceToPoint( point ) === 0, 'Passed!' ); var a = new Plane( new Vector3( 0, 1, 0 ), - 1 ); a.coplanarPoint( point ); - assert.ok( a.distanceToPoint( point ) === 0, "Passed!" ); + assert.ok( a.distanceToPoint( point ) === 0, 'Passed!' ); } ); - QUnit.test( "applyMatrix4/translate", ( assert ) => { + QUnit.test( 'applyMatrix4/translate', ( assert ) => { var a = new Plane( new Vector3( 1, 0, 0 ), 0 ); var m = new Matrix4(); m.makeRotationZ( Math.PI * 0.5 ); - assert.ok( comparePlane( a.clone().applyMatrix4( m ), new Plane( new Vector3( 0, 1, 0 ), 0 ) ), "Passed!" ); + assert.ok( comparePlane( a.clone().applyMatrix4( m ), new Plane( new Vector3( 0, 1, 0 ), 0 ) ), 'Passed!' ); var a = new Plane( new Vector3( 0, 1, 0 ), - 1 ); - assert.ok( comparePlane( a.clone().applyMatrix4( m ), new Plane( new Vector3( - 1, 0, 0 ), - 1 ) ), "Passed!" ); + assert.ok( comparePlane( a.clone().applyMatrix4( m ), new Plane( new Vector3( - 1, 0, 0 ), - 1 ) ), 'Passed!' ); m.makeTranslation( 1, 1, 1 ); - assert.ok( comparePlane( a.clone().applyMatrix4( m ), a.clone().translate( new Vector3( 1, 1, 1 ) ) ), "Passed!" ); + assert.ok( comparePlane( a.clone().applyMatrix4( m ), a.clone().translate( new Vector3( 1, 1, 1 ) ) ), 'Passed!' ); } ); - QUnit.test( "equals", ( assert ) => { + QUnit.test( 'equals', ( assert ) => { var a = new Plane( new Vector3( 1, 0, 0 ), 0 ); var b = new Plane( new Vector3( 1, 0, 0 ), 1 ); var c = new Plane( new Vector3( 0, 1, 0 ), 0 ); - assert.ok( a.normal.equals( b.normal ), "Normals: equal" ); - assert.notOk( a.normal.equals( c.normal ), "Normals: not equal" ); + assert.ok( a.normal.equals( b.normal ), 'Normals: equal' ); + assert.notOk( a.normal.equals( c.normal ), 'Normals: not equal' ); - assert.notStrictEqual( a.constant, b.constant, "Constants: not equal" ); - assert.strictEqual( a.constant, c.constant, "Constants: equal" ); + assert.notStrictEqual( a.constant, b.constant, 'Constants: not equal' ); + assert.strictEqual( a.constant, c.constant, 'Constants: equal' ); - assert.notOk( a.equals( b ), "Planes: not equal" ); - assert.notOk( a.equals( c ), "Planes: not equal" ); + assert.notOk( a.equals( b ), 'Planes: not equal' ); + assert.notOk( a.equals( c ), 'Planes: not equal' ); a.copy( b ); - assert.ok( a.normal.equals( b.normal ), "Normals after copy(): equal" ); - assert.strictEqual( a.constant, b.constant, "Constants after copy(): equal" ); - assert.ok( a.equals( b ), "Planes after copy(): equal" ); + assert.ok( a.normal.equals( b.normal ), 'Normals after copy(): equal' ); + assert.strictEqual( a.constant, b.constant, 'Constants after copy(): equal' ); + assert.ok( a.equals( b ), 'Planes after copy(): equal' ); } ); @@ -330,4 +330,4 @@ export default QUnit.module( 'Maths', () => { } ); -QUnit.module( "Plane" ); +QUnit.module( 'Plane' ); diff --git a/test/unit/src/math/Quaternion.tests.js b/test/unit/src/math/Quaternion.tests.js index fda8f48284f905..48c407ca609248 100644 --- a/test/unit/src/math/Quaternion.tests.js +++ b/test/unit/src/math/Quaternion.tests.js @@ -126,33 +126,33 @@ function slerpTestSkeleton( doSlerp, maxError, assert ) { result = doSlerp( a, b, 0 ); assert.ok( result.equals( - a[ 0 ], a[ 1 ], a[ 2 ], a[ 3 ], 0 ), "Exactly A @ t = 0" ); + a[ 0 ], a[ 1 ], a[ 2 ], a[ 3 ], 0 ), 'Exactly A @ t = 0' ); result = doSlerp( a, b, 1 ); assert.ok( result.equals( - b[ 0 ], b[ 1 ], b[ 2 ], b[ 3 ], 0 ), "Exactly B @ t = 1" ); + b[ 0 ], b[ 1 ], b[ 2 ], b[ 3 ], 0 ), 'Exactly B @ t = 1' ); result = doSlerp( a, b, 0.5 ); - assert.ok( Math.abs( result.dotA - result.dotB ) <= Number.EPSILON, "Symmetry at 0.5" ); - assert.ok( isNormal( result ), "Approximately normal (at 0.5)" ); + assert.ok( Math.abs( result.dotA - result.dotB ) <= Number.EPSILON, 'Symmetry at 0.5' ); + assert.ok( isNormal( result ), 'Approximately normal (at 0.5)' ); result = doSlerp( a, b, 0.25 ); - assert.ok( result.dotA > result.dotB, "Interpolating at 0.25" ); - assert.ok( isNormal( result ), "Approximately normal (at 0.25)" ); + assert.ok( result.dotA > result.dotB, 'Interpolating at 0.25' ); + assert.ok( isNormal( result ), 'Approximately normal (at 0.25)' ); result = doSlerp( a, b, 0.75 ); - assert.ok( result.dotA < result.dotB, "Interpolating at 0.75" ); - assert.ok( isNormal( result ), "Approximately normal (at 0.75)" ); + assert.ok( result.dotA < result.dotB, 'Interpolating at 0.75' ); + assert.ok( isNormal( result ), 'Approximately normal (at 0.75)' ); var D = Math.SQRT1_2; result = doSlerp( [ 1, 0, 0, 0 ], [ 0, 0, 1, 0 ], 0.5 ); - assert.ok( result.equals( D, 0, D, 0 ), "X/Z diagonal from axes" ); - assert.ok( isNormal( result ), "Approximately normal (X/Z diagonal)" ); + assert.ok( result.equals( D, 0, D, 0 ), 'X/Z diagonal from axes' ); + assert.ok( isNormal( result ), 'Approximately normal (X/Z diagonal)' ); result = doSlerp( [ 0, D, 0, D ], [ 0, - D, 0, D ], 0.5 ); - assert.ok( result.equals( 0, 0, 0, 1 ), "W-Unit from diagonals" ); - assert.ok( isNormal( result ), "Approximately normal (W-Unit)" ); + assert.ok( result.equals( 0, 0, 0, 1 ), 'W-Unit from diagonals' ); + assert.ok( isNormal( result ), 'Approximately normal (W-Unit)' ); } @@ -167,44 +167,44 @@ export default QUnit.module( 'Maths', () => { QUnit.module( 'Quaternion', () => { // INSTANCING - QUnit.test( "Instancing", ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { var a = new Quaternion(); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - assert.ok( a.z == 0, "Passed!" ); - assert.ok( a.w == 1, "Passed!" ); + assert.ok( a.x == 0, 'Passed!' ); + assert.ok( a.y == 0, 'Passed!' ); + assert.ok( a.z == 0, 'Passed!' ); + assert.ok( a.w == 1, 'Passed!' ); var a = new Quaternion( x, y, z, w ); - assert.ok( a.x === x, "Passed!" ); - assert.ok( a.y === y, "Passed!" ); - assert.ok( a.z === z, "Passed!" ); - assert.ok( a.w === w, "Passed!" ); + assert.ok( a.x === x, 'Passed!' ); + assert.ok( a.y === y, 'Passed!' ); + assert.ok( a.z === z, 'Passed!' ); + assert.ok( a.w === w, 'Passed!' ); } ); // STATIC STUFF - QUnit.test( "slerp", ( assert ) => { + QUnit.test( 'slerp', ( assert ) => { slerpTestSkeleton( doSlerpObject, Number.EPSILON, assert ); } ); - QUnit.test( "slerpFlat", ( assert ) => { + QUnit.test( 'slerpFlat', ( assert ) => { slerpTestSkeleton( doSlerpArray, Number.EPSILON, assert ); } ); // PROPERTIES - QUnit.test( "properties", ( assert ) => { + QUnit.test( 'properties', ( assert ) => { assert.expect( 8 ); var a = new Quaternion(); a._onChange( function () { - assert.ok( true, "onChange called" ); + assert.ok( true, 'onChange called' ); } ); @@ -213,27 +213,27 @@ export default QUnit.module( 'Maths', () => { a.z = z; a.w = w; - assert.strictEqual( a.x, x, "Check x" ); - assert.strictEqual( a.y, y, "Check y" ); - assert.strictEqual( a.z, z, "Check z" ); - assert.strictEqual( a.w, w, "Check w" ); + assert.strictEqual( a.x, x, 'Check x' ); + assert.strictEqual( a.y, y, 'Check y' ); + assert.strictEqual( a.z, z, 'Check z' ); + assert.strictEqual( a.w, w, 'Check w' ); } ); - QUnit.test( "x", ( assert ) => { + QUnit.test( 'x', ( assert ) => { var a = new Quaternion(); - assert.ok( a.x === 0, "Passed!" ); + assert.ok( a.x === 0, 'Passed!' ); a = new Quaternion( 1, 2, 3 ); - assert.ok( a.x === 1, "Passed!" ); + assert.ok( a.x === 1, 'Passed!' ); a = new Quaternion( 4, 5, 6, 1 ); - assert.ok( a.x === 4, "Passed!" ); + assert.ok( a.x === 4, 'Passed!' ); a = new Quaternion( 7, 8, 9 ); a.x = 10; - assert.ok( a.x === 10, "Passed!" ); + assert.ok( a.x === 10, 'Passed!' ); a = new Quaternion( 11, 12, 13 ); var b = false; @@ -242,27 +242,27 @@ export default QUnit.module( 'Maths', () => { b = true; } ); - assert.ok( ! b, "Passed!" ); + assert.ok( ! b, 'Passed!' ); a.x = 14; - assert.ok( b, "Passed!" ); - assert.ok( a.x === 14, "Passed!" ); + assert.ok( b, 'Passed!' ); + assert.ok( a.x === 14, 'Passed!' ); } ); - QUnit.test( "y", ( assert ) => { + QUnit.test( 'y', ( assert ) => { var a = new Quaternion(); - assert.ok( a.y === 0, "Passed!" ); + assert.ok( a.y === 0, 'Passed!' ); a = new Quaternion( 1, 2, 3 ); - assert.ok( a.y === 2, "Passed!" ); + assert.ok( a.y === 2, 'Passed!' ); a = new Quaternion( 4, 5, 6, 1 ); - assert.ok( a.y === 5, "Passed!" ); + assert.ok( a.y === 5, 'Passed!' ); a = new Quaternion( 7, 8, 9 ); a.y = 10; - assert.ok( a.y === 10, "Passed!" ); + assert.ok( a.y === 10, 'Passed!' ); a = new Quaternion( 11, 12, 13 ); var b = false; @@ -271,28 +271,28 @@ export default QUnit.module( 'Maths', () => { b = true; } ); - assert.ok( ! b, "Passed!" ); + assert.ok( ! b, 'Passed!' ); a.y = 14; - assert.ok( b, "Passed!" ); - assert.ok( a.y === 14, "Passed!" ); + assert.ok( b, 'Passed!' ); + assert.ok( a.y === 14, 'Passed!' ); } ); - QUnit.test( "z", ( assert ) => { + QUnit.test( 'z', ( assert ) => { var a = new Quaternion(); - assert.ok( a.z === 0, "Passed!" ); + assert.ok( a.z === 0, 'Passed!' ); a = new Quaternion( 1, 2, 3 ); - assert.ok( a.z === 3, "Passed!" ); + assert.ok( a.z === 3, 'Passed!' ); a = new Quaternion( 4, 5, 6, 1 ); - assert.ok( a.z === 6, "Passed!" ); + assert.ok( a.z === 6, 'Passed!' ); a = new Quaternion( 7, 8, 9 ); a.z = 10; - assert.ok( a.z === 10, "Passed!" ); + assert.ok( a.z === 10, 'Passed!' ); a = new Quaternion( 11, 12, 13 ); var b = false; @@ -301,27 +301,27 @@ export default QUnit.module( 'Maths', () => { b = true; } ); - assert.ok( ! b, "Passed!" ); + assert.ok( ! b, 'Passed!' ); a.z = 14; - assert.ok( b, "Passed!" ); - assert.ok( a.z === 14, "Passed!" ); + assert.ok( b, 'Passed!' ); + assert.ok( a.z === 14, 'Passed!' ); } ); - QUnit.test( "w", ( assert ) => { + QUnit.test( 'w', ( assert ) => { var a = new Quaternion(); - assert.ok( a.w === 1, "Passed!" ); + assert.ok( a.w === 1, 'Passed!' ); a = new Quaternion( 1, 2, 3 ); - assert.ok( a.w === 1, "Passed!" ); + assert.ok( a.w === 1, 'Passed!' ); a = new Quaternion( 4, 5, 6, 1 ); - assert.ok( a.w === 1, "Passed!" ); + assert.ok( a.w === 1, 'Passed!' ); a = new Quaternion( 7, 8, 9 ); a.w = 10; - assert.ok( a.w === 10, "Passed!" ); + assert.ok( a.w === 10, 'Passed!' ); a = new Quaternion( 11, 12, 13 ); var b = false; @@ -330,67 +330,67 @@ export default QUnit.module( 'Maths', () => { b = true; } ); - assert.ok( ! b, "Passed!" ); + assert.ok( ! b, 'Passed!' ); a.w = 14; - assert.ok( b, "Passed!" ); - assert.ok( a.w === 14, "Passed!" ); + assert.ok( b, 'Passed!' ); + assert.ok( a.w === 14, 'Passed!' ); } ); // PUBLIC STUFF - QUnit.test( "set", ( assert ) => { + QUnit.test( 'set', ( assert ) => { var a = new Quaternion(); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - assert.ok( a.z == 0, "Passed!" ); - assert.ok( a.w == 1, "Passed!" ); + assert.ok( a.x == 0, 'Passed!' ); + assert.ok( a.y == 0, 'Passed!' ); + assert.ok( a.z == 0, 'Passed!' ); + assert.ok( a.w == 1, 'Passed!' ); a.set( x, y, z, w ); - assert.ok( a.x == x, "Passed!" ); - assert.ok( a.y == y, "Passed!" ); - assert.ok( a.z === z, "Passed!" ); - assert.ok( a.w === w, "Passed!" ); + assert.ok( a.x == x, 'Passed!' ); + assert.ok( a.y == y, 'Passed!' ); + assert.ok( a.z === z, 'Passed!' ); + assert.ok( a.w === w, 'Passed!' ); } ); - QUnit.test( "clone", ( assert ) => { + QUnit.test( 'clone', ( assert ) => { var a = new Quaternion().clone(); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - assert.ok( a.z == 0, "Passed!" ); - assert.ok( a.w == 1, "Passed!" ); + assert.ok( a.x == 0, 'Passed!' ); + assert.ok( a.y == 0, 'Passed!' ); + assert.ok( a.z == 0, 'Passed!' ); + assert.ok( a.w == 1, 'Passed!' ); var b = a.set( x, y, z, w ).clone(); - assert.ok( b.x == x, "Passed!" ); - assert.ok( b.y == y, "Passed!" ); - assert.ok( b.z === z, "Passed!" ); - assert.ok( b.w === w, "Passed!" ); + assert.ok( b.x == x, 'Passed!' ); + assert.ok( b.y == y, 'Passed!' ); + assert.ok( b.z === z, 'Passed!' ); + assert.ok( b.w === w, 'Passed!' ); } ); - QUnit.test( "copy", ( assert ) => { + QUnit.test( 'copy', ( assert ) => { var a = new Quaternion( x, y, z, w ); var b = new Quaternion().copy( a ); - assert.ok( b.x == x, "Passed!" ); - assert.ok( b.y == y, "Passed!" ); - assert.ok( b.z == z, "Passed!" ); - assert.ok( b.w == w, "Passed!" ); + assert.ok( b.x == x, 'Passed!' ); + assert.ok( b.y == y, 'Passed!' ); + assert.ok( b.z == z, 'Passed!' ); + assert.ok( b.w == w, 'Passed!' ); // ensure that it is a true copy a.x = 0; a.y = - 1; a.z = 0; a.w = - 1; - assert.ok( b.x == x, "Passed!" ); - assert.ok( b.y == y, "Passed!" ); + assert.ok( b.x == x, 'Passed!' ); + assert.ok( b.y == y, 'Passed!' ); } ); - QUnit.test( "setFromEuler/setFromQuaternion", ( assert ) => { + QUnit.test( 'setFromEuler/setFromQuaternion', ( assert ) => { var angles = [ new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ) ]; @@ -401,7 +401,7 @@ export default QUnit.module( 'Maths', () => { var eulers2 = new Euler().setFromQuaternion( new Quaternion().setFromEuler( new Euler( angles[ j ].x, angles[ j ].y, angles[ j ].z, orders[ i ] ) ), orders[ i ] ); var newAngle = new Vector3( eulers2.x, eulers2.y, eulers2.z ); - assert.ok( newAngle.distanceTo( angles[ j ] ) < 0.001, "Passed!" ); + assert.ok( newAngle.distanceTo( angles[ j ] ) < 0.001, 'Passed!' ); } @@ -409,7 +409,7 @@ export default QUnit.module( 'Maths', () => { } ); - QUnit.test( "setFromAxisAngle", ( assert ) => { + QUnit.test( 'setFromAxisAngle', ( assert ) => { // TODO: find cases to validate. // assert.ok( true, "Passed!" ); @@ -417,23 +417,23 @@ export default QUnit.module( 'Maths', () => { var zero = new Quaternion(); var a = new Quaternion().setFromAxisAngle( new Vector3( 1, 0, 0 ), 0 ); - assert.ok( a.equals( zero ), "Passed!" ); + assert.ok( a.equals( zero ), 'Passed!' ); a = new Quaternion().setFromAxisAngle( new Vector3( 0, 1, 0 ), 0 ); - assert.ok( a.equals( zero ), "Passed!" ); + assert.ok( a.equals( zero ), 'Passed!' ); a = new Quaternion().setFromAxisAngle( new Vector3( 0, 0, 1 ), 0 ); - assert.ok( a.equals( zero ), "Passed!" ); + assert.ok( a.equals( zero ), 'Passed!' ); var b1 = new Quaternion().setFromAxisAngle( new Vector3( 1, 0, 0 ), Math.PI ); - assert.ok( ! a.equals( b1 ), "Passed!" ); + assert.ok( ! a.equals( b1 ), 'Passed!' ); var b2 = new Quaternion().setFromAxisAngle( new Vector3( 1, 0, 0 ), - Math.PI ); - assert.ok( ! a.equals( b2 ), "Passed!" ); + assert.ok( ! a.equals( b2 ), 'Passed!' ); b1.multiply( b2 ); - assert.ok( a.equals( b1 ), "Passed!" ); + assert.ok( a.equals( b1 ), 'Passed!' ); } ); - QUnit.test( "setFromEuler/setFromRotationMatrix", ( assert ) => { + QUnit.test( 'setFromEuler/setFromRotationMatrix', ( assert ) => { // ensure euler conversion for Quaternion matches that of Matrix4 for ( var i = 0; i < orders.length; i ++ ) { @@ -442,13 +442,13 @@ export default QUnit.module( 'Maths', () => { var m = new Matrix4().makeRotationFromEuler( changeEulerOrder( eulerAngles, orders[ i ] ) ); var q2 = new Quaternion().setFromRotationMatrix( m ); - assert.ok( qSub( q, q2 ).length() < 0.001, "Passed!" ); + assert.ok( qSub( q, q2 ).length() < 0.001, 'Passed!' ); } } ); - QUnit.test( "setFromRotationMatrix", ( assert ) => { + QUnit.test( 'setFromRotationMatrix', ( assert ) => { // contrived examples purely to please the god of code coverage... // match conditions in various 'else [if]' blocks @@ -459,24 +459,24 @@ export default QUnit.module( 'Maths', () => { var expected = new Vector4( 0.8581163303210332, 0.19069251784911848, - 0.2860387767736777, 0.38138503569823695 ); a.setFromRotationMatrix( m ); - assert.ok( Math.abs( a.x - expected.x ) <= eps, "m11 > m22 && m11 > m33: check x" ); - assert.ok( Math.abs( a.y - expected.y ) <= eps, "m11 > m22 && m11 > m33: check y" ); - assert.ok( Math.abs( a.z - expected.z ) <= eps, "m11 > m22 && m11 > m33: check z" ); - assert.ok( Math.abs( a.w - expected.w ) <= eps, "m11 > m22 && m11 > m33: check w" ); + assert.ok( Math.abs( a.x - expected.x ) <= eps, 'm11 > m22 && m11 > m33: check x' ); + assert.ok( Math.abs( a.y - expected.y ) <= eps, 'm11 > m22 && m11 > m33: check y' ); + assert.ok( Math.abs( a.z - expected.z ) <= eps, 'm11 > m22 && m11 > m33: check z' ); + assert.ok( Math.abs( a.w - expected.w ) <= eps, 'm11 > m22 && m11 > m33: check w' ); var q = new Quaternion( - 1, - 2, 1, - 1 ).normalize(); m.makeRotationFromQuaternion( q ); var expected = new Vector4( 0.37796447300922714, 0.7559289460184544, - 0.37796447300922714, 0.37796447300922714 ); a.setFromRotationMatrix( m ); - assert.ok( Math.abs( a.x - expected.x ) <= eps, "m22 > m33: check x" ); - assert.ok( Math.abs( a.y - expected.y ) <= eps, "m22 > m33: check y" ); - assert.ok( Math.abs( a.z - expected.z ) <= eps, "m22 > m33: check z" ); - assert.ok( Math.abs( a.w - expected.w ) <= eps, "m22 > m33: check w" ); + assert.ok( Math.abs( a.x - expected.x ) <= eps, 'm22 > m33: check x' ); + assert.ok( Math.abs( a.y - expected.y ) <= eps, 'm22 > m33: check y' ); + assert.ok( Math.abs( a.z - expected.z ) <= eps, 'm22 > m33: check z' ); + assert.ok( Math.abs( a.w - expected.w ) <= eps, 'm22 > m33: check w' ); } ); - QUnit.test( "setFromUnitVectors", ( assert ) => { + QUnit.test( 'setFromUnitVectors', ( assert ) => { var a = new Quaternion(); var b = new Vector3( 1, 0, 0 ); @@ -484,26 +484,26 @@ export default QUnit.module( 'Maths', () => { var expected = new Quaternion( 0, 0, Math.sqrt( 2 ) / 2, Math.sqrt( 2 ) / 2 ); a.setFromUnitVectors( b, c ); - assert.ok( Math.abs( a.x - expected.x ) <= eps, "Check x" ); - assert.ok( Math.abs( a.y - expected.y ) <= eps, "Check y" ); - assert.ok( Math.abs( a.z - expected.z ) <= eps, "Check z" ); - assert.ok( Math.abs( a.w - expected.w ) <= eps, "Check w" ); + assert.ok( Math.abs( a.x - expected.x ) <= eps, 'Check x' ); + assert.ok( Math.abs( a.y - expected.y ) <= eps, 'Check y' ); + assert.ok( Math.abs( a.z - expected.z ) <= eps, 'Check z' ); + assert.ok( Math.abs( a.w - expected.w ) <= eps, 'Check w' ); } ); - QUnit.test( "angleTo", ( assert ) => { + QUnit.test( 'angleTo', ( assert ) => { var a = new Quaternion(); var b = new Quaternion().setFromEuler( new Euler( 0, Math.PI, 0 ) ); var c = new Quaternion().setFromEuler( new Euler( 0, Math.PI * 2, 0 ) ); - assert.ok( a.angleTo( a ) === 0, "Passed!" ); - assert.ok( a.angleTo( b ) === Math.PI, "Passed!" ); - assert.ok( a.angleTo( c ) === 0, "Passed!" ); + assert.ok( a.angleTo( a ) === 0, 'Passed!' ); + assert.ok( a.angleTo( b ) === Math.PI, 'Passed!' ); + assert.ok( a.angleTo( c ) === 0, 'Passed!' ); } ); - QUnit.test( "rotateTowards", ( assert ) => { + QUnit.test( 'rotateTowards', ( assert ) => { var a = new Quaternion(); var b = new Quaternion().setFromEuler( new Euler( 0, Math.PI, 0 ) ); @@ -512,32 +512,32 @@ export default QUnit.module( 'Maths', () => { var halfPI = Math.PI * 0.5; a.rotateTowards( b, 0 ); - assert.ok( a.equals( a ) === true, "Passed!" ); + assert.ok( a.equals( a ) === true, 'Passed!' ); a.rotateTowards( b, Math.PI * 2 ); // test overshoot - assert.ok( a.equals( b ) === true, "Passed!" ); + assert.ok( a.equals( b ) === true, 'Passed!' ); a.set( 0, 0, 0, 1 ); a.rotateTowards( b, halfPI ); - assert.ok( a.angleTo( c ) - halfPI <= eps, "Passed!" ); + assert.ok( a.angleTo( c ) - halfPI <= eps, 'Passed!' ); } ); - QUnit.test( "identity", ( assert ) => { + QUnit.test( 'identity', ( assert ) => { var a = new Quaternion(); a.set( x, y, z, w ); a.identity(); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - assert.ok( a.z === 0, "Passed!" ); - assert.ok( a.w === 1, "Passed!" ); + assert.ok( a.x == 0, 'Passed!' ); + assert.ok( a.y == 0, 'Passed!' ); + assert.ok( a.z === 0, 'Passed!' ); + assert.ok( a.w === 1, 'Passed!' ); } ); - QUnit.test( "invert/conjugate", ( assert ) => { + QUnit.test( 'invert/conjugate', ( assert ) => { var a = new Quaternion( x, y, z, w ); @@ -545,83 +545,83 @@ export default QUnit.module( 'Maths', () => { var b = a.clone().conjugate(); - assert.ok( a.x == - b.x, "Passed!" ); - assert.ok( a.y == - b.y, "Passed!" ); - assert.ok( a.z == - b.z, "Passed!" ); - assert.ok( a.w == b.w, "Passed!" ); + assert.ok( a.x == - b.x, 'Passed!' ); + assert.ok( a.y == - b.y, 'Passed!' ); + assert.ok( a.z == - b.z, 'Passed!' ); + assert.ok( a.w == b.w, 'Passed!' ); } ); - QUnit.test( "dot", ( assert ) => { + QUnit.test( 'dot', ( assert ) => { var a = new Quaternion(); var b = new Quaternion(); - assert.ok( a.dot( b ) === 1, "Passed!" ); + assert.ok( a.dot( b ) === 1, 'Passed!' ); a = new Quaternion( 1, 2, 3, 1 ); b = new Quaternion( 3, 2, 1, 1 ); - assert.ok( a.dot( b ) === 11, "Passed!" ); + assert.ok( a.dot( b ) === 11, 'Passed!' ); } ); - QUnit.test( "normalize/length/lengthSq", ( assert ) => { + QUnit.test( 'normalize/length/lengthSq', ( assert ) => { var a = new Quaternion( x, y, z, w ); - assert.ok( a.length() != 1, "Passed!" ); - assert.ok( a.lengthSq() != 1, "Passed!" ); + assert.ok( a.length() != 1, 'Passed!' ); + assert.ok( a.lengthSq() != 1, 'Passed!' ); a.normalize(); - assert.ok( a.length() == 1, "Passed!" ); - assert.ok( a.lengthSq() == 1, "Passed!" ); + assert.ok( a.length() == 1, 'Passed!' ); + assert.ok( a.lengthSq() == 1, 'Passed!' ); a.set( 0, 0, 0, 0 ); - assert.ok( a.lengthSq() == 0, "Passed!" ); - assert.ok( a.length() == 0, "Passed!" ); + assert.ok( a.lengthSq() == 0, 'Passed!' ); + assert.ok( a.length() == 0, 'Passed!' ); a.normalize(); - assert.ok( a.lengthSq() == 1, "Passed!" ); - assert.ok( a.length() == 1, "Passed!" ); + assert.ok( a.lengthSq() == 1, 'Passed!' ); + assert.ok( a.length() == 1, 'Passed!' ); } ); - QUnit.test( "multiplyQuaternions/multiply", ( assert ) => { + QUnit.test( 'multiplyQuaternions/multiply', ( assert ) => { var angles = [ new Euler( 1, 0, 0 ), new Euler( 0, 1, 0 ), new Euler( 0, 0, 1 ) ]; - var q1 = new Quaternion().setFromEuler( changeEulerOrder( angles[ 0 ], "XYZ" ) ); - var q2 = new Quaternion().setFromEuler( changeEulerOrder( angles[ 1 ], "XYZ" ) ); - var q3 = new Quaternion().setFromEuler( changeEulerOrder( angles[ 2 ], "XYZ" ) ); + var q1 = new Quaternion().setFromEuler( changeEulerOrder( angles[ 0 ], 'XYZ' ) ); + var q2 = new Quaternion().setFromEuler( changeEulerOrder( angles[ 1 ], 'XYZ' ) ); + var q3 = new Quaternion().setFromEuler( changeEulerOrder( angles[ 2 ], 'XYZ' ) ); var q = new Quaternion().multiplyQuaternions( q1, q2 ).multiply( q3 ); - var m1 = new Matrix4().makeRotationFromEuler( changeEulerOrder( angles[ 0 ], "XYZ" ) ); - var m2 = new Matrix4().makeRotationFromEuler( changeEulerOrder( angles[ 1 ], "XYZ" ) ); - var m3 = new Matrix4().makeRotationFromEuler( changeEulerOrder( angles[ 2 ], "XYZ" ) ); + var m1 = new Matrix4().makeRotationFromEuler( changeEulerOrder( angles[ 0 ], 'XYZ' ) ); + var m2 = new Matrix4().makeRotationFromEuler( changeEulerOrder( angles[ 1 ], 'XYZ' ) ); + var m3 = new Matrix4().makeRotationFromEuler( changeEulerOrder( angles[ 2 ], 'XYZ' ) ); var m = new Matrix4().multiplyMatrices( m1, m2 ).multiply( m3 ); var qFromM = new Quaternion().setFromRotationMatrix( m ); - assert.ok( qSub( q, qFromM ).length() < 0.001, "Passed!" ); + assert.ok( qSub( q, qFromM ).length() < 0.001, 'Passed!' ); } ); - QUnit.test( "premultiply", ( assert ) => { + QUnit.test( 'premultiply', ( assert ) => { var a = new Quaternion( x, y, z, w ); var b = new Quaternion( 2 * x, - y, - 2 * z, w ); var expected = new Quaternion( 42, - 32, - 2, 58 ); a.premultiply( b ); - assert.ok( Math.abs( a.x - expected.x ) <= eps, "Check x" ); - assert.ok( Math.abs( a.y - expected.y ) <= eps, "Check y" ); - assert.ok( Math.abs( a.z - expected.z ) <= eps, "Check z" ); - assert.ok( Math.abs( a.w - expected.w ) <= eps, "Check w" ); + assert.ok( Math.abs( a.x - expected.x ) <= eps, 'Check x' ); + assert.ok( Math.abs( a.y - expected.y ) <= eps, 'Check y' ); + assert.ok( Math.abs( a.z - expected.z ) <= eps, 'Check z' ); + assert.ok( Math.abs( a.w - expected.w ) <= eps, 'Check w' ); } ); - QUnit.test( "slerp", ( assert ) => { + QUnit.test( 'slerp', ( assert ) => { var a = new Quaternion( x, y, z, w ); var b = new Quaternion( - x, - y, - z, - w ); @@ -629,8 +629,8 @@ export default QUnit.module( 'Maths', () => { var c = a.clone().slerp( b, 0 ); var d = a.clone().slerp( b, 1 ); - assert.ok( a.equals( c ), "Passed" ); - assert.ok( b.equals( d ), "Passed" ); + assert.ok( a.equals( c ), 'Passed' ); + assert.ok( b.equals( d ), 'Passed' ); var D = Math.SQRT1_2; @@ -639,10 +639,10 @@ export default QUnit.module( 'Maths', () => { var f = new Quaternion( 0, 0, 1, 0 ); var expected = new Quaternion( D, 0, D, 0 ); var result = e.clone().slerp( f, 0.5 ); - assert.ok( Math.abs( result.x - expected.x ) <= eps, "Check x" ); - assert.ok( Math.abs( result.y - expected.y ) <= eps, "Check y" ); - assert.ok( Math.abs( result.z - expected.z ) <= eps, "Check z" ); - assert.ok( Math.abs( result.w - expected.w ) <= eps, "Check w" ); + assert.ok( Math.abs( result.x - expected.x ) <= eps, 'Check x' ); + assert.ok( Math.abs( result.y - expected.y ) <= eps, 'Check y' ); + assert.ok( Math.abs( result.z - expected.z ) <= eps, 'Check z' ); + assert.ok( Math.abs( result.w - expected.w ) <= eps, 'Check w' ); var g = new Quaternion( 0, D, 0, D ); @@ -650,14 +650,14 @@ export default QUnit.module( 'Maths', () => { expected = new Quaternion( 0, 0, 0, 1 ); result = g.clone().slerp( h, 0.5 ); - assert.ok( Math.abs( result.x - expected.x ) <= eps, "Check x" ); - assert.ok( Math.abs( result.y - expected.y ) <= eps, "Check y" ); - assert.ok( Math.abs( result.z - expected.z ) <= eps, "Check z" ); - assert.ok( Math.abs( result.w - expected.w ) <= eps, "Check w" ); + assert.ok( Math.abs( result.x - expected.x ) <= eps, 'Check x' ); + assert.ok( Math.abs( result.y - expected.y ) <= eps, 'Check y' ); + assert.ok( Math.abs( result.z - expected.z ) <= eps, 'Check z' ); + assert.ok( Math.abs( result.w - expected.w ) <= eps, 'Check w' ); } ); - QUnit.test( "slerpQuaternions", ( assert ) => { + QUnit.test( 'slerpQuaternions', ( assert ) => { var e = new Quaternion( 1, 0, 0, 0 ); var f = new Quaternion( 0, 0, 1, 0 ); @@ -666,14 +666,14 @@ export default QUnit.module( 'Maths', () => { var a = new Quaternion(); a.slerpQuaternions( e, f, 0.5 ); - assert.ok( Math.abs( a.x - expected.x ) <= eps, "Check x" ); - assert.ok( Math.abs( a.y - expected.y ) <= eps, "Check y" ); - assert.ok( Math.abs( a.z - expected.z ) <= eps, "Check z" ); - assert.ok( Math.abs( a.w - expected.w ) <= eps, "Check w" ); + assert.ok( Math.abs( a.x - expected.x ) <= eps, 'Check x' ); + assert.ok( Math.abs( a.y - expected.y ) <= eps, 'Check y' ); + assert.ok( Math.abs( a.z - expected.z ) <= eps, 'Check z' ); + assert.ok( Math.abs( a.w - expected.w ) <= eps, 'Check w' ); } ); - QUnit.test( "random", ( assert ) => { + QUnit.test( 'random', ( assert ) => { var a = new Quaternion(); @@ -690,71 +690,71 @@ export default QUnit.module( 'Maths', () => { } ); - QUnit.test( "equals", ( assert ) => { + QUnit.test( 'equals', ( assert ) => { var a = new Quaternion( x, y, z, w ); var b = new Quaternion( - x, - y, - z, - w ); - assert.ok( a.x != b.x, "Passed!" ); - assert.ok( a.y != b.y, "Passed!" ); + assert.ok( a.x != b.x, 'Passed!' ); + assert.ok( a.y != b.y, 'Passed!' ); - assert.ok( ! a.equals( b ), "Passed!" ); - assert.ok( ! b.equals( a ), "Passed!" ); + assert.ok( ! a.equals( b ), 'Passed!' ); + assert.ok( ! b.equals( a ), 'Passed!' ); a.copy( b ); - assert.ok( a.x == b.x, "Passed!" ); - assert.ok( a.y == b.y, "Passed!" ); + assert.ok( a.x == b.x, 'Passed!' ); + assert.ok( a.y == b.y, 'Passed!' ); - assert.ok( a.equals( b ), "Passed!" ); - assert.ok( b.equals( a ), "Passed!" ); + assert.ok( a.equals( b ), 'Passed!' ); + assert.ok( b.equals( a ), 'Passed!' ); } ); - QUnit.test( "fromArray", ( assert ) => { + QUnit.test( 'fromArray', ( assert ) => { var a = new Quaternion(); a.fromArray( [ x, y, z, w ] ); - assert.ok( a.x == x, "Passed!" ); - assert.ok( a.y == y, "Passed!" ); - assert.ok( a.z === z, "Passed!" ); - assert.ok( a.w === w, "Passed!" ); + assert.ok( a.x == x, 'Passed!' ); + assert.ok( a.y == y, 'Passed!' ); + assert.ok( a.z === z, 'Passed!' ); + assert.ok( a.w === w, 'Passed!' ); a.fromArray( [ undefined, x, y, z, w, undefined ], 1 ); - assert.ok( a.x == x, "Passed!" ); - assert.ok( a.y == y, "Passed!" ); - assert.ok( a.z === z, "Passed!" ); - assert.ok( a.w === w, "Passed!" ); + assert.ok( a.x == x, 'Passed!' ); + assert.ok( a.y == y, 'Passed!' ); + assert.ok( a.z === z, 'Passed!' ); + assert.ok( a.w === w, 'Passed!' ); } ); - QUnit.test( "toArray", ( assert ) => { + QUnit.test( 'toArray', ( assert ) => { var a = new Quaternion( x, y, z, w ); var array = a.toArray(); - assert.strictEqual( array[ 0 ], x, "No array, no offset: check x" ); - assert.strictEqual( array[ 1 ], y, "No array, no offset: check y" ); - assert.strictEqual( array[ 2 ], z, "No array, no offset: check z" ); - assert.strictEqual( array[ 3 ], w, "No array, no offset: check w" ); + assert.strictEqual( array[ 0 ], x, 'No array, no offset: check x' ); + assert.strictEqual( array[ 1 ], y, 'No array, no offset: check y' ); + assert.strictEqual( array[ 2 ], z, 'No array, no offset: check z' ); + assert.strictEqual( array[ 3 ], w, 'No array, no offset: check w' ); var array = []; a.toArray( array ); - assert.strictEqual( array[ 0 ], x, "With array, no offset: check x" ); - assert.strictEqual( array[ 1 ], y, "With array, no offset: check y" ); - assert.strictEqual( array[ 2 ], z, "With array, no offset: check z" ); - assert.strictEqual( array[ 3 ], w, "With array, no offset: check w" ); + assert.strictEqual( array[ 0 ], x, 'With array, no offset: check x' ); + assert.strictEqual( array[ 1 ], y, 'With array, no offset: check y' ); + assert.strictEqual( array[ 2 ], z, 'With array, no offset: check z' ); + assert.strictEqual( array[ 3 ], w, 'With array, no offset: check w' ); var array = []; a.toArray( array, 1 ); - assert.strictEqual( array[ 0 ], undefined, "With array and offset: check [0]" ); - assert.strictEqual( array[ 1 ], x, "With array and offset: check x" ); - assert.strictEqual( array[ 2 ], y, "With array and offset: check y" ); - assert.strictEqual( array[ 3 ], z, "With array and offset: check z" ); - assert.strictEqual( array[ 4 ], w, "With array and offset: check w" ); + assert.strictEqual( array[ 0 ], undefined, 'With array and offset: check [0]' ); + assert.strictEqual( array[ 1 ], x, 'With array and offset: check x' ); + assert.strictEqual( array[ 2 ], y, 'With array and offset: check y' ); + assert.strictEqual( array[ 3 ], z, 'With array and offset: check z' ); + assert.strictEqual( array[ 4 ], w, 'With array and offset: check w' ); } ); - QUnit.test( "fromBufferAttribute", ( assert ) => { + QUnit.test( 'fromBufferAttribute', ( assert ) => { var a = new Quaternion(); @@ -786,7 +786,7 @@ export default QUnit.module( 'Maths', () => { } ); - QUnit.test( "_onChange", ( assert ) => { + QUnit.test( '_onChange', ( assert ) => { var b = false; var f = function () { @@ -797,36 +797,36 @@ export default QUnit.module( 'Maths', () => { var a = new Quaternion( 11, 12, 13, 1 ); a._onChange( f ); - assert.ok( a._onChangeCallback === f, "Passed!" ); + assert.ok( a._onChangeCallback === f, 'Passed!' ); a._onChangeCallback(); - assert.ok( b, "Passed!" ); + assert.ok( b, 'Passed!' ); } ); - QUnit.test( "_onChangeCallback", ( assert ) => { + QUnit.test( '_onChangeCallback', ( assert ) => { var b = false; var a = new Quaternion( 11, 12, 13, 1 ); var f = function () { b = true; - assert.ok( a === this, "Passed!" ); + assert.ok( a === this, 'Passed!' ); }; a._onChangeCallback = f; - assert.ok( a._onChangeCallback === f, "Passed!" ); + assert.ok( a._onChangeCallback === f, 'Passed!' ); a._onChangeCallback(); - assert.ok( b, "Passed!" ); + assert.ok( b, 'Passed!' ); } ); // OTHERS - QUnit.test( "multiplyVector3", ( assert ) => { + QUnit.test( 'multiplyVector3', ( assert ) => { var angles = [ new Euler( 1, 0, 0 ), new Euler( 0, 1, 0 ), new Euler( 0, 0, 1 ) ]; @@ -842,7 +842,7 @@ export default QUnit.module( 'Maths', () => { var qv = v0.clone().applyQuaternion( q ); var mv = v0.clone().applyMatrix4( m ); - assert.ok( qv.distanceTo( mv ) < 0.001, "Passed!" ); + assert.ok( qv.distanceTo( mv ) < 0.001, 'Passed!' ); } diff --git a/test/unit/src/math/Ray.tests.js b/test/unit/src/math/Ray.tests.js index 23ccf0f4809f63..41bb181992c407 100644 --- a/test/unit/src/math/Ray.tests.js +++ b/test/unit/src/math/Ray.tests.js @@ -19,151 +19,151 @@ export default QUnit.module( 'Maths', () => { QUnit.module( 'Ray', () => { // INSTANCING - QUnit.test( "Instancing", ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { var a = new Ray(); - assert.ok( a.origin.equals( zero3 ), "Passed!" ); - assert.ok( a.direction.equals( new Vector3( 0, 0, - 1 ) ), "Passed!" ); + assert.ok( a.origin.equals( zero3 ), 'Passed!' ); + assert.ok( a.direction.equals( new Vector3( 0, 0, - 1 ) ), 'Passed!' ); var a = new Ray( two3.clone(), one3.clone() ); - assert.ok( a.origin.equals( two3 ), "Passed!" ); - assert.ok( a.direction.equals( one3 ), "Passed!" ); + assert.ok( a.origin.equals( two3 ), 'Passed!' ); + assert.ok( a.direction.equals( one3 ), 'Passed!' ); } ); // PUBLIC STUFF - QUnit.todo( "isRay", ( assert ) => { + QUnit.todo( 'isRay', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "set", ( assert ) => { + QUnit.test( 'set', ( assert ) => { var a = new Ray(); a.set( one3, one3 ); - assert.ok( a.origin.equals( one3 ), "Passed!" ); - assert.ok( a.direction.equals( one3 ), "Passed!" ); + assert.ok( a.origin.equals( one3 ), 'Passed!' ); + assert.ok( a.direction.equals( one3 ), 'Passed!' ); } ); - QUnit.test( "recast/clone", ( assert ) => { + QUnit.test( 'recast/clone', ( assert ) => { var a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); - assert.ok( a.recast( 0 ).equals( a ), "Passed!" ); + assert.ok( a.recast( 0 ).equals( a ), 'Passed!' ); var b = a.clone(); - assert.ok( b.recast( - 1 ).equals( new Ray( new Vector3( 1, 1, 0 ), new Vector3( 0, 0, 1 ) ) ), "Passed!" ); + assert.ok( b.recast( - 1 ).equals( new Ray( new Vector3( 1, 1, 0 ), new Vector3( 0, 0, 1 ) ) ), 'Passed!' ); var c = a.clone(); - assert.ok( c.recast( 1 ).equals( new Ray( new Vector3( 1, 1, 2 ), new Vector3( 0, 0, 1 ) ) ), "Passed!" ); + assert.ok( c.recast( 1 ).equals( new Ray( new Vector3( 1, 1, 2 ), new Vector3( 0, 0, 1 ) ) ), 'Passed!' ); var d = a.clone(); var e = d.clone().recast( 1 ); - assert.ok( d.equals( a ), "Passed!" ); - assert.ok( ! e.equals( d ), "Passed!" ); - assert.ok( e.equals( c ), "Passed!" ); + assert.ok( d.equals( a ), 'Passed!' ); + assert.ok( ! e.equals( d ), 'Passed!' ); + assert.ok( e.equals( c ), 'Passed!' ); } ); - QUnit.test( "copy/equals", ( assert ) => { + QUnit.test( 'copy/equals', ( assert ) => { var a = new Ray( zero3.clone(), one3.clone() ); var b = new Ray().copy( a ); - assert.ok( b.origin.equals( zero3 ), "Passed!" ); - assert.ok( b.direction.equals( one3 ), "Passed!" ); + assert.ok( b.origin.equals( zero3 ), 'Passed!' ); + assert.ok( b.direction.equals( one3 ), 'Passed!' ); // ensure that it is a true copy a.origin = zero3; a.direction = one3; - assert.ok( b.origin.equals( zero3 ), "Passed!" ); - assert.ok( b.direction.equals( one3 ), "Passed!" ); + assert.ok( b.origin.equals( zero3 ), 'Passed!' ); + assert.ok( b.direction.equals( one3 ), 'Passed!' ); } ); - QUnit.test( "at", ( assert ) => { + QUnit.test( 'at', ( assert ) => { var a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); var point = new Vector3(); a.at( 0, point ); - assert.ok( point.equals( one3 ), "Passed!" ); + assert.ok( point.equals( one3 ), 'Passed!' ); a.at( - 1, point ); - assert.ok( point.equals( new Vector3( 1, 1, 0 ) ), "Passed!" ); + assert.ok( point.equals( new Vector3( 1, 1, 0 ) ), 'Passed!' ); a.at( 1, point ); - assert.ok( point.equals( new Vector3( 1, 1, 2 ) ), "Passed!" ); + assert.ok( point.equals( new Vector3( 1, 1, 2 ) ), 'Passed!' ); } ); - QUnit.test( "lookAt", ( assert ) => { + QUnit.test( 'lookAt', ( assert ) => { var a = new Ray( two3.clone(), one3.clone() ); var target = one3.clone(); var expected = target.sub( two3 ).normalize(); a.lookAt( target ); - assert.ok( a.direction.equals( expected ), "Check if we're looking in the right direction" ); + assert.ok( a.direction.equals( expected ), 'Check if we\'re looking in the right direction' ); } ); - QUnit.test( "closestPointToPoint", ( assert ) => { + QUnit.test( 'closestPointToPoint', ( assert ) => { var a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); var point = new Vector3(); // behind the ray a.closestPointToPoint( zero3, point ); - assert.ok( point.equals( one3 ), "Passed!" ); + assert.ok( point.equals( one3 ), 'Passed!' ); // front of the ray a.closestPointToPoint( new Vector3( 0, 0, 50 ), point ); - assert.ok( point.equals( new Vector3( 1, 1, 50 ) ), "Passed!" ); + assert.ok( point.equals( new Vector3( 1, 1, 50 ) ), 'Passed!' ); // exactly on the ray a.closestPointToPoint( one3, point ); - assert.ok( point.equals( one3 ), "Passed!" ); + assert.ok( point.equals( one3 ), 'Passed!' ); } ); - QUnit.test( "distanceToPoint", ( assert ) => { + QUnit.test( 'distanceToPoint', ( assert ) => { var a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); // behind the ray var b = a.distanceToPoint( zero3 ); - assert.ok( b === Math.sqrt( 3 ), "Passed!" ); + assert.ok( b === Math.sqrt( 3 ), 'Passed!' ); // front of the ray var c = a.distanceToPoint( new Vector3( 0, 0, 50 ) ); - assert.ok( c === Math.sqrt( 2 ), "Passed!" ); + assert.ok( c === Math.sqrt( 2 ), 'Passed!' ); // exactly on the ray var d = a.distanceToPoint( one3 ); - assert.ok( d === 0, "Passed!" ); + assert.ok( d === 0, 'Passed!' ); } ); - QUnit.test( "distanceSqToPoint", ( assert ) => { + QUnit.test( 'distanceSqToPoint', ( assert ) => { var a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); // behind the ray var b = a.distanceSqToPoint( zero3 ); - assert.ok( b === 3, "Passed!" ); + assert.ok( b === 3, 'Passed!' ); // front of the ray var c = a.distanceSqToPoint( new Vector3( 0, 0, 50 ) ); - assert.ok( c === 2, "Passed!" ); + assert.ok( c === 2, 'Passed!' ); // exactly on the ray var d = a.distanceSqToPoint( one3 ); - assert.ok( d === 0, "Passed!" ); + assert.ok( d === 0, 'Passed!' ); } ); - QUnit.test( "distanceSqToSegment", ( assert ) => { + QUnit.test( 'distanceSqToSegment', ( assert ) => { var a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); var ptOnLine = new Vector3(); @@ -174,33 +174,33 @@ export default QUnit.module( 'Maths', () => { var v1 = new Vector3( 50, 50, 50 ); // just a far away point var distSqr = a.distanceSqToSegment( v0, v1, ptOnLine, ptOnSegment ); - assert.ok( ptOnSegment.distanceTo( v0 ) < 0.0001, "Passed!" ); - assert.ok( ptOnLine.distanceTo( new Vector3( 1, 1, 50 ) ) < 0.0001, "Passed!" ); + assert.ok( ptOnSegment.distanceTo( v0 ) < 0.0001, 'Passed!' ); + assert.ok( ptOnLine.distanceTo( new Vector3( 1, 1, 50 ) ) < 0.0001, 'Passed!' ); // ((3-1) * (3-1) + (5-1) * (5-1) = 4 + 16 = 20 - assert.ok( Math.abs( distSqr - 20 ) < 0.0001, "Passed!" ); + assert.ok( Math.abs( distSqr - 20 ) < 0.0001, 'Passed!' ); //segment behind the ray var v0 = new Vector3( - 50, - 50, - 50 ); // just a far away point var v1 = new Vector3( - 3, - 5, - 4 ); var distSqr = a.distanceSqToSegment( v0, v1, ptOnLine, ptOnSegment ); - assert.ok( ptOnSegment.distanceTo( v1 ) < 0.0001, "Passed!" ); - assert.ok( ptOnLine.distanceTo( one3 ) < 0.0001, "Passed!" ); + assert.ok( ptOnSegment.distanceTo( v1 ) < 0.0001, 'Passed!' ); + assert.ok( ptOnLine.distanceTo( one3 ) < 0.0001, 'Passed!' ); // ((-3-1) * (-3-1) + (-5-1) * (-5-1) + (-4-1) + (-4-1) = 16 + 36 + 25 = 77 - assert.ok( Math.abs( distSqr - 77 ) < 0.0001, "Passed!" ); + assert.ok( Math.abs( distSqr - 77 ) < 0.0001, 'Passed!' ); //exact intersection between the ray and the segment var v0 = new Vector3( - 50, - 50, - 50 ); var v1 = new Vector3( 50, 50, 50 ); var distSqr = a.distanceSqToSegment( v0, v1, ptOnLine, ptOnSegment ); - assert.ok( ptOnSegment.distanceTo( one3 ) < 0.0001, "Passed!" ); - assert.ok( ptOnLine.distanceTo( one3 ) < 0.0001, "Passed!" ); - assert.ok( distSqr < 0.0001, "Passed!" ); + assert.ok( ptOnSegment.distanceTo( one3 ) < 0.0001, 'Passed!' ); + assert.ok( ptOnLine.distanceTo( one3 ) < 0.0001, 'Passed!' ); + assert.ok( distSqr < 0.0001, 'Passed!' ); } ); - QUnit.test( "intersectSphere", ( assert ) => { + QUnit.test( 'intersectSphere', ( assert ) => { var TOL = 0.0001; var point = new Vector3(); @@ -213,37 +213,37 @@ export default QUnit.module( 'Maths', () => { // sphere (radius of 2) located behind ray a0, should result in null var b = new Sphere( new Vector3( 0, 0, 3 ), 2 ); a0.intersectSphere( b, point.copy( posInf3 ) ); - assert.ok( point.equals( posInf3 ), "Passed!" ); + assert.ok( point.equals( posInf3 ), 'Passed!' ); // sphere (radius of 2) located in front of, but too far right of ray a0, should result in null var b = new Sphere( new Vector3( 3, 0, - 1 ), 2 ); a0.intersectSphere( b, point.copy( posInf3 ) ); - assert.ok( point.equals( posInf3 ), "Passed!" ); + assert.ok( point.equals( posInf3 ), 'Passed!' ); // sphere (radius of 2) located below ray a1, should result in null var b = new Sphere( new Vector3( 1, - 2, 1 ), 2 ); a1.intersectSphere( b, point.copy( posInf3 ) ); - assert.ok( point.equals( posInf3 ), "Passed!" ); + assert.ok( point.equals( posInf3 ), 'Passed!' ); // sphere (radius of 1) located to the left of ray a1, should result in intersection at 0, 1, 1 var b = new Sphere( new Vector3( - 1, 1, 1 ), 1 ); a1.intersectSphere( b, point ); - assert.ok( point.distanceTo( new Vector3( 0, 1, 1 ) ) < TOL, "Passed!" ); + assert.ok( point.distanceTo( new Vector3( 0, 1, 1 ) ) < TOL, 'Passed!' ); // sphere (radius of 1) located in front of ray a0, should result in intersection at 0, 0, -1 var b = new Sphere( new Vector3( 0, 0, - 2 ), 1 ); a0.intersectSphere( b, point ); - assert.ok( point.distanceTo( new Vector3( 0, 0, - 1 ) ) < TOL, "Passed!" ); + assert.ok( point.distanceTo( new Vector3( 0, 0, - 1 ) ) < TOL, 'Passed!' ); // sphere (radius of 2) located in front & right of ray a0, should result in intersection at 0, 0, -1, or left-most edge of sphere var b = new Sphere( new Vector3( 2, 0, - 1 ), 2 ); a0.intersectSphere( b, point ); - assert.ok( point.distanceTo( new Vector3( 0, 0, - 1 ) ) < TOL, "Passed!" ); + assert.ok( point.distanceTo( new Vector3( 0, 0, - 1 ) ) < TOL, 'Passed!' ); // same situation as above, but move the sphere a fraction more to the right, and ray a0 should now just miss var b = new Sphere( new Vector3( 2.01, 0, - 1 ), 2 ); a0.intersectSphere( b, point.copy( posInf3 ) ); - assert.ok( point.equals( posInf3 ), "Passed!" ); + assert.ok( point.equals( posInf3 ), 'Passed!' ); // following QUnit.tests are for situations where the ray origin is inside the sphere @@ -252,25 +252,25 @@ export default QUnit.module( 'Maths', () => { // thus keeping the intersection point always in front of the ray. var b = new Sphere( zero3.clone(), 1 ); a0.intersectSphere( b, point ); - assert.ok( point.distanceTo( new Vector3( 0, 0, - 1 ) ) < TOL, "Passed!" ); + assert.ok( point.distanceTo( new Vector3( 0, 0, - 1 ) ) < TOL, 'Passed!' ); // sphere (radius of 4) center located behind ray a0 origin / sphere surrounds the ray origin, so the first intersect point 0, 0, 5, // is behind ray a0. Therefore, second exit point on back of sphere will be returned: 0, 0, -3 // thus keeping the intersection point always in front of the ray. var b = new Sphere( new Vector3( 0, 0, 1 ), 4 ); a0.intersectSphere( b, point ); - assert.ok( point.distanceTo( new Vector3( 0, 0, - 3 ) ) < TOL, "Passed!" ); + assert.ok( point.distanceTo( new Vector3( 0, 0, - 3 ) ) < TOL, 'Passed!' ); // sphere (radius of 4) center located in front of ray a0 origin / sphere surrounds the ray origin, so the first intersect point 0, 0, 3, // is behind ray a0. Therefore, second exit point on back of sphere will be returned: 0, 0, -5 // thus keeping the intersection point always in front of the ray. var b = new Sphere( new Vector3( 0, 0, - 1 ), 4 ); a0.intersectSphere( b, point ); - assert.ok( point.distanceTo( new Vector3( 0, 0, - 5 ) ) < TOL, "Passed!" ); + assert.ok( point.distanceTo( new Vector3( 0, 0, - 5 ) ) < TOL, 'Passed!' ); } ); - QUnit.test( "intersectsSphere", ( assert ) => { + QUnit.test( 'intersectsSphere', ( assert ) => { var a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); var b = new Sphere( zero3, 0.5 ); @@ -279,21 +279,21 @@ export default QUnit.module( 'Maths', () => { var e = new Sphere( two3, 0.1 ); var f = new Sphere( two3, 1 ); - assert.ok( ! a.intersectsSphere( b ), "Passed!" ); - assert.ok( ! a.intersectsSphere( c ), "Passed!" ); - assert.ok( a.intersectsSphere( d ), "Passed!" ); - assert.ok( ! a.intersectsSphere( e ), "Passed!" ); - assert.ok( ! a.intersectsSphere( f ), "Passed!" ); + assert.ok( ! a.intersectsSphere( b ), 'Passed!' ); + assert.ok( ! a.intersectsSphere( c ), 'Passed!' ); + assert.ok( a.intersectsSphere( d ), 'Passed!' ); + assert.ok( ! a.intersectsSphere( e ), 'Passed!' ); + assert.ok( ! a.intersectsSphere( f ), 'Passed!' ); } ); - QUnit.todo( "distanceToPlane", ( assert ) => { + QUnit.todo( 'distanceToPlane', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "intersectPlane", ( assert ) => { + QUnit.test( 'intersectPlane', ( assert ) => { var a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); var point = new Vector3(); @@ -301,57 +301,57 @@ export default QUnit.module( 'Maths', () => { // parallel plane behind var b = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 0, 0, 1 ), new Vector3( 1, 1, - 1 ) ); a.intersectPlane( b, point.copy( posInf3 ) ); - assert.ok( point.equals( posInf3 ), "Passed!" ); + assert.ok( point.equals( posInf3 ), 'Passed!' ); // parallel plane coincident with origin var c = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 0, 0, 1 ), new Vector3( 1, 1, 0 ) ); a.intersectPlane( c, point.copy( posInf3 ) ); - assert.ok( point.equals( posInf3 ), "Passed!" ); + assert.ok( point.equals( posInf3 ), 'Passed!' ); // parallel plane infront var d = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 0, 0, 1 ), new Vector3( 1, 1, 1 ) ); a.intersectPlane( d, point.copy( posInf3 ) ); - assert.ok( point.equals( a.origin ), "Passed!" ); + assert.ok( point.equals( a.origin ), 'Passed!' ); // perpendical ray that overlaps exactly var e = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 1, 0, 0 ), one3 ); a.intersectPlane( e, point.copy( posInf3 ) ); - assert.ok( point.equals( a.origin ), "Passed!" ); + assert.ok( point.equals( a.origin ), 'Passed!' ); // perpendical ray that doesn't overlap var f = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 1, 0, 0 ), zero3 ); a.intersectPlane( f, point.copy( posInf3 ) ); - assert.ok( point.equals( posInf3 ), "Passed!" ); + assert.ok( point.equals( posInf3 ), 'Passed!' ); } ); - QUnit.test( "intersectsPlane", ( assert ) => { + QUnit.test( 'intersectsPlane', ( assert ) => { var a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); // parallel plane in front of the ray var b = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 0, 0, 1 ), one3.clone().sub( new Vector3( 0, 0, - 1 ) ) ); - assert.ok( a.intersectsPlane( b ), "Passed!" ); + assert.ok( a.intersectsPlane( b ), 'Passed!' ); // parallel plane coincident with origin var c = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 0, 0, 1 ), one3.clone().sub( new Vector3( 0, 0, 0 ) ) ); - assert.ok( a.intersectsPlane( c ), "Passed!" ); + assert.ok( a.intersectsPlane( c ), 'Passed!' ); // parallel plane behind the ray var d = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 0, 0, 1 ), one3.clone().sub( new Vector3( 0, 0, 1 ) ) ); - assert.ok( ! a.intersectsPlane( d ), "Passed!" ); + assert.ok( ! a.intersectsPlane( d ), 'Passed!' ); // perpendical ray that overlaps exactly var e = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 1, 0, 0 ), one3 ); - assert.ok( a.intersectsPlane( e ), "Passed!" ); + assert.ok( a.intersectsPlane( e ), 'Passed!' ); // perpendical ray that doesn't overlap var f = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 1, 0, 0 ), zero3 ); - assert.ok( ! a.intersectsPlane( f ), "Passed!" ); + assert.ok( ! a.intersectsPlane( f ), 'Passed!' ); } ); - QUnit.test( "intersectBox", ( assert ) => { + QUnit.test( 'intersectBox', ( assert ) => { var TOL = 0.0001; @@ -360,49 +360,49 @@ export default QUnit.module( 'Maths', () => { var a = new Ray( new Vector3( - 2, 0, 0 ), new Vector3( 1, 0, 0 ) ); //ray should intersect box at -1,0,0 - assert.ok( a.intersectsBox( box ) === true, "Passed!" ); + assert.ok( a.intersectsBox( box ) === true, 'Passed!' ); a.intersectBox( box, point ); - assert.ok( point.distanceTo( new Vector3( - 1, 0, 0 ) ) < TOL, "Passed!" ); + assert.ok( point.distanceTo( new Vector3( - 1, 0, 0 ) ) < TOL, 'Passed!' ); var b = new Ray( new Vector3( - 2, 0, 0 ), new Vector3( - 1, 0, 0 ) ); //ray is point away from box, it should not intersect - assert.ok( b.intersectsBox( box ) === false, "Passed!" ); + assert.ok( b.intersectsBox( box ) === false, 'Passed!' ); b.intersectBox( box, point.copy( posInf3 ) ); - assert.ok( point.equals( posInf3 ), "Passed!" ); + assert.ok( point.equals( posInf3 ), 'Passed!' ); var c = new Ray( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ) ); // ray is inside box, should return exit point - assert.ok( c.intersectsBox( box ) === true, "Passed!" ); + assert.ok( c.intersectsBox( box ) === true, 'Passed!' ); c.intersectBox( box, point ); - assert.ok( point.distanceTo( new Vector3( 1, 0, 0 ) ) < TOL, "Passed!" ); + assert.ok( point.distanceTo( new Vector3( 1, 0, 0 ) ) < TOL, 'Passed!' ); var d = new Ray( new Vector3( 0, 2, 1 ), new Vector3( 0, - 1, - 1 ).normalize() ); //tilted ray should intersect box at 0,1,0 - assert.ok( d.intersectsBox( box ) === true, "Passed!" ); + assert.ok( d.intersectsBox( box ) === true, 'Passed!' ); d.intersectBox( box, point ); - assert.ok( point.distanceTo( new Vector3( 0, 1, 0 ) ) < TOL, "Passed!" ); + assert.ok( point.distanceTo( new Vector3( 0, 1, 0 ) ) < TOL, 'Passed!' ); var e = new Ray( new Vector3( 1, - 2, 1 ), new Vector3( 0, 1, 0 ).normalize() ); //handle case where ray is coplanar with one of the boxes side - box in front of ray - assert.ok( e.intersectsBox( box ) === true, "Passed!" ); + assert.ok( e.intersectsBox( box ) === true, 'Passed!' ); e.intersectBox( box, point ); - assert.ok( point.distanceTo( new Vector3( 1, - 1, 1 ) ) < TOL, "Passed!" ); + assert.ok( point.distanceTo( new Vector3( 1, - 1, 1 ) ) < TOL, 'Passed!' ); var f = new Ray( new Vector3( 1, - 2, 0 ), new Vector3( 0, - 1, 0 ).normalize() ); //handle case where ray is coplanar with one of the boxes side - box behind ray - assert.ok( f.intersectsBox( box ) === false, "Passed!" ); + assert.ok( f.intersectsBox( box ) === false, 'Passed!' ); f.intersectBox( box, point.copy( posInf3 ) ); - assert.ok( point.equals( posInf3 ), "Passed!" ); + assert.ok( point.equals( posInf3 ), 'Passed!' ); } ); - QUnit.todo( "intersectsBox", ( assert ) => { + QUnit.todo( 'intersectsBox', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "intersectTriangle", ( assert ) => { + QUnit.test( 'intersectTriangle', ( assert ) => { var ray = new Ray(); var a = new Vector3( 1, 1, 0 ); @@ -413,73 +413,73 @@ export default QUnit.module( 'Maths', () => { // DdN == 0 ray.set( ray.origin, zero3.clone() ); ray.intersectTriangle( a, b, c, false, point.copy( posInf3 ) ); - assert.ok( point.equals( posInf3 ), "No intersection if direction == zero" ); + assert.ok( point.equals( posInf3 ), 'No intersection if direction == zero' ); // DdN > 0, backfaceCulling = true ray.set( ray.origin, one3.clone() ); ray.intersectTriangle( a, b, c, true, point.copy( posInf3 ) ); - assert.ok( point.equals( posInf3 ), "No intersection with backside faces if backfaceCulling is true" ); + assert.ok( point.equals( posInf3 ), 'No intersection with backside faces if backfaceCulling is true' ); // DdN > 0 ray.set( ray.origin, one3.clone() ); ray.intersectTriangle( a, b, c, false, point ); - assert.ok( Math.abs( point.x - 2 / 3 ) <= eps, "Successful intersection: check x" ); - assert.ok( Math.abs( point.y - 2 / 3 ) <= eps, "Successful intersection: check y" ); - assert.ok( Math.abs( point.z - 2 / 3 ) <= eps, "Successful intersection: check z" ); + assert.ok( Math.abs( point.x - 2 / 3 ) <= eps, 'Successful intersection: check x' ); + assert.ok( Math.abs( point.y - 2 / 3 ) <= eps, 'Successful intersection: check y' ); + assert.ok( Math.abs( point.z - 2 / 3 ) <= eps, 'Successful intersection: check z' ); // DdN > 0, DdQxE2 < 0 b.multiplyScalar( - 1 ); ray.intersectTriangle( a, b, c, false, point.copy( posInf3 ) ); - assert.ok( point.equals( posInf3 ), "No intersection" ); + assert.ok( point.equals( posInf3 ), 'No intersection' ); // DdN > 0, DdE1xQ < 0 a.multiplyScalar( - 1 ); ray.intersectTriangle( a, b, c, false, point.copy( posInf3 ) ); - assert.ok( point.equals( posInf3 ), "No intersection" ); + assert.ok( point.equals( posInf3 ), 'No intersection' ); // DdN > 0, DdQxE2 + DdE1xQ > DdN b.multiplyScalar( - 1 ); ray.intersectTriangle( a, b, c, false, point.copy( posInf3 ) ); - assert.ok( point.equals( posInf3 ), "No intersection" ); + assert.ok( point.equals( posInf3 ), 'No intersection' ); // DdN < 0, QdN < 0 a.multiplyScalar( - 1 ); b.multiplyScalar( - 1 ); ray.direction.multiplyScalar( - 1 ); ray.intersectTriangle( a, b, c, false, point.copy( posInf3 ) ); - assert.ok( point.equals( posInf3 ), "No intersection when looking in the wrong direction" ); + assert.ok( point.equals( posInf3 ), 'No intersection when looking in the wrong direction' ); } ); - QUnit.test( "applyMatrix4", ( assert ) => { + QUnit.test( 'applyMatrix4', ( assert ) => { var a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); var m = new Matrix4(); - assert.ok( a.clone().applyMatrix4( m ).equals( a ), "Passed!" ); + assert.ok( a.clone().applyMatrix4( m ).equals( a ), 'Passed!' ); var a = new Ray( zero3.clone(), new Vector3( 0, 0, 1 ) ); m.makeRotationZ( Math.PI ); - assert.ok( a.clone().applyMatrix4( m ).equals( a ), "Passed!" ); + assert.ok( a.clone().applyMatrix4( m ).equals( a ), 'Passed!' ); m.makeRotationX( Math.PI ); var b = a.clone(); b.direction.negate(); var a2 = a.clone().applyMatrix4( m ); - assert.ok( a2.origin.distanceTo( b.origin ) < 0.0001, "Passed!" ); - assert.ok( a2.direction.distanceTo( b.direction ) < 0.0001, "Passed!" ); + assert.ok( a2.origin.distanceTo( b.origin ) < 0.0001, 'Passed!' ); + assert.ok( a2.direction.distanceTo( b.direction ) < 0.0001, 'Passed!' ); a.origin = new Vector3( 0, 0, 1 ); b.origin = new Vector3( 0, 0, - 1 ); var a2 = a.clone().applyMatrix4( m ); - assert.ok( a2.origin.distanceTo( b.origin ) < 0.0001, "Passed!" ); - assert.ok( a2.direction.distanceTo( b.direction ) < 0.0001, "Passed!" ); + assert.ok( a2.origin.distanceTo( b.origin ) < 0.0001, 'Passed!' ); + assert.ok( a2.direction.distanceTo( b.direction ) < 0.0001, 'Passed!' ); } ); - QUnit.todo( "equals", ( assert ) => { + QUnit.todo( 'equals', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/math/Spherical.tests.js b/test/unit/src/math/Spherical.tests.js index 7043ed6d34f17f..b873edbebf3b4a 100644 --- a/test/unit/src/math/Spherical.tests.js +++ b/test/unit/src/math/Spherical.tests.js @@ -11,32 +11,32 @@ export default QUnit.module( 'Maths', () => { QUnit.module( 'Spherical', () => { // INSTANCING - QUnit.test( "Instancing", ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { var a = new Spherical(); var radius = 10.0; var phi = Math.acos( - 0.5 ); var theta = Math.sqrt( Math.PI ) * phi; - assert.strictEqual( a.radius, 1.0, "Default values: check radius" ); - assert.strictEqual( a.phi, 0, "Default values: check phi" ); - assert.strictEqual( a.theta, 0, "Default values: check theta" ); + assert.strictEqual( a.radius, 1.0, 'Default values: check radius' ); + assert.strictEqual( a.phi, 0, 'Default values: check phi' ); + assert.strictEqual( a.theta, 0, 'Default values: check theta' ); var a = new Spherical( radius, phi, theta ); - assert.strictEqual( a.radius, radius, "Custom values: check radius" ); - assert.strictEqual( a.phi, phi, "Custom values: check phi" ); - assert.strictEqual( a.theta, theta, "Custom values: check theta" ); + assert.strictEqual( a.radius, radius, 'Custom values: check radius' ); + assert.strictEqual( a.phi, phi, 'Custom values: check phi' ); + assert.strictEqual( a.theta, theta, 'Custom values: check theta' ); } ); // PUBLIC STUFF - QUnit.todo( "isSpherical", ( assert ) => { + QUnit.todo( 'isSpherical', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "set", ( assert ) => { + QUnit.test( 'set', ( assert ) => { var a = new Spherical(); var radius = 10.0; @@ -44,13 +44,13 @@ export default QUnit.module( 'Maths', () => { var theta = Math.sqrt( Math.PI ) * phi; a.set( radius, phi, theta ); - assert.strictEqual( a.radius, radius, "Check radius" ); - assert.strictEqual( a.phi, phi, "Check phi" ); - assert.strictEqual( a.theta, theta, "Check theta" ); + assert.strictEqual( a.radius, radius, 'Check radius' ); + assert.strictEqual( a.phi, phi, 'Check phi' ); + assert.strictEqual( a.theta, theta, 'Check theta' ); } ); - QUnit.test( "clone", ( assert ) => { + QUnit.test( 'clone', ( assert ) => { var radius = 10.0; var phi = Math.acos( - 0.5 ); @@ -58,14 +58,14 @@ export default QUnit.module( 'Maths', () => { var a = new Spherical( radius, phi, theta ); var b = a.clone(); - assert.propEqual( a, b, "Check a and b are equal after clone()" ); + assert.propEqual( a, b, 'Check a and b are equal after clone()' ); a.radius = 2.0; - assert.notPropEqual( a, b, "Check a and b are not equal after modification" ); + assert.notPropEqual( a, b, 'Check a and b are not equal after modification' ); } ); - QUnit.test( "copy", ( assert ) => { + QUnit.test( 'copy', ( assert ) => { var radius = 10.0; var phi = Math.acos( - 0.5 ); @@ -73,14 +73,14 @@ export default QUnit.module( 'Maths', () => { var a = new Spherical( radius, phi, theta ); var b = new Spherical().copy( a ); - assert.propEqual( a, b, "Check a and b are equal after copy()" ); + assert.propEqual( a, b, 'Check a and b are equal after copy()' ); a.radius = 2.0; - assert.notPropEqual( a, b, "Check a and b are not equal after modification" ); + assert.notPropEqual( a, b, 'Check a and b are not equal after modification' ); } ); - QUnit.test( "makeSafe", ( assert ) => { + QUnit.test( 'makeSafe', ( assert ) => { var EPS = 0.000001; // from source var tooLow = 0.0; @@ -89,19 +89,19 @@ export default QUnit.module( 'Maths', () => { var a = new Spherical( 1, tooLow, 0 ); a.makeSafe(); - assert.strictEqual( a.phi, EPS, "Check if small values are set to EPS" ); + assert.strictEqual( a.phi, EPS, 'Check if small values are set to EPS' ); a.set( 1, tooHigh, 0 ); a.makeSafe(); - assert.strictEqual( a.phi, Math.PI - EPS, "Check if high values are set to (Math.PI - EPS)" ); + assert.strictEqual( a.phi, Math.PI - EPS, 'Check if high values are set to (Math.PI - EPS)' ); a.set( 1, justRight, 0 ); a.makeSafe(); - assert.strictEqual( a.phi, justRight, "Check that valid values don't get changed" ); + assert.strictEqual( a.phi, justRight, 'Check that valid values don\'t get changed' ); } ); - QUnit.test( "setFromVector3", ( assert ) => { + QUnit.test( 'setFromVector3', ( assert ) => { var a = new Spherical( 1, 1, 1 ); var b = new Vector3( 0, 0, 0 ); @@ -109,14 +109,14 @@ export default QUnit.module( 'Maths', () => { var expected = new Spherical( 4.554032147688322, 1.3494066171539107, 2.356194490192345 ); a.setFromVector3( b ); - assert.strictEqual( a.radius, 0, "Zero-length vector: check radius" ); - assert.strictEqual( a.phi, 0, "Zero-length vector: check phi" ); - assert.strictEqual( a.theta, 0, "Zero-length vector: check theta" ); + assert.strictEqual( a.radius, 0, 'Zero-length vector: check radius' ); + assert.strictEqual( a.phi, 0, 'Zero-length vector: check phi' ); + assert.strictEqual( a.theta, 0, 'Zero-length vector: check theta' ); a.setFromVector3( c ); - assert.ok( Math.abs( a.radius - expected.radius ) <= eps, "Normal vector: check radius" ); - assert.ok( Math.abs( a.phi - expected.phi ) <= eps, "Normal vector: check phi" ); - assert.ok( Math.abs( a.theta - expected.theta ) <= eps, "Normal vector: check theta" ); + assert.ok( Math.abs( a.radius - expected.radius ) <= eps, 'Normal vector: check radius' ); + assert.ok( Math.abs( a.phi - expected.phi ) <= eps, 'Normal vector: check phi' ); + assert.ok( Math.abs( a.theta - expected.theta ) <= eps, 'Normal vector: check theta' ); } ); diff --git a/test/unit/src/math/Triangle.tests.js b/test/unit/src/math/Triangle.tests.js index 5a81e04c15fe7a..1044674312ac95 100644 --- a/test/unit/src/math/Triangle.tests.js +++ b/test/unit/src/math/Triangle.tests.js @@ -16,182 +16,182 @@ export default QUnit.module( 'Maths', () => { QUnit.module( 'Triangle', () => { // INSTANCING - QUnit.test( "Instancing", ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { var a = new Triangle(); - assert.ok( a.a.equals( zero3 ), "Passed!" ); - assert.ok( a.b.equals( zero3 ), "Passed!" ); - assert.ok( a.c.equals( zero3 ), "Passed!" ); + assert.ok( a.a.equals( zero3 ), 'Passed!' ); + assert.ok( a.b.equals( zero3 ), 'Passed!' ); + assert.ok( a.c.equals( zero3 ), 'Passed!' ); var a = new Triangle( one3.clone().negate(), one3.clone(), two3.clone() ); - assert.ok( a.a.equals( one3.clone().negate() ), "Passed!" ); - assert.ok( a.b.equals( one3 ), "Passed!" ); - assert.ok( a.c.equals( two3 ), "Passed!" ); + assert.ok( a.a.equals( one3.clone().negate() ), 'Passed!' ); + assert.ok( a.b.equals( one3 ), 'Passed!' ); + assert.ok( a.c.equals( two3 ), 'Passed!' ); } ); // STATIC STUFF - QUnit.todo( "getNormal", ( assert ) => { + QUnit.todo( 'getNormal', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getBarycoord", ( assert ) => { + QUnit.todo( 'getBarycoord', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "containsPoint", ( assert ) => { + QUnit.todo( 'containsPoint', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.test( "set", ( assert ) => { + QUnit.test( 'set', ( assert ) => { var a = new Triangle(); a.set( one3.clone().negate(), one3, two3 ); - assert.ok( a.a.equals( one3.clone().negate() ), "Passed!" ); - assert.ok( a.b.equals( one3 ), "Passed!" ); - assert.ok( a.c.equals( two3 ), "Passed!" ); + assert.ok( a.a.equals( one3.clone().negate() ), 'Passed!' ); + assert.ok( a.b.equals( one3 ), 'Passed!' ); + assert.ok( a.c.equals( two3 ), 'Passed!' ); } ); - QUnit.test( "setFromPointsAndIndices", ( assert ) => { + QUnit.test( 'setFromPointsAndIndices', ( assert ) => { var a = new Triangle(); var points = [ one3, one3.clone().negate(), two3 ]; a.setFromPointsAndIndices( points, 1, 0, 2 ); - assert.ok( a.a.equals( one3.clone().negate() ), "Passed!" ); - assert.ok( a.b.equals( one3 ), "Passed!" ); - assert.ok( a.c.equals( two3 ), "Passed!" ); + assert.ok( a.a.equals( one3.clone().negate() ), 'Passed!' ); + assert.ok( a.b.equals( one3 ), 'Passed!' ); + assert.ok( a.c.equals( two3 ), 'Passed!' ); } ); - QUnit.test( "setFromAttributeAndIndices", ( assert ) => { + QUnit.test( 'setFromAttributeAndIndices', ( assert ) => { var a = new Triangle(); var attribute = new BufferAttribute( new Float32Array( [ 1, 1, 1, - 1, - 1, - 1, 2, 2, 2 ] ), 3 ); a.setFromAttributeAndIndices( attribute, 1, 0, 2 ); - assert.ok( a.a.equals( one3.clone().negate() ), "Passed!" ); - assert.ok( a.b.equals( one3 ), "Passed!" ); - assert.ok( a.c.equals( two3 ), "Passed!" ); + assert.ok( a.a.equals( one3.clone().negate() ), 'Passed!' ); + assert.ok( a.b.equals( one3 ), 'Passed!' ); + assert.ok( a.c.equals( two3 ), 'Passed!' ); } ); - QUnit.todo( "clone", ( assert ) => { + QUnit.todo( 'clone', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "copy", ( assert ) => { + QUnit.test( 'copy', ( assert ) => { var a = new Triangle( one3.clone().negate(), one3.clone(), two3.clone() ); var b = new Triangle().copy( a ); - assert.ok( b.a.equals( one3.clone().negate() ), "Passed!" ); - assert.ok( b.b.equals( one3 ), "Passed!" ); - assert.ok( b.c.equals( two3 ), "Passed!" ); + assert.ok( b.a.equals( one3.clone().negate() ), 'Passed!' ); + assert.ok( b.b.equals( one3 ), 'Passed!' ); + assert.ok( b.c.equals( two3 ), 'Passed!' ); // ensure that it is a true copy a.a = one3; a.b = zero3; a.c = zero3; - assert.ok( b.a.equals( one3.clone().negate() ), "Passed!" ); - assert.ok( b.b.equals( one3 ), "Passed!" ); - assert.ok( b.c.equals( two3 ), "Passed!" ); + assert.ok( b.a.equals( one3.clone().negate() ), 'Passed!' ); + assert.ok( b.b.equals( one3 ), 'Passed!' ); + assert.ok( b.c.equals( two3 ), 'Passed!' ); } ); - QUnit.test( "getArea", ( assert ) => { + QUnit.test( 'getArea', ( assert ) => { var a = new Triangle(); - assert.ok( a.getArea() == 0, "Passed!" ); + assert.ok( a.getArea() == 0, 'Passed!' ); var a = new Triangle( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); - assert.ok( a.getArea() == 0.5, "Passed!" ); + assert.ok( a.getArea() == 0.5, 'Passed!' ); var a = new Triangle( new Vector3( 2, 0, 0 ), new Vector3( 0, 0, 0 ), new Vector3( 0, 0, 2 ) ); - assert.ok( a.getArea() == 2, "Passed!" ); + assert.ok( a.getArea() == 2, 'Passed!' ); // colinear triangle. var a = new Triangle( new Vector3( 2, 0, 0 ), new Vector3( 0, 0, 0 ), new Vector3( 3, 0, 0 ) ); - assert.ok( a.getArea() == 0, "Passed!" ); + assert.ok( a.getArea() == 0, 'Passed!' ); } ); - QUnit.test( "getMidpoint", ( assert ) => { + QUnit.test( 'getMidpoint', ( assert ) => { var a = new Triangle(); var midpoint = new Vector3(); - assert.ok( a.getMidpoint( midpoint ).equals( new Vector3( 0, 0, 0 ) ), "Passed!" ); + assert.ok( a.getMidpoint( midpoint ).equals( new Vector3( 0, 0, 0 ) ), 'Passed!' ); var a = new Triangle( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); - assert.ok( a.getMidpoint( midpoint ).equals( new Vector3( 1 / 3, 1 / 3, 0 ) ), "Passed!" ); + assert.ok( a.getMidpoint( midpoint ).equals( new Vector3( 1 / 3, 1 / 3, 0 ) ), 'Passed!' ); var a = new Triangle( new Vector3( 2, 0, 0 ), new Vector3( 0, 0, 0 ), new Vector3( 0, 0, 2 ) ); - assert.ok( a.getMidpoint( midpoint ).equals( new Vector3( 2 / 3, 0, 2 / 3 ) ), "Passed!" ); + assert.ok( a.getMidpoint( midpoint ).equals( new Vector3( 2 / 3, 0, 2 / 3 ) ), 'Passed!' ); } ); - QUnit.test( "getNormal", ( assert ) => { + QUnit.test( 'getNormal', ( assert ) => { var a = new Triangle(); var normal = new Vector3(); - assert.ok( a.getNormal( normal ).equals( new Vector3( 0, 0, 0 ) ), "Passed!" ); + assert.ok( a.getNormal( normal ).equals( new Vector3( 0, 0, 0 ) ), 'Passed!' ); var a = new Triangle( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); - assert.ok( a.getNormal( normal ).equals( new Vector3( 0, 0, 1 ) ), "Passed!" ); + assert.ok( a.getNormal( normal ).equals( new Vector3( 0, 0, 1 ) ), 'Passed!' ); var a = new Triangle( new Vector3( 2, 0, 0 ), new Vector3( 0, 0, 0 ), new Vector3( 0, 0, 2 ) ); - assert.ok( a.getNormal( normal ).equals( new Vector3( 0, 1, 0 ) ), "Passed!" ); + assert.ok( a.getNormal( normal ).equals( new Vector3( 0, 1, 0 ) ), 'Passed!' ); } ); - QUnit.test( "getPlane", ( assert ) => { + QUnit.test( 'getPlane', ( assert ) => { var a = new Triangle(); var plane = new Plane(); var normal = new Vector3(); a.getPlane( plane ); - assert.notOk( isNaN( plane.distanceToPoint( a.a ) ), "Passed!" ); - assert.notOk( isNaN( plane.distanceToPoint( a.b ) ), "Passed!" ); - assert.notOk( isNaN( plane.distanceToPoint( a.c ) ), "Passed!" ); + assert.notOk( isNaN( plane.distanceToPoint( a.a ) ), 'Passed!' ); + assert.notOk( isNaN( plane.distanceToPoint( a.b ) ), 'Passed!' ); + assert.notOk( isNaN( plane.distanceToPoint( a.c ) ), 'Passed!' ); assert.notPropEqual( plane.normal, { x: NaN, y: NaN, z: NaN - }, "Passed!" ); + }, 'Passed!' ); var a = new Triangle( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); a.getPlane( plane ); a.getNormal( normal ); - assert.ok( plane.distanceToPoint( a.a ) == 0, "Passed!" ); - assert.ok( plane.distanceToPoint( a.b ) == 0, "Passed!" ); - assert.ok( plane.distanceToPoint( a.c ) == 0, "Passed!" ); - assert.ok( plane.normal.equals( normal ), "Passed!" ); + assert.ok( plane.distanceToPoint( a.a ) == 0, 'Passed!' ); + assert.ok( plane.distanceToPoint( a.b ) == 0, 'Passed!' ); + assert.ok( plane.distanceToPoint( a.c ) == 0, 'Passed!' ); + assert.ok( plane.normal.equals( normal ), 'Passed!' ); var a = new Triangle( new Vector3( 2, 0, 0 ), new Vector3( 0, 0, 0 ), new Vector3( 0, 0, 2 ) ); a.getPlane( plane ); a.getNormal( normal ); - assert.ok( plane.distanceToPoint( a.a ) == 0, "Passed!" ); - assert.ok( plane.distanceToPoint( a.b ) == 0, "Passed!" ); - assert.ok( plane.distanceToPoint( a.c ) == 0, "Passed!" ); - assert.ok( plane.normal.clone().normalize().equals( normal ), "Passed!" ); + assert.ok( plane.distanceToPoint( a.a ) == 0, 'Passed!' ); + assert.ok( plane.distanceToPoint( a.b ) == 0, 'Passed!' ); + assert.ok( plane.distanceToPoint( a.c ) == 0, 'Passed!' ); + assert.ok( plane.normal.clone().normalize().equals( normal ), 'Passed!' ); } ); - QUnit.test( "getBarycoord", ( assert ) => { + QUnit.test( 'getBarycoord', ( assert ) => { var a = new Triangle(); @@ -200,66 +200,66 @@ export default QUnit.module( 'Maths', () => { var midpoint = new Vector3(); a.getBarycoord( a.a, barycoord ); - assert.ok( barycoord.equals( bad ), "Passed!" ); + assert.ok( barycoord.equals( bad ), 'Passed!' ); a.getBarycoord( a.b, barycoord ); - assert.ok( barycoord.equals( bad ), "Passed!" ); + assert.ok( barycoord.equals( bad ), 'Passed!' ); a.getBarycoord( a.c, barycoord ); - assert.ok( barycoord.equals( bad ), "Passed!" ); + assert.ok( barycoord.equals( bad ), 'Passed!' ); var a = new Triangle( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); a.getMidpoint( midpoint ); a.getBarycoord( a.a, barycoord ); - assert.ok( barycoord.equals( new Vector3( 1, 0, 0 ) ), "Passed!" ); + assert.ok( barycoord.equals( new Vector3( 1, 0, 0 ) ), 'Passed!' ); a.getBarycoord( a.b, barycoord ); - assert.ok( barycoord.equals( new Vector3( 0, 1, 0 ) ), "Passed!" ); + assert.ok( barycoord.equals( new Vector3( 0, 1, 0 ) ), 'Passed!' ); a.getBarycoord( a.c, barycoord ); - assert.ok( barycoord.equals( new Vector3( 0, 0, 1 ) ), "Passed!" ); + assert.ok( barycoord.equals( new Vector3( 0, 0, 1 ) ), 'Passed!' ); a.getBarycoord( midpoint, barycoord ); - assert.ok( barycoord.distanceTo( new Vector3( 1 / 3, 1 / 3, 1 / 3 ) ) < 0.0001, "Passed!" ); + assert.ok( barycoord.distanceTo( new Vector3( 1 / 3, 1 / 3, 1 / 3 ) ) < 0.0001, 'Passed!' ); var a = new Triangle( new Vector3( 2, 0, 0 ), new Vector3( 0, 0, 0 ), new Vector3( 0, 0, 2 ) ); a.getMidpoint( midpoint ); a.getBarycoord( a.a, barycoord ); - assert.ok( barycoord.equals( new Vector3( 1, 0, 0 ) ), "Passed!" ); + assert.ok( barycoord.equals( new Vector3( 1, 0, 0 ) ), 'Passed!' ); a.getBarycoord( a.b, barycoord ); - assert.ok( barycoord.equals( new Vector3( 0, 1, 0 ) ), "Passed!" ); + assert.ok( barycoord.equals( new Vector3( 0, 1, 0 ) ), 'Passed!' ); a.getBarycoord( a.c, barycoord ); - assert.ok( barycoord.equals( new Vector3( 0, 0, 1 ) ), "Passed!" ); + assert.ok( barycoord.equals( new Vector3( 0, 0, 1 ) ), 'Passed!' ); a.getBarycoord( midpoint, barycoord ); - assert.ok( barycoord.distanceTo( new Vector3( 1 / 3, 1 / 3, 1 / 3 ) ) < 0.0001, "Passed!" ); + assert.ok( barycoord.distanceTo( new Vector3( 1 / 3, 1 / 3, 1 / 3 ) ) < 0.0001, 'Passed!' ); } ); - QUnit.test( "containsPoint", ( assert ) => { + QUnit.test( 'containsPoint', ( assert ) => { var a = new Triangle(); var midpoint = new Vector3(); - assert.ok( ! a.containsPoint( a.a ), "Passed!" ); - assert.ok( ! a.containsPoint( a.b ), "Passed!" ); - assert.ok( ! a.containsPoint( a.c ), "Passed!" ); + assert.ok( ! a.containsPoint( a.a ), 'Passed!' ); + assert.ok( ! a.containsPoint( a.b ), 'Passed!' ); + assert.ok( ! a.containsPoint( a.c ), 'Passed!' ); var a = new Triangle( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); a.getMidpoint( midpoint ); - assert.ok( a.containsPoint( a.a ), "Passed!" ); - assert.ok( a.containsPoint( a.b ), "Passed!" ); - assert.ok( a.containsPoint( a.c ), "Passed!" ); - assert.ok( a.containsPoint( midpoint ), "Passed!" ); - assert.ok( ! a.containsPoint( new Vector3( - 1, - 1, - 1 ) ), "Passed!" ); + assert.ok( a.containsPoint( a.a ), 'Passed!' ); + assert.ok( a.containsPoint( a.b ), 'Passed!' ); + assert.ok( a.containsPoint( a.c ), 'Passed!' ); + assert.ok( a.containsPoint( midpoint ), 'Passed!' ); + assert.ok( ! a.containsPoint( new Vector3( - 1, - 1, - 1 ) ), 'Passed!' ); var a = new Triangle( new Vector3( 2, 0, 0 ), new Vector3( 0, 0, 0 ), new Vector3( 0, 0, 2 ) ); a.getMidpoint( midpoint ); - assert.ok( a.containsPoint( a.a ), "Passed!" ); - assert.ok( a.containsPoint( a.b ), "Passed!" ); - assert.ok( a.containsPoint( a.c ), "Passed!" ); - assert.ok( a.containsPoint( midpoint ), "Passed!" ); - assert.ok( ! a.containsPoint( new Vector3( - 1, - 1, - 1 ) ), "Passed!" ); + assert.ok( a.containsPoint( a.a ), 'Passed!' ); + assert.ok( a.containsPoint( a.b ), 'Passed!' ); + assert.ok( a.containsPoint( a.c ), 'Passed!' ); + assert.ok( a.containsPoint( midpoint ), 'Passed!' ); + assert.ok( ! a.containsPoint( new Vector3( - 1, - 1, - 1 ) ), 'Passed!' ); } ); - QUnit.test( "intersectsBox", ( assert ) => { + QUnit.test( 'intersectsBox', ( assert ) => { var a = new Box3( one3.clone(), two3.clone() ); var b = new Triangle( new Vector3( 1.5, 1.5, 2.5 ), new Vector3( 2.5, 1.5, 1.5 ), new Vector3( 1.5, 2.5, 1.5 ) ); @@ -268,68 +268,68 @@ export default QUnit.module( 'Maths', () => { var e = new Triangle( new Vector3( 1.5, 1.8, 3 ), new Vector3( 3, 1.8, 1.5 ), new Vector3( 1.5, 2.5, 1.5 ) ); var f = new Triangle( new Vector3( 1.5, 2.5, 3 ), new Vector3( 3, 2.5, 1.5 ), new Vector3( 1.5, 2.5, 1.5 ) ); - assert.ok( b.intersectsBox( a ), "Passed!" ); - assert.ok( c.intersectsBox( a ), "Passed!" ); - assert.ok( d.intersectsBox( a ), "Passed!" ); - assert.ok( ! e.intersectsBox( a ), "Passed!" ); - assert.ok( ! f.intersectsBox( a ), "Passed!" ); + assert.ok( b.intersectsBox( a ), 'Passed!' ); + assert.ok( c.intersectsBox( a ), 'Passed!' ); + assert.ok( d.intersectsBox( a ), 'Passed!' ); + assert.ok( ! e.intersectsBox( a ), 'Passed!' ); + assert.ok( ! f.intersectsBox( a ), 'Passed!' ); } ); - QUnit.test( "closestPointToPoint", ( assert ) => { + QUnit.test( 'closestPointToPoint', ( assert ) => { var a = new Triangle( new Vector3( - 1, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); var point = new Vector3(); // point lies inside the triangle a.closestPointToPoint( new Vector3( 0, 0.5, 0 ), point ); - assert.ok( point.equals( new Vector3( 0, 0.5, 0 ) ), "Passed!" ); + assert.ok( point.equals( new Vector3( 0, 0.5, 0 ) ), 'Passed!' ); // point lies on a vertex a.closestPointToPoint( a.a, point ); - assert.ok( point.equals( a.a ), "Passed!" ); + assert.ok( point.equals( a.a ), 'Passed!' ); a.closestPointToPoint( a.b, point ); - assert.ok( point.equals( a.b ), "Passed!" ); + assert.ok( point.equals( a.b ), 'Passed!' ); a.closestPointToPoint( a.c, point ); - assert.ok( point.equals( a.c ), "Passed!" ); + assert.ok( point.equals( a.c ), 'Passed!' ); // point lies on an edge a.closestPointToPoint( zero3.clone(), point ); - assert.ok( point.equals( zero3.clone() ), "Passed!" ); + assert.ok( point.equals( zero3.clone() ), 'Passed!' ); // point lies outside the triangle a.closestPointToPoint( new Vector3( - 2, 0, 0 ), point ); - assert.ok( point.equals( new Vector3( - 1, 0, 0 ) ), "Passed!" ); + assert.ok( point.equals( new Vector3( - 1, 0, 0 ) ), 'Passed!' ); a.closestPointToPoint( new Vector3( 2, 0, 0 ), point ); - assert.ok( point.equals( new Vector3( 1, 0, 0 ) ), "Passed!" ); + assert.ok( point.equals( new Vector3( 1, 0, 0 ) ), 'Passed!' ); a.closestPointToPoint( new Vector3( 0, 2, 0 ), point ); - assert.ok( point.equals( new Vector3( 0, 1, 0 ) ), "Passed!" ); + assert.ok( point.equals( new Vector3( 0, 1, 0 ) ), 'Passed!' ); a.closestPointToPoint( new Vector3( 0, - 2, 0 ), point ); - assert.ok( point.equals( new Vector3( 0, 0, 0 ) ), "Passed!" ); + assert.ok( point.equals( new Vector3( 0, 0, 0 ) ), 'Passed!' ); } ); - QUnit.test( "isFrontFacing", ( assert ) => { + QUnit.test( 'isFrontFacing', ( assert ) => { var a = new Triangle(); var dir = new Vector3(); - assert.ok( ! a.isFrontFacing( dir ), "Passed!" ); + assert.ok( ! a.isFrontFacing( dir ), 'Passed!' ); var a = new Triangle( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); var dir = new Vector3( 0, 0, - 1 ); - assert.ok( a.isFrontFacing( dir ), "Passed!" ); + assert.ok( a.isFrontFacing( dir ), 'Passed!' ); var a = new Triangle( new Vector3( 0, 0, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 1, 0, 0 ) ); - assert.ok( ! a.isFrontFacing( dir ), "Passed!" ); + assert.ok( ! a.isFrontFacing( dir ), 'Passed!' ); } ); - QUnit.test( "equals", ( assert ) => { + QUnit.test( 'equals', ( assert ) => { var a = new Triangle( new Vector3( 1, 0, 0 ), @@ -347,13 +347,13 @@ export default QUnit.module( 'Maths', () => { new Vector3( 0, 0, 1 ) ); - assert.ok( a.equals( a ), "a equals a" ); - assert.notOk( a.equals( b ), "a does not equal b" ); - assert.notOk( a.equals( c ), "a does not equal c" ); - assert.notOk( b.equals( c ), "b does not equal c" ); + assert.ok( a.equals( a ), 'a equals a' ); + assert.notOk( a.equals( b ), 'a does not equal b' ); + assert.notOk( a.equals( c ), 'a does not equal c' ); + assert.notOk( b.equals( c ), 'b does not equal c' ); a.copy( b ); - assert.ok( a.equals( a ), "a equals b after copy()" ); + assert.ok( a.equals( a ), 'a equals b after copy()' ); } ); diff --git a/test/unit/src/math/Vector2.tests.js b/test/unit/src/math/Vector2.tests.js index 6db76dc499ce59..989845c466df7f 100644 --- a/test/unit/src/math/Vector2.tests.js +++ b/test/unit/src/math/Vector2.tests.js @@ -14,621 +14,621 @@ export default QUnit.module( 'Maths', () => { QUnit.module( 'Vector2', () => { // INSTANCING - QUnit.test( "Instancing", ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { var a = new Vector2(); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); + assert.ok( a.x == 0, 'Passed!' ); + assert.ok( a.y == 0, 'Passed!' ); var a = new Vector2( x, y ); - assert.ok( a.x === x, "Passed!" ); - assert.ok( a.y === y, "Passed!" ); + assert.ok( a.x === x, 'Passed!' ); + assert.ok( a.y === y, 'Passed!' ); } ); // PROPERTIES // ( [Itee] WHAT ??? o_O ) - QUnit.test( "properties", ( assert ) => { + QUnit.test( 'properties', ( assert ) => { var a = new Vector2( 0, 0 ); var width = 100; var height = 200; - assert.ok( a.width = width, "Set width" ); - assert.ok( a.height = height, "Set height" ); + assert.ok( a.width = width, 'Set width' ); + assert.ok( a.height = height, 'Set height' ); a.set( width, height ); - assert.strictEqual( a.width, width, "Get width" ); - assert.strictEqual( a.height, height, "Get height" ); + assert.strictEqual( a.width, width, 'Get width' ); + assert.strictEqual( a.height, height, 'Get height' ); } ); - QUnit.todo( "width", ( assert ) => { + QUnit.todo( 'width', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "height", ( assert ) => { + QUnit.todo( 'height', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isVector2", ( assert ) => { + QUnit.todo( 'isVector2', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "set", ( assert ) => { + QUnit.test( 'set', ( assert ) => { var a = new Vector2(); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); + assert.ok( a.x == 0, 'Passed!' ); + assert.ok( a.y == 0, 'Passed!' ); a.set( x, y ); - assert.ok( a.x == x, "Passed!" ); - assert.ok( a.y == y, "Passed!" ); + assert.ok( a.x == x, 'Passed!' ); + assert.ok( a.y == y, 'Passed!' ); } ); - QUnit.todo( "setScalar", ( assert ) => { + QUnit.todo( 'setScalar', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setX", ( assert ) => { + QUnit.todo( 'setX', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setY", ( assert ) => { + QUnit.todo( 'setY', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setComponent", ( assert ) => { + QUnit.todo( 'setComponent', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getComponent", ( assert ) => { + QUnit.todo( 'getComponent', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "clone", ( assert ) => { + QUnit.todo( 'clone', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "copy", ( assert ) => { + QUnit.test( 'copy', ( assert ) => { var a = new Vector2( x, y ); var b = new Vector2().copy( a ); - assert.ok( b.x == x, "Passed!" ); - assert.ok( b.y == y, "Passed!" ); + assert.ok( b.x == x, 'Passed!' ); + assert.ok( b.y == y, 'Passed!' ); // ensure that it is a true copy a.x = 0; a.y = - 1; - assert.ok( b.x == x, "Passed!" ); - assert.ok( b.y == y, "Passed!" ); + assert.ok( b.x == x, 'Passed!' ); + assert.ok( b.y == y, 'Passed!' ); } ); - QUnit.test( "add", ( assert ) => { + QUnit.test( 'add', ( assert ) => { var a = new Vector2( x, y ); var b = new Vector2( - x, - y ); a.add( b ); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); + assert.ok( a.x == 0, 'Passed!' ); + assert.ok( a.y == 0, 'Passed!' ); var c = new Vector2().addVectors( b, b ); - assert.ok( c.x == - 2 * x, "Passed!" ); - assert.ok( c.y == - 2 * y, "Passed!" ); + assert.ok( c.x == - 2 * x, 'Passed!' ); + assert.ok( c.y == - 2 * y, 'Passed!' ); } ); - QUnit.todo( "addScalar", ( assert ) => { + QUnit.todo( 'addScalar', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "addVectors", ( assert ) => { + QUnit.todo( 'addVectors', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "addScaledVector", ( assert ) => { + QUnit.test( 'addScaledVector', ( assert ) => { var a = new Vector2( x, y ); var b = new Vector2( 2, 3 ); var s = 3; a.addScaledVector( b, s ); - assert.strictEqual( a.x, x + b.x * s, "Check x" ); - assert.strictEqual( a.y, y + b.y * s, "Check y" ); + assert.strictEqual( a.x, x + b.x * s, 'Check x' ); + assert.strictEqual( a.y, y + b.y * s, 'Check y' ); } ); - QUnit.test( "sub", ( assert ) => { + QUnit.test( 'sub', ( assert ) => { var a = new Vector2( x, y ); var b = new Vector2( - x, - y ); a.sub( b ); - assert.ok( a.x == 2 * x, "Passed!" ); - assert.ok( a.y == 2 * y, "Passed!" ); + assert.ok( a.x == 2 * x, 'Passed!' ); + assert.ok( a.y == 2 * y, 'Passed!' ); var c = new Vector2().subVectors( a, a ); - assert.ok( c.x == 0, "Passed!" ); - assert.ok( c.y == 0, "Passed!" ); + assert.ok( c.x == 0, 'Passed!' ); + assert.ok( c.y == 0, 'Passed!' ); } ); - QUnit.todo( "subScalar", ( assert ) => { + QUnit.todo( 'subScalar', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "subVectors", ( assert ) => { + QUnit.todo( 'subVectors', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "multiply", ( assert ) => { + QUnit.todo( 'multiply', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "multiplyScalar", ( assert ) => { + QUnit.todo( 'multiplyScalar', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "divide", ( assert ) => { + QUnit.todo( 'divide', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "divideScalar", ( assert ) => { + QUnit.todo( 'divideScalar', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "applyMatrix3", ( assert ) => { + QUnit.test( 'applyMatrix3', ( assert ) => { var a = new Vector2( x, y ); var m = new Matrix3().set( 2, 3, 5, 7, 11, 13, 17, 19, 23 ); a.applyMatrix3( m ); - assert.strictEqual( a.x, 18, "Check x" ); - assert.strictEqual( a.y, 60, "Check y" ); + assert.strictEqual( a.x, 18, 'Check x' ); + assert.strictEqual( a.y, 60, 'Check y' ); } ); - QUnit.todo( "min", ( assert ) => { + QUnit.todo( 'min', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "max", ( assert ) => { + QUnit.todo( 'max', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "clamp", ( assert ) => { + QUnit.todo( 'clamp', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "clampScalar", ( assert ) => { + QUnit.todo( 'clampScalar', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "clampLength", ( assert ) => { + QUnit.todo( 'clampLength', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "floor", ( assert ) => { + QUnit.todo( 'floor', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "ceil", ( assert ) => { + QUnit.todo( 'ceil', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "round", ( assert ) => { + QUnit.todo( 'round', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "roundToZero", ( assert ) => { + QUnit.todo( 'roundToZero', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "negate", ( assert ) => { + QUnit.test( 'negate', ( assert ) => { var a = new Vector2( x, y ); a.negate(); - assert.ok( a.x == - x, "Passed!" ); - assert.ok( a.y == - y, "Passed!" ); + assert.ok( a.x == - x, 'Passed!' ); + assert.ok( a.y == - y, 'Passed!' ); } ); - QUnit.test( "dot", ( assert ) => { + QUnit.test( 'dot', ( assert ) => { var a = new Vector2( x, y ); var b = new Vector2( - x, - y ); var c = new Vector2(); var result = a.dot( b ); - assert.ok( result == ( - x * x - y * y ), "Passed!" ); + assert.ok( result == ( - x * x - y * y ), 'Passed!' ); var result = a.dot( c ); - assert.ok( result == 0, "Passed!" ); + assert.ok( result == 0, 'Passed!' ); } ); - QUnit.test( "cross", ( assert ) => { + QUnit.test( 'cross', ( assert ) => { var a = new Vector2( x, y ); var b = new Vector2( 2 * x, - y ); var answer = - 18; var crossed = a.cross( b ); - assert.ok( Math.abs( answer - crossed ) <= eps, "Check cross" ); + assert.ok( Math.abs( answer - crossed ) <= eps, 'Check cross' ); } ); - QUnit.todo( "lengthSq", ( assert ) => { + QUnit.todo( 'lengthSq', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "length", ( assert ) => { + QUnit.todo( 'length', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "manhattanLength", ( assert ) => { + QUnit.test( 'manhattanLength', ( assert ) => { var a = new Vector2( x, 0 ); var b = new Vector2( 0, - y ); var c = new Vector2(); - assert.strictEqual( a.manhattanLength(), x, "Positive component" ); - assert.strictEqual( b.manhattanLength(), y, "Negative component" ); - assert.strictEqual( c.manhattanLength(), 0, "Empty component" ); + assert.strictEqual( a.manhattanLength(), x, 'Positive component' ); + assert.strictEqual( b.manhattanLength(), y, 'Negative component' ); + assert.strictEqual( c.manhattanLength(), 0, 'Empty component' ); a.set( x, y ); - assert.strictEqual( a.manhattanLength(), Math.abs( x ) + Math.abs( y ), "Two components" ); + assert.strictEqual( a.manhattanLength(), Math.abs( x ) + Math.abs( y ), 'Two components' ); } ); - QUnit.test( "normalize", ( assert ) => { + QUnit.test( 'normalize', ( assert ) => { var a = new Vector2( x, 0 ); var b = new Vector2( 0, - y ); a.normalize(); - assert.ok( a.length() == 1, "Passed!" ); - assert.ok( a.x == 1, "Passed!" ); + assert.ok( a.length() == 1, 'Passed!' ); + assert.ok( a.x == 1, 'Passed!' ); b.normalize(); - assert.ok( b.length() == 1, "Passed!" ); - assert.ok( b.y == - 1, "Passed!" ); + assert.ok( b.length() == 1, 'Passed!' ); + assert.ok( b.y == - 1, 'Passed!' ); } ); - QUnit.todo( "angle", ( assert ) => { + QUnit.todo( 'angle', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "distanceTo", ( assert ) => { + QUnit.todo( 'distanceTo', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "distanceToSquared", ( assert ) => { + QUnit.todo( 'distanceToSquared', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "manhattanDistanceTo", ( assert ) => { + QUnit.todo( 'manhattanDistanceTo', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "setLength", ( assert ) => { + QUnit.test( 'setLength', ( assert ) => { var a = new Vector2( x, 0 ); - assert.ok( a.length() == x, "Passed!" ); + assert.ok( a.length() == x, 'Passed!' ); a.setLength( y ); - assert.ok( a.length() == y, "Passed!" ); + assert.ok( a.length() == y, 'Passed!' ); var a = new Vector2( 0, 0 ); - assert.ok( a.length() == 0, "Passed!" ); + assert.ok( a.length() == 0, 'Passed!' ); a.setLength( y ); - assert.ok( a.length() == 0, "Passed!" ); + assert.ok( a.length() == 0, 'Passed!' ); a.setLength(); - assert.ok( isNaN( a.length() ), "Passed!" ); + assert.ok( isNaN( a.length() ), 'Passed!' ); } ); - QUnit.todo( "lerp", ( assert ) => { + QUnit.todo( 'lerp', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "lerpVectors", ( assert ) => { + QUnit.todo( 'lerpVectors', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "equals", ( assert ) => { + QUnit.test( 'equals', ( assert ) => { var a = new Vector2( x, 0 ); var b = new Vector2( 0, - y ); - assert.ok( a.x != b.x, "Passed!" ); - assert.ok( a.y != b.y, "Passed!" ); + assert.ok( a.x != b.x, 'Passed!' ); + assert.ok( a.y != b.y, 'Passed!' ); - assert.ok( ! a.equals( b ), "Passed!" ); - assert.ok( ! b.equals( a ), "Passed!" ); + assert.ok( ! a.equals( b ), 'Passed!' ); + assert.ok( ! b.equals( a ), 'Passed!' ); a.copy( b ); - assert.ok( a.x == b.x, "Passed!" ); - assert.ok( a.y == b.y, "Passed!" ); + assert.ok( a.x == b.x, 'Passed!' ); + assert.ok( a.y == b.y, 'Passed!' ); - assert.ok( a.equals( b ), "Passed!" ); - assert.ok( b.equals( a ), "Passed!" ); + assert.ok( a.equals( b ), 'Passed!' ); + assert.ok( b.equals( a ), 'Passed!' ); } ); - QUnit.test( "fromArray", ( assert ) => { + QUnit.test( 'fromArray', ( assert ) => { var a = new Vector2(); var array = [ 1, 2, 3, 4 ]; a.fromArray( array ); - assert.strictEqual( a.x, 1, "No offset: check x" ); - assert.strictEqual( a.y, 2, "No offset: check y" ); + assert.strictEqual( a.x, 1, 'No offset: check x' ); + assert.strictEqual( a.y, 2, 'No offset: check y' ); a.fromArray( array, 2 ); - assert.strictEqual( a.x, 3, "With offset: check x" ); - assert.strictEqual( a.y, 4, "With offset: check y" ); + assert.strictEqual( a.x, 3, 'With offset: check x' ); + assert.strictEqual( a.y, 4, 'With offset: check y' ); } ); - QUnit.test( "toArray", ( assert ) => { + QUnit.test( 'toArray', ( assert ) => { var a = new Vector2( x, y ); var array = a.toArray(); - assert.strictEqual( array[ 0 ], x, "No array, no offset: check x" ); - assert.strictEqual( array[ 1 ], y, "No array, no offset: check y" ); + assert.strictEqual( array[ 0 ], x, 'No array, no offset: check x' ); + assert.strictEqual( array[ 1 ], y, 'No array, no offset: check y' ); var array = []; a.toArray( array ); - assert.strictEqual( array[ 0 ], x, "With array, no offset: check x" ); - assert.strictEqual( array[ 1 ], y, "With array, no offset: check y" ); + assert.strictEqual( array[ 0 ], x, 'With array, no offset: check x' ); + assert.strictEqual( array[ 1 ], y, 'With array, no offset: check y' ); var array = []; a.toArray( array, 1 ); - assert.strictEqual( array[ 0 ], undefined, "With array and offset: check [0]" ); - assert.strictEqual( array[ 1 ], x, "With array and offset: check x" ); - assert.strictEqual( array[ 2 ], y, "With array and offset: check y" ); + assert.strictEqual( array[ 0 ], undefined, 'With array and offset: check [0]' ); + assert.strictEqual( array[ 1 ], x, 'With array and offset: check x' ); + assert.strictEqual( array[ 2 ], y, 'With array and offset: check y' ); } ); - QUnit.test( "fromBufferAttribute", ( assert ) => { + QUnit.test( 'fromBufferAttribute', ( assert ) => { var a = new Vector2(); var attr = new BufferAttribute( new Float32Array( [ 1, 2, 3, 4 ] ), 2 ); a.fromBufferAttribute( attr, 0 ); - assert.strictEqual( a.x, 1, "Offset 0: check x" ); - assert.strictEqual( a.y, 2, "Offset 0: check y" ); + assert.strictEqual( a.x, 1, 'Offset 0: check x' ); + assert.strictEqual( a.y, 2, 'Offset 0: check y' ); a.fromBufferAttribute( attr, 1 ); - assert.strictEqual( a.x, 3, "Offset 1: check x" ); - assert.strictEqual( a.y, 4, "Offset 1: check y" ); + assert.strictEqual( a.x, 3, 'Offset 1: check x' ); + assert.strictEqual( a.y, 4, 'Offset 1: check y' ); } ); - QUnit.todo( "rotateAround", ( assert ) => { + QUnit.todo( 'rotateAround', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // TODO (Itee) refactor/split - QUnit.test( "setX,setY", ( assert ) => { + QUnit.test( 'setX,setY', ( assert ) => { var a = new Vector2(); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); + assert.ok( a.x == 0, 'Passed!' ); + assert.ok( a.y == 0, 'Passed!' ); a.setX( x ); a.setY( y ); - assert.ok( a.x == x, "Passed!" ); - assert.ok( a.y == y, "Passed!" ); + assert.ok( a.x == x, 'Passed!' ); + assert.ok( a.y == y, 'Passed!' ); } ); - QUnit.test( "setComponent,getComponent", ( assert ) => { + QUnit.test( 'setComponent,getComponent', ( assert ) => { var a = new Vector2(); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); + assert.ok( a.x == 0, 'Passed!' ); + assert.ok( a.y == 0, 'Passed!' ); a.setComponent( 0, 1 ); a.setComponent( 1, 2 ); - assert.ok( a.getComponent( 0 ) == 1, "Passed!" ); - assert.ok( a.getComponent( 1 ) == 2, "Passed!" ); + assert.ok( a.getComponent( 0 ) == 1, 'Passed!' ); + assert.ok( a.getComponent( 1 ) == 2, 'Passed!' ); } ); - QUnit.test( "multiply/divide", ( assert ) => { + QUnit.test( 'multiply/divide', ( assert ) => { var a = new Vector2( x, y ); var b = new Vector2( - x, - y ); a.multiplyScalar( - 2 ); - assert.ok( a.x == x * - 2, "Passed!" ); - assert.ok( a.y == y * - 2, "Passed!" ); + assert.ok( a.x == x * - 2, 'Passed!' ); + assert.ok( a.y == y * - 2, 'Passed!' ); b.multiplyScalar( - 2 ); - assert.ok( b.x == 2 * x, "Passed!" ); - assert.ok( b.y == 2 * y, "Passed!" ); + assert.ok( b.x == 2 * x, 'Passed!' ); + assert.ok( b.y == 2 * y, 'Passed!' ); a.divideScalar( - 2 ); - assert.ok( a.x == x, "Passed!" ); - assert.ok( a.y == y, "Passed!" ); + assert.ok( a.x == x, 'Passed!' ); + assert.ok( a.y == y, 'Passed!' ); b.divideScalar( - 2 ); - assert.ok( b.x == - x, "Passed!" ); - assert.ok( b.y == - y, "Passed!" ); + assert.ok( b.x == - x, 'Passed!' ); + assert.ok( b.y == - y, 'Passed!' ); } ); - QUnit.test( "min/max/clamp", ( assert ) => { + QUnit.test( 'min/max/clamp', ( assert ) => { var a = new Vector2( x, y ); var b = new Vector2( - x, - y ); var c = new Vector2(); c.copy( a ).min( b ); - assert.ok( c.x == - x, "Passed!" ); - assert.ok( c.y == - y, "Passed!" ); + assert.ok( c.x == - x, 'Passed!' ); + assert.ok( c.y == - y, 'Passed!' ); c.copy( a ).max( b ); - assert.ok( c.x == x, "Passed!" ); - assert.ok( c.y == y, "Passed!" ); + assert.ok( c.x == x, 'Passed!' ); + assert.ok( c.y == y, 'Passed!' ); c.set( - 2 * x, 2 * y ); c.clamp( b, a ); - assert.ok( c.x == - x, "Passed!" ); - assert.ok( c.y == y, "Passed!" ); + assert.ok( c.x == - x, 'Passed!' ); + assert.ok( c.y == y, 'Passed!' ); c.set( - 2 * x, 2 * x ); c.clampScalar( - x, x ); - assert.equal( c.x, - x, "scalar clamp x" ); - assert.equal( c.y, x, "scalar clamp y" ); + assert.equal( c.x, - x, 'scalar clamp x' ); + assert.equal( c.y, x, 'scalar clamp y' ); } ); - QUnit.test( "rounding", ( assert ) => { + QUnit.test( 'rounding', ( assert ) => { - assert.deepEqual( new Vector2( - 0.1, 0.1 ).floor(), new Vector2( - 1, 0 ), "floor .1" ); - assert.deepEqual( new Vector2( - 0.5, 0.5 ).floor(), new Vector2( - 1, 0 ), "floor .5" ); - assert.deepEqual( new Vector2( - 0.9, 0.9 ).floor(), new Vector2( - 1, 0 ), "floor .9" ); + assert.deepEqual( new Vector2( - 0.1, 0.1 ).floor(), new Vector2( - 1, 0 ), 'floor .1' ); + assert.deepEqual( new Vector2( - 0.5, 0.5 ).floor(), new Vector2( - 1, 0 ), 'floor .5' ); + assert.deepEqual( new Vector2( - 0.9, 0.9 ).floor(), new Vector2( - 1, 0 ), 'floor .9' ); - assert.deepEqual( new Vector2( - 0.1, 0.1 ).ceil(), new Vector2( 0, 1 ), "ceil .1" ); - assert.deepEqual( new Vector2( - 0.5, 0.5 ).ceil(), new Vector2( 0, 1 ), "ceil .5" ); - assert.deepEqual( new Vector2( - 0.9, 0.9 ).ceil(), new Vector2( 0, 1 ), "ceil .9" ); + assert.deepEqual( new Vector2( - 0.1, 0.1 ).ceil(), new Vector2( 0, 1 ), 'ceil .1' ); + assert.deepEqual( new Vector2( - 0.5, 0.5 ).ceil(), new Vector2( 0, 1 ), 'ceil .5' ); + assert.deepEqual( new Vector2( - 0.9, 0.9 ).ceil(), new Vector2( 0, 1 ), 'ceil .9' ); - assert.deepEqual( new Vector2( - 0.1, 0.1 ).round(), new Vector2( 0, 0 ), "round .1" ); - assert.deepEqual( new Vector2( - 0.5, 0.5 ).round(), new Vector2( 0, 1 ), "round .5" ); - assert.deepEqual( new Vector2( - 0.9, 0.9 ).round(), new Vector2( - 1, 1 ), "round .9" ); + assert.deepEqual( new Vector2( - 0.1, 0.1 ).round(), new Vector2( 0, 0 ), 'round .1' ); + assert.deepEqual( new Vector2( - 0.5, 0.5 ).round(), new Vector2( 0, 1 ), 'round .5' ); + assert.deepEqual( new Vector2( - 0.9, 0.9 ).round(), new Vector2( - 1, 1 ), 'round .9' ); - assert.deepEqual( new Vector2( - 0.1, 0.1 ).roundToZero(), new Vector2( 0, 0 ), "roundToZero .1" ); - assert.deepEqual( new Vector2( - 0.5, 0.5 ).roundToZero(), new Vector2( 0, 0 ), "roundToZero .5" ); - assert.deepEqual( new Vector2( - 0.9, 0.9 ).roundToZero(), new Vector2( 0, 0 ), "roundToZero .9" ); - assert.deepEqual( new Vector2( - 1.1, 1.1 ).roundToZero(), new Vector2( - 1, 1 ), "roundToZero 1.1" ); - assert.deepEqual( new Vector2( - 1.5, 1.5 ).roundToZero(), new Vector2( - 1, 1 ), "roundToZero 1.5" ); - assert.deepEqual( new Vector2( - 1.9, 1.9 ).roundToZero(), new Vector2( - 1, 1 ), "roundToZero 1.9" ); + assert.deepEqual( new Vector2( - 0.1, 0.1 ).roundToZero(), new Vector2( 0, 0 ), 'roundToZero .1' ); + assert.deepEqual( new Vector2( - 0.5, 0.5 ).roundToZero(), new Vector2( 0, 0 ), 'roundToZero .5' ); + assert.deepEqual( new Vector2( - 0.9, 0.9 ).roundToZero(), new Vector2( 0, 0 ), 'roundToZero .9' ); + assert.deepEqual( new Vector2( - 1.1, 1.1 ).roundToZero(), new Vector2( - 1, 1 ), 'roundToZero 1.1' ); + assert.deepEqual( new Vector2( - 1.5, 1.5 ).roundToZero(), new Vector2( - 1, 1 ), 'roundToZero 1.5' ); + assert.deepEqual( new Vector2( - 1.9, 1.9 ).roundToZero(), new Vector2( - 1, 1 ), 'roundToZero 1.9' ); } ); - QUnit.test( "length/lengthSq", ( assert ) => { + QUnit.test( 'length/lengthSq', ( assert ) => { var a = new Vector2( x, 0 ); var b = new Vector2( 0, - y ); var c = new Vector2(); - assert.ok( a.length() == x, "Passed!" ); - assert.ok( a.lengthSq() == x * x, "Passed!" ); - assert.ok( b.length() == y, "Passed!" ); - assert.ok( b.lengthSq() == y * y, "Passed!" ); - assert.ok( c.length() == 0, "Passed!" ); - assert.ok( c.lengthSq() == 0, "Passed!" ); + assert.ok( a.length() == x, 'Passed!' ); + assert.ok( a.lengthSq() == x * x, 'Passed!' ); + assert.ok( b.length() == y, 'Passed!' ); + assert.ok( b.lengthSq() == y * y, 'Passed!' ); + assert.ok( c.length() == 0, 'Passed!' ); + assert.ok( c.lengthSq() == 0, 'Passed!' ); a.set( x, y ); - assert.ok( a.length() == Math.sqrt( x * x + y * y ), "Passed!" ); - assert.ok( a.lengthSq() == ( x * x + y * y ), "Passed!" ); + assert.ok( a.length() == Math.sqrt( x * x + y * y ), 'Passed!' ); + assert.ok( a.lengthSq() == ( x * x + y * y ), 'Passed!' ); } ); - QUnit.test( "distanceTo/distanceToSquared", ( assert ) => { + QUnit.test( 'distanceTo/distanceToSquared', ( assert ) => { var a = new Vector2( x, 0 ); var b = new Vector2( 0, - y ); var c = new Vector2(); - assert.ok( a.distanceTo( c ) == x, "Passed!" ); - assert.ok( a.distanceToSquared( c ) == x * x, "Passed!" ); + assert.ok( a.distanceTo( c ) == x, 'Passed!' ); + assert.ok( a.distanceToSquared( c ) == x * x, 'Passed!' ); - assert.ok( b.distanceTo( c ) == y, "Passed!" ); - assert.ok( b.distanceToSquared( c ) == y * y, "Passed!" ); + assert.ok( b.distanceTo( c ) == y, 'Passed!' ); + assert.ok( b.distanceToSquared( c ) == y * y, 'Passed!' ); } ); - QUnit.test( "lerp/clone", ( assert ) => { + QUnit.test( 'lerp/clone', ( assert ) => { var a = new Vector2( x, 0 ); var b = new Vector2( 0, - y ); - assert.ok( a.lerp( a, 0 ).equals( a.lerp( a, 0.5 ) ), "Passed!" ); - assert.ok( a.lerp( a, 0 ).equals( a.lerp( a, 1 ) ), "Passed!" ); + assert.ok( a.lerp( a, 0 ).equals( a.lerp( a, 0.5 ) ), 'Passed!' ); + assert.ok( a.lerp( a, 0 ).equals( a.lerp( a, 1 ) ), 'Passed!' ); - assert.ok( a.clone().lerp( b, 0 ).equals( a ), "Passed!" ); + assert.ok( a.clone().lerp( b, 0 ).equals( a ), 'Passed!' ); - assert.ok( a.clone().lerp( b, 0.5 ).x == x * 0.5, "Passed!" ); - assert.ok( a.clone().lerp( b, 0.5 ).y == - y * 0.5, "Passed!" ); + assert.ok( a.clone().lerp( b, 0.5 ).x == x * 0.5, 'Passed!' ); + assert.ok( a.clone().lerp( b, 0.5 ).y == - y * 0.5, 'Passed!' ); - assert.ok( a.clone().lerp( b, 1 ).equals( b ), "Passed!" ); + assert.ok( a.clone().lerp( b, 1 ).equals( b ), 'Passed!' ); } ); - QUnit.test( "setComponent/getComponent exceptions", ( assert ) => { + QUnit.test( 'setComponent/getComponent exceptions', ( assert ) => { var a = new Vector2( 0, 0 ); @@ -639,7 +639,7 @@ export default QUnit.module( 'Maths', () => { }, /index is out of range/, - "setComponent with an out of range index throws Error" + 'setComponent with an out of range index throws Error' ); assert.throws( function () { @@ -648,41 +648,41 @@ export default QUnit.module( 'Maths', () => { }, /index is out of range/, - "getComponent with an out of range index throws Error" + 'getComponent with an out of range index throws Error' ); } ); - QUnit.test( "setScalar/addScalar/subScalar", ( assert ) => { + QUnit.test( 'setScalar/addScalar/subScalar', ( assert ) => { var a = new Vector2( 1, 1 ); var s = 3; a.setScalar( s ); - assert.strictEqual( a.x, s, "setScalar: check x" ); - assert.strictEqual( a.y, s, "setScalar: check y" ); + assert.strictEqual( a.x, s, 'setScalar: check x' ); + assert.strictEqual( a.y, s, 'setScalar: check y' ); a.addScalar( s ); - assert.strictEqual( a.x, 2 * s, "addScalar: check x" ); - assert.strictEqual( a.y, 2 * s, "addScalar: check y" ); + assert.strictEqual( a.x, 2 * s, 'addScalar: check x' ); + assert.strictEqual( a.y, 2 * s, 'addScalar: check y' ); a.subScalar( 2 * s ); - assert.strictEqual( a.x, 0, "subScalar: check x" ); - assert.strictEqual( a.y, 0, "subScalar: check y" ); + assert.strictEqual( a.x, 0, 'subScalar: check x' ); + assert.strictEqual( a.y, 0, 'subScalar: check y' ); } ); - QUnit.test( "multiply/divide", ( assert ) => { + QUnit.test( 'multiply/divide', ( assert ) => { var a = new Vector2( x, y ); var b = new Vector2( 2 * x, 2 * y ); var c = new Vector2( 4 * x, 4 * y ); a.multiply( b ); - assert.strictEqual( a.x, x * b.x, "multiply: check x" ); - assert.strictEqual( a.y, y * b.y, "multiply: check y" ); + assert.strictEqual( a.x, x * b.x, 'multiply: check x' ); + assert.strictEqual( a.y, y * b.y, 'multiply: check y' ); b.divide( c ); - assert.strictEqual( b.x, 0.5, "divide: check x" ); - assert.strictEqual( b.y, 0.5, "divide: check y" ); + assert.strictEqual( b.x, 0.5, 'divide: check x' ); + assert.strictEqual( b.y, 0.5, 'divide: check y' ); } ); diff --git a/test/unit/src/math/Vector3.tests.js b/test/unit/src/math/Vector3.tests.js index ff4fbb39a686d6..a911d84fbbaa5f 100644 --- a/test/unit/src/math/Vector3.tests.js +++ b/test/unit/src/math/Vector3.tests.js @@ -23,210 +23,210 @@ export default QUnit.module( 'Maths', () => { QUnit.module( 'Vector3', () => { // INSTANCING - QUnit.test( "Instancing", ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { var a = new Vector3(); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - assert.ok( a.z == 0, "Passed!" ); + assert.ok( a.x == 0, 'Passed!' ); + assert.ok( a.y == 0, 'Passed!' ); + assert.ok( a.z == 0, 'Passed!' ); var a = new Vector3( x, y, z ); - assert.ok( a.x === x, "Passed!" ); - assert.ok( a.y === y, "Passed!" ); - assert.ok( a.z === z, "Passed!" ); + assert.ok( a.x === x, 'Passed!' ); + assert.ok( a.y === y, 'Passed!' ); + assert.ok( a.z === z, 'Passed!' ); } ); // PUBLIC STUFF - QUnit.todo( "isVector3", ( assert ) => { + QUnit.todo( 'isVector3', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "set", ( assert ) => { + QUnit.test( 'set', ( assert ) => { var a = new Vector3(); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - assert.ok( a.z == 0, "Passed!" ); + assert.ok( a.x == 0, 'Passed!' ); + assert.ok( a.y == 0, 'Passed!' ); + assert.ok( a.z == 0, 'Passed!' ); a.set( x, y, z ); - assert.ok( a.x == x, "Passed!" ); - assert.ok( a.y == y, "Passed!" ); - assert.ok( a.z == z, "Passed!" ); + assert.ok( a.x == x, 'Passed!' ); + assert.ok( a.y == y, 'Passed!' ); + assert.ok( a.z == z, 'Passed!' ); } ); - QUnit.todo( "setScalar", ( assert ) => { + QUnit.todo( 'setScalar', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setX", ( assert ) => { + QUnit.todo( 'setX', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setY", ( assert ) => { + QUnit.todo( 'setY', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setZ", ( assert ) => { + QUnit.todo( 'setZ', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setComponent", ( assert ) => { + QUnit.todo( 'setComponent', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getComponent", ( assert ) => { + QUnit.todo( 'getComponent', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "clone", ( assert ) => { + QUnit.todo( 'clone', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "copy", ( assert ) => { + QUnit.test( 'copy', ( assert ) => { var a = new Vector3( x, y, z ); var b = new Vector3().copy( a ); - assert.ok( b.x == x, "Passed!" ); - assert.ok( b.y == y, "Passed!" ); - assert.ok( b.z == z, "Passed!" ); + assert.ok( b.x == x, 'Passed!' ); + assert.ok( b.y == y, 'Passed!' ); + assert.ok( b.z == z, 'Passed!' ); // ensure that it is a true copy a.x = 0; a.y = - 1; a.z = - 2; - assert.ok( b.x == x, "Passed!" ); - assert.ok( b.y == y, "Passed!" ); - assert.ok( b.z == z, "Passed!" ); + assert.ok( b.x == x, 'Passed!' ); + assert.ok( b.y == y, 'Passed!' ); + assert.ok( b.z == z, 'Passed!' ); } ); - QUnit.test( "add", ( assert ) => { + QUnit.test( 'add', ( assert ) => { var a = new Vector3( x, y, z ); var b = new Vector3( - x, - y, - z ); a.add( b ); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - assert.ok( a.z == 0, "Passed!" ); + assert.ok( a.x == 0, 'Passed!' ); + assert.ok( a.y == 0, 'Passed!' ); + assert.ok( a.z == 0, 'Passed!' ); var c = new Vector3().addVectors( b, b ); - assert.ok( c.x == - 2 * x, "Passed!" ); - assert.ok( c.y == - 2 * y, "Passed!" ); - assert.ok( c.z == - 2 * z, "Passed!" ); + assert.ok( c.x == - 2 * x, 'Passed!' ); + assert.ok( c.y == - 2 * y, 'Passed!' ); + assert.ok( c.z == - 2 * z, 'Passed!' ); } ); - QUnit.todo( "addScalar", ( assert ) => { + QUnit.todo( 'addScalar', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "addVectors", ( assert ) => { + QUnit.todo( 'addVectors', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "addScaledVector", ( assert ) => { + QUnit.test( 'addScaledVector', ( assert ) => { var a = new Vector3( x, y, z ); var b = new Vector3( 2, 3, 4 ); var s = 3; a.addScaledVector( b, s ); - assert.strictEqual( a.x, x + b.x * s, "Check x" ); - assert.strictEqual( a.y, y + b.y * s, "Check y" ); - assert.strictEqual( a.z, z + b.z * s, "Check z" ); + assert.strictEqual( a.x, x + b.x * s, 'Check x' ); + assert.strictEqual( a.y, y + b.y * s, 'Check y' ); + assert.strictEqual( a.z, z + b.z * s, 'Check z' ); } ); - QUnit.test( "sub", ( assert ) => { + QUnit.test( 'sub', ( assert ) => { var a = new Vector3( x, y, z ); var b = new Vector3( - x, - y, - z ); a.sub( b ); - assert.ok( a.x == 2 * x, "Passed!" ); - assert.ok( a.y == 2 * y, "Passed!" ); - assert.ok( a.z == 2 * z, "Passed!" ); + assert.ok( a.x == 2 * x, 'Passed!' ); + assert.ok( a.y == 2 * y, 'Passed!' ); + assert.ok( a.z == 2 * z, 'Passed!' ); var c = new Vector3().subVectors( a, a ); - assert.ok( c.x == 0, "Passed!" ); - assert.ok( c.y == 0, "Passed!" ); - assert.ok( c.z == 0, "Passed!" ); + assert.ok( c.x == 0, 'Passed!' ); + assert.ok( c.y == 0, 'Passed!' ); + assert.ok( c.z == 0, 'Passed!' ); } ); - QUnit.todo( "subScalar", ( assert ) => { + QUnit.todo( 'subScalar', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "subVectors", ( assert ) => { + QUnit.todo( 'subVectors', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "multiply", ( assert ) => { + QUnit.todo( 'multiply', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "multiplyScalar", ( assert ) => { + QUnit.todo( 'multiplyScalar', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "multiplyVectors", ( assert ) => { + QUnit.test( 'multiplyVectors', ( assert ) => { var a = new Vector3( x, y, z ); var b = new Vector3( 2, 3, - 5 ); var c = new Vector3().multiplyVectors( a, b ); - assert.strictEqual( c.x, x * 2, "Check x" ); - assert.strictEqual( c.y, y * 3, "Check y" ); - assert.strictEqual( c.z, z * - 5, "Check z" ); + assert.strictEqual( c.x, x * 2, 'Check x' ); + assert.strictEqual( c.y, y * 3, 'Check y' ); + assert.strictEqual( c.z, z * - 5, 'Check z' ); } ); - QUnit.test( "applyEuler", ( assert ) => { + QUnit.test( 'applyEuler', ( assert ) => { var a = new Vector3( x, y, z ); var euler = new Euler( 90, - 45, 0 ); var expected = new Vector3( - 2.352970120501014, - 4.7441750936226645, 0.9779234597246458 ); a.applyEuler( euler ); - assert.ok( Math.abs( a.x - expected.x ) <= eps, "Check x" ); - assert.ok( Math.abs( a.y - expected.y ) <= eps, "Check y" ); - assert.ok( Math.abs( a.z - expected.z ) <= eps, "Check z" ); + assert.ok( Math.abs( a.x - expected.x ) <= eps, 'Check x' ); + assert.ok( Math.abs( a.y - expected.y ) <= eps, 'Check y' ); + assert.ok( Math.abs( a.z - expected.z ) <= eps, 'Check z' ); } ); - QUnit.test( "applyAxisAngle", ( assert ) => { + QUnit.test( 'applyAxisAngle', ( assert ) => { var a = new Vector3( x, y, z ); var axis = new Vector3( 0, 1, 0 ); @@ -234,25 +234,25 @@ export default QUnit.module( 'Maths', () => { var expected = new Vector3( 3 * Math.sqrt( 2 ), 3, Math.sqrt( 2 ) ); a.applyAxisAngle( axis, angle ); - assert.ok( Math.abs( a.x - expected.x ) <= eps, "Check x" ); - assert.ok( Math.abs( a.y - expected.y ) <= eps, "Check y" ); - assert.ok( Math.abs( a.z - expected.z ) <= eps, "Check z" ); + assert.ok( Math.abs( a.x - expected.x ) <= eps, 'Check x' ); + assert.ok( Math.abs( a.y - expected.y ) <= eps, 'Check y' ); + assert.ok( Math.abs( a.z - expected.z ) <= eps, 'Check z' ); } ); - QUnit.test( "applyMatrix3", ( assert ) => { + QUnit.test( 'applyMatrix3', ( assert ) => { var a = new Vector3( x, y, z ); var m = new Matrix3().set( 2, 3, 5, 7, 11, 13, 17, 19, 23 ); a.applyMatrix3( m ); - assert.strictEqual( a.x, 33, "Check x" ); - assert.strictEqual( a.y, 99, "Check y" ); - assert.strictEqual( a.z, 183, "Check z" ); + assert.strictEqual( a.x, 33, 'Check x' ); + assert.strictEqual( a.y, 99, 'Check y' ); + assert.strictEqual( a.z, 183, 'Check z' ); } ); - QUnit.test( "applyMatrix4", ( assert ) => { + QUnit.test( 'applyMatrix4', ( assert ) => { var a = new Vector3( x, y, z ); @@ -261,16 +261,16 @@ export default QUnit.module( 'Maths', () => { var m = new Matrix4().makeRotationX( Math.PI ); a.applyMatrix4( m ); b.applyMatrix4( m ); - assert.ok( a.x == b.x / b.w, "Passed!" ); - assert.ok( a.y == b.y / b.w, "Passed!" ); - assert.ok( a.z == b.z / b.w, "Passed!" ); + assert.ok( a.x == b.x / b.w, 'Passed!' ); + assert.ok( a.y == b.y / b.w, 'Passed!' ); + assert.ok( a.z == b.z / b.w, 'Passed!' ); var m = new Matrix4().makeTranslation( 3, 2, 1 ); a.applyMatrix4( m ); b.applyMatrix4( m ); - assert.ok( a.x == b.x / b.w, "Passed!" ); - assert.ok( a.y == b.y / b.w, "Passed!" ); - assert.ok( a.z == b.z / b.w, "Passed!" ); + assert.ok( a.x == b.x / b.w, 'Passed!' ); + assert.ok( a.y == b.y / b.w, 'Passed!' ); + assert.ok( a.z == b.z / b.w, 'Passed!' ); var m = new Matrix4().set( 1, 0, 0, 0, @@ -280,242 +280,242 @@ export default QUnit.module( 'Maths', () => { ); a.applyMatrix4( m ); b.applyMatrix4( m ); - assert.ok( a.x == b.x / b.w, "Passed!" ); - assert.ok( a.y == b.y / b.w, "Passed!" ); - assert.ok( a.z == b.z / b.w, "Passed!" ); + assert.ok( a.x == b.x / b.w, 'Passed!' ); + assert.ok( a.y == b.y / b.w, 'Passed!' ); + assert.ok( a.z == b.z / b.w, 'Passed!' ); } ); - QUnit.test( "applyQuaternion", ( assert ) => { + QUnit.test( 'applyQuaternion', ( assert ) => { var a = new Vector3( x, y, z ); a.applyQuaternion( new Quaternion() ); - assert.strictEqual( a.x, x, "Identity rotation: check x" ); - assert.strictEqual( a.y, y, "Identity rotation: check y" ); - assert.strictEqual( a.z, z, "Identity rotation: check z" ); + assert.strictEqual( a.x, x, 'Identity rotation: check x' ); + assert.strictEqual( a.y, y, 'Identity rotation: check y' ); + assert.strictEqual( a.z, z, 'Identity rotation: check z' ); a.applyQuaternion( new Quaternion( x, y, z, w ) ); - assert.strictEqual( a.x, 108, "Normal rotation: check x" ); - assert.strictEqual( a.y, 162, "Normal rotation: check y" ); - assert.strictEqual( a.z, 216, "Normal rotation: check z" ); + assert.strictEqual( a.x, 108, 'Normal rotation: check x' ); + assert.strictEqual( a.y, 162, 'Normal rotation: check y' ); + assert.strictEqual( a.z, 216, 'Normal rotation: check z' ); } ); - QUnit.todo( "project", ( assert ) => { + QUnit.todo( 'project', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "unproject", ( assert ) => { + QUnit.todo( 'unproject', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "transformDirection", ( assert ) => { + QUnit.test( 'transformDirection', ( assert ) => { var a = new Vector3( x, y, z ); var m = new Matrix4(); var transformed = new Vector3( 0.3713906763541037, 0.5570860145311556, 0.7427813527082074 ); a.transformDirection( m ); - assert.ok( Math.abs( a.x - transformed.x ) <= eps, "Check x" ); - assert.ok( Math.abs( a.y - transformed.y ) <= eps, "Check y" ); - assert.ok( Math.abs( a.z - transformed.z ) <= eps, "Check z" ); + assert.ok( Math.abs( a.x - transformed.x ) <= eps, 'Check x' ); + assert.ok( Math.abs( a.y - transformed.y ) <= eps, 'Check y' ); + assert.ok( Math.abs( a.z - transformed.z ) <= eps, 'Check z' ); } ); - QUnit.todo( "divide", ( assert ) => { + QUnit.todo( 'divide', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "divideScalar", ( assert ) => { + QUnit.todo( 'divideScalar', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "min", ( assert ) => { + QUnit.todo( 'min', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "max", ( assert ) => { + QUnit.todo( 'max', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "clamp", ( assert ) => { + QUnit.todo( 'clamp', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "clampScalar", ( assert ) => { + QUnit.test( 'clampScalar', ( assert ) => { var a = new Vector3( - 0.01, 0.5, 1.5 ); var clamped = new Vector3( 0.1, 0.5, 1.0 ); a.clampScalar( 0.1, 1.0 ); - assert.ok( Math.abs( a.x - clamped.x ) <= 0.001, "Check x" ); - assert.ok( Math.abs( a.y - clamped.y ) <= 0.001, "Check y" ); - assert.ok( Math.abs( a.z - clamped.z ) <= 0.001, "Check z" ); + assert.ok( Math.abs( a.x - clamped.x ) <= 0.001, 'Check x' ); + assert.ok( Math.abs( a.y - clamped.y ) <= 0.001, 'Check y' ); + assert.ok( Math.abs( a.z - clamped.z ) <= 0.001, 'Check z' ); } ); - QUnit.todo( "clampLength", ( assert ) => { + QUnit.todo( 'clampLength', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "floor", ( assert ) => { + QUnit.todo( 'floor', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "ceil", ( assert ) => { + QUnit.todo( 'ceil', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "round", ( assert ) => { + QUnit.todo( 'round', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "roundToZero", ( assert ) => { + QUnit.todo( 'roundToZero', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "negate", ( assert ) => { + QUnit.test( 'negate', ( assert ) => { var a = new Vector3( x, y, z ); a.negate(); - assert.ok( a.x == - x, "Passed!" ); - assert.ok( a.y == - y, "Passed!" ); - assert.ok( a.z == - z, "Passed!" ); + assert.ok( a.x == - x, 'Passed!' ); + assert.ok( a.y == - y, 'Passed!' ); + assert.ok( a.z == - z, 'Passed!' ); } ); - QUnit.test( "dot", ( assert ) => { + QUnit.test( 'dot', ( assert ) => { var a = new Vector3( x, y, z ); var b = new Vector3( - x, - y, - z ); var c = new Vector3(); var result = a.dot( b ); - assert.ok( result == ( - x * x - y * y - z * z ), "Passed!" ); + assert.ok( result == ( - x * x - y * y - z * z ), 'Passed!' ); var result = a.dot( c ); - assert.ok( result == 0, "Passed!" ); + assert.ok( result == 0, 'Passed!' ); } ); - QUnit.todo( "lengthSq", ( assert ) => { + QUnit.todo( 'lengthSq', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "length", ( assert ) => { + QUnit.todo( 'length', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "manhattanLength", ( assert ) => { + QUnit.test( 'manhattanLength', ( assert ) => { var a = new Vector3( x, 0, 0 ); var b = new Vector3( 0, - y, 0 ); var c = new Vector3( 0, 0, z ); var d = new Vector3(); - assert.ok( a.manhattanLength() == x, "Positive x" ); - assert.ok( b.manhattanLength() == y, "Negative y" ); - assert.ok( c.manhattanLength() == z, "Positive z" ); - assert.ok( d.manhattanLength() == 0, "Empty initialization" ); + assert.ok( a.manhattanLength() == x, 'Positive x' ); + assert.ok( b.manhattanLength() == y, 'Negative y' ); + assert.ok( c.manhattanLength() == z, 'Positive z' ); + assert.ok( d.manhattanLength() == 0, 'Empty initialization' ); a.set( x, y, z ); - assert.ok( a.manhattanLength() == Math.abs( x ) + Math.abs( y ) + Math.abs( z ), "All components" ); + assert.ok( a.manhattanLength() == Math.abs( x ) + Math.abs( y ) + Math.abs( z ), 'All components' ); } ); - QUnit.test( "normalize", ( assert ) => { + QUnit.test( 'normalize', ( assert ) => { var a = new Vector3( x, 0, 0 ); var b = new Vector3( 0, - y, 0 ); var c = new Vector3( 0, 0, z ); a.normalize(); - assert.ok( a.length() == 1, "Passed!" ); - assert.ok( a.x == 1, "Passed!" ); + assert.ok( a.length() == 1, 'Passed!' ); + assert.ok( a.x == 1, 'Passed!' ); b.normalize(); - assert.ok( b.length() == 1, "Passed!" ); - assert.ok( b.y == - 1, "Passed!" ); + assert.ok( b.length() == 1, 'Passed!' ); + assert.ok( b.y == - 1, 'Passed!' ); c.normalize(); - assert.ok( c.length() == 1, "Passed!" ); - assert.ok( c.z == 1, "Passed!" ); + assert.ok( c.length() == 1, 'Passed!' ); + assert.ok( c.z == 1, 'Passed!' ); } ); - QUnit.test( "setLength", ( assert ) => { + QUnit.test( 'setLength', ( assert ) => { var a = new Vector3( x, 0, 0 ); - assert.ok( a.length() == x, "Passed!" ); + assert.ok( a.length() == x, 'Passed!' ); a.setLength( y ); - assert.ok( a.length() == y, "Passed!" ); + assert.ok( a.length() == y, 'Passed!' ); var a = new Vector3( 0, 0, 0 ); - assert.ok( a.length() == 0, "Passed!" ); + assert.ok( a.length() == 0, 'Passed!' ); a.setLength( y ); - assert.ok( a.length() == 0, "Passed!" ); + assert.ok( a.length() == 0, 'Passed!' ); a.setLength(); - assert.ok( isNaN( a.length() ), "Passed!" ); + assert.ok( isNaN( a.length() ), 'Passed!' ); } ); - QUnit.todo( "lerp", ( assert ) => { + QUnit.todo( 'lerp', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "lerpVectors", ( assert ) => { + QUnit.todo( 'lerpVectors', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "cross", ( assert ) => { + QUnit.test( 'cross', ( assert ) => { var a = new Vector3( x, y, z ); var b = new Vector3( 2 * x, - y, 0.5 * z ); var crossed = new Vector3( 18, 12, - 18 ); a.cross( b ); - assert.ok( Math.abs( a.x - crossed.x ) <= eps, "Check x" ); - assert.ok( Math.abs( a.y - crossed.y ) <= eps, "Check y" ); - assert.ok( Math.abs( a.z - crossed.z ) <= eps, "Check z" ); + assert.ok( Math.abs( a.x - crossed.x ) <= eps, 'Check x' ); + assert.ok( Math.abs( a.y - crossed.y ) <= eps, 'Check y' ); + assert.ok( Math.abs( a.z - crossed.z ) <= eps, 'Check z' ); } ); - QUnit.test( "crossVectors", ( assert ) => { + QUnit.test( 'crossVectors', ( assert ) => { var a = new Vector3( x, y, z ); var b = new Vector3( x, - y, z ); @@ -523,69 +523,69 @@ export default QUnit.module( 'Maths', () => { var crossed = new Vector3( 24, 0, - 12 ); c.crossVectors( a, b ); - assert.ok( Math.abs( c.x - crossed.x ) <= eps, "Check x" ); - assert.ok( Math.abs( c.y - crossed.y ) <= eps, "Check y" ); - assert.ok( Math.abs( c.z - crossed.z ) <= eps, "Check z" ); + assert.ok( Math.abs( c.x - crossed.x ) <= eps, 'Check x' ); + assert.ok( Math.abs( c.y - crossed.y ) <= eps, 'Check y' ); + assert.ok( Math.abs( c.z - crossed.z ) <= eps, 'Check z' ); } ); - QUnit.test( "projectOnVector", ( assert ) => { + QUnit.test( 'projectOnVector', ( assert ) => { var a = new Vector3( 1, 0, 0 ); var b = new Vector3(); var normal = new Vector3( 10, 0, 0 ); - assert.ok( b.copy( a ).projectOnVector( normal ).equals( new Vector3( 1, 0, 0 ) ), "Passed!" ); + assert.ok( b.copy( a ).projectOnVector( normal ).equals( new Vector3( 1, 0, 0 ) ), 'Passed!' ); a.set( 0, 1, 0 ); - assert.ok( b.copy( a ).projectOnVector( normal ).equals( new Vector3( 0, 0, 0 ) ), "Passed!" ); + assert.ok( b.copy( a ).projectOnVector( normal ).equals( new Vector3( 0, 0, 0 ) ), 'Passed!' ); a.set( 0, 0, - 1 ); - assert.ok( b.copy( a ).projectOnVector( normal ).equals( new Vector3( 0, 0, 0 ) ), "Passed!" ); + assert.ok( b.copy( a ).projectOnVector( normal ).equals( new Vector3( 0, 0, 0 ) ), 'Passed!' ); a.set( - 1, 0, 0 ); - assert.ok( b.copy( a ).projectOnVector( normal ).equals( new Vector3( - 1, 0, 0 ) ), "Passed!" ); + assert.ok( b.copy( a ).projectOnVector( normal ).equals( new Vector3( - 1, 0, 0 ) ), 'Passed!' ); } ); - QUnit.test( "projectOnPlane", ( assert ) => { + QUnit.test( 'projectOnPlane', ( assert ) => { var a = new Vector3( 1, 0, 0 ); var b = new Vector3(); var normal = new Vector3( 1, 0, 0 ); - assert.ok( b.copy( a ).projectOnPlane( normal ).equals( new Vector3( 0, 0, 0 ) ), "Passed!" ); + assert.ok( b.copy( a ).projectOnPlane( normal ).equals( new Vector3( 0, 0, 0 ) ), 'Passed!' ); a.set( 0, 1, 0 ); - assert.ok( b.copy( a ).projectOnPlane( normal ).equals( new Vector3( 0, 1, 0 ) ), "Passed!" ); + assert.ok( b.copy( a ).projectOnPlane( normal ).equals( new Vector3( 0, 1, 0 ) ), 'Passed!' ); a.set( 0, 0, - 1 ); - assert.ok( b.copy( a ).projectOnPlane( normal ).equals( new Vector3( 0, 0, - 1 ) ), "Passed!" ); + assert.ok( b.copy( a ).projectOnPlane( normal ).equals( new Vector3( 0, 0, - 1 ) ), 'Passed!' ); a.set( - 1, 0, 0 ); - assert.ok( b.copy( a ).projectOnPlane( normal ).equals( new Vector3( 0, 0, 0 ) ), "Passed!" ); + assert.ok( b.copy( a ).projectOnPlane( normal ).equals( new Vector3( 0, 0, 0 ) ), 'Passed!' ); } ); - QUnit.test( "reflect", ( assert ) => { + QUnit.test( 'reflect', ( assert ) => { var a = new Vector3(); var normal = new Vector3( 0, 1, 0 ); var b = new Vector3(); a.set( 0, - 1, 0 ); - assert.ok( b.copy( a ).reflect( normal ).equals( new Vector3( 0, 1, 0 ) ), "Passed!" ); + assert.ok( b.copy( a ).reflect( normal ).equals( new Vector3( 0, 1, 0 ) ), 'Passed!' ); a.set( 1, - 1, 0 ); - assert.ok( b.copy( a ).reflect( normal ).equals( new Vector3( 1, 1, 0 ) ), "Passed!" ); + assert.ok( b.copy( a ).reflect( normal ).equals( new Vector3( 1, 1, 0 ) ), 'Passed!' ); a.set( 1, - 1, 0 ); normal.set( 0, - 1, 0 ); - assert.ok( b.copy( a ).reflect( normal ).equals( new Vector3( 1, 1, 0 ) ), "Passed!" ); + assert.ok( b.copy( a ).reflect( normal ).equals( new Vector3( 1, 1, 0 ) ), 'Passed!' ); } ); - QUnit.test( "angleTo", ( assert ) => { + QUnit.test( 'angleTo', ( assert ) => { var a = new Vector3( 0, - 0.18851655680720186, 0.9820700116639124 ); var b = new Vector3( 0, 0.18851655680720186, - 0.9820700116639124 ); @@ -605,25 +605,25 @@ export default QUnit.module( 'Maths', () => { } ); - QUnit.todo( "distanceTo", ( assert ) => { + QUnit.todo( 'distanceTo', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "distanceToSquared", ( assert ) => { + QUnit.todo( 'distanceToSquared', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "manhattanDistanceTo", ( assert ) => { + QUnit.todo( 'manhattanDistanceTo', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "setFromSpherical", ( assert ) => { + QUnit.test( 'setFromSpherical', ( assert ) => { var a = new Vector3(); var phi = Math.acos( - 0.5 ); @@ -632,180 +632,180 @@ export default QUnit.module( 'Maths', () => { var expected = new Vector3( - 4.677914006701843, - 5, - 7.288149322420796 ); a.setFromSpherical( sph ); - assert.ok( Math.abs( a.x - expected.x ) <= eps, "Check x" ); - assert.ok( Math.abs( a.y - expected.y ) <= eps, "Check y" ); - assert.ok( Math.abs( a.z - expected.z ) <= eps, "Check z" ); + assert.ok( Math.abs( a.x - expected.x ) <= eps, 'Check x' ); + assert.ok( Math.abs( a.y - expected.y ) <= eps, 'Check y' ); + assert.ok( Math.abs( a.z - expected.z ) <= eps, 'Check z' ); } ); - QUnit.test( "setFromCylindrical", ( assert ) => { + QUnit.test( 'setFromCylindrical', ( assert ) => { var a = new Vector3(); var cyl = new Cylindrical( 10, Math.PI * 0.125, 20 ); var expected = new Vector3( 3.826834323650898, 20, 9.238795325112868 ); a.setFromCylindrical( cyl ); - assert.ok( Math.abs( a.x - expected.x ) <= eps, "Check x" ); - assert.ok( Math.abs( a.y - expected.y ) <= eps, "Check y" ); - assert.ok( Math.abs( a.z - expected.z ) <= eps, "Check z" ); + assert.ok( Math.abs( a.x - expected.x ) <= eps, 'Check x' ); + assert.ok( Math.abs( a.y - expected.y ) <= eps, 'Check y' ); + assert.ok( Math.abs( a.z - expected.z ) <= eps, 'Check z' ); } ); - QUnit.test( "setFromMatrixPosition", ( assert ) => { + QUnit.test( 'setFromMatrixPosition', ( assert ) => { var a = new Vector3(); var m = new Matrix4().set( 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53 ); a.setFromMatrixPosition( m ); - assert.strictEqual( a.x, 7, "Check x" ); - assert.strictEqual( a.y, 19, "Check y" ); - assert.strictEqual( a.z, 37, "Check z" ); + assert.strictEqual( a.x, 7, 'Check x' ); + assert.strictEqual( a.y, 19, 'Check y' ); + assert.strictEqual( a.z, 37, 'Check z' ); } ); - QUnit.test( "setFromMatrixScale", ( assert ) => { + QUnit.test( 'setFromMatrixScale', ( assert ) => { var a = new Vector3(); var m = new Matrix4().set( 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53 ); var expected = new Vector3( 25.573423705088842, 31.921779399024736, 35.70714214271425 ); a.setFromMatrixScale( m ); - assert.ok( Math.abs( a.x - expected.x ) <= eps, "Check x" ); - assert.ok( Math.abs( a.y - expected.y ) <= eps, "Check y" ); - assert.ok( Math.abs( a.z - expected.z ) <= eps, "Check z" ); + assert.ok( Math.abs( a.x - expected.x ) <= eps, 'Check x' ); + assert.ok( Math.abs( a.y - expected.y ) <= eps, 'Check y' ); + assert.ok( Math.abs( a.z - expected.z ) <= eps, 'Check z' ); } ); - QUnit.test( "setFromMatrixColumn", ( assert ) => { + QUnit.test( 'setFromMatrixColumn', ( assert ) => { var a = new Vector3(); var m = new Matrix4().set( 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53 ); a.setFromMatrixColumn( m, 0 ); - assert.strictEqual( a.x, 2, "Index 0: check x" ); - assert.strictEqual( a.y, 11, "Index 0: check y" ); - assert.strictEqual( a.z, 23, "Index 0: check z" ); + assert.strictEqual( a.x, 2, 'Index 0: check x' ); + assert.strictEqual( a.y, 11, 'Index 0: check y' ); + assert.strictEqual( a.z, 23, 'Index 0: check z' ); a.setFromMatrixColumn( m, 2 ); - assert.strictEqual( a.x, 5, "Index 2: check x" ); - assert.strictEqual( a.y, 17, "Index 2: check y" ); - assert.strictEqual( a.z, 31, "Index 2: check z" ); + assert.strictEqual( a.x, 5, 'Index 2: check x' ); + assert.strictEqual( a.y, 17, 'Index 2: check y' ); + assert.strictEqual( a.z, 31, 'Index 2: check z' ); } ); - QUnit.test( "equals", ( assert ) => { + QUnit.test( 'equals', ( assert ) => { var a = new Vector3( x, 0, z ); var b = new Vector3( 0, - y, 0 ); - assert.ok( a.x != b.x, "Passed!" ); - assert.ok( a.y != b.y, "Passed!" ); - assert.ok( a.z != b.z, "Passed!" ); + assert.ok( a.x != b.x, 'Passed!' ); + assert.ok( a.y != b.y, 'Passed!' ); + assert.ok( a.z != b.z, 'Passed!' ); - assert.ok( ! a.equals( b ), "Passed!" ); - assert.ok( ! b.equals( a ), "Passed!" ); + assert.ok( ! a.equals( b ), 'Passed!' ); + assert.ok( ! b.equals( a ), 'Passed!' ); a.copy( b ); - assert.ok( a.x == b.x, "Passed!" ); - assert.ok( a.y == b.y, "Passed!" ); - assert.ok( a.z == b.z, "Passed!" ); + assert.ok( a.x == b.x, 'Passed!' ); + assert.ok( a.y == b.y, 'Passed!' ); + assert.ok( a.z == b.z, 'Passed!' ); - assert.ok( a.equals( b ), "Passed!" ); - assert.ok( b.equals( a ), "Passed!" ); + assert.ok( a.equals( b ), 'Passed!' ); + assert.ok( b.equals( a ), 'Passed!' ); } ); - QUnit.test( "fromArray", ( assert ) => { + QUnit.test( 'fromArray', ( assert ) => { var a = new Vector3(); var array = [ 1, 2, 3, 4, 5, 6 ]; a.fromArray( array ); - assert.strictEqual( a.x, 1, "No offset: check x" ); - assert.strictEqual( a.y, 2, "No offset: check y" ); - assert.strictEqual( a.z, 3, "No offset: check z" ); + assert.strictEqual( a.x, 1, 'No offset: check x' ); + assert.strictEqual( a.y, 2, 'No offset: check y' ); + assert.strictEqual( a.z, 3, 'No offset: check z' ); a.fromArray( array, 3 ); - assert.strictEqual( a.x, 4, "With offset: check x" ); - assert.strictEqual( a.y, 5, "With offset: check y" ); - assert.strictEqual( a.z, 6, "With offset: check z" ); + assert.strictEqual( a.x, 4, 'With offset: check x' ); + assert.strictEqual( a.y, 5, 'With offset: check y' ); + assert.strictEqual( a.z, 6, 'With offset: check z' ); } ); - QUnit.test( "toArray", ( assert ) => { + QUnit.test( 'toArray', ( assert ) => { var a = new Vector3( x, y, z ); var array = a.toArray(); - assert.strictEqual( array[ 0 ], x, "No array, no offset: check x" ); - assert.strictEqual( array[ 1 ], y, "No array, no offset: check y" ); - assert.strictEqual( array[ 2 ], z, "No array, no offset: check z" ); + assert.strictEqual( array[ 0 ], x, 'No array, no offset: check x' ); + assert.strictEqual( array[ 1 ], y, 'No array, no offset: check y' ); + assert.strictEqual( array[ 2 ], z, 'No array, no offset: check z' ); var array = []; a.toArray( array ); - assert.strictEqual( array[ 0 ], x, "With array, no offset: check x" ); - assert.strictEqual( array[ 1 ], y, "With array, no offset: check y" ); - assert.strictEqual( array[ 2 ], z, "With array, no offset: check z" ); + assert.strictEqual( array[ 0 ], x, 'With array, no offset: check x' ); + assert.strictEqual( array[ 1 ], y, 'With array, no offset: check y' ); + assert.strictEqual( array[ 2 ], z, 'With array, no offset: check z' ); var array = []; a.toArray( array, 1 ); - assert.strictEqual( array[ 0 ], undefined, "With array and offset: check [0]" ); - assert.strictEqual( array[ 1 ], x, "With array and offset: check x" ); - assert.strictEqual( array[ 2 ], y, "With array and offset: check y" ); - assert.strictEqual( array[ 3 ], z, "With array and offset: check z" ); + assert.strictEqual( array[ 0 ], undefined, 'With array and offset: check [0]' ); + assert.strictEqual( array[ 1 ], x, 'With array and offset: check x' ); + assert.strictEqual( array[ 2 ], y, 'With array and offset: check y' ); + assert.strictEqual( array[ 3 ], z, 'With array and offset: check z' ); } ); - QUnit.test( "fromBufferAttribute", ( assert ) => { + QUnit.test( 'fromBufferAttribute', ( assert ) => { var a = new Vector3(); var attr = new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3 ); a.fromBufferAttribute( attr, 0 ); - assert.strictEqual( a.x, 1, "Offset 0: check x" ); - assert.strictEqual( a.y, 2, "Offset 0: check y" ); - assert.strictEqual( a.z, 3, "Offset 0: check z" ); + assert.strictEqual( a.x, 1, 'Offset 0: check x' ); + assert.strictEqual( a.y, 2, 'Offset 0: check y' ); + assert.strictEqual( a.z, 3, 'Offset 0: check z' ); a.fromBufferAttribute( attr, 1 ); - assert.strictEqual( a.x, 4, "Offset 1: check x" ); - assert.strictEqual( a.y, 5, "Offset 1: check y" ); - assert.strictEqual( a.z, 6, "Offset 1: check z" ); + assert.strictEqual( a.x, 4, 'Offset 1: check x' ); + assert.strictEqual( a.y, 5, 'Offset 1: check y' ); + assert.strictEqual( a.z, 6, 'Offset 1: check z' ); } ); // TODO (Itee) refactor/split - QUnit.test( "setX,setY,setZ", ( assert ) => { + QUnit.test( 'setX,setY,setZ', ( assert ) => { var a = new Vector3(); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - assert.ok( a.z == 0, "Passed!" ); + assert.ok( a.x == 0, 'Passed!' ); + assert.ok( a.y == 0, 'Passed!' ); + assert.ok( a.z == 0, 'Passed!' ); a.setX( x ); a.setY( y ); a.setZ( z ); - assert.ok( a.x == x, "Passed!" ); - assert.ok( a.y == y, "Passed!" ); - assert.ok( a.z == z, "Passed!" ); + assert.ok( a.x == x, 'Passed!' ); + assert.ok( a.y == y, 'Passed!' ); + assert.ok( a.z == z, 'Passed!' ); } ); - QUnit.test( "setComponent,getComponent", ( assert ) => { + QUnit.test( 'setComponent,getComponent', ( assert ) => { var a = new Vector3(); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - assert.ok( a.z == 0, "Passed!" ); + assert.ok( a.x == 0, 'Passed!' ); + assert.ok( a.y == 0, 'Passed!' ); + assert.ok( a.z == 0, 'Passed!' ); a.setComponent( 0, 1 ); a.setComponent( 1, 2 ); a.setComponent( 2, 3 ); - assert.ok( a.getComponent( 0 ) == 1, "Passed!" ); - assert.ok( a.getComponent( 1 ) == 2, "Passed!" ); - assert.ok( a.getComponent( 2 ) == 3, "Passed!" ); + assert.ok( a.getComponent( 0 ) == 1, 'Passed!' ); + assert.ok( a.getComponent( 1 ) == 2, 'Passed!' ); + assert.ok( a.getComponent( 2 ) == 3, 'Passed!' ); } ); - QUnit.test( "setComponent/getComponent exceptions", ( assert ) => { + QUnit.test( 'setComponent/getComponent exceptions', ( assert ) => { var a = new Vector3(); @@ -816,7 +816,7 @@ export default QUnit.module( 'Maths', () => { }, /index is out of range/, - "setComponent with an out of range index throws Error" + 'setComponent with an out of range index throws Error' ); assert.throws( function () { @@ -825,167 +825,167 @@ export default QUnit.module( 'Maths', () => { }, /index is out of range/, - "getComponent with an out of range index throws Error" + 'getComponent with an out of range index throws Error' ); } ); - QUnit.test( "min/max/clamp", ( assert ) => { + QUnit.test( 'min/max/clamp', ( assert ) => { var a = new Vector3( x, y, z ); var b = new Vector3( - x, - y, - z ); var c = new Vector3(); c.copy( a ).min( b ); - assert.ok( c.x == - x, "Passed!" ); - assert.ok( c.y == - y, "Passed!" ); - assert.ok( c.z == - z, "Passed!" ); + assert.ok( c.x == - x, 'Passed!' ); + assert.ok( c.y == - y, 'Passed!' ); + assert.ok( c.z == - z, 'Passed!' ); c.copy( a ).max( b ); - assert.ok( c.x == x, "Passed!" ); - assert.ok( c.y == y, "Passed!" ); - assert.ok( c.z == z, "Passed!" ); + assert.ok( c.x == x, 'Passed!' ); + assert.ok( c.y == y, 'Passed!' ); + assert.ok( c.z == z, 'Passed!' ); c.set( - 2 * x, 2 * y, - 2 * z ); c.clamp( b, a ); - assert.ok( c.x == - x, "Passed!" ); - assert.ok( c.y == y, "Passed!" ); - assert.ok( c.z == - z, "Passed!" ); + assert.ok( c.x == - x, 'Passed!' ); + assert.ok( c.y == y, 'Passed!' ); + assert.ok( c.z == - z, 'Passed!' ); } ); - QUnit.test( "distanceTo/distanceToSquared", ( assert ) => { + QUnit.test( 'distanceTo/distanceToSquared', ( assert ) => { var a = new Vector3( x, 0, 0 ); var b = new Vector3( 0, - y, 0 ); var c = new Vector3( 0, 0, z ); var d = new Vector3(); - assert.ok( a.distanceTo( d ) == x, "Passed!" ); - assert.ok( a.distanceToSquared( d ) == x * x, "Passed!" ); + assert.ok( a.distanceTo( d ) == x, 'Passed!' ); + assert.ok( a.distanceToSquared( d ) == x * x, 'Passed!' ); - assert.ok( b.distanceTo( d ) == y, "Passed!" ); - assert.ok( b.distanceToSquared( d ) == y * y, "Passed!" ); + assert.ok( b.distanceTo( d ) == y, 'Passed!' ); + assert.ok( b.distanceToSquared( d ) == y * y, 'Passed!' ); - assert.ok( c.distanceTo( d ) == z, "Passed!" ); - assert.ok( c.distanceToSquared( d ) == z * z, "Passed!" ); + assert.ok( c.distanceTo( d ) == z, 'Passed!' ); + assert.ok( c.distanceToSquared( d ) == z * z, 'Passed!' ); } ); - QUnit.test( "setScalar/addScalar/subScalar", ( assert ) => { + QUnit.test( 'setScalar/addScalar/subScalar', ( assert ) => { var a = new Vector3(); var s = 3; a.setScalar( s ); - assert.strictEqual( a.x, s, "setScalar: check x" ); - assert.strictEqual( a.y, s, "setScalar: check y" ); - assert.strictEqual( a.z, s, "setScalar: check z" ); + assert.strictEqual( a.x, s, 'setScalar: check x' ); + assert.strictEqual( a.y, s, 'setScalar: check y' ); + assert.strictEqual( a.z, s, 'setScalar: check z' ); a.addScalar( s ); - assert.strictEqual( a.x, 2 * s, "addScalar: check x" ); - assert.strictEqual( a.y, 2 * s, "addScalar: check y" ); - assert.strictEqual( a.z, 2 * s, "addScalar: check z" ); + assert.strictEqual( a.x, 2 * s, 'addScalar: check x' ); + assert.strictEqual( a.y, 2 * s, 'addScalar: check y' ); + assert.strictEqual( a.z, 2 * s, 'addScalar: check z' ); a.subScalar( 2 * s ); - assert.strictEqual( a.x, 0, "subScalar: check x" ); - assert.strictEqual( a.y, 0, "subScalar: check y" ); - assert.strictEqual( a.z, 0, "subScalar: check z" ); + assert.strictEqual( a.x, 0, 'subScalar: check x' ); + assert.strictEqual( a.y, 0, 'subScalar: check y' ); + assert.strictEqual( a.z, 0, 'subScalar: check z' ); } ); - QUnit.test( "multiply/divide", ( assert ) => { + QUnit.test( 'multiply/divide', ( assert ) => { var a = new Vector3( x, y, z ); var b = new Vector3( 2 * x, 2 * y, 2 * z ); var c = new Vector3( 4 * x, 4 * y, 4 * z ); a.multiply( b ); - assert.strictEqual( a.x, x * b.x, "multiply: check x" ); - assert.strictEqual( a.y, y * b.y, "multiply: check y" ); - assert.strictEqual( a.z, z * b.z, "multiply: check z" ); + assert.strictEqual( a.x, x * b.x, 'multiply: check x' ); + assert.strictEqual( a.y, y * b.y, 'multiply: check y' ); + assert.strictEqual( a.z, z * b.z, 'multiply: check z' ); b.divide( c ); - assert.ok( Math.abs( b.x - 0.5 ) <= eps, "divide: check z" ); - assert.ok( Math.abs( b.y - 0.5 ) <= eps, "divide: check z" ); - assert.ok( Math.abs( b.z - 0.5 ) <= eps, "divide: check z" ); + assert.ok( Math.abs( b.x - 0.5 ) <= eps, 'divide: check z' ); + assert.ok( Math.abs( b.y - 0.5 ) <= eps, 'divide: check z' ); + assert.ok( Math.abs( b.z - 0.5 ) <= eps, 'divide: check z' ); } ); - QUnit.test( "multiply/divide", ( assert ) => { + QUnit.test( 'multiply/divide', ( assert ) => { var a = new Vector3( x, y, z ); var b = new Vector3( - x, - y, - z ); a.multiplyScalar( - 2 ); - assert.ok( a.x == x * - 2, "Passed!" ); - assert.ok( a.y == y * - 2, "Passed!" ); - assert.ok( a.z == z * - 2, "Passed!" ); + assert.ok( a.x == x * - 2, 'Passed!' ); + assert.ok( a.y == y * - 2, 'Passed!' ); + assert.ok( a.z == z * - 2, 'Passed!' ); b.multiplyScalar( - 2 ); - assert.ok( b.x == 2 * x, "Passed!" ); - assert.ok( b.y == 2 * y, "Passed!" ); - assert.ok( b.z == 2 * z, "Passed!" ); + assert.ok( b.x == 2 * x, 'Passed!' ); + assert.ok( b.y == 2 * y, 'Passed!' ); + assert.ok( b.z == 2 * z, 'Passed!' ); a.divideScalar( - 2 ); - assert.ok( a.x == x, "Passed!" ); - assert.ok( a.y == y, "Passed!" ); - assert.ok( a.z == z, "Passed!" ); + assert.ok( a.x == x, 'Passed!' ); + assert.ok( a.y == y, 'Passed!' ); + assert.ok( a.z == z, 'Passed!' ); b.divideScalar( - 2 ); - assert.ok( b.x == - x, "Passed!" ); - assert.ok( b.y == - y, "Passed!" ); - assert.ok( b.z == - z, "Passed!" ); + assert.ok( b.x == - x, 'Passed!' ); + assert.ok( b.y == - y, 'Passed!' ); + assert.ok( b.z == - z, 'Passed!' ); } ); - QUnit.test( "project/unproject", ( assert ) => { + QUnit.test( 'project/unproject', ( assert ) => { var a = new Vector3( x, y, z ); var camera = new PerspectiveCamera( 75, 16 / 9, 0.1, 300.0 ); var projected = new Vector3( - 0.36653213611158914, - 0.9774190296309043, 1.0506835611870624 ); a.project( camera ); - assert.ok( Math.abs( a.x - projected.x ) <= eps, "project: check x" ); - assert.ok( Math.abs( a.y - projected.y ) <= eps, "project: check y" ); - assert.ok( Math.abs( a.z - projected.z ) <= eps, "project: check z" ); + assert.ok( Math.abs( a.x - projected.x ) <= eps, 'project: check x' ); + assert.ok( Math.abs( a.y - projected.y ) <= eps, 'project: check y' ); + assert.ok( Math.abs( a.z - projected.z ) <= eps, 'project: check z' ); a.unproject( camera ); - assert.ok( Math.abs( a.x - x ) <= eps, "unproject: check x" ); - assert.ok( Math.abs( a.y - y ) <= eps, "unproject: check y" ); - assert.ok( Math.abs( a.z - z ) <= eps, "unproject: check z" ); + assert.ok( Math.abs( a.x - x ) <= eps, 'unproject: check x' ); + assert.ok( Math.abs( a.y - y ) <= eps, 'unproject: check y' ); + assert.ok( Math.abs( a.z - z ) <= eps, 'unproject: check z' ); } ); - QUnit.test( "length/lengthSq", ( assert ) => { + QUnit.test( 'length/lengthSq', ( assert ) => { var a = new Vector3( x, 0, 0 ); var b = new Vector3( 0, - y, 0 ); var c = new Vector3( 0, 0, z ); var d = new Vector3(); - assert.ok( a.length() == x, "Passed!" ); - assert.ok( a.lengthSq() == x * x, "Passed!" ); - assert.ok( b.length() == y, "Passed!" ); - assert.ok( b.lengthSq() == y * y, "Passed!" ); - assert.ok( c.length() == z, "Passed!" ); - assert.ok( c.lengthSq() == z * z, "Passed!" ); - assert.ok( d.length() == 0, "Passed!" ); - assert.ok( d.lengthSq() == 0, "Passed!" ); + assert.ok( a.length() == x, 'Passed!' ); + assert.ok( a.lengthSq() == x * x, 'Passed!' ); + assert.ok( b.length() == y, 'Passed!' ); + assert.ok( b.lengthSq() == y * y, 'Passed!' ); + assert.ok( c.length() == z, 'Passed!' ); + assert.ok( c.lengthSq() == z * z, 'Passed!' ); + assert.ok( d.length() == 0, 'Passed!' ); + assert.ok( d.lengthSq() == 0, 'Passed!' ); a.set( x, y, z ); - assert.ok( a.length() == Math.sqrt( x * x + y * y + z * z ), "Passed!" ); - assert.ok( a.lengthSq() == ( x * x + y * y + z * z ), "Passed!" ); + assert.ok( a.length() == Math.sqrt( x * x + y * y + z * z ), 'Passed!' ); + assert.ok( a.lengthSq() == ( x * x + y * y + z * z ), 'Passed!' ); } ); - QUnit.test( "lerp/clone", ( assert ) => { + QUnit.test( 'lerp/clone', ( assert ) => { var a = new Vector3( x, 0, z ); var b = new Vector3( 0, - y, 0 ); - assert.ok( a.lerp( a, 0 ).equals( a.lerp( a, 0.5 ) ), "Passed!" ); - assert.ok( a.lerp( a, 0 ).equals( a.lerp( a, 1 ) ), "Passed!" ); + assert.ok( a.lerp( a, 0 ).equals( a.lerp( a, 0.5 ) ), 'Passed!' ); + assert.ok( a.lerp( a, 0 ).equals( a.lerp( a, 1 ) ), 'Passed!' ); - assert.ok( a.clone().lerp( b, 0 ).equals( a ), "Passed!" ); + assert.ok( a.clone().lerp( b, 0 ).equals( a ), 'Passed!' ); - assert.ok( a.clone().lerp( b, 0.5 ).x == x * 0.5, "Passed!" ); - assert.ok( a.clone().lerp( b, 0.5 ).y == - y * 0.5, "Passed!" ); - assert.ok( a.clone().lerp( b, 0.5 ).z == z * 0.5, "Passed!" ); + assert.ok( a.clone().lerp( b, 0.5 ).x == x * 0.5, 'Passed!' ); + assert.ok( a.clone().lerp( b, 0.5 ).y == - y * 0.5, 'Passed!' ); + assert.ok( a.clone().lerp( b, 0.5 ).z == z * 0.5, 'Passed!' ); - assert.ok( a.clone().lerp( b, 1 ).equals( b ), "Passed!" ); + assert.ok( a.clone().lerp( b, 1 ).equals( b ), 'Passed!' ); } ); diff --git a/test/unit/src/math/Vector4.tests.js b/test/unit/src/math/Vector4.tests.js index 40465d56d9ea40..f2cb9e8ea89d86 100644 --- a/test/unit/src/math/Vector4.tests.js +++ b/test/unit/src/math/Vector4.tests.js @@ -16,358 +16,358 @@ export default QUnit.module( 'Maths', () => { QUnit.module( 'Vector4', () => { // INSTANCING - QUnit.test( "Instancing", ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { var a = new Vector4(); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - assert.ok( a.z == 0, "Passed!" ); - assert.ok( a.w == 1, "Passed!" ); + assert.ok( a.x == 0, 'Passed!' ); + assert.ok( a.y == 0, 'Passed!' ); + assert.ok( a.z == 0, 'Passed!' ); + assert.ok( a.w == 1, 'Passed!' ); var a = new Vector4( x, y, z, w ); - assert.ok( a.x === x, "Passed!" ); - assert.ok( a.y === y, "Passed!" ); - assert.ok( a.z === z, "Passed!" ); - assert.ok( a.w === w, "Passed!" ); + assert.ok( a.x === x, 'Passed!' ); + assert.ok( a.y === y, 'Passed!' ); + assert.ok( a.z === z, 'Passed!' ); + assert.ok( a.w === w, 'Passed!' ); } ); // PUBLIC STUFF - QUnit.todo( "isVector4", ( assert ) => { + QUnit.todo( 'isVector4', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "set", ( assert ) => { + QUnit.test( 'set', ( assert ) => { var a = new Vector4(); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - assert.ok( a.z == 0, "Passed!" ); - assert.ok( a.w == 1, "Passed!" ); + assert.ok( a.x == 0, 'Passed!' ); + assert.ok( a.y == 0, 'Passed!' ); + assert.ok( a.z == 0, 'Passed!' ); + assert.ok( a.w == 1, 'Passed!' ); a.set( x, y, z, w ); - assert.ok( a.x == x, "Passed!" ); - assert.ok( a.y == y, "Passed!" ); - assert.ok( a.z == z, "Passed!" ); - assert.ok( a.w == w, "Passed!" ); + assert.ok( a.x == x, 'Passed!' ); + assert.ok( a.y == y, 'Passed!' ); + assert.ok( a.z == z, 'Passed!' ); + assert.ok( a.w == w, 'Passed!' ); } ); - QUnit.todo( "setScalar", ( assert ) => { + QUnit.todo( 'setScalar', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setX", ( assert ) => { + QUnit.todo( 'setX', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setY", ( assert ) => { + QUnit.todo( 'setY', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setZ", ( assert ) => { + QUnit.todo( 'setZ', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setW", ( assert ) => { + QUnit.todo( 'setW', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setComponent", ( assert ) => { + QUnit.todo( 'setComponent', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getComponent", ( assert ) => { + QUnit.todo( 'getComponent', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "clone", ( assert ) => { + QUnit.todo( 'clone', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "copy", ( assert ) => { + QUnit.test( 'copy', ( assert ) => { var a = new Vector4( x, y, z, w ); var b = new Vector4().copy( a ); - assert.ok( b.x == x, "Passed!" ); - assert.ok( b.y == y, "Passed!" ); - assert.ok( b.z == z, "Passed!" ); - assert.ok( b.w == w, "Passed!" ); + assert.ok( b.x == x, 'Passed!' ); + assert.ok( b.y == y, 'Passed!' ); + assert.ok( b.z == z, 'Passed!' ); + assert.ok( b.w == w, 'Passed!' ); // ensure that it is a true copy a.x = 0; a.y = - 1; a.z = - 2; a.w = - 3; - assert.ok( b.x == x, "Passed!" ); - assert.ok( b.y == y, "Passed!" ); - assert.ok( b.z == z, "Passed!" ); - assert.ok( b.w == w, "Passed!" ); + assert.ok( b.x == x, 'Passed!' ); + assert.ok( b.y == y, 'Passed!' ); + assert.ok( b.z == z, 'Passed!' ); + assert.ok( b.w == w, 'Passed!' ); } ); - QUnit.test( "add", ( assert ) => { + QUnit.test( 'add', ( assert ) => { var a = new Vector4( x, y, z, w ); var b = new Vector4( - x, - y, - z, - w ); a.add( b ); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - assert.ok( a.z == 0, "Passed!" ); - assert.ok( a.w == 0, "Passed!" ); + assert.ok( a.x == 0, 'Passed!' ); + assert.ok( a.y == 0, 'Passed!' ); + assert.ok( a.z == 0, 'Passed!' ); + assert.ok( a.w == 0, 'Passed!' ); var c = new Vector4().addVectors( b, b ); - assert.ok( c.x == - 2 * x, "Passed!" ); - assert.ok( c.y == - 2 * y, "Passed!" ); - assert.ok( c.z == - 2 * z, "Passed!" ); - assert.ok( c.w == - 2 * w, "Passed!" ); + assert.ok( c.x == - 2 * x, 'Passed!' ); + assert.ok( c.y == - 2 * y, 'Passed!' ); + assert.ok( c.z == - 2 * z, 'Passed!' ); + assert.ok( c.w == - 2 * w, 'Passed!' ); } ); - QUnit.todo( "addScalar", ( assert ) => { + QUnit.todo( 'addScalar', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "addVectors", ( assert ) => { + QUnit.todo( 'addVectors', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "addScaledVector", ( assert ) => { + QUnit.test( 'addScaledVector', ( assert ) => { var a = new Vector4( x, y, z, w ); var b = new Vector4( 6, 7, 8, 9 ); var s = 3; a.addScaledVector( b, s ); - assert.strictEqual( a.x, x + b.x * s, "Check x" ); - assert.strictEqual( a.y, y + b.y * s, "Check y" ); - assert.strictEqual( a.z, z + b.z * s, "Check z" ); - assert.strictEqual( a.w, w + b.w * s, "Check w" ); + assert.strictEqual( a.x, x + b.x * s, 'Check x' ); + assert.strictEqual( a.y, y + b.y * s, 'Check y' ); + assert.strictEqual( a.z, z + b.z * s, 'Check z' ); + assert.strictEqual( a.w, w + b.w * s, 'Check w' ); } ); - QUnit.test( "sub", ( assert ) => { + QUnit.test( 'sub', ( assert ) => { var a = new Vector4( x, y, z, w ); var b = new Vector4( - x, - y, - z, - w ); a.sub( b ); - assert.ok( a.x == 2 * x, "Passed!" ); - assert.ok( a.y == 2 * y, "Passed!" ); - assert.ok( a.z == 2 * z, "Passed!" ); - assert.ok( a.w == 2 * w, "Passed!" ); + assert.ok( a.x == 2 * x, 'Passed!' ); + assert.ok( a.y == 2 * y, 'Passed!' ); + assert.ok( a.z == 2 * z, 'Passed!' ); + assert.ok( a.w == 2 * w, 'Passed!' ); var c = new Vector4().subVectors( a, a ); - assert.ok( c.x == 0, "Passed!" ); - assert.ok( c.y == 0, "Passed!" ); - assert.ok( c.z == 0, "Passed!" ); - assert.ok( c.w == 0, "Passed!" ); + assert.ok( c.x == 0, 'Passed!' ); + assert.ok( c.y == 0, 'Passed!' ); + assert.ok( c.z == 0, 'Passed!' ); + assert.ok( c.w == 0, 'Passed!' ); } ); - QUnit.todo( "subScalar", ( assert ) => { + QUnit.todo( 'subScalar', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "subVectors", ( assert ) => { + QUnit.todo( 'subVectors', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "multiplyScalar", ( assert ) => { + QUnit.todo( 'multiplyScalar', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "applyMatrix4", ( assert ) => { + QUnit.test( 'applyMatrix4', ( assert ) => { var a = new Vector4( x, y, z, w ); var m = new Matrix4().makeRotationX( Math.PI ); var expected = new Vector4( 2, - 3, - 4, 5 ); a.applyMatrix4( m ); - assert.ok( Math.abs( a.x - expected.x ) <= eps, "Rotation matrix: check x" ); - assert.ok( Math.abs( a.y - expected.y ) <= eps, "Rotation matrix: check y" ); - assert.ok( Math.abs( a.z - expected.z ) <= eps, "Rotation matrix: check z" ); - assert.ok( Math.abs( a.w - expected.w ) <= eps, "Rotation matrix: check w" ); + assert.ok( Math.abs( a.x - expected.x ) <= eps, 'Rotation matrix: check x' ); + assert.ok( Math.abs( a.y - expected.y ) <= eps, 'Rotation matrix: check y' ); + assert.ok( Math.abs( a.z - expected.z ) <= eps, 'Rotation matrix: check z' ); + assert.ok( Math.abs( a.w - expected.w ) <= eps, 'Rotation matrix: check w' ); a.set( x, y, z, w ); m.makeTranslation( 5, 7, 11 ); expected.set( 27, 38, 59, 5 ); a.applyMatrix4( m ); - assert.ok( Math.abs( a.x - expected.x ) <= eps, "Translation matrix: check x" ); - assert.ok( Math.abs( a.y - expected.y ) <= eps, "Translation matrix: check y" ); - assert.ok( Math.abs( a.z - expected.z ) <= eps, "Translation matrix: check z" ); - assert.ok( Math.abs( a.w - expected.w ) <= eps, "Translation matrix: check w" ); + assert.ok( Math.abs( a.x - expected.x ) <= eps, 'Translation matrix: check x' ); + assert.ok( Math.abs( a.y - expected.y ) <= eps, 'Translation matrix: check y' ); + assert.ok( Math.abs( a.z - expected.z ) <= eps, 'Translation matrix: check z' ); + assert.ok( Math.abs( a.w - expected.w ) <= eps, 'Translation matrix: check w' ); a.set( x, y, z, w ); m.set( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0 ); expected.set( 2, 3, 4, 4 ); a.applyMatrix4( m ); - assert.ok( Math.abs( a.x - expected.x ) <= eps, "Custom matrix: check x" ); - assert.ok( Math.abs( a.y - expected.y ) <= eps, "Custom matrix: check y" ); - assert.ok( Math.abs( a.z - expected.z ) <= eps, "Custom matrix: check z" ); - assert.ok( Math.abs( a.w - expected.w ) <= eps, "Custom matrix: check w" ); + assert.ok( Math.abs( a.x - expected.x ) <= eps, 'Custom matrix: check x' ); + assert.ok( Math.abs( a.y - expected.y ) <= eps, 'Custom matrix: check y' ); + assert.ok( Math.abs( a.z - expected.z ) <= eps, 'Custom matrix: check z' ); + assert.ok( Math.abs( a.w - expected.w ) <= eps, 'Custom matrix: check w' ); a.set( x, y, z, w ); m.set( 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53 ); expected.set( 68, 224, 442, 664 ); a.applyMatrix4( m ); - assert.ok( Math.abs( a.x - expected.x ) <= eps, "Bogus matrix: check x" ); - assert.ok( Math.abs( a.y - expected.y ) <= eps, "Bogus matrix: check y" ); - assert.ok( Math.abs( a.z - expected.z ) <= eps, "Bogus matrix: check z" ); - assert.ok( Math.abs( a.w - expected.w ) <= eps, "Bogus matrix: check w" ); + assert.ok( Math.abs( a.x - expected.x ) <= eps, 'Bogus matrix: check x' ); + assert.ok( Math.abs( a.y - expected.y ) <= eps, 'Bogus matrix: check y' ); + assert.ok( Math.abs( a.z - expected.z ) <= eps, 'Bogus matrix: check z' ); + assert.ok( Math.abs( a.w - expected.w ) <= eps, 'Bogus matrix: check w' ); } ); - QUnit.todo( "divideScalar", ( assert ) => { + QUnit.todo( 'divideScalar', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setAxisAngleFromQuaternion", ( assert ) => { + QUnit.todo( 'setAxisAngleFromQuaternion', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setAxisAngleFromRotationMatrix", ( assert ) => { + QUnit.todo( 'setAxisAngleFromRotationMatrix', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "min", ( assert ) => { + QUnit.todo( 'min', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "max", ( assert ) => { + QUnit.todo( 'max', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "clamp", ( assert ) => { + QUnit.todo( 'clamp', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "clampScalar", ( assert ) => { + QUnit.test( 'clampScalar', ( assert ) => { var a = new Vector4( - 0.1, 0.01, 0.5, 1.5 ); var clamped = new Vector4( 0.1, 0.1, 0.5, 1.0 ); a.clampScalar( 0.1, 1.0 ); - assert.ok( Math.abs( a.x - clamped.x ) <= eps, "Check x" ); - assert.ok( Math.abs( a.y - clamped.y ) <= eps, "Check y" ); - assert.ok( Math.abs( a.z - clamped.z ) <= eps, "Check z" ); - assert.ok( Math.abs( a.w - clamped.w ) <= eps, "Check w" ); + assert.ok( Math.abs( a.x - clamped.x ) <= eps, 'Check x' ); + assert.ok( Math.abs( a.y - clamped.y ) <= eps, 'Check y' ); + assert.ok( Math.abs( a.z - clamped.z ) <= eps, 'Check z' ); + assert.ok( Math.abs( a.w - clamped.w ) <= eps, 'Check w' ); } ); - QUnit.todo( "clampLength", ( assert ) => { + QUnit.todo( 'clampLength', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "floor", ( assert ) => { + QUnit.todo( 'floor', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "ceil", ( assert ) => { + QUnit.todo( 'ceil', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "round", ( assert ) => { + QUnit.todo( 'round', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "roundToZero", ( assert ) => { + QUnit.todo( 'roundToZero', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "negate", ( assert ) => { + QUnit.test( 'negate', ( assert ) => { var a = new Vector4( x, y, z, w ); a.negate(); - assert.ok( a.x == - x, "Passed!" ); - assert.ok( a.y == - y, "Passed!" ); - assert.ok( a.z == - z, "Passed!" ); - assert.ok( a.w == - w, "Passed!" ); + assert.ok( a.x == - x, 'Passed!' ); + assert.ok( a.y == - y, 'Passed!' ); + assert.ok( a.z == - z, 'Passed!' ); + assert.ok( a.w == - w, 'Passed!' ); } ); - QUnit.test( "dot", ( assert ) => { + QUnit.test( 'dot', ( assert ) => { var a = new Vector4( x, y, z, w ); var b = new Vector4( - x, - y, - z, - w ); var c = new Vector4( 0, 0, 0, 0 ); var result = a.dot( b ); - assert.ok( result == ( - x * x - y * y - z * z - w * w ), "Passed!" ); + assert.ok( result == ( - x * x - y * y - z * z - w * w ), 'Passed!' ); var result = a.dot( c ); - assert.ok( result == 0, "Passed!" ); + assert.ok( result == 0, 'Passed!' ); } ); - QUnit.todo( "lengthSq", ( assert ) => { + QUnit.todo( 'lengthSq', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "length", ( assert ) => { + QUnit.todo( 'length', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "manhattanLength", ( assert ) => { + QUnit.test( 'manhattanLength', ( assert ) => { var a = new Vector4( x, 0, 0, 0 ); var b = new Vector4( 0, - y, 0, 0 ); @@ -375,21 +375,21 @@ export default QUnit.module( 'Maths', () => { var d = new Vector4( 0, 0, 0, w ); var e = new Vector4( 0, 0, 0, 0 ); - assert.ok( a.manhattanLength() == x, "Positive x" ); - assert.ok( b.manhattanLength() == y, "Negative y" ); - assert.ok( c.manhattanLength() == z, "Positive z" ); - assert.ok( d.manhattanLength() == w, "Positive w" ); - assert.ok( e.manhattanLength() == 0, "Empty initialization" ); + assert.ok( a.manhattanLength() == x, 'Positive x' ); + assert.ok( b.manhattanLength() == y, 'Negative y' ); + assert.ok( c.manhattanLength() == z, 'Positive z' ); + assert.ok( d.manhattanLength() == w, 'Positive w' ); + assert.ok( e.manhattanLength() == 0, 'Empty initialization' ); a.set( x, y, z, w ); assert.ok( a.manhattanLength() == Math.abs( x ) + Math.abs( y ) + Math.abs( z ) + Math.abs( w ), - "All components" + 'All components' ); } ); - QUnit.test( "normalize", ( assert ) => { + QUnit.test( 'normalize', ( assert ) => { var a = new Vector4( x, 0, 0, 0 ); var b = new Vector4( 0, - y, 0, 0 ); @@ -397,180 +397,180 @@ export default QUnit.module( 'Maths', () => { var d = new Vector4( 0, 0, 0, - w ); a.normalize(); - assert.ok( a.length() == 1, "Passed!" ); - assert.ok( a.x == 1, "Passed!" ); + assert.ok( a.length() == 1, 'Passed!' ); + assert.ok( a.x == 1, 'Passed!' ); b.normalize(); - assert.ok( b.length() == 1, "Passed!" ); - assert.ok( b.y == - 1, "Passed!" ); + assert.ok( b.length() == 1, 'Passed!' ); + assert.ok( b.y == - 1, 'Passed!' ); c.normalize(); - assert.ok( c.length() == 1, "Passed!" ); - assert.ok( c.z == 1, "Passed!" ); + assert.ok( c.length() == 1, 'Passed!' ); + assert.ok( c.z == 1, 'Passed!' ); d.normalize(); - assert.ok( d.length() == 1, "Passed!" ); - assert.ok( d.w == - 1, "Passed!" ); + assert.ok( d.length() == 1, 'Passed!' ); + assert.ok( d.w == - 1, 'Passed!' ); } ); - QUnit.test( "setLength", ( assert ) => { + QUnit.test( 'setLength', ( assert ) => { var a = new Vector4( x, 0, 0, 0 ); - assert.ok( a.length() == x, "Passed!" ); + assert.ok( a.length() == x, 'Passed!' ); a.setLength( y ); - assert.ok( a.length() == y, "Passed!" ); + assert.ok( a.length() == y, 'Passed!' ); var a = new Vector4( 0, 0, 0, 0 ); - assert.ok( a.length() == 0, "Passed!" ); + assert.ok( a.length() == 0, 'Passed!' ); a.setLength( y ); - assert.ok( a.length() == 0, "Passed!" ); + assert.ok( a.length() == 0, 'Passed!' ); a.setLength(); - assert.ok( isNaN( a.length() ), "Passed!" ); + assert.ok( isNaN( a.length() ), 'Passed!' ); } ); - QUnit.todo( "lerp", ( assert ) => { + QUnit.todo( 'lerp', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "lerpVectors", ( assert ) => { + QUnit.todo( 'lerpVectors', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.test( "equals", ( assert ) => { + QUnit.test( 'equals', ( assert ) => { var a = new Vector4( x, 0, z, 0 ); var b = new Vector4( 0, - y, 0, - w ); - assert.ok( a.x != b.x, "Passed!" ); - assert.ok( a.y != b.y, "Passed!" ); - assert.ok( a.z != b.z, "Passed!" ); - assert.ok( a.w != b.w, "Passed!" ); + assert.ok( a.x != b.x, 'Passed!' ); + assert.ok( a.y != b.y, 'Passed!' ); + assert.ok( a.z != b.z, 'Passed!' ); + assert.ok( a.w != b.w, 'Passed!' ); - assert.ok( ! a.equals( b ), "Passed!" ); - assert.ok( ! b.equals( a ), "Passed!" ); + assert.ok( ! a.equals( b ), 'Passed!' ); + assert.ok( ! b.equals( a ), 'Passed!' ); a.copy( b ); - assert.ok( a.x == b.x, "Passed!" ); - assert.ok( a.y == b.y, "Passed!" ); - assert.ok( a.z == b.z, "Passed!" ); - assert.ok( a.w == b.w, "Passed!" ); + assert.ok( a.x == b.x, 'Passed!' ); + assert.ok( a.y == b.y, 'Passed!' ); + assert.ok( a.z == b.z, 'Passed!' ); + assert.ok( a.w == b.w, 'Passed!' ); - assert.ok( a.equals( b ), "Passed!" ); - assert.ok( b.equals( a ), "Passed!" ); + assert.ok( a.equals( b ), 'Passed!' ); + assert.ok( b.equals( a ), 'Passed!' ); } ); - QUnit.test( "fromArray", ( assert ) => { + QUnit.test( 'fromArray', ( assert ) => { var a = new Vector4(); var array = [ 1, 2, 3, 4, 5, 6, 7, 8 ]; a.fromArray( array ); - assert.strictEqual( a.x, 1, "No offset: check x" ); - assert.strictEqual( a.y, 2, "No offset: check y" ); - assert.strictEqual( a.z, 3, "No offset: check z" ); - assert.strictEqual( a.w, 4, "No offset: check w" ); + assert.strictEqual( a.x, 1, 'No offset: check x' ); + assert.strictEqual( a.y, 2, 'No offset: check y' ); + assert.strictEqual( a.z, 3, 'No offset: check z' ); + assert.strictEqual( a.w, 4, 'No offset: check w' ); a.fromArray( array, 4 ); - assert.strictEqual( a.x, 5, "With offset: check x" ); - assert.strictEqual( a.y, 6, "With offset: check y" ); - assert.strictEqual( a.z, 7, "With offset: check z" ); - assert.strictEqual( a.w, 8, "With offset: check w" ); + assert.strictEqual( a.x, 5, 'With offset: check x' ); + assert.strictEqual( a.y, 6, 'With offset: check y' ); + assert.strictEqual( a.z, 7, 'With offset: check z' ); + assert.strictEqual( a.w, 8, 'With offset: check w' ); } ); - QUnit.test( "toArray", ( assert ) => { + QUnit.test( 'toArray', ( assert ) => { var a = new Vector4( x, y, z, w ); var array = a.toArray(); - assert.strictEqual( array[ 0 ], x, "No array, no offset: check x" ); - assert.strictEqual( array[ 1 ], y, "No array, no offset: check y" ); - assert.strictEqual( array[ 2 ], z, "No array, no offset: check z" ); - assert.strictEqual( array[ 3 ], w, "No array, no offset: check w" ); + assert.strictEqual( array[ 0 ], x, 'No array, no offset: check x' ); + assert.strictEqual( array[ 1 ], y, 'No array, no offset: check y' ); + assert.strictEqual( array[ 2 ], z, 'No array, no offset: check z' ); + assert.strictEqual( array[ 3 ], w, 'No array, no offset: check w' ); var array = []; a.toArray( array ); - assert.strictEqual( array[ 0 ], x, "With array, no offset: check x" ); - assert.strictEqual( array[ 1 ], y, "With array, no offset: check y" ); - assert.strictEqual( array[ 2 ], z, "With array, no offset: check z" ); - assert.strictEqual( array[ 3 ], w, "With array, no offset: check w" ); + assert.strictEqual( array[ 0 ], x, 'With array, no offset: check x' ); + assert.strictEqual( array[ 1 ], y, 'With array, no offset: check y' ); + assert.strictEqual( array[ 2 ], z, 'With array, no offset: check z' ); + assert.strictEqual( array[ 3 ], w, 'With array, no offset: check w' ); var array = []; a.toArray( array, 1 ); - assert.strictEqual( array[ 0 ], undefined, "With array and offset: check [0]" ); - assert.strictEqual( array[ 1 ], x, "With array and offset: check x" ); - assert.strictEqual( array[ 2 ], y, "With array and offset: check y" ); - assert.strictEqual( array[ 3 ], z, "With array and offset: check z" ); - assert.strictEqual( array[ 4 ], w, "With array and offset: check w" ); + assert.strictEqual( array[ 0 ], undefined, 'With array and offset: check [0]' ); + assert.strictEqual( array[ 1 ], x, 'With array and offset: check x' ); + assert.strictEqual( array[ 2 ], y, 'With array and offset: check y' ); + assert.strictEqual( array[ 3 ], z, 'With array and offset: check z' ); + assert.strictEqual( array[ 4 ], w, 'With array and offset: check w' ); } ); - QUnit.test( "fromBufferAttribute", ( assert ) => { + QUnit.test( 'fromBufferAttribute', ( assert ) => { var a = new Vector4(); var attr = new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ), 4 ); a.fromBufferAttribute( attr, 0 ); - assert.strictEqual( a.x, 1, "Offset 0: check x" ); - assert.strictEqual( a.y, 2, "Offset 0: check y" ); - assert.strictEqual( a.z, 3, "Offset 0: check z" ); - assert.strictEqual( a.w, 4, "Offset 0: check w" ); + assert.strictEqual( a.x, 1, 'Offset 0: check x' ); + assert.strictEqual( a.y, 2, 'Offset 0: check y' ); + assert.strictEqual( a.z, 3, 'Offset 0: check z' ); + assert.strictEqual( a.w, 4, 'Offset 0: check w' ); a.fromBufferAttribute( attr, 1 ); - assert.strictEqual( a.x, 5, "Offset 1: check x" ); - assert.strictEqual( a.y, 6, "Offset 1: check y" ); - assert.strictEqual( a.z, 7, "Offset 1: check z" ); - assert.strictEqual( a.w, 8, "Offset 1: check w" ); + assert.strictEqual( a.x, 5, 'Offset 1: check x' ); + assert.strictEqual( a.y, 6, 'Offset 1: check y' ); + assert.strictEqual( a.z, 7, 'Offset 1: check z' ); + assert.strictEqual( a.w, 8, 'Offset 1: check w' ); } ); // TODO (Itee) refactor/split - QUnit.test( "setX,setY,setZ,setW", ( assert ) => { + QUnit.test( 'setX,setY,setZ,setW', ( assert ) => { var a = new Vector4(); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - assert.ok( a.z == 0, "Passed!" ); - assert.ok( a.w == 1, "Passed!" ); + assert.ok( a.x == 0, 'Passed!' ); + assert.ok( a.y == 0, 'Passed!' ); + assert.ok( a.z == 0, 'Passed!' ); + assert.ok( a.w == 1, 'Passed!' ); a.setX( x ); a.setY( y ); a.setZ( z ); a.setW( w ); - assert.ok( a.x == x, "Passed!" ); - assert.ok( a.y == y, "Passed!" ); - assert.ok( a.z == z, "Passed!" ); - assert.ok( a.w == w, "Passed!" ); + assert.ok( a.x == x, 'Passed!' ); + assert.ok( a.y == y, 'Passed!' ); + assert.ok( a.z == z, 'Passed!' ); + assert.ok( a.w == w, 'Passed!' ); } ); - QUnit.test( "setComponent,getComponent", ( assert ) => { + QUnit.test( 'setComponent,getComponent', ( assert ) => { var a = new Vector4(); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - assert.ok( a.z == 0, "Passed!" ); - assert.ok( a.w == 1, "Passed!" ); + assert.ok( a.x == 0, 'Passed!' ); + assert.ok( a.y == 0, 'Passed!' ); + assert.ok( a.z == 0, 'Passed!' ); + assert.ok( a.w == 1, 'Passed!' ); a.setComponent( 0, 1 ); a.setComponent( 1, 2 ); a.setComponent( 2, 3 ); a.setComponent( 3, 4 ); - assert.ok( a.getComponent( 0 ) == 1, "Passed!" ); - assert.ok( a.getComponent( 1 ) == 2, "Passed!" ); - assert.ok( a.getComponent( 2 ) == 3, "Passed!" ); - assert.ok( a.getComponent( 3 ) == 4, "Passed!" ); + assert.ok( a.getComponent( 0 ) == 1, 'Passed!' ); + assert.ok( a.getComponent( 1 ) == 2, 'Passed!' ); + assert.ok( a.getComponent( 2 ) == 3, 'Passed!' ); + assert.ok( a.getComponent( 3 ) == 4, 'Passed!' ); } ); - QUnit.test( "setComponent/getComponent exceptions", ( assert ) => { + QUnit.test( 'setComponent/getComponent exceptions', ( assert ) => { var a = new Vector4(); @@ -581,7 +581,7 @@ export default QUnit.module( 'Maths', () => { }, /index is out of range/, - "setComponent with an out of range index throws Error" + 'setComponent with an out of range index throws Error' ); assert.throws( function () { @@ -590,91 +590,91 @@ export default QUnit.module( 'Maths', () => { }, /index is out of range/, - "getComponent with an out of range index throws Error" + 'getComponent with an out of range index throws Error' ); } ); - QUnit.test( "setScalar/addScalar/subScalar", ( assert ) => { + QUnit.test( 'setScalar/addScalar/subScalar', ( assert ) => { var a = new Vector4(); var s = 3; a.setScalar( s ); - assert.strictEqual( a.x, s, "setScalar: check x" ); - assert.strictEqual( a.y, s, "setScalar: check y" ); - assert.strictEqual( a.z, s, "setScalar: check z" ); - assert.strictEqual( a.w, s, "setScalar: check w" ); + assert.strictEqual( a.x, s, 'setScalar: check x' ); + assert.strictEqual( a.y, s, 'setScalar: check y' ); + assert.strictEqual( a.z, s, 'setScalar: check z' ); + assert.strictEqual( a.w, s, 'setScalar: check w' ); a.addScalar( s ); - assert.strictEqual( a.x, 2 * s, "addScalar: check x" ); - assert.strictEqual( a.y, 2 * s, "addScalar: check y" ); - assert.strictEqual( a.z, 2 * s, "addScalar: check z" ); - assert.strictEqual( a.w, 2 * s, "addScalar: check w" ); + assert.strictEqual( a.x, 2 * s, 'addScalar: check x' ); + assert.strictEqual( a.y, 2 * s, 'addScalar: check y' ); + assert.strictEqual( a.z, 2 * s, 'addScalar: check z' ); + assert.strictEqual( a.w, 2 * s, 'addScalar: check w' ); a.subScalar( 2 * s ); - assert.strictEqual( a.x, 0, "subScalar: check x" ); - assert.strictEqual( a.y, 0, "subScalar: check y" ); - assert.strictEqual( a.z, 0, "subScalar: check z" ); - assert.strictEqual( a.w, 0, "subScalar: check w" ); + assert.strictEqual( a.x, 0, 'subScalar: check x' ); + assert.strictEqual( a.y, 0, 'subScalar: check y' ); + assert.strictEqual( a.z, 0, 'subScalar: check z' ); + assert.strictEqual( a.w, 0, 'subScalar: check w' ); } ); - QUnit.test( "multiply/divide", ( assert ) => { + QUnit.test( 'multiply/divide', ( assert ) => { var a = new Vector4( x, y, z, w ); var b = new Vector4( - x, - y, - z, - w ); a.multiplyScalar( - 2 ); - assert.ok( a.x == x * - 2, "Passed!" ); - assert.ok( a.y == y * - 2, "Passed!" ); - assert.ok( a.z == z * - 2, "Passed!" ); - assert.ok( a.w == w * - 2, "Passed!" ); + assert.ok( a.x == x * - 2, 'Passed!' ); + assert.ok( a.y == y * - 2, 'Passed!' ); + assert.ok( a.z == z * - 2, 'Passed!' ); + assert.ok( a.w == w * - 2, 'Passed!' ); b.multiplyScalar( - 2 ); - assert.ok( b.x == 2 * x, "Passed!" ); - assert.ok( b.y == 2 * y, "Passed!" ); - assert.ok( b.z == 2 * z, "Passed!" ); - assert.ok( b.w == 2 * w, "Passed!" ); + assert.ok( b.x == 2 * x, 'Passed!' ); + assert.ok( b.y == 2 * y, 'Passed!' ); + assert.ok( b.z == 2 * z, 'Passed!' ); + assert.ok( b.w == 2 * w, 'Passed!' ); a.divideScalar( - 2 ); - assert.ok( a.x == x, "Passed!" ); - assert.ok( a.y == y, "Passed!" ); - assert.ok( a.z == z, "Passed!" ); - assert.ok( a.w == w, "Passed!" ); + assert.ok( a.x == x, 'Passed!' ); + assert.ok( a.y == y, 'Passed!' ); + assert.ok( a.z == z, 'Passed!' ); + assert.ok( a.w == w, 'Passed!' ); b.divideScalar( - 2 ); - assert.ok( b.x == - x, "Passed!" ); - assert.ok( b.y == - y, "Passed!" ); - assert.ok( b.z == - z, "Passed!" ); - assert.ok( b.w == - w, "Passed!" ); + assert.ok( b.x == - x, 'Passed!' ); + assert.ok( b.y == - y, 'Passed!' ); + assert.ok( b.z == - z, 'Passed!' ); + assert.ok( b.w == - w, 'Passed!' ); } ); - QUnit.test( "min/max/clamp", ( assert ) => { + QUnit.test( 'min/max/clamp', ( assert ) => { var a = new Vector4( x, y, z, w ); var b = new Vector4( - x, - y, - z, - w ); var c = new Vector4(); c.copy( a ).min( b ); - assert.ok( c.x == - x, "Passed!" ); - assert.ok( c.y == - y, "Passed!" ); - assert.ok( c.z == - z, "Passed!" ); - assert.ok( c.w == - w, "Passed!" ); + assert.ok( c.x == - x, 'Passed!' ); + assert.ok( c.y == - y, 'Passed!' ); + assert.ok( c.z == - z, 'Passed!' ); + assert.ok( c.w == - w, 'Passed!' ); c.copy( a ).max( b ); - assert.ok( c.x == x, "Passed!" ); - assert.ok( c.y == y, "Passed!" ); - assert.ok( c.z == z, "Passed!" ); - assert.ok( c.w == w, "Passed!" ); + assert.ok( c.x == x, 'Passed!' ); + assert.ok( c.y == y, 'Passed!' ); + assert.ok( c.z == z, 'Passed!' ); + assert.ok( c.w == w, 'Passed!' ); c.set( - 2 * x, 2 * y, - 2 * z, 2 * w ); c.clamp( b, a ); - assert.ok( c.x == - x, "Passed!" ); - assert.ok( c.y == y, "Passed!" ); - assert.ok( c.z == - z, "Passed!" ); - assert.ok( c.w == w, "Passed!" ); + assert.ok( c.x == - x, 'Passed!' ); + assert.ok( c.y == y, 'Passed!' ); + assert.ok( c.z == - z, 'Passed!' ); + assert.ok( c.w == w, 'Passed!' ); } ); - QUnit.test( "length/lengthSq", ( assert ) => { + QUnit.test( 'length/lengthSq', ( assert ) => { var a = new Vector4( x, 0, 0, 0 ); var b = new Vector4( 0, - y, 0, 0 ); @@ -682,38 +682,38 @@ export default QUnit.module( 'Maths', () => { var d = new Vector4( 0, 0, 0, w ); var e = new Vector4( 0, 0, 0, 0 ); - assert.ok( a.length() == x, "Passed!" ); - assert.ok( a.lengthSq() == x * x, "Passed!" ); - assert.ok( b.length() == y, "Passed!" ); - assert.ok( b.lengthSq() == y * y, "Passed!" ); - assert.ok( c.length() == z, "Passed!" ); - assert.ok( c.lengthSq() == z * z, "Passed!" ); - assert.ok( d.length() == w, "Passed!" ); - assert.ok( d.lengthSq() == w * w, "Passed!" ); - assert.ok( e.length() == 0, "Passed!" ); - assert.ok( e.lengthSq() == 0, "Passed!" ); + assert.ok( a.length() == x, 'Passed!' ); + assert.ok( a.lengthSq() == x * x, 'Passed!' ); + assert.ok( b.length() == y, 'Passed!' ); + assert.ok( b.lengthSq() == y * y, 'Passed!' ); + assert.ok( c.length() == z, 'Passed!' ); + assert.ok( c.lengthSq() == z * z, 'Passed!' ); + assert.ok( d.length() == w, 'Passed!' ); + assert.ok( d.lengthSq() == w * w, 'Passed!' ); + assert.ok( e.length() == 0, 'Passed!' ); + assert.ok( e.lengthSq() == 0, 'Passed!' ); a.set( x, y, z, w ); - assert.ok( a.length() == Math.sqrt( x * x + y * y + z * z + w * w ), "Passed!" ); - assert.ok( a.lengthSq() == ( x * x + y * y + z * z + w * w ), "Passed!" ); + assert.ok( a.length() == Math.sqrt( x * x + y * y + z * z + w * w ), 'Passed!' ); + assert.ok( a.lengthSq() == ( x * x + y * y + z * z + w * w ), 'Passed!' ); } ); - QUnit.test( "lerp/clone", ( assert ) => { + QUnit.test( 'lerp/clone', ( assert ) => { var a = new Vector4( x, 0, z, 0 ); var b = new Vector4( 0, - y, 0, - w ); - assert.ok( a.lerp( a, 0 ).equals( a.lerp( a, 0.5 ) ), "Passed!" ); - assert.ok( a.lerp( a, 0 ).equals( a.lerp( a, 1 ) ), "Passed!" ); + assert.ok( a.lerp( a, 0 ).equals( a.lerp( a, 0.5 ) ), 'Passed!' ); + assert.ok( a.lerp( a, 0 ).equals( a.lerp( a, 1 ) ), 'Passed!' ); - assert.ok( a.clone().lerp( b, 0 ).equals( a ), "Passed!" ); + assert.ok( a.clone().lerp( b, 0 ).equals( a ), 'Passed!' ); - assert.ok( a.clone().lerp( b, 0.5 ).x == x * 0.5, "Passed!" ); - assert.ok( a.clone().lerp( b, 0.5 ).y == - y * 0.5, "Passed!" ); - assert.ok( a.clone().lerp( b, 0.5 ).z == z * 0.5, "Passed!" ); - assert.ok( a.clone().lerp( b, 0.5 ).w == - w * 0.5, "Passed!" ); + assert.ok( a.clone().lerp( b, 0.5 ).x == x * 0.5, 'Passed!' ); + assert.ok( a.clone().lerp( b, 0.5 ).y == - y * 0.5, 'Passed!' ); + assert.ok( a.clone().lerp( b, 0.5 ).z == z * 0.5, 'Passed!' ); + assert.ok( a.clone().lerp( b, 0.5 ).w == - w * 0.5, 'Passed!' ); - assert.ok( a.clone().lerp( b, 1 ).equals( b ), "Passed!" ); + assert.ok( a.clone().lerp( b, 1 ).equals( b ), 'Passed!' ); } ); diff --git a/test/unit/src/math/interpolants/CubicInterpolant.tests.js b/test/unit/src/math/interpolants/CubicInterpolant.tests.js index 4dde8590c26889..e6df61fa1f27ce 100644 --- a/test/unit/src/math/interpolants/CubicInterpolant.tests.js +++ b/test/unit/src/math/interpolants/CubicInterpolant.tests.js @@ -9,16 +9,16 @@ export default QUnit.module( 'Maths', () => { QUnit.module( 'CubicInterpolant', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/math/interpolants/DiscreteInterpolant.tests.js b/test/unit/src/math/interpolants/DiscreteInterpolant.tests.js index 9a36d6aed8e971..1b2944644359ad 100644 --- a/test/unit/src/math/interpolants/DiscreteInterpolant.tests.js +++ b/test/unit/src/math/interpolants/DiscreteInterpolant.tests.js @@ -9,16 +9,16 @@ export default QUnit.module( 'Maths', () => { QUnit.module( 'DiscreteInterpolant', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/math/interpolants/LinearInterpolant.tests.js b/test/unit/src/math/interpolants/LinearInterpolant.tests.js index fac50addf81980..6b794c2c4a493b 100644 --- a/test/unit/src/math/interpolants/LinearInterpolant.tests.js +++ b/test/unit/src/math/interpolants/LinearInterpolant.tests.js @@ -9,16 +9,16 @@ export default QUnit.module( 'Maths', () => { QUnit.module( 'LinearInterpolant', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/math/interpolants/QuaternionLinearInterpolant.tests.js b/test/unit/src/math/interpolants/QuaternionLinearInterpolant.tests.js index da749036f0a86b..9f1341437f50f6 100644 --- a/test/unit/src/math/interpolants/QuaternionLinearInterpolant.tests.js +++ b/test/unit/src/math/interpolants/QuaternionLinearInterpolant.tests.js @@ -9,16 +9,16 @@ export default QUnit.module( 'Maths', () => { QUnit.module( 'QuaternionLinearInterpolant', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/objects/Bone.tests.js b/test/unit/src/objects/Bone.tests.js index faf1e818212479..266953a2f1663c 100644 --- a/test/unit/src/objects/Bone.tests.js +++ b/test/unit/src/objects/Bone.tests.js @@ -7,23 +7,23 @@ export default QUnit.module( 'Objects', () => { QUnit.module( 'Bone', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isBone", ( assert ) => { + QUnit.todo( 'isBone', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/objects/Group.tests.js b/test/unit/src/objects/Group.tests.js index 38c4cb466ad2b3..2b87deefe6e646 100644 --- a/test/unit/src/objects/Group.tests.js +++ b/test/unit/src/objects/Group.tests.js @@ -7,16 +7,16 @@ export default QUnit.module( 'Objects', () => { QUnit.module( 'Group', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/objects/LOD.tests.js b/test/unit/src/objects/LOD.tests.js index 88e304a8ae7418..e5aa1f3fd430a0 100644 --- a/test/unit/src/objects/LOD.tests.js +++ b/test/unit/src/objects/LOD.tests.js @@ -9,42 +9,42 @@ export default QUnit.module( 'Objects', () => { QUnit.module( 'LOD', () => { // INHERITANCE - QUnit.test( "Extending", ( assert ) => { + QUnit.test( 'Extending', ( assert ) => { var lod = new LOD(); - assert.strictEqual( ( lod instanceof Object3D ), true, "LOD extends from Object3D" ); + assert.strictEqual( ( lod instanceof Object3D ), true, 'LOD extends from Object3D' ); } ); // PROPERTIES - QUnit.test( "levels", ( assert ) => { + QUnit.test( 'levels', ( assert ) => { var lod = new LOD(); var levels = lod.levels; - assert.strictEqual( Array.isArray( levels ), true, "LOD.levels is of type array." ); - assert.strictEqual( levels.length, 0, "LOD.levels is empty by default." ); + assert.strictEqual( Array.isArray( levels ), true, 'LOD.levels is of type array.' ); + assert.strictEqual( levels.length, 0, 'LOD.levels is empty by default.' ); } ); - QUnit.test( "autoUpdate", ( assert ) => { + QUnit.test( 'autoUpdate', ( assert ) => { var lod = new LOD(); - assert.strictEqual( lod.autoUpdate, true, "LOD.autoUpdate is of type boolean and true by default." ); + assert.strictEqual( lod.autoUpdate, true, 'LOD.autoUpdate is of type boolean and true by default.' ); } ); // PUBLIC STUFF - QUnit.test( "isLOD", ( assert ) => { + QUnit.test( 'isLOD', ( assert ) => { var lod = new LOD(); - assert.strictEqual( lod.isLOD, true, ".isLOD property is defined." ); + assert.strictEqual( lod.isLOD, true, '.isLOD property is defined.' ); } ); - QUnit.test( "copy", ( assert ) => { + QUnit.test( 'copy', ( assert ) => { var lod1 = new LOD(); var lod2 = new LOD(); @@ -61,11 +61,11 @@ export default QUnit.module( 'Objects', () => { lod2.copy( lod1 ); - assert.strictEqual( lod2.autoUpdate, false, "LOD.autoUpdate is correctly copied." ); - assert.strictEqual( lod2.levels.length, 3, "LOD.levels has the correct length after the copy." ); + assert.strictEqual( lod2.autoUpdate, false, 'LOD.autoUpdate is correctly copied.' ); + assert.strictEqual( lod2.levels.length, 3, 'LOD.levels has the correct length after the copy.' ); } ); - QUnit.test( "addLevel", ( assert ) => { + QUnit.test( 'addLevel', ( assert ) => { var lod = new LOD(); @@ -77,13 +77,13 @@ export default QUnit.module( 'Objects', () => { lod.addLevel( mid, 25 ); lod.addLevel( low, 50 ); - assert.strictEqual( lod.levels.length, 3, "LOD.levels has the correct length." ); - assert.deepEqual( lod.levels[ 0 ], { distance: 5, object: high }, "First entry correct." ); - assert.deepEqual( lod.levels[ 1 ], { distance: 25, object: mid }, "Second entry correct." ); - assert.deepEqual( lod.levels[ 2 ], { distance: 50, object: low }, "Third entry correct." ); + assert.strictEqual( lod.levels.length, 3, 'LOD.levels has the correct length.' ); + assert.deepEqual( lod.levels[ 0 ], { distance: 5, object: high }, 'First entry correct.' ); + assert.deepEqual( lod.levels[ 1 ], { distance: 25, object: mid }, 'Second entry correct.' ); + assert.deepEqual( lod.levels[ 2 ], { distance: 50, object: low }, 'Third entry correct.' ); } ); - QUnit.test( "getObjectForDistance", ( assert ) => { + QUnit.test( 'getObjectForDistance', ( assert ) => { var lod = new LOD(); @@ -91,24 +91,24 @@ export default QUnit.module( 'Objects', () => { var mid = new Object3D(); var low = new Object3D(); - assert.strictEqual( lod.getObjectForDistance( 5 ), null, "Returns null if no LOD levels are defined." ); + assert.strictEqual( lod.getObjectForDistance( 5 ), null, 'Returns null if no LOD levels are defined.' ); lod.addLevel( high, 5 ); - assert.strictEqual( lod.getObjectForDistance( 0 ), high, "Returns always the same object if only one LOD level is defined." ); - assert.strictEqual( lod.getObjectForDistance( 10 ), high, "Returns always the same object if only one LOD level is defined." ); + assert.strictEqual( lod.getObjectForDistance( 0 ), high, 'Returns always the same object if only one LOD level is defined.' ); + assert.strictEqual( lod.getObjectForDistance( 10 ), high, 'Returns always the same object if only one LOD level is defined.' ); lod.addLevel( mid, 25 ); lod.addLevel( low, 50 ); - assert.strictEqual( lod.getObjectForDistance( 0 ), high, "Returns the high resolution object." ); - assert.strictEqual( lod.getObjectForDistance( 10 ), high, "Returns the high resolution object." ); - assert.strictEqual( lod.getObjectForDistance( 25 ), mid, "Returns the mid resolution object." ); - assert.strictEqual( lod.getObjectForDistance( 50 ), low, "Returns the low resolution object." ); - assert.strictEqual( lod.getObjectForDistance( 60 ), low, "Returns the low resolution object." ); + assert.strictEqual( lod.getObjectForDistance( 0 ), high, 'Returns the high resolution object.' ); + assert.strictEqual( lod.getObjectForDistance( 10 ), high, 'Returns the high resolution object.' ); + assert.strictEqual( lod.getObjectForDistance( 25 ), mid, 'Returns the mid resolution object.' ); + assert.strictEqual( lod.getObjectForDistance( 50 ), low, 'Returns the low resolution object.' ); + assert.strictEqual( lod.getObjectForDistance( 60 ), low, 'Returns the low resolution object.' ); } ); - QUnit.test( "raycast", ( assert ) => { + QUnit.test( 'raycast', ( assert ) => { var lod = new LOD(); var raycaster = new Raycaster(); @@ -116,17 +116,17 @@ export default QUnit.module( 'Objects', () => { lod.raycast( raycaster, intersections ); - assert.strictEqual( intersections.length, 0, "Does not fail if raycasting is used with a LOD object without levels." ); + assert.strictEqual( intersections.length, 0, 'Does not fail if raycasting is used with a LOD object without levels.' ); } ); - QUnit.todo( "update", ( assert ) => { + QUnit.todo( 'update', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "toJSON", ( assert ) => { + QUnit.todo( 'toJSON', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/objects/Line.tests.js b/test/unit/src/objects/Line.tests.js index 2a54e6e5601081..ee0031bd0520df 100644 --- a/test/unit/src/objects/Line.tests.js +++ b/test/unit/src/objects/Line.tests.js @@ -7,35 +7,35 @@ export default QUnit.module( 'Objects', () => { QUnit.module( 'Line', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isLine", ( assert ) => { + QUnit.todo( 'isLine', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "raycast", ( assert ) => { + QUnit.todo( 'raycast', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "clone", ( assert ) => { + QUnit.todo( 'clone', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/objects/LineLoop.tests.js b/test/unit/src/objects/LineLoop.tests.js index 5df0bdfa7866d9..ff4d78d8542eb7 100644 --- a/test/unit/src/objects/LineLoop.tests.js +++ b/test/unit/src/objects/LineLoop.tests.js @@ -7,23 +7,23 @@ export default QUnit.module( 'Objects', () => { QUnit.module( 'LineLoop', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isLineLoop", ( assert ) => { + QUnit.todo( 'isLineLoop', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/objects/LineSegments.tests.js b/test/unit/src/objects/LineSegments.tests.js index ec4bf61297d914..d48af05a09ed3c 100644 --- a/test/unit/src/objects/LineSegments.tests.js +++ b/test/unit/src/objects/LineSegments.tests.js @@ -7,23 +7,23 @@ export default QUnit.module( 'Objects', () => { QUnit.module( 'LineSegments', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isLineSegments", ( assert ) => { + QUnit.todo( 'isLineSegments', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/objects/Points.tests.js b/test/unit/src/objects/Points.tests.js index 9ba508efc3fced..d7d052d0ca5381 100644 --- a/test/unit/src/objects/Points.tests.js +++ b/test/unit/src/objects/Points.tests.js @@ -7,23 +7,23 @@ export default QUnit.module( 'Objects', () => { QUnit.module( 'Points', () => { // INHERITANCE - QUnit.todo( "isPoints", ( assert ) => { + QUnit.todo( 'isPoints', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "raycast", ( assert ) => { + QUnit.todo( 'raycast', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "clone", ( assert ) => { + QUnit.todo( 'clone', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/objects/Skeleton.tests.js b/test/unit/src/objects/Skeleton.tests.js index 43216e87d66e22..b5e740af787ddb 100644 --- a/test/unit/src/objects/Skeleton.tests.js +++ b/test/unit/src/objects/Skeleton.tests.js @@ -7,34 +7,34 @@ export default QUnit.module( 'Objects', () => { QUnit.module( 'Skeleton', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "calculateInverses", ( assert ) => { + QUnit.todo( 'calculateInverses', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "pose", ( assert ) => { + QUnit.todo( 'pose', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "update", ( assert ) => { + QUnit.todo( 'update', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "clone", ( assert ) => { + QUnit.todo( 'clone', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/objects/SkinnedMesh.tests.js b/test/unit/src/objects/SkinnedMesh.tests.js index b4d9adfae06824..def9197c7ef2c3 100644 --- a/test/unit/src/objects/SkinnedMesh.tests.js +++ b/test/unit/src/objects/SkinnedMesh.tests.js @@ -7,53 +7,53 @@ export default QUnit.module( 'Objects', () => { QUnit.module( 'SkinnedMesh', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isSkinnedMesh", ( assert ) => { + QUnit.todo( 'isSkinnedMesh', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "initBones", ( assert ) => { + QUnit.todo( 'initBones', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "bind", ( assert ) => { + QUnit.todo( 'bind', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "pose", ( assert ) => { + QUnit.todo( 'pose', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "normalizeSkinWeights", ( assert ) => { + QUnit.todo( 'normalizeSkinWeights', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "updateMatrixWorld", ( assert ) => { + QUnit.todo( 'updateMatrixWorld', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "clone", ( assert ) => { + QUnit.todo( 'clone', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/objects/Sprite.tests.js b/test/unit/src/objects/Sprite.tests.js index 37024e707b4562..713a5e2867a406 100644 --- a/test/unit/src/objects/Sprite.tests.js +++ b/test/unit/src/objects/Sprite.tests.js @@ -7,35 +7,35 @@ export default QUnit.module( 'Objects', () => { QUnit.module( 'Sprite', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isSprite", ( assert ) => { + QUnit.todo( 'isSprite', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "raycast", ( assert ) => { + QUnit.todo( 'raycast', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "clone", ( assert ) => { + QUnit.todo( 'clone', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/renderers/WebGLCubeRenderTarget.tests.js b/test/unit/src/renderers/WebGLCubeRenderTarget.tests.js index 1b9c8d47559049..d94332bf65d405 100644 --- a/test/unit/src/renderers/WebGLCubeRenderTarget.tests.js +++ b/test/unit/src/renderers/WebGLCubeRenderTarget.tests.js @@ -7,16 +7,16 @@ export default QUnit.module( 'Renderers', () => { QUnit.module( 'WebGLCubeRenderTarget', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isWebGLCubeRenderTarget", ( assert ) => { + QUnit.todo( 'isWebGLCubeRenderTarget', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/renderers/WebGLRenderTarget.tests.js b/test/unit/src/renderers/WebGLRenderTarget.tests.js index 9de59ae552f515..8cb2703454b59b 100644 --- a/test/unit/src/renderers/WebGLRenderTarget.tests.js +++ b/test/unit/src/renderers/WebGLRenderTarget.tests.js @@ -7,47 +7,47 @@ export default QUnit.module( 'Renderers', () => { QUnit.module( 'WebGLRenderTarget', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isWebGLRenderTarget", ( assert ) => { + QUnit.todo( 'isWebGLRenderTarget', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setSize", ( assert ) => { + QUnit.todo( 'setSize', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "clone", ( assert ) => { + QUnit.todo( 'clone', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "copy", ( assert ) => { + QUnit.todo( 'copy', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "dispose", ( assert ) => { + QUnit.todo( 'dispose', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/renderers/WebGLRenderer.tests.js b/test/unit/src/renderers/WebGLRenderer.tests.js index 916b2ff221fc66..94f7a581cb60d3 100644 --- a/test/unit/src/renderers/WebGLRenderer.tests.js +++ b/test/unit/src/renderers/WebGLRenderer.tests.js @@ -303,71 +303,133 @@ var customWebGLContext = function () { this.activeTexture = function () {}; + this.attachShader = function () {}; + this.bindAttribLocation = function () {}; + this.bindBuffer = function () {}; + this.bindFramebuffer = function () {}; + this.bindRenderbuffer = function () {}; + this.bindTexture = function () {}; + this.blendColor = function () {}; + this.blendEquation = function () {}; + this.blendEquationSeparate = function () {}; + this.blendFunc = function () {}; + this.blendFuncSeparate = function () {}; + this.bufferData = function () {}; + this.bufferSubData = function () {}; + this.checkFramebufferStatus = function () {}; + this.clear = function () {}; + this.clearColor = function () {}; + this.clearDepth = function () {}; + this.clearStencil = function () {}; + this.colorMask = function () {}; + this.compileShader = function () {}; + this.compressedTexImage2D = function () {}; + this.compressedTexSubImage2D = function () {}; + this.copyTexImage2D = function () {}; + this.copyTexSubImage2D = function () {}; + this.createBuffer = function () {}; + this.createFramebuffer = function () {}; + this.createProgram = function () {}; + this.createRenderbuffer = function () {}; + this.createShader = function () {}; + this.createTexture = function () {}; + this.cullFace = function () {}; + this.deleteBuffer = function () {}; + this.deleteFramebuffer = function () {}; + this.deleteProgram = function () {}; + this.deleteRenderbuffer = function () {}; + this.deleteShader = function () {}; + this.deleteTexture = function () {}; + this.depthFunc = function () {}; + this.depthMask = function () {}; + this.depthRange = function () {}; + this.detachShader = function () {}; + this.disable = function () {}; + this.disableVertexAttribArray = function () {}; + this.drawArrays = function () {}; + this.drawElements = function () {}; + this.enable = function () {}; + this.enableVertexAttribArray = function () {}; + this.finish = function () {}; + this.flush = function () {}; + this.framebufferRenderbuffer = function () {}; + this.framebufferTexture2D = function () {}; + this.frontFace = function () {}; + this.generateMipmap = function () {}; + this.getActiveAttrib = function () {}; + this.getActiveUniform = function () {}; + this.getAttachedShaders = function () {}; + this.getAttribLocation = function () {}; + this.getBufferParameter = function () {}; + this.getContextAttributes = function () {}; + this.getError = function () {}; + this.getExtension = function () {}; + this.getFramebufferAttachmentParameter = function () {}; var parameters = {}; - parameters[ this.VERSION ] = "Custom"; + parameters[ this.VERSION ] = 'Custom'; this.getParameter = function ( parameterID ) { return parameters[ parameterID ]; @@ -375,80 +437,151 @@ var customWebGLContext = function () { }; this.getProgramParameter = function () {}; + this.getProgramInfoLog = function () {}; + this.getRenderbufferParameter = function () {}; + this.getShaderParameter = function () {}; + this.getShaderInfoLog = function () {}; + this.getShaderPrecisionFormat = function () { return { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 }; }; + this.getShaderSource = function () {}; + this.getSupportedExtensions = function () {}; + this.getTexParameter = function () {}; + this.getUniform = function () {}; + this.getUniformLocation = function () {}; + this.getVertexAttrib = function () {}; + this.getVertexAttribOffset = function () {}; + this.hint = function () {}; + this.isBuffer = function () {}; + this.isContextLost = function () {}; + this.isEnabled = function () {}; + this.isFramebuffer = function () {}; + this.isProgram = function () {}; + this.isRenderbuffer = function () {}; + this.isShader = function () {}; + this.isTexture = function () {}; + this.lineWidth = function () {}; + this.linkProgram = function () {}; + this.pixelStorei = function () {}; + this.polygonOffset = function () {}; + this.readPixels = function () {}; + this.renderbufferStorage = function () {}; + this.sampleCoverage = function () {}; + this.scissor = function () {}; + this.shaderSource = function () {}; + this.stencilFunc = function () {}; + this.stencilFuncSeparate = function () {}; + this.stencilMask = function () {}; + this.stencilMaskSeparate = function () {}; + this.stencilOp = function () {}; + this.stencilOpSeparate = function () {}; + this.texParameterf = function () {}; + this.texParameteri = function () {}; + this.texImage2D = function () {}; + this.texSubImage2D = function () {}; + this.uniform1f = function () {}; + this.uniform1fv = function () {}; + this.uniform1i = function () {}; + this.uniform1iv = function () {}; + this.uniform2f = function () {}; + this.uniform2fv = function () {}; + this.uniform2i = function () {}; + this.uniform2iv = function () {}; + this.uniform3f = function () {}; + this.uniform3fv = function () {}; + this.uniform3i = function () {}; + this.uniform3iv = function () {}; + this.uniform4f = function () {}; + this.uniform4fv = function () {}; + this.uniform4i = function () {}; + this.uniform4iv = function () {}; + this.uniformMatrix2fv = function () {}; + this.uniformMatrix3fv = function () {}; + this.uniformMatrix4fv = function () {}; + this.useProgram = function () {}; + this.validateProgram = function () {}; + this.vertexAttrib1f = function () {}; + this.vertexAttrib1fv = function () {}; + this.vertexAttrib2f = function () {}; + this.vertexAttrib2fv = function () {}; + this.vertexAttrib3f = function () {}; + this.vertexAttrib3fv = function () {}; + this.vertexAttrib4f = function () {}; + this.vertexAttrib4fv = function () {}; + this.vertexAttribPointer = function () {}; + this.viewport = function () {}; @@ -458,9 +591,9 @@ export default QUnit.module( 'Renderers', () => { QUnit.module( 'WebGLRenderer-webonly', () => { - QUnit.test( "Instancing", ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( new WebGLRenderer(), "Can instantiate a renderer." ); + assert.ok( new WebGLRenderer(), 'Can instantiate a renderer.' ); } ); diff --git a/test/unit/src/renderers/shaders/ShaderChunk.tests.js b/test/unit/src/renderers/shaders/ShaderChunk.tests.js index 2395548dc8faa8..dfba178976fe55 100644 --- a/test/unit/src/renderers/shaders/ShaderChunk.tests.js +++ b/test/unit/src/renderers/shaders/ShaderChunk.tests.js @@ -10,7 +10,7 @@ export default QUnit.module( 'Renderers', () => { QUnit.todo( 'write me !', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/renderers/shaders/ShaderLib.tests.js b/test/unit/src/renderers/shaders/ShaderLib.tests.js index 4d211693b89662..a83d00f6c4f82f 100644 --- a/test/unit/src/renderers/shaders/ShaderLib.tests.js +++ b/test/unit/src/renderers/shaders/ShaderLib.tests.js @@ -10,7 +10,7 @@ export default QUnit.module( 'Renderers', () => { QUnit.todo( 'write me !', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/renderers/shaders/UniformsLib.tests.js b/test/unit/src/renderers/shaders/UniformsLib.tests.js index cf3520fcf2c291..f40d4e30cf3c24 100644 --- a/test/unit/src/renderers/shaders/UniformsLib.tests.js +++ b/test/unit/src/renderers/shaders/UniformsLib.tests.js @@ -9,15 +9,15 @@ export default QUnit.module( 'Renderers', () => { QUnit.module( 'UniformsLib', () => { // PUBLIC STUFF - QUnit.todo( "merge", ( assert ) => { + QUnit.todo( 'merge', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "clone", ( assert ) => { + QUnit.todo( 'clone', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/renderers/shaders/UniformsUtils.tests.js b/test/unit/src/renderers/shaders/UniformsUtils.tests.js index 4ae7d75bd083d8..691baef8438506 100644 --- a/test/unit/src/renderers/shaders/UniformsUtils.tests.js +++ b/test/unit/src/renderers/shaders/UniformsUtils.tests.js @@ -10,7 +10,7 @@ export default QUnit.module( 'Renderers', () => { QUnit.todo( 'write me !', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/renderers/webgl/WebGLAttributes.tests.js b/test/unit/src/renderers/webgl/WebGLAttributes.tests.js index d43fb18fad1454..e26d64b8c7fb17 100644 --- a/test/unit/src/renderers/webgl/WebGLAttributes.tests.js +++ b/test/unit/src/renderers/webgl/WebGLAttributes.tests.js @@ -9,28 +9,28 @@ export default QUnit.module( 'Renderers', () => { QUnit.module( 'WebGLAttributes', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "get", ( assert ) => { + QUnit.todo( 'get', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "remove", ( assert ) => { + QUnit.todo( 'remove', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "update", ( assert ) => { + QUnit.todo( 'update', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/renderers/webgl/WebGLBackground.tests.js b/test/unit/src/renderers/webgl/WebGLBackground.tests.js index be7ee3c25e8e1d..eb5803b0fb9069 100644 --- a/test/unit/src/renderers/webgl/WebGLBackground.tests.js +++ b/test/unit/src/renderers/webgl/WebGLBackground.tests.js @@ -9,40 +9,40 @@ export default QUnit.module( 'Renderers', () => { QUnit.module( 'WebGLBackground', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "getClearColor", ( assert ) => { + QUnit.todo( 'getClearColor', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setClearColor", ( assert ) => { + QUnit.todo( 'setClearColor', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getClearAlpha", ( assert ) => { + QUnit.todo( 'getClearAlpha', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setClearAlpha", ( assert ) => { + QUnit.todo( 'setClearAlpha', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "render", ( assert ) => { + QUnit.todo( 'render', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/renderers/webgl/WebGLBufferRenderer.tests.js b/test/unit/src/renderers/webgl/WebGLBufferRenderer.tests.js index cd4a9dde11c12e..c4f5207d9b651f 100644 --- a/test/unit/src/renderers/webgl/WebGLBufferRenderer.tests.js +++ b/test/unit/src/renderers/webgl/WebGLBufferRenderer.tests.js @@ -9,28 +9,28 @@ export default QUnit.module( 'Renderers', () => { QUnit.module( 'WebGLBufferRenderer', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "setMode", ( assert ) => { + QUnit.todo( 'setMode', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "render", ( assert ) => { + QUnit.todo( 'render', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "renderInstances", ( assert ) => { + QUnit.todo( 'renderInstances', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/renderers/webgl/WebGLCapabilities.tests.js b/test/unit/src/renderers/webgl/WebGLCapabilities.tests.js index 85f831e5fb8c57..531644361f4b6b 100644 --- a/test/unit/src/renderers/webgl/WebGLCapabilities.tests.js +++ b/test/unit/src/renderers/webgl/WebGLCapabilities.tests.js @@ -9,100 +9,100 @@ export default QUnit.module( 'Renderers', () => { QUnit.module( 'WebGLCapabilities', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "getMaxAnisotropy", ( assert ) => { + QUnit.todo( 'getMaxAnisotropy', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getMaxPrecision", ( assert ) => { + QUnit.todo( 'getMaxPrecision', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "precision", ( assert ) => { + QUnit.todo( 'precision', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "logarithmicDepthBuffer", ( assert ) => { + QUnit.todo( 'logarithmicDepthBuffer', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "maxTextures", ( assert ) => { + QUnit.todo( 'maxTextures', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "maxVertexTextures", ( assert ) => { + QUnit.todo( 'maxVertexTextures', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "maxTextureSize", ( assert ) => { + QUnit.todo( 'maxTextureSize', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "maxCubemapSize", ( assert ) => { + QUnit.todo( 'maxCubemapSize', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "maxAttributes", ( assert ) => { + QUnit.todo( 'maxAttributes', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "maxVertexUniforms", ( assert ) => { + QUnit.todo( 'maxVertexUniforms', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "maxVaryings", ( assert ) => { + QUnit.todo( 'maxVaryings', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "maxFragmentUniforms", ( assert ) => { + QUnit.todo( 'maxFragmentUniforms', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "vertexTextures", ( assert ) => { + QUnit.todo( 'vertexTextures', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "floatFragmentTextures", ( assert ) => { + QUnit.todo( 'floatFragmentTextures', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "floatVertexTextures", ( assert ) => { + QUnit.todo( 'floatVertexTextures', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/renderers/webgl/WebGLClipping.tests.js b/test/unit/src/renderers/webgl/WebGLClipping.tests.js index 9904ee36e387cb..dda9cc5b9be619 100644 --- a/test/unit/src/renderers/webgl/WebGLClipping.tests.js +++ b/test/unit/src/renderers/webgl/WebGLClipping.tests.js @@ -9,34 +9,34 @@ export default QUnit.module( 'Renderers', () => { QUnit.module( 'WebGLClipping', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "init", ( assert ) => { + QUnit.todo( 'init', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "beginShadows", ( assert ) => { + QUnit.todo( 'beginShadows', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "endShadows", ( assert ) => { + QUnit.todo( 'endShadows', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setState", ( assert ) => { + QUnit.todo( 'setState', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/renderers/webgl/WebGLGeometries.tests.js b/test/unit/src/renderers/webgl/WebGLGeometries.tests.js index 2e76f0cfaeee4b..e1284cae8b6b55 100644 --- a/test/unit/src/renderers/webgl/WebGLGeometries.tests.js +++ b/test/unit/src/renderers/webgl/WebGLGeometries.tests.js @@ -9,28 +9,28 @@ export default QUnit.module( 'Renderers', () => { QUnit.module( 'WebGLGeometries', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "get", ( assert ) => { + QUnit.todo( 'get', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "update", ( assert ) => { + QUnit.todo( 'update', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getWireframeAttribute", ( assert ) => { + QUnit.todo( 'getWireframeAttribute', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/renderers/webgl/WebGLIndexedBufferRenderer.tests.js b/test/unit/src/renderers/webgl/WebGLIndexedBufferRenderer.tests.js index 5a624b9cbd8c84..2c4f75eabd5497 100644 --- a/test/unit/src/renderers/webgl/WebGLIndexedBufferRenderer.tests.js +++ b/test/unit/src/renderers/webgl/WebGLIndexedBufferRenderer.tests.js @@ -9,34 +9,34 @@ export default QUnit.module( 'Renderers', () => { QUnit.module( 'WebGLIndexedBufferRenderer', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "setMode", ( assert ) => { + QUnit.todo( 'setMode', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setIndex", ( assert ) => { + QUnit.todo( 'setIndex', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "render", ( assert ) => { + QUnit.todo( 'render', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "renderInstances", ( assert ) => { + QUnit.todo( 'renderInstances', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/renderers/webgl/WebGLLights.tests.js b/test/unit/src/renderers/webgl/WebGLLights.tests.js index d458e6f2f66d40..966892f9b42a79 100644 --- a/test/unit/src/renderers/webgl/WebGLLights.tests.js +++ b/test/unit/src/renderers/webgl/WebGLLights.tests.js @@ -9,22 +9,22 @@ export default QUnit.module( 'Renderers', () => { QUnit.module( 'WebGLLights', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "setup", ( assert ) => { + QUnit.todo( 'setup', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "state", ( assert ) => { + QUnit.todo( 'state', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/renderers/webgl/WebGLMorphtargets.tests.js b/test/unit/src/renderers/webgl/WebGLMorphtargets.tests.js index 07f0e4fd1e3d4b..cd5c007bf30a54 100644 --- a/test/unit/src/renderers/webgl/WebGLMorphtargets.tests.js +++ b/test/unit/src/renderers/webgl/WebGLMorphtargets.tests.js @@ -9,16 +9,16 @@ export default QUnit.module( 'Renderers', () => { QUnit.module( 'WebGLMorphtargets', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "update", ( assert ) => { + QUnit.todo( 'update', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/renderers/webgl/WebGLObjects.tests.js b/test/unit/src/renderers/webgl/WebGLObjects.tests.js index 94e00cbbd9edfb..882118897d2506 100644 --- a/test/unit/src/renderers/webgl/WebGLObjects.tests.js +++ b/test/unit/src/renderers/webgl/WebGLObjects.tests.js @@ -9,22 +9,22 @@ export default QUnit.module( 'Renderers', () => { QUnit.module( 'WebGLObjects', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "update", ( assert ) => { + QUnit.todo( 'update', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "clear", ( assert ) => { + QUnit.todo( 'clear', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/renderers/webgl/WebGLProgram.tests.js b/test/unit/src/renderers/webgl/WebGLProgram.tests.js index 5aa6cd61936b16..58620985d83cf0 100644 --- a/test/unit/src/renderers/webgl/WebGLProgram.tests.js +++ b/test/unit/src/renderers/webgl/WebGLProgram.tests.js @@ -9,41 +9,41 @@ export default QUnit.module( 'Renderers', () => { QUnit.module( 'WebGLProgram', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PROPERTIES - QUnit.todo( "uniforms", ( assert ) => { + QUnit.todo( 'uniforms', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "attributes", ( assert ) => { + QUnit.todo( 'attributes', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "getUniforms", ( assert ) => { + QUnit.todo( 'getUniforms', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getAttributes", ( assert ) => { + QUnit.todo( 'getAttributes', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "destroy", ( assert ) => { + QUnit.todo( 'destroy', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/renderers/webgl/WebGLPrograms.tests.js b/test/unit/src/renderers/webgl/WebGLPrograms.tests.js index 4b26facba50506..e14ea724193bc1 100644 --- a/test/unit/src/renderers/webgl/WebGLPrograms.tests.js +++ b/test/unit/src/renderers/webgl/WebGLPrograms.tests.js @@ -9,40 +9,40 @@ export default QUnit.module( 'Renderers', () => { QUnit.module( 'WebGLPrograms', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "getParameters", ( assert ) => { + QUnit.todo( 'getParameters', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getProgramCode", ( assert ) => { + QUnit.todo( 'getProgramCode', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "acquireProgram", ( assert ) => { + QUnit.todo( 'acquireProgram', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "releaseProgram", ( assert ) => { + QUnit.todo( 'releaseProgram', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "programs", ( assert ) => { + QUnit.todo( 'programs', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/renderers/webgl/WebGLProperties.tests.js b/test/unit/src/renderers/webgl/WebGLProperties.tests.js index 08f770391b2038..d7ee88b496fcf0 100644 --- a/test/unit/src/renderers/webgl/WebGLProperties.tests.js +++ b/test/unit/src/renderers/webgl/WebGLProperties.tests.js @@ -9,28 +9,28 @@ export default QUnit.module( 'Renderers', () => { QUnit.module( 'WebGLProperties', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "get", ( assert ) => { + QUnit.todo( 'get', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "remove", ( assert ) => { + QUnit.todo( 'remove', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "clear", ( assert ) => { + QUnit.todo( 'clear', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/renderers/webgl/WebGLShader.tests.js b/test/unit/src/renderers/webgl/WebGLShader.tests.js index d0c03a72d0d9f5..6eb5319e2080ba 100644 --- a/test/unit/src/renderers/webgl/WebGLShader.tests.js +++ b/test/unit/src/renderers/webgl/WebGLShader.tests.js @@ -9,9 +9,9 @@ export default QUnit.module( 'Renderers', () => { QUnit.module( 'WebGLShader', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/renderers/webgl/WebGLShadowMap.tests.js b/test/unit/src/renderers/webgl/WebGLShadowMap.tests.js index 88562a21e733cf..164b13456307bd 100644 --- a/test/unit/src/renderers/webgl/WebGLShadowMap.tests.js +++ b/test/unit/src/renderers/webgl/WebGLShadowMap.tests.js @@ -9,16 +9,16 @@ export default QUnit.module( 'Renderers', () => { QUnit.module( 'WebGLShadowMap', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "render", ( assert ) => { + QUnit.todo( 'render', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/renderers/webgl/WebGLState.tests.js b/test/unit/src/renderers/webgl/WebGLState.tests.js index 8a6c14be097bbb..dea6faf591f604 100644 --- a/test/unit/src/renderers/webgl/WebGLState.tests.js +++ b/test/unit/src/renderers/webgl/WebGLState.tests.js @@ -9,148 +9,148 @@ export default QUnit.module( 'Renderers', () => { QUnit.module( 'WebGLState', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "buffers", ( assert ) => { + QUnit.todo( 'buffers', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "initAttributes", ( assert ) => { + QUnit.todo( 'initAttributes', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "enableAttribute", ( assert ) => { + QUnit.todo( 'enableAttribute', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "enableAttributeAndDivisor", ( assert ) => { + QUnit.todo( 'enableAttributeAndDivisor', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "disableUnusedAttributes", ( assert ) => { + QUnit.todo( 'disableUnusedAttributes', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "enable", ( assert ) => { + QUnit.todo( 'enable', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "disable", ( assert ) => { + QUnit.todo( 'disable', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "getCompressedTextureFormats", ( assert ) => { + QUnit.todo( 'getCompressedTextureFormats', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "useProgram", ( assert ) => { + QUnit.todo( 'useProgram', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setBlending", ( assert ) => { + QUnit.todo( 'setBlending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setMaterial", ( assert ) => { + QUnit.todo( 'setMaterial', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setFlipSided", ( assert ) => { + QUnit.todo( 'setFlipSided', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setCullFace", ( assert ) => { + QUnit.todo( 'setCullFace', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setLineWidth", ( assert ) => { + QUnit.todo( 'setLineWidth', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setPolygonOffset", ( assert ) => { + QUnit.todo( 'setPolygonOffset', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setScissorTest", ( assert ) => { + QUnit.todo( 'setScissorTest', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "activeTexture", ( assert ) => { + QUnit.todo( 'activeTexture', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "bindTexture", ( assert ) => { + QUnit.todo( 'bindTexture', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "compressedTexImage2D", ( assert ) => { + QUnit.todo( 'compressedTexImage2D', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "texImage2D", ( assert ) => { + QUnit.todo( 'texImage2D', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "scissor", ( assert ) => { + QUnit.todo( 'scissor', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "viewport", ( assert ) => { + QUnit.todo( 'viewport', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "reset", ( assert ) => { + QUnit.todo( 'reset', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/renderers/webgl/WebGLTextures.tests.js b/test/unit/src/renderers/webgl/WebGLTextures.tests.js index a3d9f480213b6f..73d016edb3b89d 100644 --- a/test/unit/src/renderers/webgl/WebGLTextures.tests.js +++ b/test/unit/src/renderers/webgl/WebGLTextures.tests.js @@ -9,36 +9,36 @@ export default QUnit.module( 'Renderers', () => { QUnit.module( 'WebGLTextures', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "setTexture2D", ( assert ) => { + QUnit.todo( 'setTexture2D', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setTextureCube", ( assert ) => { + QUnit.todo( 'setTextureCube', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setTextureCubeDynamic", ( assert ) => { + QUnit.todo( 'setTextureCubeDynamic', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setupRenderTarget", ( assert ) => { + QUnit.todo( 'setupRenderTarget', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "updateRenderTargetMipmap", ( assert ) => { + QUnit.todo( 'updateRenderTargetMipmap', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/renderers/webgl/WebGLUniforms.tests.js b/test/unit/src/renderers/webgl/WebGLUniforms.tests.js index 6e5b27975fcdab..fd2482b74675d5 100644 --- a/test/unit/src/renderers/webgl/WebGLUniforms.tests.js +++ b/test/unit/src/renderers/webgl/WebGLUniforms.tests.js @@ -9,34 +9,34 @@ export default QUnit.module( 'Renderers', () => { QUnit.module( 'WebGLUniforms', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "setValue", ( assert ) => { + QUnit.todo( 'setValue', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "setOptional", ( assert ) => { + QUnit.todo( 'setOptional', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "upload", ( assert ) => { + QUnit.todo( 'upload', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "seqWithValue", ( assert ) => { + QUnit.todo( 'seqWithValue', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/renderers/webgl/WebGLUtils.tests.js b/test/unit/src/renderers/webgl/WebGLUtils.tests.js index ded01681fddc94..e42cdf351e7d36 100644 --- a/test/unit/src/renderers/webgl/WebGLUtils.tests.js +++ b/test/unit/src/renderers/webgl/WebGLUtils.tests.js @@ -9,16 +9,16 @@ export default QUnit.module( 'Renderers', () => { QUnit.module( 'WebGLUtils', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "convert", ( assert ) => { + QUnit.todo( 'convert', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/scenes/Fog.tests.js b/test/unit/src/scenes/Fog.tests.js index 9eb741101b4a9f..af1d154c12b039 100644 --- a/test/unit/src/scenes/Fog.tests.js +++ b/test/unit/src/scenes/Fog.tests.js @@ -7,35 +7,35 @@ export default QUnit.module( 'Fog', () => { QUnit.module( 'Scene', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isFog", ( assert ) => { + QUnit.todo( 'isFog', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "clone", ( assert ) => { + QUnit.todo( 'clone', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "toJSON", ( assert ) => { + QUnit.todo( 'toJSON', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/scenes/FogExp2.tests.js b/test/unit/src/scenes/FogExp2.tests.js index 86db63472ab444..8bdbecc9de54a5 100644 --- a/test/unit/src/scenes/FogExp2.tests.js +++ b/test/unit/src/scenes/FogExp2.tests.js @@ -7,35 +7,35 @@ export default QUnit.module( 'FoxExp2', () => { QUnit.module( 'Scene', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isFogExp2", ( assert ) => { + QUnit.todo( 'isFogExp2', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "clone", ( assert ) => { + QUnit.todo( 'clone', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "toJSON", ( assert ) => { + QUnit.todo( 'toJSON', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/scenes/Scene.tests.js b/test/unit/src/scenes/Scene.tests.js index 0e96c235760053..09b5396c587dce 100644 --- a/test/unit/src/scenes/Scene.tests.js +++ b/test/unit/src/scenes/Scene.tests.js @@ -7,35 +7,35 @@ export default QUnit.module( 'Scenes', () => { QUnit.module( 'Scene', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isScene", ( assert ) => { + QUnit.todo( 'isScene', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "copy", ( assert ) => { + QUnit.todo( 'copy', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "toJSON", ( assert ) => { + QUnit.todo( 'toJSON', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/textures/CanvasTexture.tests.js b/test/unit/src/textures/CanvasTexture.tests.js index 29b75c4ed49243..4ddc5385bbfcf8 100644 --- a/test/unit/src/textures/CanvasTexture.tests.js +++ b/test/unit/src/textures/CanvasTexture.tests.js @@ -7,23 +7,23 @@ export default QUnit.module( 'Textures', () => { QUnit.module( 'CanvasTexture', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isCanvasTexture", ( assert ) => { + QUnit.todo( 'isCanvasTexture', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/textures/CompressedTexture.tests.js b/test/unit/src/textures/CompressedTexture.tests.js index 778e94edaabd16..f631b69c6cdc6b 100644 --- a/test/unit/src/textures/CompressedTexture.tests.js +++ b/test/unit/src/textures/CompressedTexture.tests.js @@ -7,23 +7,23 @@ export default QUnit.module( 'Textures', () => { QUnit.module( 'CompressedTexture', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isCompressedTexture", ( assert ) => { + QUnit.todo( 'isCompressedTexture', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/textures/CubeTexture.tests.js b/test/unit/src/textures/CubeTexture.tests.js index 128a861cc9f178..9fecbe1a23864e 100644 --- a/test/unit/src/textures/CubeTexture.tests.js +++ b/test/unit/src/textures/CubeTexture.tests.js @@ -7,30 +7,30 @@ export default QUnit.module( 'Textures', () => { QUnit.module( 'CubeTexture', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PROPERTIES - QUnit.todo( "images", ( assert ) => { + QUnit.todo( 'images', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isCubeTexture", ( assert ) => { + QUnit.todo( 'isCubeTexture', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/textures/DataTexture.tests.js b/test/unit/src/textures/DataTexture.tests.js index 2d3d4ceb3b6a01..5d345d4a676a99 100644 --- a/test/unit/src/textures/DataTexture.tests.js +++ b/test/unit/src/textures/DataTexture.tests.js @@ -7,23 +7,23 @@ export default QUnit.module( 'Textures', () => { QUnit.module( 'DataTexture', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isDataTexture", ( assert ) => { + QUnit.todo( 'isDataTexture', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/textures/DepthTexture.tests.js b/test/unit/src/textures/DepthTexture.tests.js index cf922f17802212..1834bcd1a81f64 100644 --- a/test/unit/src/textures/DepthTexture.tests.js +++ b/test/unit/src/textures/DepthTexture.tests.js @@ -7,23 +7,23 @@ export default QUnit.module( 'Textures', () => { QUnit.module( 'DepthTexture', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isDepthTexture", ( assert ) => { + QUnit.todo( 'isDepthTexture', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/textures/Texture.tests.js b/test/unit/src/textures/Texture.tests.js index 4ec0d6074f618b..b241f28767a4d1 100644 --- a/test/unit/src/textures/Texture.tests.js +++ b/test/unit/src/textures/Texture.tests.js @@ -7,53 +7,53 @@ export default QUnit.module( 'Textures', () => { QUnit.module( 'Texture', () => { // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PROPERTIES - QUnit.todo( "needsUpdate", ( assert ) => { + QUnit.todo( 'needsUpdate', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isTexture", ( assert ) => { + QUnit.todo( 'isTexture', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "clone", ( assert ) => { + QUnit.todo( 'clone', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "copy", ( assert ) => { + QUnit.todo( 'copy', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "toJSON", ( assert ) => { + QUnit.todo( 'toJSON', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "dispose", ( assert ) => { + QUnit.todo( 'dispose', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( "transformUv", ( assert ) => { + QUnit.todo( 'transformUv', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/textures/VideoTexture.tests.js b/test/unit/src/textures/VideoTexture.tests.js index 1dd8e9bf901e4c..9456d2755f4865 100644 --- a/test/unit/src/textures/VideoTexture.tests.js +++ b/test/unit/src/textures/VideoTexture.tests.js @@ -7,23 +7,23 @@ export default QUnit.module( 'Textures', () => { QUnit.module( 'VideoTexture', () => { // INHERITANCE - QUnit.todo( "Extending", ( assert ) => { + QUnit.todo( 'Extending', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // INSTANCING - QUnit.todo( "Instancing", ( assert ) => { + QUnit.todo( 'Instancing', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); // PUBLIC STUFF - QUnit.todo( "isVideoTexture", ( assert ) => { + QUnit.todo( 'isVideoTexture', ( assert ) => { - assert.ok( false, "everything's gonna be alright" ); + assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/utils.tests.js b/test/unit/src/utils.tests.js index b6b158a2c5e00d..f393b2679ef6f7 100644 --- a/test/unit/src/utils.tests.js +++ b/test/unit/src/utils.tests.js @@ -1,6 +1,6 @@ /* global QUnit */ -import { arrayMin, arrayMax } from '../../../src/utils'; +import { arrayMin, arrayMax, getTypedArray } from '../../../src/utils'; QUnit.module( 'utils', () => { @@ -29,4 +29,18 @@ QUnit.module( 'utils', () => { } ); + QUnit.test( 'getTypedArray', ( assert ) => { + + assert.ok( getTypedArray( 'Int8Array', Buffer.from( '', 'utf8' ) ) instanceof Int8Array, 'Int8Array' ); + assert.ok( getTypedArray( 'Uint8Array', Buffer.from( '', 'utf8' ) ) instanceof Uint8Array, 'Uint8Array' ); + assert.ok( getTypedArray( 'Uint8ClampedArray', Buffer.from( '', 'utf8' ) ) instanceof Uint8ClampedArray, 'Uint8ClampedArray' ); + assert.ok( getTypedArray( 'Int16Array', Buffer.from( '', 'utf8' ) ) instanceof Int16Array, 'Int16Array' ); + assert.ok( getTypedArray( 'Uint16Array', Buffer.from( '', 'utf8' ) ) instanceof Uint16Array, 'Uint16Array' ); + assert.ok( getTypedArray( 'Int32Array', Buffer.from( '', 'utf8' ) ) instanceof Int32Array, 'Int32Array' ); + assert.ok( getTypedArray( 'Uint32Array', Buffer.from( '', 'utf8' ) ) instanceof Uint32Array, 'Uint32Array' ); + assert.ok( getTypedArray( 'Float32Array', Buffer.from( '', 'utf8' ) ) instanceof Float32Array, 'Float32Array' ); + assert.ok( getTypedArray( 'Float64Array', Buffer.from( '', 'utf8' ) ) instanceof Float64Array, 'Float64Array' ); + + } ); + } ); diff --git a/test/unit/utils/SmartComparer.js b/test/unit/utils/SmartComparer.js index ec2d3b810444fb..e21abee26a9bf5 100644 --- a/test/unit/utils/SmartComparer.js +++ b/test/unit/utils/SmartComparer.js @@ -165,7 +165,7 @@ function SmartComparer() { var key = keys1[ i ]; - if ( key === "uuid" || key === "id" ) { + if ( key === 'uuid' || key === 'id' ) { continue; @@ -196,7 +196,7 @@ function SmartComparer() { function makeFail( msg, val1, val2 ) { message = msg; - if ( arguments.length > 1 ) message += " (" + val1 + " vs " + val2 + ")"; + if ( arguments.length > 1 ) message += ' (' + val1 + ' vs ' + val2 + ')'; return false; @@ -205,8 +205,8 @@ function SmartComparer() { function addContext( msg ) { // There should already be a validation message. Add more context to it. - message = message || "Error"; - message += ", at " + msg; + message = message || 'Error'; + message += ', at ' + msg; return false; diff --git a/test/unit/utils/console-wrapper.js b/test/unit/utils/console-wrapper.js index c552baa246b23a..43500400bc9c9c 100644 --- a/test/unit/utils/console-wrapper.js +++ b/test/unit/utils/console-wrapper.js @@ -11,12 +11,12 @@ // See https://github.com/mrdoob/three.js/issues/20760#issuecomment-735190998 export const CONSOLE_LEVEL = { - OFF : 0, - ERROR : 1, - WARN : 2, - LOG : 3, - INFO : 4, - DEBUG : 5, + OFF: 0, + ERROR: 1, + WARN: 2, + LOG: 3, + INFO: 4, + DEBUG: 5, ALL: 6, DEFAULT: 6 }; diff --git a/test/unit/utils/qunit-utils.js b/test/unit/utils/qunit-utils.js index e80de57ba306f4..4ce8a862f1c6aa 100644 --- a/test/unit/utils/qunit-utils.js +++ b/test/unit/utils/qunit-utils.js @@ -32,7 +32,7 @@ QUnit.assert.fail = function ( message ) { QUnit.assert.numEqual = function ( actual, expected, message ) { var diff = Math.abs( actual - expected ); - message = message || ( actual + " should be equal to " + expected ); + message = message || ( actual + ' should be equal to ' + expected ); this.pushResult( { result: diff < 0.1, actual: actual, @@ -80,8 +80,8 @@ function checkGeometryClone( geom ) { // Clone var copy = geom.clone(); - QUnit.assert.notEqual( copy.uuid, geom.uuid, "clone uuid should differ from original" ); - QUnit.assert.notEqual( copy.id, geom.id, "clone id should differ from original" ); + QUnit.assert.notEqual( copy.uuid, geom.uuid, 'clone uuid should differ from original' ); + QUnit.assert.notEqual( copy.id, geom.id, 'clone id should differ from original' ); var differingProp = getDifferingProp( geom, copy ); QUnit.assert.ok( differingProp === undefined, 'properties are equal' ); @@ -121,10 +121,10 @@ function getDifferingProp( geometryA, geometryB ) { // Compare json file with its source geometry. function checkGeometryJsonWriting( geom, json ) { - QUnit.assert.equal( json.metadata.version, "4.5", "check metadata version" ); + QUnit.assert.equal( json.metadata.version, '4.5', 'check metadata version' ); QUnit.assert.equalKey( geom, json, 'type' ); QUnit.assert.equalKey( geom, json, 'uuid' ); - QUnit.assert.equal( json.id, undefined, "should not persist id" ); + QUnit.assert.equal( json.id, undefined, 'should not persist id' ); var params = geom.parameters; if ( ! params ) { @@ -143,7 +143,7 @@ function checkGeometryJsonWriting( geom, json ) { // All parameters from json should be transfered to the geometry. // json is flat. Ignore first level json properties that are not parameters. - var notParameters = [ "metadata", "uuid", "type" ]; + var notParameters = [ 'metadata', 'uuid', 'type' ]; var keys = Object.keys( json ); for ( var i = 0, l = keys.length; i < l; i ++ ) { @@ -221,7 +221,7 @@ function runStdLightTests( assert, lights ) { // THREE.Light doesn't get parsed by ObjectLoader as it's only // used as an abstract base class - so we skip the JSON tests - if ( light.type !== "Light" ) { + if ( light.type !== 'Light' ) { // json round trip checkLightJsonRoundtrip( assert, light ); @@ -238,29 +238,29 @@ function checkLightCopyClone( assert, light ) { var newLight = new light.constructor( 0xc0ffee ); newLight.copy( light ); - QUnit.assert.notEqual( newLight.uuid, light.uuid, "Copied light's UUID differs from original" ); - QUnit.assert.notEqual( newLight.id, light.id, "Copied light's id differs from original" ); - QUnit.assert.smartEqual( newLight, light, "Copied light is equal to original" ); + QUnit.assert.notEqual( newLight.uuid, light.uuid, 'Copied light\'s UUID differs from original' ); + QUnit.assert.notEqual( newLight.id, light.id, 'Copied light\'s id differs from original' ); + QUnit.assert.smartEqual( newLight, light, 'Copied light is equal to original' ); // real copy? newLight.color.setHex( 0xc0ffee ); QUnit.assert.notStrictEqual( - newLight.color.getHex(), light.color.getHex(), "Copied light is independent from original" + newLight.color.getHex(), light.color.getHex(), 'Copied light is independent from original' ); // Clone var clone = light.clone(); // better get a new var - QUnit.assert.notEqual( clone.uuid, light.uuid, "Cloned light's UUID differs from original" ); - QUnit.assert.notEqual( clone.id, light.id, "Clone light's id differs from original" ); - QUnit.assert.smartEqual( clone, light, "Clone light is equal to original" ); + QUnit.assert.notEqual( clone.uuid, light.uuid, 'Cloned light\'s UUID differs from original' ); + QUnit.assert.notEqual( clone.id, light.id, 'Clone light\'s id differs from original' ); + QUnit.assert.smartEqual( clone, light, 'Clone light is equal to original' ); // real clone? clone.color.setHex( 0xc0ffee ); QUnit.assert.notStrictEqual( - clone.color.getHex(), light.color.getHex(), "Clone light is independent from original" + clone.color.getHex(), light.color.getHex(), 'Clone light is independent from original' ); - if ( light.type !== "Light" ) { + if ( light.type !== 'Light' ) { // json round trip with clone checkLightJsonRoundtrip( assert, clone ); @@ -272,12 +272,12 @@ function checkLightCopyClone( assert, light ) { // Compare json file with its source Light. function checkLightJsonWriting( assert, light, json ) { - assert.equal( json.metadata.version, "4.5", "check metadata version" ); + assert.equal( json.metadata.version, '4.5', 'check metadata version' ); var object = json.object; assert.equalKey( light, object, 'type' ); assert.equalKey( light, object, 'uuid' ); - assert.equal( object.id, undefined, "should not persist id" ); + assert.equal( object.id, undefined, 'should not persist id' ); } diff --git a/utils/build/rollup.config.js b/utils/build/rollup.config.js index 50097ed82da026..f6ddd15b39e9a4 100644 --- a/utils/build/rollup.config.js +++ b/utils/build/rollup.config.js @@ -159,6 +159,7 @@ export function glconstants() { READ_FRAMEBUFFER: 36008, DRAW_FRAMEBUFFER: 36009, SAMPLE_ALPHA_TO_COVERAGE: 32926, + SRGB8: 35905, SRGB8_ALPHA8: 35907 }; diff --git a/utils/build/rollup.examples.config.js b/utils/build/rollup.examples.config.js index 59b1cd8b01e5a4..caa708a30cd8d4 100644 --- a/utils/build/rollup.examples.config.js +++ b/utils/build/rollup.examples.config.js @@ -170,6 +170,7 @@ const jsmFolder = path.resolve( __dirname, '../../examples/jsm' ); // list of all .js file nested in the examples/jsm folder const files = glob.sync( '**/*.js', { cwd: jsmFolder, ignore: [ // don't convert libs + 'capabilities/*', 'libs/**/*', 'loaders/ifc/**/*',